以前很少用到仿真,这次在仿真的过程中,遇到了某个警告,于是转过头又去研究了FIFO中的Safety Circuit的作用。
FIFO在FPGA中用的很多,常用于做少量数据的缓存和同步数据时钟域, 本文将介绍Memory Collision Error on RAMB36E1错误及相应的解决方案,其中涉及到Vivodo FIFO IP核的Safety Circuit设置。
事情是这样的,在某个设计中,我需要用异步FIFO同步数据的时钟域,在这个工程中,读写会持续进行,虽然读时钟速率是写时钟速率的N倍,但是读使能N个读时钟周期才会拉高一次,所以两边速率可以说是一致;在写入一半的数据后,读过程也开始了,两边一读一写,FIFO内部的数据量不增不减。
在仿真的过程中,我遇到了下图的仿真警告提示。
之所以说不是错误而是警告,是因为这个提示并没有影响最终的结果。仿真依旧在运行,直到结束。
随后搜集了一番资料,在参考资料1(AR34859)中,解决方案是对FIFO内部的Block RAM,在双端口模式下,使用WRITE_FIRST或NO_CHANGE模式;
在资料2(Xilinx Memeory Resource pdf)的17页,介绍了Block RAM写模式,几种模式中,区别主要在
最后,官方给出了避免Conflict的建议。虽然,FIFO内部确实使用了Block RAM,但Xilinx对其加密了,无法看到内部的实现细节;官方应该不至于在FIFO Block RAM的设置上有这种错误,感觉问题并不是出现在这。
把FIFO单独拿出来做仿真测试时,却怎么也无法复原这个BUG。于是找到参考资料3(FIFO IP核手册),在Reset相关章节发现了一点玄机。
FIFO Asynchronous Reset Timing Without Safety Circuit
在异步FIFO里,只能选择异步复位,而FIFO内部会把输入的异步复位信号同步到各自的时钟域;根据上图,复位信号拉低后,还是有一段时间不能对FIFO有读写操作,那么怎么知道是哪段时间呢。IP核的设置里面,可以设置在复位状态下,FULL的输出状态,设置为1,这样就可以根据FULL防止写入,复位后EMPTY为1,也可以防止读取。
而在我对FIFO的操作中,我好心的把异步复位信号同步到RD时钟域下,然后输入到FIFO的RST端口,但是却没有注意到这个地方。
我取消了异步复位信号的同步,直接输入到FIFO的RST,复位与写使能之间的时间隔得足够长,警告果然消失了。
这里,再介绍另一种方法,选中上图的Enable Safety Circuit,在Safety Circuit启用下,时序图又变成这样:
FIFO Asynchronous Reset Timing With Safety Circuit
在复位后,需要等待WR_RST_BUSY从1到0后,才能进行其他的操作(包括复位和写);同理,读取数据也需要等待RD_RST_BUSY从1到0。
此外,Enable Safety Circuit会同步FIFO内部的BRAM输入信号和输出信号,具体可以看看参考资料4(AR42571);文档也提到了,复位信号最好保持MAX(3, C_SYNCHRONIZER_STAGE)个慢时钟周期,两次复位中间要间隔6个慢时钟周期。
全部0条评论
快来发表一下你的评论吧 !