https://blog.youkuaiyun.com/Times_poem/article/details/52023063?utm_source=blogxgwz35
我们可以对异步FIFO的地址采用binary编码,这样并不影响异步FIFO的功能,前提是读写地址同步时能够保持正确。这种情况在功能仿真时完全正确,问题只有到时序仿真时才会遇到。毛刺可以说是异步电路的杀手,一个毛刺被触发器采样后会被放大,然后传播,导致电路功能出错。binary编码的地址总线在跳变时极易产生毛刺,因为binary编码是多位跳变,在实现电路时不可能做到所有的地址总线等长,address bus skew必然存在,而且写地址和读地址分属不同时钟域,读写时钟完全异步,这样地址总线在进行同步过程中出错不可避免,比如写地址在从0111到1000转换时4条地址线同时跳变,这样读时钟在进行写地址同步后得到的写地址可能是0000-1111的某个值,这个完全不能确定,所以用这个同步后的写地址进行FIFO空判断的时候难免出错。
这个时候gray码体现了价值,一次只有一位数据发生变化,这样在进行地址同步的时候,只有两种情况:1.地址同步正确;2.地址同步出错,但是只有1位出错;第一种正确的情况不需要分析,我们关注第二种,假设写地址从000->001,读时钟域同步出错,写地址为000->000,也就是地址没有跳变,但是用这个错误的写地址去做空判断不会出错,最多是让空标志在FIFO不是真正空的时候产生,而不会出现空读的情形。所以gray码保证的是同步后的读写地址即使在出错的情形下依然能够保证FIFO功能的正确性,当然同步后的读写地址出错总是存在的(因为时钟异步,采样点不确定)。这里需要注意gray码只是在相邻两次跳变之间才会出现只有1位数据不一致的情形,超过两个周期则不一定,所有地址总线bus skew一定不能超过一个周期,否则可能出现gray码多位数据跳变的情况,这个时候gray码就失去了作用,因为这时候同步后的地址已经不能保证只有1位跳变了
为什么要提到gray code?
在做cdc asyncfifo check时,会检查bus skew check,如果write/read pointer的位数是1,questa tool工具会报错,说"Gray code bus skew check on this write pointer will be ignored"这个error可以waive,因为本来就pointer就是1bit,当然没办法做bus skew check.
作者:胡建东
链接:https://zhuanlan.zhihu.com/p/36371393
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
3.同步器同步n bit数据
当n=1时,参见上面的亚稳态传播,1bit数据产生亚稳态以后就算错了也是变成0或者1第二拍也会正确,所以同步1bit数据可以采后面几拍的数据,这样就能保证采集过来的数据是正确的,后面会试验给大家看。当然,要实现这点首先是快时钟必须是慢时钟的好几倍才行,至少2倍。
多bit数据传输和1bit数据唯一的区别就是多路对齐,保证每一路数据延迟一致 ,这样就和传输1bit数据一样了。下面给大家推荐一个约束set_bus_skew,可以约束一条总线上每根线的延迟相差不大。
命令用法——set_bus_skew [-from 寄存器名] [-to 寄存器名] xx ns。比如在图3中约束src_gray_ff_reg到dest_graysync_ff_reg之间的两根线延迟保持一致,完整命令如下,保证两根线延迟都在2.5ns,一个快时钟域周期:
set_bus_skew -from [get_cells src_gray_ff_reg[*]] -to[get_cells {dest_graysync_ff_reg[0][*]}] 2.500
图3. 寄存器图