一文讲清楚Setup / Hold / Recovery / Removal
时序约束Setup / Hold / Recovery / Removal1. 同步路径时序约束1.1 Setup Time建立时间时钟沿到来之前数据必须在触发器 D 端保持稳定的最小时间。setup window ├────────────┤ data ──────XXXXXXXXXXXX──↑──────────── 采样沿时钟上升沿违例原因组合逻辑路径过长数据来不及在时钟沿前稳定。解决方法降低时钟频率加长周期插入流水级切割组合逻辑使用更快的标准单元1.2 Hold Time保持时间时钟沿到来之后数据必须在触发器 D 端继续稳定的最小时间。↑────────────┤ data ──────────────────↑XXXXXXXXXXXX── 采样沿时钟上升沿 ├────────────┤ hold window违例原因时钟偏斜clock skew导致下一级触发器的时钟晚到数据已经从上一级传过来了。解决方法插入 buffer / delay cell 增加数据路径延迟优化时钟树减小 skew1.3 Setup 与 Hold 的关系┌─────┐ ┌─────┐ clk ───┘ └─────┘ └───── ← setup →↑← hold → │ 采样沿 data ───[必须稳定]──↑──[必须稳定]──SetupHold相对于时钟沿之前之后数据要求必须提前稳定必须延后变化违例本质数据到得太晚数据变得太快与频率关系有关降频可解决无关必须修复2. 异步控制路径时序约束2.1 Recovery Time恢复时间异步控制信号如复位释放deassert之后到下一个有效时钟沿之间必须保持稳定的最小时间。┌─────┐ ┌─────┐ clk ───┘ └─────┘ └───── reset ────────┐ └─────────────── 复位释放 ↑ ├── recovery ──┤ ↑ 采样沿含义复位释放后触发器需要足够时间恢复到正常同步工作状态下一个时钟沿才能正确采样数据。类比 Setup复位释放必须提前足够久类似数据必须在时钟沿前稳定足够久。2.2 Removal Time移除时间有效时钟沿之后异步控制信号必须继续保持asserted的最小时间之后才能释放。┌─────┐ ┌─────┐ clk ───┘ └─────┘ └───── ↑ reset ──────────┐ └────────── 复位释放 ↑──── removal ────┤↑ 采样沿 释放点含义时钟沿刚过之后如果复位立刻释放触发器可能还没完成内部状态锁存就退出复位导致亚稳态。类比 Hold复位在时钟沿之后必须维持一段时间类似数据在时钟沿后必须保持稳定。2.3 Recovery 与 Removal 的关系RecoveryRemoval相对于时钟沿之前之后信号要求复位释放必须提前足够久复位释放必须延后足够久违例本质复位释放太靠近时钟沿复位在时钟沿后立刻释放类比Setup TimeHold Time3. 四种时序约束对比总览同步数据路径异步控制路径时钟沿前必须稳定Setup TimeRecovery Time时钟沿后必须稳定Hold TimeRemoval Time信号类型D 端数据异步复位 / 置位端时序检查原语$setup(data, clk, limit)$recovery(rst, clk, limit)$hold(clk, data, limit)$removal(rst, clk, limit)4. 违例场景详解4.1 Setup ViolationFF1 ────[组合逻辑路径太长]────→ FF2 ↑ clk 到了数据还没稳定数据到达时间 时钟周期 - setup 要求后仿中触发器输出 X 态4.2 Hold ViolationFF1 ────[逻辑路径太短]────→ FF2 FF1.clk ──────→ FF1 采样后数据立刻传到 FF2.D FF2.clk ──────→ FF2 时钟因为 skew 晚到 FF2 采到了新数据应该是旧数据数据变化太快在 hold window 内翻转与频率无关降频无法解决4.3 Recovery Violationasync_rst 释放 ────→ 离时钟沿太近 ────→ 触发器未恢复到正常状态 ────→ 输出不确定复位释放时刻不受控可能刚好落在 recovery window 内后仿中触发器输出 X 态4.4 Removal Violation时钟沿 ────→ 触发器正在锁存 ────→ 复位立刻释放 ────→ 锁存被中断 ────→ 亚稳态复位在时钟沿后过早释放后仿中触发器输出 X 态5. 解决方案异步复位同步释放Recovery / Removal 违例的根本原因是异步控制信号的释放时刻不受时钟控制。标准解决方案是使用两级 FF 同步器5.1 电路结构async_rst ──→ [FF1] ──→ [FF2] ──→ sync_rst ↑ ↑ posedge clk posedge clk5.2 代码实现always (posedge clk or posedge async_rst) begin if (async_rst) begin rst_d1 1b1; // 异步复位立即生效不等时钟 rst_d2 1b1; end else begin rst_d1 1b0; // 同步释放跟着时钟走 rst_d2 rst_d1; // 第二拍才真正释放 end end5.3 工作原理阶段行为特点复位 assertasync_rst一来FF1/FF2 立刻置 1异步不需要时钟复位 deassertasync_rst撤销后FF1 下个时钟沿变 0FF2 再下一拍变 0同步跟着时钟走5.4 为什么需要两级第一级 FF异步信号释放时刻随机可能在 recovery/removal 窗口内导致亚稳态但给了整整一个时钟周期去稳定第二级 FF等一周期后再采亚稳态概率极低输出干净稳定的信号5.5 效果复位 assert → 异步生效保证复位立即可靠复位 deassert → 同步释放sync_rst的翻转始终与时钟沿对齐天然满足 recovery / removal 约束6. 后仿中的表现门级仿真反标 SDF 后标准单元内部的时序检查会被激活// 标准单元内部的时序检查仿真器自动执行 $setup(D, posedge CLK, t_setup); $hold(posedge CLK, D, t_hold); $recovery(CLR, posedge CLK, t_recovery); $removal(CLR, posedge CLK, t_removal);违例时触发器输出X 态模拟亚稳态X 态沿数据通路传播导致后续功能异常 — 这正是后仿要捕获的问题。