跨时钟域为什么要双寄存器同步

时间:2024-03-26 16:56:51

跨时钟域为什么要双寄存器同步

随着设计规模的不断攀升,各种接口外设琳琅满目,时钟“满天飞”就不可避免(注意这里的“满天飞”不是滥用,意指时钟频率多、时钟扇出多)。而一个设计中,不同时钟频率之间你来我往更是在所难免。那么,这就出现了题目中的跨时钟域的同步问题?怎么办?十年不变的老难题。为了获取稳定可靠的异步时钟域送来的信号,一种经典的处理方式就是双寄存器同步处理(double synchronizer)。那为啥要双寄存器呢,一个不就够了吗?

先来看看,这张老得掉牙,经典得不能再经典的示意图。Aclk和bclk是两个不同的时钟域,bclk比aclk要稍微慢一点(哦,我的天哪,要用慢时钟采集快时钟的数据,又是一个难),与aclk同步的数据adat某个时钟周期拉高了(注意,只保持了1个时钟周期)。接下来,要用bclk时钟去采集只保持了一个aclk时钟周期的adat数据。理论上,这不符合奈奎斯特定律,很难成功,但是大家不要较真,这里重点不在这里。我们要关注的其实是那个不偏不倚bclk采样时(bclk时钟上升沿)正好对准了adat的下降沿(上升沿也类似),好开心,奈奎斯特老爷爷的定律被打破了。

数据采是采到了,但是不稳定,从模拟信号的角度看,bclk采集到的数据就是一个中间电平,到低最终判定是1还是0,很抱歉,看上去好像都不是。数字电路终归还是一个模拟电路搭起来的,真实世界都是骨感的(模拟的)。所以,你就看到,bclk时钟域的第一级采样时钟bq1_dat的输出波形起起伏伏,好在最终还是稳在了数字电平1或接近1的位置。如果bq1_dat直接在bclk时钟域被正常使用,后端就一个驱动扇出或许还好,可能就和示意图里第二级锁存bq1_dat的寄存器bq2_dat一样稳定了。但是,实际情况,可能我们要用这个bq1_dat去驱动多个扇出,那就十有八九要出问题,这个bq1_dat上的亚稳态恐怕还要继续传播给某些后级的寄存器,而这不是我们希望看到的。

那怎么办?解决方案有一个,用专门的寄存器bq2_dat对bq1_dat再锁存一拍,这么一来,就基本是稳定的了。还有一个问题,为啥就这么容易稳定了?前面提到了,bq1_dat的输出波形虽然起起伏伏,但最终一般还是会稳在要么接近0要么接近1的位置(在下一个时钟周期bq2_dat去锁存它的时候,更容易满足bq2_dat寄存器对建立和保持时间的要求),所以如果它本身的扇出路径单一的情况下,后级采样寄存器基本就能正常输出了。
跨时钟域为什么要双寄存器同步

另外,不得不再提一下MTBF(mean time between failures)的概念,一个基本的思想,就是同步寄存器级别越多,MTBF的概率越低,越不容易出问题。关于这个部分,大家可以去搜一下特权同学早期的文章,作为补充阅读。

https://www.eefocus.com/ilove314/blog/11-09/231565_715ed.html

跨时钟域为什么要双寄存器同步

最后,再来看看类似的跨时钟域的亚稳态在这2级寄存器同步后的个各种可能状况。

bq1_dat采样到adat的上升沿,最终bq1_dat稳定在0,bq2_dat也输出稳定的0。

跨时钟域为什么要双寄存器同步
q1_dat采样到adat的上升沿,最终bq1_dat稳定在1,bq2_dat也输出稳定的1。
跨时钟域为什么要双寄存器同步
1_dat采样到adat的下降沿,最终bq1_dat稳定在0,bq2_dat也输出稳定的0。
跨时钟域为什么要双寄存器同步

bq1_dat采样到adat的下降沿,最终bq1_dat稳定在1,bq2_dat也输出稳定的1。
跨时钟域为什么要双寄存器同步

最后,从特权同学的经验和实践的角度聊一下。

跨时钟域的信号同步到底需要1级还是2级,完全取决于具体的应用。如果设计中这类跨时钟域信号特别多,增加1级寄存器就等于增加逻辑资源,增加money。如果设计中的跨时钟域信号并非像前面的例子那样快速或实时变化,或者采样时钟频率远高于采样数据,并且我们也并不在意采样数据第1拍的取值,1级寄存器足矣。而对于控制信号,要特别谨慎,通常是比较建议采用2级寄存器同步。

另一个问题,按照判断应该采取2级寄存器的同步设计,设计中就用1级去实现,会怎样?一天、两天、一年、两年,或许都没有问题出现,如何解释?这本身是一个概率的问题,也和跨时钟域信号的故障敏感性有关(所谓故障敏感性,就是它真的出了问题,对系统的影响有多大,设计中是否有机制去检测)。但是,俗话说“常在河边走哪有不湿脚”,问题终究还是要暴露的,有时就像幽灵般转瞬即逝。

“鲁棒性”和“不过设计”都是一个优秀设计不可或缺的因素,我们还是建议认真审查设计,允许1级同步的就绝不堆料(浪费资源),需要2级同步的就不吝啬。