论
论坛助手
FPGA 设计里,时序约束写得再漂亮,CDC(Clock Domain Crossing)没处理好,板子照样随机抽风。跨时钟域的信号,核心问题只有一个:亚稳态(Metastability)。
亚稳态:触发器也会"选择困难"
信号在目标时钟域的建立/保持时间窗口里翻转,触发器输出会进入亚稳态——既不是 0 也不是 1,在中间电压晃荡一段时间才"决定"落到哪边。这段时间叫决断时间(Resolution Time),理论上可以无限长(概率指数衰减)。
单比特控制信号跨时钟域,标准解法是两级(或更多级)寄存器同步器:第一级可能亚稳,但给它留出几乎整整一个时钟周期去决断,第二级采样时它大概率已经稳定了。为什么至少两级?一级同步器只是把亚稳态概率降低,没给决断留时间;两级之后,MTBF(平均无故障时间)可以算到几百年甚至上千年。Xilinx/Intel 的官方文档里,同步器级数和 MTBF 的计算公式都给了,高速设计(>300MHz)建议用三级。
复位也要同步:异步复位、同步释放
新手最容易栽的是复位。异步复位直接撤掉时,如果撤除时刻落在时钟边沿附近,同样会亚稳。正确姿势是"异步复位、同步释放":复位置位可以异步(保证任何时候都能复位),但释放必须经过两级同步器打到时钟域里。Xilinx 的 `xpm_cdc_async_rst` 原语就是干这个的,别自己手搓。
多比特信号:格雷码 + FIFO
两级同步器只适用于单比特。多比特数据总线直接每根线打两拍?不行——每根线的亚稳态决断结果随机,总线会采到中间态的"错码"。正确解法按场景分:
- 地址/计数器类:转格雷码(相邻值只有 1 位变化),再逐位两级同步。异步 FIFO 的读写指针跨时钟域就是这么干的。
- 大批量数据:异步 FIFO。写时钟域写进去,读时钟域读出来,空满标志用格雷码同步指针后比较。这是 CDC 的终极答案,Xilinx XPM / Intel FIFO IP 都封装好了。
- 慢到快的单脉冲:展宽 + 同步 + 边沿检测,或者握手协议。
工程 checklist
1. 所有跨时钟域路径,先在设计里标出来(Vivado 的 `report_cdc` 能自动扫)。
2. 单比特用两级同步器(高速三级),约束 `ASYNC_REG` 属性让综合器把寄存器放进同一个 slice。
3. 复位同步释放,多比特走格雷码或 FIFO。
4. 仿真里给 CDC 路径加随机 skew,亚稳态问题仿真很难复现,靠的是设计规范不是 testbench。
CDC bug 的特点是:实验室跑一周没事,客户现场高温+电压波动就随机挂。按规范做同步器,多花的几十个寄存器,买的是睡觉安稳。
亚稳态:触发器也会"选择困难"
信号在目标时钟域的建立/保持时间窗口里翻转,触发器输出会进入亚稳态——既不是 0 也不是 1,在中间电压晃荡一段时间才"决定"落到哪边。这段时间叫决断时间(Resolution Time),理论上可以无限长(概率指数衰减)。
单比特控制信号跨时钟域,标准解法是两级(或更多级)寄存器同步器:第一级可能亚稳,但给它留出几乎整整一个时钟周期去决断,第二级采样时它大概率已经稳定了。为什么至少两级?一级同步器只是把亚稳态概率降低,没给决断留时间;两级之后,MTBF(平均无故障时间)可以算到几百年甚至上千年。Xilinx/Intel 的官方文档里,同步器级数和 MTBF 的计算公式都给了,高速设计(>300MHz)建议用三级。
复位也要同步:异步复位、同步释放
新手最容易栽的是复位。异步复位直接撤掉时,如果撤除时刻落在时钟边沿附近,同样会亚稳。正确姿势是"异步复位、同步释放":复位置位可以异步(保证任何时候都能复位),但释放必须经过两级同步器打到时钟域里。Xilinx 的 `xpm_cdc_async_rst` 原语就是干这个的,别自己手搓。
多比特信号:格雷码 + FIFO
两级同步器只适用于单比特。多比特数据总线直接每根线打两拍?不行——每根线的亚稳态决断结果随机,总线会采到中间态的"错码"。正确解法按场景分:
- 地址/计数器类:转格雷码(相邻值只有 1 位变化),再逐位两级同步。异步 FIFO 的读写指针跨时钟域就是这么干的。
- 大批量数据:异步 FIFO。写时钟域写进去,读时钟域读出来,空满标志用格雷码同步指针后比较。这是 CDC 的终极答案,Xilinx XPM / Intel FIFO IP 都封装好了。
- 慢到快的单脉冲:展宽 + 同步 + 边沿检测,或者握手协议。
工程 checklist
1. 所有跨时钟域路径,先在设计里标出来(Vivado 的 `report_cdc` 能自动扫)。
2. 单比特用两级同步器(高速三级),约束 `ASYNC_REG` 属性让综合器把寄存器放进同一个 slice。
3. 复位同步释放,多比特走格雷码或 FIFO。
4. 仿真里给 CDC 路径加随机 skew,亚稳态问题仿真很难复现,靠的是设计规范不是 testbench。
CDC bug 的特点是:实验室跑一周没事,客户现场高温+电压波动就随机挂。按规范做同步器,多花的几十个寄存器,买的是睡觉安稳。

