编 者 按
前段时间和几个人闲谈,看看在FPGA里面实现一个Mem加法器怎么玩儿
加法器
看一个很简单的代码:
val memContext=Array.fill(16*1024)(0) def addOne(index:Int)={ memContext(index)=memContext(index) }
一个很简单的功能。一个16K大小的数组。在软件人眼里这连最初级的面试题都算不上是吧~
那么我们考虑下在FPGA里面的实现。数组位宽如此之大,如果谁上来说用寄存器实现那真的要贻笑大方了~这种情况无他,只能使用Block Mem来实现。
相比于软件,逻辑设计引入了时序的概念,也就是加上了时钟这个维度。这里是要首先读出原始的数据加1后再写回回去。而对于Block Mem,其读延迟至少有一拍的读延迟,这里实现需要先读后写,如果要实现每拍均能处理一个指令那显然是需要Mem Write First类型了。
Block Mem
对于Block Mem,下面是Xilinx中Block Ram的结构图:
对于Block RAM,地址线在进入到Memory Array之前会先经过一级寄存器。Memory Array选择输出则会经过一级Latch,随后可通过选择器选择是直接输出还是再经过一级寄存器输出。
对于Block RAM的使用,如果选择读延迟为1 cycle,那么Dout会通过Latches输出,如果读延迟为2 cycle,那么Dout将会通过寄存器输出。初学FPGA那会儿,一般在使用Block RAM时,往往就无脑的选择一拍的delay设计模式。现在再来看,在FPGA设计里,这种形式往往不利于提升时钟频率。在FPGA设计里,如果想要尽可能提高时钟频率,那么对于Block Ram的使用则需要将Block Ram中Dout前的寄存器给使用起来,即读延迟需要两拍的延迟。而再考虑Block RAM的拼接,布局布线的位置,那么可能就需要更高的读延迟了。
对于高频设计,Memory的Write First的设计实现就需要考虑读延迟的拍数了~
假定Read Latency为N,那么上面的例子就相当于:
全部0条评论
快来发表一下你的评论吧 !