4. CDC同步器类型与选择
跨时钟域(CDC)问题的本质,是信号在源时钟域被采样、在目的时钟域被再次采样时,可能违反目的触发器的建立/保持时间,从而产生亚稳态。同步器的任务不是"消除"亚稳态,而是把亚稳态的传播概率压到可接受水平,并保证数据或事件在功能上被正确传递。选择哪种同步器,取决于三个关键问题:跨域的是电平、脉冲还是多比特数据?源时钟与目的时钟的频率关系如何?是否需要保证数据不丢失、不重复、且顺序正确?下面按这五类同步器逐一展开。
两级触发器:单比特电平信号的基础同步
两级触发器(2-FF)是最基础的同步结构:源域信号先进入目的域的第一级触发器,再经第二级触发器输出。第一级可能进入亚稳态,但经过一个目的时钟周期后,它稳定到 0 或 1 的概率极高,第二级采样时基本不会传播亚稳态。其适用条件是:信号必须是电平信号,且在目的域被识别前保持足够长时间。经验上,源域信号宽度应大于目的时钟周期的 1.5~2 倍,否则可能被完全漏采。
2-FF 的典型应用是慢速控制信号、复位释放、模式选择等。它不能用于多比特总线,因为各比特的亚稳态收敛时间不同,会导致目的域采到"半新半旧"的非法组合。若必须传多比特,应改用格雷码或握手/FIFO。此外,2-FF 只做同步,不做边沿检测;若源域是单周期脉冲,目的域可能采不到,此时需要脉冲同步器。
脉冲同步器:把源域脉冲转成目的域可识别的翻转
脉冲同步器的思路是:在源域用触发器对输入脉冲做翻转(toggle),把"一个脉冲"变成"电平翻转一次";这个翻转电平经 2-FF 同步到目的域后,再在目的域做边沿检测,还原出一个目的域单周期脉冲。这样即使源脉冲很窄,只要它被源域触发器捕获一次,翻转就会保持,目的域一定能看到。
关键约束是脉冲间隔:两个源脉冲之间必须间隔足够长,使翻转信号完成跨域同步并被目的域检测到,否则会漏脉冲。一般要求源脉冲间隔大于 2~3 个目的时钟周期。脉冲同步器适合事件通知、中断请求、单比特触发等场景,但不保证脉冲计数精确,也不适合高频连续脉冲流。
握手同步器:多比特数据的可靠传递
当需要传递多比特数据且速率不高时,握手同步器是稳妥选择。其结构是:源域把数据放在数据总线上并保持稳定,然后拉高 req;req 经 2-FF 同步到目的域,目的域采样数据后拉高 ack;ack 再经 2-FF 同步回源域,源域收到 ack 后才撤销 req 并更新数据。由于数据在 req 有效期间保持不变,目的域采样时数据已稳定,避免了多比特亚稳态问题。
握手同步器的代价是吞吐率低:一次完整传输至少需要 4~6 个同步周期,适合配置寄存器、低速命令、状态回读等场景。实现时要特别注意:req 和 ack 必须各自独立做 2-FF 同步;数据总线本身不做同步,只要求"在 req 有效期间稳定"。
异步FIFO:高吞吐、多比特、连续数据流
异步FIFO是跨时钟域传多比特数据最常用的方案,适合连续数据流、高吞吐、读写时钟频率差异较大的场景,如 ADC 采样数据跨到处理时钟域、视频像素跨域等。其核心是双端口 RAM 加读写指针:写指针在写时钟域递增,读指针在读时钟域递增;指针跨域比较时采用格雷码,因为格雷码相邻值只有 1 位变化,跨域采样最多只错 1 位,不会产生非法指针跳变。
空/满判断是异步FIFO的关键:写满标志由写指针与同步过来的读指针比较产生,读空标志由读指针与同步过来的写指针比较产生。由于指针同步有延迟,空/满判断会偏保守(可能提前报满或报空),但不会导致数据覆盖或读出无效数据。设计时要确认深度足够覆盖同步延迟和突发长度,并注意复位时读写指针的同步释放。
DMUX同步器:多比特数据与使能同源传递
DMUX(数据多路复用/解复用)同步器的做法是:把多比特数据与一个使能/有效信号一起处理,使能信号经 2-FF 同步到目的域,目的域用同步后的使能去选通数据。它适用于数据变化不频繁、且数据在使能有效期间保持稳定的场景,本质上是握手同步器的一种简化变体。相比握手,它省去了 ack 回传,吞吐率略高,但要求源域保证"数据在使能有效窗口内不变",否则仍可能采到不稳定数据。
五类同步器的选择对照
| 同步器 | 跨域对象 | 速率/吞吐 | 关键约束 | 典型场景 |
|---|---|---|---|---|
| 两级触发器 2-FF | 单比特电平 | 低 | 信号宽度 > 1.5~2 个目的周期 | 复位释放、模式选择、慢速控制 |
| 脉冲同步器 | 单比特脉冲 | 低~中 | 脉冲间隔 > 2~3 个目的周期 | 事件通知、中断请求、触发 |
| 握手同步器 | 多比特数据 | 低 | req/ack 双向同步,数据保持稳定 | 配置寄存器、低速命令、状态回读 |
| 异步 FIFO | 多比特数据流 | 高 | 格雷码指针,深度覆盖同步延迟 | ADC 采样、视频像素、连续数据流 |
| DMUX 同步器 | 多比特数据 + 使能 | 中 | 数据在使能窗口内稳定 | 数据变化不频繁的跨域传递 |
实现与验证要点
无论选择哪种同步器,实现时都应遵循几条通用规则。第一,同步器必须使用目的时钟域的时钟,且两级触发器之间不能插入组合逻辑,否则会破坏亚稳态收敛的时序窗口。第二,源域信号在跨域前应先用源时钟打一拍,避免毛刺直接进入同步链。第三,多比特数据绝不允许逐位独立同步,必须用握手、DMUX 或异步FIFO 保证一致性。
验证方面,静态检查可用 CDC 工具识别未同步的跨域路径、多比特直接同步、同步链中插入组合逻辑等问题;动态验证则通过随机相位、频率扫描和复位交叉来制造亚稳态窗口。一个实用的判断方法是:在目的域观察同步后的信号,确认它不会出现非 0 非 1 的中间态,且功能上不丢事件、不重复采样、不采到非法数据组合。对于异步FIFO,还应重点检查空/满标志在极端读写速率下的行为,确认不会出现"假空导致读空"或"假满导致写覆盖"。