格雷码在异步FIFO中的使用

异步FIFO通过比较读写地址进行满空判断,但是读写地址属于不同的时钟域,所以在比较之前需要先将读写地址进行同步处理,将写地址同步到读时钟域再和读地址比较进行FIFO空状态判断(同步后的写地址一定是小于或者等于当前的写地址,所以此时判断FIFO为空不一定是真空,这样更保守),将读地址同步到写时钟域再和写地址比较进行FIFO满状态判断(同步后的读地址一定是小于或者等于当前的读地址,所以此时判断FIFO为满不一定是真空,这样更保守),这样可以保证FIFO的特性:FIFO空之后不能继续读取,FIFO满之后不能继续写入。

大多数情形下,异步FIFO两端的时钟不是同频的,或者读快写慢,或者读慢写快,这时候进行地址同步的时候,可能会有地址遗漏,以读慢写快为例,进行满标志判断的时候需要将读地址同步到写时钟域,因为读慢写快,所以不会有读地址遗漏,同步后的读地址滞后当前读地址,所以可能满标志会提前产生。进行空标志判断的时候需要将写地址同步到读地址,因为读慢写快,所以当读时钟同步写地址的时候,必然会漏掉一部分写地址(写时钟快,写地址随写时钟翻转,直到满标志出现为止),那到底读时钟会同步到哪个写地址?不必在意是哪一个,我们关注的是漏掉的地址会不会对FIFO的空标志产生影响。比如写地址从0写到10,期间读时钟域只同步到了2,5,7这三个写地址,漏掉了其他地址。同步到7地址时,真实的写地址可能已经写到10地址,相当于“在读时钟域还没来得及觉察的情况下,写时钟域可能偷偷写了数据到FIFO去”,这样在比较读写地址的时候不会产生FIFO“空”读操作。漏掉的地址也没有对FIFO的逻辑操作产生影响。

我们可以对异步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位跳变了。

另外需要将地址总线打两拍,这是为了避免亚稳态传播,理论上将打两拍不能消除亚稳态现象,因为时钟异步,亚稳态不可避免,但是可以极大降低亚稳态传播的概率,低频情况下甚至STA不需要分析这里的异步时序,因为寄存器都可以在一拍内将亚稳态消除,恢复到正常0/1态。而在高频情况下则不一定,尤其在28nm工艺以下,需要检查两级触发器的延迟,保证延迟低,这样可以提高Tr,提高系统MTBF。

异步FIFO使用格雷码的唯一目的就是“即使在亚稳态进行读写指针抽样也能进行正确的空满状态判断”。

回答一:
格雷码是的确非常有用。它的特点就是相邻码只有一位发生翻转,比如00->01->11->10->00...
在编写状态机时,我也喜欢用这种相邻状态只发生一位翻转的编码。这样从一个状态切换到下一个状态,就只有一位寄存器发生变化。这么做可以带来降低功耗的好处,因为寄存器的翻转是消耗动态功耗的,而这种编码将翻转的次数降到最低,所有有利于降低功耗。
回答二:
你说的降低功耗的前提是,一个状态到下一个状态的变化也要遵循格雷码连续的变化,否则,就不成立了。比如:如你所说,00<->01<->11<->10这样的变化,确实是有利于降低功耗;但是,状态的变化不一定就是这样变化,它有可能是00<->11,01<->10这样的变化,那么你说的有利于降低功耗就不成立。
 回答三:
 低功耗设计的内容还是很博大精深的。如何合理的选择信号形式,以使得系统在发生状态变化时只有少数信号发生翻转?所依赖的公式为

P=a*C*V^2*f

其中a为信号翻转率,C为系统等效电容,V为电路驱动电压,f为时钟频率。使用格雷码降低功耗就是想使a小下来。当然如果电路中做不到严格的格雷码也没关系,只要是有利于减小a的,就有利于功耗的降低。
期待牛人能对低功耗设计的内容普及一下。在移动的智能终端上低功耗的问题已经越来越受重视了。
回答四:
主要是为了多比特同步,这个例子中功耗是次要的因素
 回答五:
 格雷码有两个作用,一是消除多个比特同时变化带来的潜在竞争与冒险,二是降低功耗(翻转次数减少)。在状态机中通常为了简单起见表示现态与次态的状态参数并不使用格雷码而是二进制码,因为一个状态的变化可能是发散的而非单向的,就是说不同的条件对应不同的次态,这个时候用格雷码对状态进行编码达不到一次只变化一位的目的,除非在特殊情况下,即状态机的变化是单向的,总是由S0到S1,再到S2,等等,这个时候用格雷码就能达到原来的目的。
 回答六:
 十进制计数容易产生毛刺,格雷码则不会产生毛刺。
 回答七:
 格雷码每次只有一位跳变,两级寄存才安全。
 回答八:
在异步的FIFO中,采用格雷码进行计数,相邻的数据仅仅只有1bit变化,这样在两个时钟域同步的时候仅仅可能只有1bit产生亚稳态,通过同步以后,亚稳态可以消除,最坏的情况是这1bit采错,但是即使是采错地址也只是相差1个,这对判断空满标志不会产生影响。
如果是采用10十进制进行编码,则相邻的数据可能有很多位同时进行变化,那么如果多位同时产生亚稳态而且同时采错数据,会对寄存器的空满标志做出严重错误的判断,会丢失数据或者读出无用的数据,使系统出错。
 回答九:
由于跳变减少,可减少功耗,多用于低功耗设计中。
 回答十:
 我在想这个问题,如果单指gray的话确实如此,但是在实际应用中,往往是将二进制的转换成gray,就是说不管如何二进制的数依然会存在同时其转换的外加逻辑必然会带来损耗。在多比特的情况,功耗是否会跟多呢?gray一般是用在不同时钟域的连续数值的传送,即数据必须是递增或递减的。这样,其主要是在asynchronou fifo中使用,感觉功耗并不会下降

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值