赞
踩
之前我在学习的过程中,在找资料的过程中花费了大量时间,但也找到一些大佬的优质文章,为了减少各位粉丝查找优质资源的时间,在这里开创一个转载个人认为内容比较优质的文章,学习一下大佬阅读、分析手册的思路,提升对FPGA底层、应用的知识。
如果觉得对你有帮助,可以订阅该专栏,后续会一直转载优质内容。
以下为大佬文章正文,如有侵权,请通知删除:
所使用EDA软件:VIVADO2018.3
FPGA型号:xc7a35tcsg325-2
很久没写了,随便写一篇BRAM的吧。说到BRAM ,很多人都喜欢拿它来DRAM比较 ,两者都有啥优缺点,其实我也拿不准。不过一般来说,存储较大的数据时用BRAM,存储较小的数据时用DRAM。 多大为大,多小为小,这个不用care。 一句话,你能让时序跑过,功能没毛病的前提下,最后总体资源还OK就行了,不用纠结。
在做读操作的时候,BRAM和DRAM不同。DRAM是组合逻辑直接输出,BRAM则是时序逻辑输出。我们看一下BRAM(图1)的结构就可以知道为啥。因为我们DRAM把地址送进去的时候是不需要时钟的(地址作为LUT输入,数据作为LUT输出,中间无寄存)。然而BRAM把地址送进去的时候是要过寄存器滴,所以数据也是要有时钟才能输出。此外BRAM的输出还内嵌了个寄存器,我们打拍输出的时候可以使用它,这样就能省下SLICE上的寄存器资源。
接下来我们通过解释IP的形式大概讲一下BRAM
图2:显示了BRAM IP的基本选项
左边的IP SYMBOL(省略末尾的a/b)
addr:端口地址输入
clk :端口时钟输入
din : 端口数据输入
dout: 端口数据输出
ena: 端口使能输入,高有效
rst : 端口复位输入,高有效
wea:写使能/Byte 写使能输入,高有效
右边的Basic选项
Interface类型可以选Native或者AXI。用RAM的话一般都只用Native ,AXI的话一般是用到相应的处理器内核时,处理器内的数据需要和BRAM交互(如ZYNQ中的PS和PL交互)。
MEMORY 类型 可以选RAM,或者ROM。RAM可以选SP SDP TDP 。ROM 由于只读,所以只会有SP 和 DP。
ECC,当MEMORY类型为SDP RAM的时候可以用ECC,ECC主要作用是单bit纠错,双bit检错。ECC分为软ECC和硬ECC,软ECC在数据位宽较小的时候使用(16以内),并且需要消耗BRAM以外的FPGA资源。硬ECC在数据位宽较大时候使用,不需要消耗额外FPGA资源。
Write Enable,写使能。在BRAM 作写操作的时候,可以用写相应的bit来指示当前byte是否写入。
Algorithm Options 。这个算法选项主要用于决定BRAM的拼接的方式,一般在BRAM深度、宽度较大的时候起作用(准确来讲是1个18K BRAM或者1个36K BRAM无法满足BRAM所需存储大小的时候)。它有三个选项,1.Minimum Area(小面积)。2.低功耗(Lower Power)。3.(Fixed Primitives)固定原语,可选16kx1,8kx2等。前两个看名字就知道是啥意思,第3个的话就是用固定原语的方式来生成你想要的BRAM,这个主要是在不同器件间工程移植用的比较多,例如你在XILINX 移植到ALTERA或者LATTICE的器件,它们单个BRAM 的原语都是类似的。如果要在多平台对工程/IP进行移植,用这个选项的话修改的东西会比较少。
图3:显示了BRAM Port A的选项
Memory Size(图4)
里面主要配置的有读/写的数据宽度,读/写数据的深度。在做设计的时候我一般推荐用的2^n以及18K/36 BRAM的数据宽度/深度(图5、图6)特性来决定。
然后详细说说BRAM的三种模式,敲黑板咯,这是重点
第一种,WRITE_FIRST(写先于读),其时序图如图7所示
WRITE_FIRST的时序图,在红线以前,WE=0 ,即端口做的是读操作。在CLK上升沿后,地址aa里的数据打到DO。在红线后,WE=1,即端口做的是写操作。在CLK上升沿后,DI的数据存入到地址bb里,与此同时输入的数据DI直接打到去输出DO,(⊙﹏⊙)原先存在bb里的数据嘛还没出来就被冲掉。就像老实人还没表白就被渣男抢占了,这就是WRITE_FIRST的特性。
第二种,READ_FIRST(读先于写),其时序图如图8所示
READ_FIRST的时序图,在红线以前,WE=0 ,即端口做的是读操作。在CLK上升沿后,地址aa里的数据打到DO。在红线后,WE=1,即端口做的是写操作。在CLK上升沿后,DI的数据存入到地址bb里,与此同时原先存放在地址bb的数据输出到DO。就像处了一段时间,新男/女朋友替换掉前男/女朋友。这就是READ_FIRST的特性。
第三种,NO_CHANGE,其时序图如图9所示
NO_CHANGE的时序图,在红线以前,WE=0 ,即端口做的是读操作。在CLK上升沿后,地址aa里的数据打到DO。在红线后,WE=1,即端口做的是写操作。在CLK上升沿后,DI的数据存入到地址bb里,与此同时输出DO的数据保持不变(依旧是地址aa里的数据)。就像处了一段时间,表面上其乐融融,实际内部已经被隔壁老王给替代。这就是NO_CHANGE的特性。
ENA、ENB是BRAM对应端口的使能信号。
PortA Optional Output Register(图10),与复位相关的几个选项
里面的选项有4个,都是为了提高BRAM的运行频率或者改善时序的(当然也增加了延迟)
1.Primitives Output Register ,使用BRAM内部的寄存器打拍输出
2.Primitives Output Register ,使用SLICE的寄存器打拍输出
3.SoftECC Input Register ,当使用软ECC的时候,用SLICE的寄存器打拍。
4.REGCEA,当使用Primitives Output Register时,可以用REGCEA 来使能/去使能相应的输出。
PortA Optional Resert(图11),与复位相关的几个选项
1.RSTA Pin ,BRAM复位,高有效
2.Output Reset Value ,复位时,输出的值
3.Reset Memory Latch ,当不使用Primitives Output Register时,复位操作是复位锁存器的。当我们使用Primitives Output Register时,不选该选项,复位操作只复位寄存器。选上该选项,寄存器和锁存器同时复位
4.Reset Prority ,复位优先级。它的选项有CE 和 SR 。当我们选择CE的时候,只有ENA为高时,RSTA复位才生效(图12)。当我们选择SR时,无论ENA是高是低,RSTA复位都会生效(图13)。
PortA Address Change A(图14),该选项用于指示读地址是否改变,在某些低功耗场景会应用到(实际上我并没用过)。
PORTB的内容与PORTA一样,省略。
接下来,大概说一下Other Options(图15)
Pipeline Stages Within Mux ,这个选项时可选0,1,2,3。这是在大位宽、大深度的BRAM拼接场景,我们会用MUX来输出地址所对应的数据,输出数据后为了更好的时序,可以用寄存器打拍。(这个选项的使用需要PORTA PORTB同时开启,并且还要开CORE OUTPUT REGISTER,即SLICE上的寄存器)
Memory Initialization。给BRAM赋予初值,需要用到COE文件。
Structual/UniSim Simulation Model Options,用于仿真时,对读写冲突、写写冲突的告警(注:读写冲突即PORTA PORTB在同一时刻对同一地址做一读一写操作,写写冲突即PORTA PORTB在同一时刻对同一地址做写操作)
Behavioral Simulation Model Options ,用于关闭仿真时的冲突告警、超出范围告警。
Safety logic to minimize BRAM data corruption,在PORTA 或PORTB进行复位时,用busy信号对其进行指示。
关于读写冲突、写写冲突,在这里列两张表(图16、图17)给大家参考参考。不过在设计中还是推荐用逻辑去避免这种情况。
当然,这些冲突只有在TDP模式下才会有,SDP SP模式下是不会产生的。在可以避免冲突的情况下,官方推荐使用NO CHANGE模式来节省功耗。
最后看下Summary(图18)
从Summary可以看到,这个IP我用的是位宽16,地址深度16(2^4)的BRAM ,1个18K BRAM就可以搞定。读延迟为2clk,这里需要注意的是这个2clk是对于采样而言的。如图19所示,我们在第一条红线给地址,然后锁存器上立马有数据(do_l)了,然后由于我加了个寄存器,数据打1拍才输出(do_r),但是数据刚发送不可能立刻采集到,需要等待一个时钟上升沿(即1拍)才能采集,所以Read Latency = (1拍+1拍)=2拍
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。