跨时钟域传输的黄金搭档:异步FIFO与格雷码

本文首发于公众号【木叶芯】,版权所有,禁止转载。

如需转载,请在评论区留言或私信申请,经同意后可转载,否则属于侵权行为

作者昵称:城外南风起

原文链接:跨时钟域传输的黄金搭档:异步FIFO与格雷码

————————————————

异步FIFO里为什么要用格雷码? 技术面被问到这个问题。

最初学习信号跨时钟域传输的时候,只是想当然地认为多比特信号在跨时钟域传输时发生错误的概率肯定比单比特大,所以才会采用格雷码,保证每次只有一位信号变化,但没有深入追究这个问题。

在面试官的不断追问下,我就被问住了。面完以后发现,这个问题在之前看的论文里已经讲得很详细了[1]。摘录如下:

The problem is that multiple signals that are synchronized to one clock will experience small data changing skews that can occasionally be sampled on different rising clock edges in a second clock domain. Even if we could perfectly control and match the trace lengths of the multiple signals, differences in rise and fall times as well as process variations across a die could introduce enough skew to cause sampling failures on otherwise carefully matched traces.

大意是每个比特之间总有一些小的skew,导致它们无法被在同一个时钟沿被采样。即便在布局布线的时候完美地控制它们的路径长度,每个比特信号的上升下降时间、die上的加工工艺差异分布也会引起skew。

作者给了一个具体的例子:

If a simple 4-bit binary counter changes from address 7 (binary 0111) to address 8 (binary 1000), all four counter bits will change at the same time. If a synchronizing clock edge comes in the middle of this transition, it is possible that any 4-bit binary pattern could be sampled and synchronized into the new clock domain.

四位二进制码从0111变为1000的过程中,这两个数虽然在数值上相邻,但它们的每个比特都将发生改变,这时如果它们之间有skew,采样的值就可能是任意的四位二进制数,这会给空满标志的判断带来问题,如果错误触发空满标志还好,但如果在空满成立时没有触发,就会导致数据被覆盖掉或者重复读出。

如果使用格雷码,每次只改变一位信号,就不会出现上述的问题。例如,格雷码从0001递增到0011时,即便没有采集到变化后的0011,也会采集到变化之前的0001,这只会导致“不该报空满而报了空满”,但并不会导致“该报空满而未报”的情况。详细来说,如果是读指针从0001递增到0011,假设写时钟域采到的是0001,那么也只是会报写满(因为写时钟域不知道读时钟域已经读到下一个地址了),从而停止写入,这是安全的;同理,如果是写指针从0001递增到0011,假设读时钟域采到的是0001,那么也只是会报读空(因为读时钟域不知道写时钟域已经写到下一个地址了),从而停止读出,这也是安全的。

这个问题清楚了,就可以讲下一个问题。 如果写时钟频率很高,相对读时钟是一个快时钟,那么如果读时钟域才读了一个数,写时钟域就写了两三个数,写地址也随之变化了两三次,这是否会引起多bit跨时钟域的问题呢?举个例子,如果现在同步到读时钟域的格雷码写指针是011,而写时钟快很多,写时钟域的格雷码写指针已经发生变化:011→010→110,在读时钟域这边,就需要直接同步110,那么,读时钟域的格雷码写指针就会从011变为110,第0位和第2位都发生变化,这会在采样时造成影响吗?

答案是不会。变两位就变两位呀,管他干什么? 读时钟域的格雷码写指针是为了去和读指针作比较的,变两位才是好事,变一位反而得不到正确的空信号。进一步地,我们所说的多bit信号跨时钟域传输问题中的多bit是针对源时钟域(即写时钟域)而言的,在之前的例子中,如果不用格雷码,写指针变化顺序为:010→011→100,在011变为100的过程中,所有位都发生变化,目标时钟域(读时钟域)采样时写指针会无法确定,可能是任意3位二进制数。但是,如果使用了格雷码,变化顺序为:011→010→110,注意,这个变化次序是逐个的,并不是从011直接变为110,所以,即便读时钟域已经同步了011,写时钟域的写指针又由于变化太快变到了110,同步时刻来临时,采样值也要么是010(没采到第2位的变化),要么是110(采到第2位的变化)。关键是理清一个点:多bit变化的含义是写时钟域的写指针相对于前一个写时钟域的写指针的变化,而不是写时钟域的写指针相对于读时钟域的写指针之间的变化。 如果不使用格雷码,多bit变化将使采样紊乱,使用格雷码,将多bit变化变为单bit变化,就不会采到错误的值,即便采到变化前的值,也是安全、正确的

参考文献:

[1] CUMMINGS C E.Clock domain crossing (CDC) design&verification techniques using systemverilog[EB/OL].[2008-09-26].http://www.sunburst-design.com/papers.

————————————————

感谢您的阅读,欢迎 点赞 / 评论 / 收藏 / 打赏 ~

我是城外南风起,欢迎关注我的公众号【木叶芯】。

跨时钟域传输的黄金搭档:异步FIFO与格雷码_第1张图片
以下链接可以快速搜索公众号内的文章:号内搜

木叶飞舞之处,火亦生生不息。

你可能感兴趣的:(Digital,IC,FPGA,fifo,格雷码,verilog,CDC,fpga)