时序分析:建立/保持时间与亚稳态
1. 设计动机
两个触发器在同一个时钟域里传数据:发端 FF 在时钟沿把数据打出来,经过组合逻辑,到收端 FF 的 D 端。问题是——收端 FF 在自己的时钟沿采数据时,数据到了没有?稳了没有?
如果数据到得太晚,违反建立时间(Setup Time, tSU),收端采到半稳定数据,输出可能卡在 0/1 之间的"亚稳态",系统偶发跑飞。这就是数字系统"看波形没问题但偶发死机"的头号根因。本章讲清楚:怎么算裕量、怎么判违例、亚稳态怎么缓解。
本章是时序逻辑的"验收标准"。所有同步设计最终都要回答:在目标时钟频率下,建立时间够不够、保持时间够不够、跨时钟域会不会亚稳。
2. 原理与逻辑图
2.1 同时钟域数据通路
发端 Launch FF 在时钟沿把 Q 打出来,经过组合逻辑延迟,到达收端 Capture FF 的 D 端。收端 FF 在同一个时钟沿(下一拍)采样这个 D。
关键延迟:
- Tco:发端 FF 从时钟沿到 Q 输出的延迟(clk-out)。
- Tlogic:组合逻辑延迟。
- Tskew:时钟到达两个 FF 的时刻差(时钟树偏斜)。
- tSU:收端 FF 要求数据比时钟沿提前稳定的时间。
- tH:收端 FF 要求数据比时钟沿之后继续保持的时间。
2.2 建立时间(Setup)
数据必须在捕获沿之前 tSU 时间就稳定。建立时间方程:
Tco+Tlogic+Tskew≤Tclk−tSU
左边是数据实际到达 D 的时刻(相对发端沿),右边是收端沿减去建立窗口。数据路径太慢 → 左边太大 → 建立违例(Setup Violation),表现为"频率跑不上去"。
2.3 保持时间(Hold)
数据在捕获沿之后还要保持 tH 不能变。保持时间方程:
Tco+Tlogic,min≥tH
数据路径太快 → 还没等 tH 过完,新数据就来了 → 保持违例(Hold Violation)。保持违例比建立违例更隐蔽——上电就错,跟频率无关。
3. 静态分析(时序余量)
以典型 28nm FPGA 参数(量级示意):Tco=0.3ns,Tlogic=2.0ns,Tskew=0.1ns,tSU=0.5ns,tH=0.2ns。
| 时钟周期 | 建立余量 slack_setup | 判定 |
|---|---|---|
| 10ns (100MHz) | 10−0.3−2.0−0.1−0.5=7.1ns | ✓ 富余 |
| 5ns (200MHz) | 5−0.3−2.0−0.1−0.5=2.1ns | ✓ |
| 3ns (333MHz) | 3−0.3−2.0−0.1−0.5=0.1ns | 勉强 |
| 2.5ns (400MHz) | 2.5−0.3−2.0−0.1−0.5=−0.4ns | ✗ 建立违例 |
保持余量:Tco,min+Tlogic,min−tH。只要数据路径最短延迟大于 tH 就 OK,与时钟周期无关。
4. 动态分析(时序波形与亚稳态)
下面用波形画出建立/保持窗口:CLK 上升沿为中心,左边 tSU、右边 tH 是"禁区",数据落在禁区外才安全。
亚稳态波形:数据恰好在建立/保持窗口内翻转,收端输出既不是干净 0 也不是干净 1,在中间电平停留不确定时间后才落到某一态。
Q 在亚稳电平(~0.5V)徘徊了好几拍,第 7 拍后才落到 1——这就是亚稳态:时间不确定、电平非法。
5. 时序约束与亚稳态分析
5.1 时序约束(Timing Constraints)
- 创建时钟:告诉工具主时钟频率 Tclk,工具据此算建立/保持裕量。
- 输入延迟/输出延迟:告诉工具外部数据相对时钟的到达/要求时刻。
- 多周期路径:某些路径不需要每个周期都稳定(如使能每隔几拍才有效),放宽约束。
- 伪路径(false path):不会真发生的路径(如异步输入),工具不该查它的建立保持。
5.2 亚稳态与 MTBF
触发器采样异步输入时,若数据落在建立/保持窗口内,输出可能进入亚稳态。亚稳态持续时间不确定,概率上平均无故障时间 MTBF:
MTBF=T0⋅fclk⋅fdataetmeta/τ
时钟越快、异步事件越多,MTBF 越短。唯一硬件缓解办法:同步器——用两级(或多级)触发器打拍,第一级可能亚稳,但等它稳定后再进第二级,第二级输出几乎一定合法。
5.3 跨时钟域(CDC)
- 单 bit 异步信号:过两级同步器。
- 多 bit 总线跨时钟域:不能逐位同步(各位到达时刻不一致会拼出错值),必须用握手或异步 FIFO。
- 控制信号跨域:同步器;数据总线跨域:异步 FIFO。
<>
第一级 FF 采样到异步数据时可能进入亚稳态,但亚稳态不是永久的——它会在时间常数 τ 内指数级收敛到某个合法电平。两级同步器让第二级在下一个时钟沿才采样第一级输出,此时第一级大概率已经收敛。级数越多,留给收敛的时间越多,MTBF 指数提升。代价是延迟增加 1~2 拍。
6. 元件取值与工程权衡
- 建立裕量要留多少:一般要求 slack_setup > 0.2ns(工艺/电压/温度变化),不要卡 0.01ns 上线。
- 同步器级数:2 级是默认;时钟频率 > 200MHz 或异步率高时用 3 级。
- 跨域宽度:单 bit 用同步器;多 bit 别逐位同步,用 FIFO/握手。
- 时钟偏斜 skew:时钟树设计决定最高频率,skew 越大可用周期越小,高速设计看时序报告 slack。
7. 完整设计示例
- 需求:50MHz 时钟(周期 20ns),数据路径 Tco=0.5ns,Tlogic=8ns,Tskew=0.2ns,tSU=0.5ns。
- 算建立裕量:slack = 20 − 0.5 − 8 − 0.2 − 0.5 = 10.8ns,非常富余。
- 若跑 200MHz(周期 5ns):slack = 5 − 0.5 − 8 − 0.2 − 0.5 = −4.2ns,建立违例,必须缩短组合逻辑(流水线、插寄存器)。
- 保持检查:最短数据路径 Tcomin=0.3ns,Tlogicmin=0.5ns,tH=0.2ns;0.3+0.5−0.2=0.6ns>0,保持 OK。
- 异步按键:按键直接进 D 会亚稳,必须过两级同步器。
- 结论:50MHz 下设计满足建立保持,按键加同步器后可上线。
8. 仿真与实验
在 Logisim / FPGA 仿真器中:
- 搭 Launch FF → 若干门延迟 → Capture FF,用仿真器观察数据到达 D 的时刻 vs 时钟沿。
- 故意缩短时钟周期,观察 Capture FF 输出不定(亚稳)。
- 在异步输入后加两级同步器,对比加之前/之后输出是否稳定。
- 用 FPGA 时序分析工具(如 Quartus/Vivado 的 Timing Analyzer)看 slack 报告,确认所有路径正裕量。
扩展与变种电路
扩展1:两级触发器同步器 2-FF Synchronizer
异步单 bit 输入(按键、跨时钟域信号)过两级触发器,把亚稳风险降到可接受。
- 异步输入不满足建立/保持,FF1 可能亚稳。
- 但 FF1 的输出在下一个时钟沿时大概率已收敛,FF2 采到的是合法电平。
- 延迟 = 2 个时钟周期;MTBF 随级数指数提升。
- 仅适用单 bit 控制信号;多 bit 总线不能逐位同步。
设计要点:同步器两级必须是同一时钟域、同一组 FF,中间不要插组合逻辑。取值/对比:2 级 vs 3 级——高速/高异步率用 3 级。适用:按键、UART RX、跨域使能;不适用:多 bit 数据总线(用 FIFO)。
- 现象:跨时钟域后总线偶尔拼出错值,比如应该传
1000却采到0111。 - 原因:各位经过同步器的延迟略有差异,且数据本身各位到达时刻不同,逐位同步会拼出中间态。
- 解决:多 bit 跨域用异步 FIFO 或握手协议(req/ack),不能逐位过同步器。
扩展2:复位同步器(异步置位、同步释放)Reset Synchronizer
复位释放沿本身也可能违反建立时间,必须"异步生效、同步释放"。
- 复位有效时:/RST 异步直接清两个 FF,内部复位立刻生效(不等时钟)。
- 复位释放时:/RST 先撤,但 FF1.D=1 要等下一个时钟沿才打入,再下一个沿 FF2 才输出 1——释放被延迟 2 拍,对齐到时钟沿。
- 这样释放沿不违反建立时间,避免复位释放导致亚稳。
设计要点:复位树异步生效、同步释放是通用做法。取值/对比:全异步复位 vs 异步置位同步释放——前者释放沿可能亚稳,后者安全。适用:FPGA/MCU 复位设计;不适用:极慢/慢边沿复位源(还要先整形)。
- 现象:上电后系统偶发跑飞,复位释放时刻不确定。
- 原因:RC 慢边沿在复位阈值附近徘徊很久,正好被时钟沿采样到亚稳区。
- 解决:复位源(上电 POR、按键、看门狗)先经施密特整形,再进复位同步器。
9. 常见坑与故障现象
- 异步输入不过同步器:按键、外部总线直接进数据端,偶发亚稳导致状态机跑飞。异步单 bit 必过两级同步器。
- 保持违例没查:只看建立时间 slack,忘了保持。保持违例上电就错、跟频率无关,最难查。时序报告必须同时看 setup 和 hold。
- 多 bit 跨域逐位同步:拼出错值。多 bit 用异步 FIFO/握手。
- 复位直接全局异步释放:释放沿亚稳。要异步置位、同步释放。
10. 自测题
建立时间 slack = −0.3ns 意味着什么?怎么解决?
数据路径太慢,在当前时钟频率下数据到达 Capture FF 的 D 端时已经晚于建立窗口,FF 可能采样错误。解决:降低时钟频率(加大周期)、缩短数据路径(插入流水线寄存器、简化组合逻辑)、或换更快的工艺/FF。
为什么保持违例比建立违例更难查?
建立违例跟频率有关,降频就消失、容易复现;保持违例是数据路径太快,上电就错、跟频率无关,即使降频也错。而且它通常只在某些极端条件(最佳工艺角)出现,仿真和常温测试可能发现不了。
一个 8 位数据总线从慢时钟域传到快时钟域,能给每一位各加一个两级同步器吗?
不能。各位同步器延迟略有差异,且数据本身各位变化时刻不同,逐位同步会拼出中间错值(比如该传 1000 采成 0111)。多 bit 跨时钟域必须用异步 FIFO 或 req/ack 握手,保证整组数据同时有效。
11. 参考资料
- sources/notes/metastability-clockreset.md
- AMD/Xilinx 复位设计与时序约束应用文档