在异步FIFO的设计中,最重要的一个问题就是如何进行FIFO空满的判断?
- 由于异步FIFO的特性,需要读写指针的跨时钟域同步,在同步时引发相邻数据的中间状态采样的问题,如何将相邻数据发生跳变时,出现的中间状态变得可控是解题的关键。“因此需要新的编码方式”。
二进制为什么不能用?
- 在同步FIFO的设计中,FIFO空满的判断一般是通过读写指针的比较,进行判断,在异步FIFO中对于跨时钟域的读写指针之间的同步,由于二进制编码的原因,在相邻的数据之间发生变化时,会出现多bit的同时跳变,eg: (4’b0111 —> 4’b1000)四bit的数据同时发生跳变,这就导致在进行数据采样时,可能采到的值有16种情况【每一位都有可能发生跳变】,而后,在读写指针的比较时,可能会出现真实状态下FIFO已经满了,由于数据跳变的不确定性,错误读写指针进行同步,而导致判断后的结果是非满,出现数据溢出的现象。【空,也一样】
使用格雷码的原理:
- 使用格雷码,每次只改变一bit信号。例如,格雷码从0100 (二进制编码 0111) 递增到1100(二进制编码 1000)时,即使进行中间状态采样,其结果也只有两种情况:递增前原指针和递增后新指针。显然递增后新指针是最新情况的反映,如果抽样到这个指针,那么和我们的设计预期是一致的,如果抽样到递增前的原指针,会有什么结果呢?假设现在抽样读指针,那么最坏的情况就是把“不满”判断成了“满”,使得本来被允许的写操作被禁止了,但是这并不会对逻辑产生影响,只是带来了写操作的延迟。同样的,如果现在抽样写指针,那么 最坏的情况就是把“不空”判断成了“空”,使得本来被允许的读操作被禁止了,但是这也不会对逻辑产生影响,只是带来了读操作的延迟。
当写时钟远大于读时钟时,即格雷码出现多bit的跳变时,会出现问题么?
- 其实这个问题的关键还是对于异步FIFO使用格雷码的本质问题,需要明白,使用格雷码不会使得我们采样到的数据的中间状态不可控,即使时多bit发生跳变,其中每相邻的两个数之间还是只有1bit数据发生了变化,而且不论发生了多少位的格雷码跳变,采集到的值都是在一定的范围的,是可控。(下面引用别的博客进行解释)
- 如果不用格雷码,写指针变化顺序为:010→011→100,在011变为100的过程中,所有位都发生变化,目标时钟域(读时钟域)采样时写指针会无法确定,可能是任意3位二进制数。但是,如果使用了格雷码,变化顺序为:011→010→110,注意,这个变化次序是逐个的,并不是从011直接变为110,所以,即便读时钟域已经同步了011,写时钟域的写指针又由于变化太快变到了110,同步时刻来临时,采样值也要么是010(没采到第2位的变化),要么是110(采到第2位的变化)。
参考
https://mp.weixin.qq.com/s/EE_Dt6D9j1HnjllePwjzgw
https://blog.csdn.net/qijitao/article/details/50969328
https://blog.csdn.net/qijitao/article/details/50969328