028-87409729
: 9:00-18:00
17348136089
: 7*24h
初涉 FPGA 时,不少开发者习惯沿用 C 语言的思维编写代码,只要综合通过便急于上板验证。然而,状态机无故跳变、数据偶发性异常等Bug 却屡见不鲜。其常见原因之一,就是跨时钟信号处理不当所引发的亚稳态。
亚稳态是什么
简单来说,亚稳态是指触发器无法在规定时间内将输出稳定到有效的逻辑0或逻辑1,而是短暂处于两者之间的不确定状态。经过一段无法准确预测的时间后,输出才会重新收敛到稳定电平,但最终稳定为逻辑0还是逻辑1,同样无法预先确定。
这恰如物理学中的“薛定谔的猫”:在触发器输出最终稳定之前,其逻辑状态暂时悬而未决。当然,这只是一种帮助理解亚稳态的形象比喻,并不意味着触发器真的处于量子叠加状态。

薛定谔的猫(图片来源于网络,侵删)
亚稳态是如何产生的
触发器在时钟有效边沿附近存在一个敏感窗口,该窗口由时钟边沿之前的建立时间 (T_su) 和时钟边沿之后的保持时间 (T_h) 共同构成。当数据信号恰好在这一窗口内发生跳变时,触发器的建立时间或保持时间要求便会遭到破坏,使其无法及时判断应当采样逻辑0还是逻辑1,从而可能进入亚稳态。
正常情况下,触发器的输出会在时钟有效边沿之后,经过时钟到输出延迟 (T_co) 达到稳定状态;而发生亚稳态时,输出可能无法在规定的 (T_co) 内稳定,需要经历一段不可预测的亚稳态恢复时间 (T_met),最终收敛到逻辑0或逻辑1。
如果触发器的输出在下一级触发器采样之前仍未恢复稳定,亚稳态便可能传播至后级逻辑,进而引发状态机异常跳转、计数错误或数据损坏等系统故障。
此类风险在跨时钟域(CDC)场景下尤为突出。由于不同频率或相位的时钟之间通常不存在固定的相位关系,异步信号边沿可能在任意时刻到达,因此始终存在落入接收触发器敏感窗口的可能。

怎么“驯服”这只猫?
针对不同信号类型,需采取相应的同步策略:
01
单bit控制信号:两级寄存器同步(打两拍)
最经典的处理方式是将两个触发器串联,并统一使用目标时钟进行采样。第一拍可能进入亚稳态,但在第二个触发器采样前,通常可以获得接近一个目标时钟周期的恢复时间,从而大幅降低亚稳态传播到后级逻辑的概率。
在VIVADO中,应为同步链寄存器添加
(*ASYNC_REG ="TRUE"*) reg r_sync_ff1;
(*ASYNC_REG ="TRUE"*) reg r_sync_ff2;
always @(posedge dst_clk) begin
r_sync_ff1 <= i_async_in;
r_sync_ff2 <= r_sync_ff2;
end
assign sync_out = r_sync_ff2;
该属性可以防止同步链被不当优化,并引导布局布线工具将相关寄存器紧密放置,从而缩短寄存器间的走线延迟,提高可用恢复时间和MTBF,两级触发器之间保持直接连接,避免插入组合逻辑;第一级触发器的输出也不应该连接同步链之外的其他逻辑。
02
多bit数据总线:按场景选择同步方案
普通多bit总线不能简单地对每一位分别使用两级寄存器同步。由于各bit的传播延迟和亚稳态恢复时间可能不同,目标时钟域可能采到来自不同时刻的数据,形成源时钟中域从未出现过的错误组合。
对于连续数据流,通常采用异步FIFO,异步FIFO使用格雷码跨时钟域传递读写指针,使指针正常递增时最多只有1bit发生变化,送入同步器的格雷码应直接来自寄存器输出,并配合适当的位间偏斜或最大延迟约束,避免组合毛刺或过大的位间延迟破坏格雷码每次仅1bit变化的特性。由于跨域指针存在同步延迟,FIFO的空(empty)、满(full)标志通常具有一定的保守性,设计FIFO深度时需要预留余量。

对于更新频率较低的配置数据,可以采用握手协议或多周期路径(MCP)结构。源时钟域应先将多bit数据置于总线上并保持稳定,然后发送请求(REQ)或Enable信号。该控制信号经过两级同步后进入目标时钟域,目标时钟域检测到请求后再采集多bit数据。
数据采集完成后,目标时钟域通过应答(ACK)信号通知源端,源端收到同步后的ACK后,才可以释放或更新数据。仅对Enable信号进行同步,却不能保证多bit数据总线具有足够的稳定时间,无法确保跨时钟域传输安全。

03
快时钟到慢时钟:脉冲展宽或Toggle同步
两级同步器只能降低亚稳态传播概率,不能保证目标时钟一定捕获宽度过窄的脉冲。当快时钟域产生的脉冲短于目标时钟的采样间隔时,慢时钟域可能完全漏采。
常见方法是将脉冲展宽,使其能够覆盖足够数量的目标时钟采样边沿,然后再通过两级同步器传递。工程中常采用不小于目标时钟周期约1.5倍的宽度,但最终要求应结合时钟关系、建立保持时间以及所使用的 CDC 结构确定。
另一种方法是Toggle翻转同步:源端每检测到一次事件便翻转一个状态位,目标端对该状态位进行两级同步,再通过异或或边沿检测恢复单周期脉冲。该方法仍然存在事件吞吐率限制;若相邻事件间隔太短,状态位可能连续翻转两次后恢复原值,导致目标时钟域漏检。因此,最小事件间隔必须大于目标端完整观察一次状态变化所需的同步与检测时间。
跨时钟处理在高速采集卡的实际应用
以迈硕灵动系列采集卡LD8172/4A-3G为例,ADC与FPGA之间采用JESD204B接口。JESD204B接收核在ADC时钟域内完成数据解码、Lane对齐和通道同步,后级DSP、DDR或PCIe模块则工作在独立的系统时钟域,因此需要进行跨时钟域处理。

完成通道对齐后,各通道数据被组合成完整的同步采样帧,并整体写入异步FIFO。FIFO写端使用ADC域时钟,读端使用系统,从而在保持数据顺序和通道对应关系的同时,实现高速采样数据的安全跨域传输。
采样长度、触发阈值和通道使能等低速配置参数,则通过请求—应答握手协议从系统时钟域传递到采集时钟域。JESD204B负责ADC与FPGA之间的链路同步,异步FIFO负责高速数据跨域,握手协议负责配置和控制信号跨域。
总结
亚稳态虽无法消除,却完全可以被有效控制。保持硬件底层思维,准确区分信号类型,选择恰当的同步策略,并辅以正确的综合属性约束,就能将时钟世界里这只"薛定谔的猫"牢牢关在笼子里。