开写之前,首先我要声明一下,本文中总结的主要内容都可以在这篇在线论文中找到:Clock Domain Crossing (CDC) Design & Verification Techniques Using SystemVerilog。如果你想更加深入地了解详情,可以自行阅读原著。我相信每一个首次尝试将自己充分仿真完毕的Verilog设计综合到FPGA开发板上的时候,都曾经有过一段跟跨时钟域问题相爱相杀的惨痛经历。在进一步讨论之前,我希望大家记住4条我总结的想要避免跨时钟域问题必须融会贯通的黄金定律。
- 定律1,信号跨时钟域前必须被寄存!!!
原因:输出端寄存后再跨时钟域,可以使输出数据干净,防止末端组合逻辑因综合后延迟时间不确定导致同步性能难以评估。
- 定律2,跨时钟域时每次只能改变一根信号线!!!
原因:常见的同步器都无法解决多路信号跨时钟域后的同步问题。
- 定律3,跨时钟域信号必须在目标时钟域的3个时钟沿以上时间里保持稳定!!!
原因:这个要求是为了确保信号可以被正确采样。
- 定律4,跨时钟域的一定要是电平信号而不是脉冲信号!!!
原因:你觉得你这个脉冲在源时钟域里是一个周期,可过去之后是几个周期你可控制不了。
I. 什么是跨时钟域问题
各种重要定义
- 何谓之快,何谓之慢
在讨论跨时钟域问题时,如果待跨越时钟域的信号稳定时长超过目标时钟域的3个连续边沿,则谓之为慢信号。
反之,如果信号的稳定保持时间不足目标时钟域的1.5个周期,则谓之快信号。
- 何为电平,何为脉冲
世界上并没有绝对的电平,如果一个信号从来都不发生变化,那么它就是多余的。问题在于,脉冲发生变化前的稳定时间要持续多久才能确保跨时钟域的过程中没有问题呢?
- 建立/保持时间以及亚稳态
在目标时钟域的采样边沿附近,有一个限制被采样信号发生改变的时间窗口。建立时间即是指该窗口内位于采样沿之前的部分,而保持时间则是指采样沿之后的部分。
如果采样的时钟边沿刚好撞上了信号的变化过程,则被采样到的信号不能在短时间能确定为0或是1,这种情况被称为亚稳态。亚稳态是不可能被完全避免的,而通常的处理办法就是使用多级寄存器将该种状态与后续的组合逻辑进行隔离,以防止该状态被传向下一级寄存器。
想要了解更多有关建立时间和保持时间的内容,可以读一下这篇文章:为什么建立时间和保持时间如此重要。
II. 各种同步器
"同步器,是一种通过使用本地时钟采样的方式,将异步信号的变化过程变得与本地时钟同步的电路。"
Dally & Poulton
在绝大多数场景下,两拍同步器就已经足以消除电路中的亚稳态了。
两拍同步器
电路第一个寄存器首先使用本地时钟对异步信号进行采样,采样之后可能会输出亚稳态,但没有关系,因为这个亚稳态将会有一整个时钟周期的时间来回归稳定(0或1)。然后第二个寄存器会使用同样的时钟对已经稳定下来的信号进行第二次采样,并进一步把它向后级的组合逻辑推送。
三拍同步器
对于那些高速电路而言,两拍同步器有时候就不够用了,这时候可能就需要使用三拍同步器来进一步提高MTBF(MTBF,全称是Mean Time Before Failure,指两次发生电路故障间隔时间的数学期望)。
同步器不是万能的
如果有笨蛋在信号跨时钟域之前忘记用寄存器打一拍的话,那么即使是同步器也救不了你!!!
这就是第1条黄金定律的来历,请各位千万记得在跨越时钟域之前将信号用寄存器打一拍寄存一次。事实上,在设计任何一个模块的时候,都应该尽量确保每一个信号输出前的最后端点是寄存器而不是组合逻辑。
对于多位位宽的跨时钟域传输,是不是只有用异步FIFO,RAM等缓冲区了?
其实只要遵守我提到的4条黄金定律,什么样的跨时钟域传输办法都可以开发出来啊,只要你脑洞够大。比如说,只要符合每次跨时钟域只改变一根信号线,那多比特位宽可以只改变一根信号线吗?你想想格雷码是不是可以做到?如果不是格雷码怎么办?可以用单比特的握手信号REQ延迟一拍同步到对面时钟域通过对面时钟同步后再传回产生ACK信号保证足够长的数据准备时间也可以保证数据稳定哦。其实思路有很多很多,但是本文一开始提到的4条黄金定律是铁律,只要满足的话,用什么办法都可以达到目的,只有效率的区别。本文内容来自我写的一份培训PPT,因为是全英文的,翻译传图比较花时间,所以一时还没贴完整。