保持时间违例为什么降频率修不好:hold 检查与周期无关的直觉证明
做时序收敛的人都见过这个场景:setup 违例一大堆,降点频率、放宽点约束,路径就过了;可轮到 hold 违例,把时钟从 1 GHz 降到 100 MHz,报告里的违例一条不少,甚至斜率都没变。本文回答的就是这件事——保持时间违例为什么降频率修不好。基础概念(setup/hold 定义、亚稳态)见 建立时间、保持时间与亚稳态,这篇只聚焦「为什么降频无效」这一个问题。
本文要回答的问题
- setup 和 hold 检查的公式到底差在哪,为什么一个含周期、一个不含?
- 降频率改变了什么、没改变什么?
- hold 违例真正该用什么手段修?
- 哪些「直觉」其实是误区?
一、简短结论
因为 hold 检查的是「同一个时钟沿」到达发起端和捕获端的相对先后,不是「相邻两个沿」之间的时间差。 时钟变慢只是把沿与沿的间隔拉大,而 hold 检查从来不看沿间隔——它看的是:捕获沿到达的那一刻,发起端的新数据是不是已经冲过来把旧数据冲掉了。这个先后关系由数据通路延迟和时钟偏斜(clock skew)决定,跟周期长度无关。所以降频对 setup 是解药,对 hold 是无效药。
二、五条理由:从公式到直觉
理由 1:把两个公式并排写,周期项的有无一目了然
setup 检查(单周期路径):
T_clk + T_capture ≥ T_launch + T_cq + T_data + T_setuphold 检查:
T_launch + T_cq + T_data ≥ T_capture + T_hold注意 hold 不等式里没有 T_clk。setup 问的是「下一个沿来之前数据能不能到」,沿的间隔就是周期,所以周期在里面;hold 问的是「这个沿采样的瞬间数据稳不稳」,参与比较的两项——数据到达时间、捕获时钟到达时间——都从同一个沿起算,周期自然被约掉了。这是「保持时间违例为什么降频率修不好」最硬的答案:你调的变量根本不在公式里。
理由 2:换一个时钟沿看,setup 跨沿、hold 同沿
setup 检查是一对沿:launch 沿(第 0 拍)发数据,capture 沿(第 1 拍)收数据,两者间隔一个周期。hold 检查是同一个沿:capture 寄存器在沿到来瞬间要求输入保持 T_hold 不变,而 launch 寄存器也在同一个沿开始输出新数据。问题就变成一场赛跑:新数据跑完 T_cq + T_data 到达捕获端 D 口,捕获时钟沿经过偏斜到达捕获端 CK 口——谁晚到谁赢。降频不改变这条赛道上任何一段的长度,赛跑结果原样保留。
理由 3:物理直觉——数据「太新」而不是「太慢」
setup 违例是数据太慢,给它更多时间(更大周期)就能救。hold 违例恰恰相反,是数据太新、来得太早:旧数据还没被安全采样,新数据就已经扑到 D 口了。典型的「太早」场景是纯走线直连的两级触发器、时钟树末端偏斜大的相邻寄存器。这种「快」是电路结构决定的,把时间轴拉长不会让快的东西变慢——就像比赛抢跑,把比赛时长延长并不能阻止抢跑。
理由 4:降频改变的是沿的绝对位置,不改变沿之间的相对关系
假设时钟偏斜 skew = T_capture − T_launch = +0.3 ns,数据路径延迟 T_cq + T_data = 0.2 ns。无论周期是 1 ns 还是 10 ns,这两个差值都由工艺、布线、时钟树决定,降频分毫不动。违例量 0.1 ns 在 1 GHz 下是 0.1 ns,在 100 MHz 下还是 0.1 ns。静态时序分析(STA)工具报 hold 时甚至不需要知道时钟频率——你只要给它波形关系,它只看同沿的相对延迟。
理由 5:工程事实——hold 修复手段全部不动周期
反向印证:工业界修 hold 的工具箱里没有任何一件跟频率有关。标准做法是插 buffer/delay cell 把数据路径「垫长」、修时钟树把偏斜拧小、或换用更慢的单元(降驱动、换高阈值管)。这些手段全在改 hold 不等式左右两边的延迟项,没有一项碰 T_clk——因为碰了也没用。
下面这张对比卡把 setup 与 hold 对降频的响应放在一起看,差异一眼可见。
读这张卡抓住一条主线:左栏所有修复都围绕「时间窗」,右栏所有修复都围绕「相对延迟」。降频是时间窗手段,天然只对左栏有效。
三、一个具体例子:0.15 ns 的 hold 违例
假设一条最短路径:FF1(launch)→ 一段很短的组合逻辑 → FF2(capture)。
- T_cq = 0.08 ns,T_data = 0.07 ns(数据侧共 0.15 ns)
- 时钟树偏斜:capture 钟比 launch 钟晚到 0.25 ns(skew = +0.25 ns)
- FF2 的 T_hold = 0.05 ns
hold 裕量 = (T_cq + T_data) − (skew + T_hold) = 0.15 − 0.30 = −0.15 ns,违例。
现在把频率从 1 GHz 降到 500 MHz:周期从 1 ns 变 2 ns,上面五个数一个都没动,裕量还是 −0.15 ns。降到 1 MHz 也一样——数据仍然在 capture 沿之后 0.15 ns 就把旧值冲掉了。
修复手法是对照的:在 FF1→FF2 之间插两个 delay cell,各贡献 0.1 ns,数据侧变 0.35 ns,裕量变 +0.05 ns,收工。整个过程周期从来没出场。
这张图的主线是同一个时钟沿兵分两路:上路走时钟树到 FF2 的 CK 口,下路被 FF1 转成新数据冲到 FF2 的 D 口。hold 检查比的就是这两路谁慢——时钟那路晚到 0.25 ns,数据这路只花 0.15 ns,数据「赢」了比赛,于是违例。橙色块是唯一有效的修复位置:把数据这条路垫长。请注意图里没有任何一个元素随频率变化,这就是降频无效的几何表达。
四、常见误区
误区一:「降频总没错,先降了再说。」 降频只治 setup。对 hold 它不仅无效,还可能掩盖问题——测试台上降频后功能「正常」,其实是低速下采样沿避开了危险窗口的假象,回到目标频率芯片照样失效。hold 违例必须在 signoff 频率下修干净。
误区二:「hold 是快路径问题,那就把所有路径都做慢。」 过度修复会直接制造 setup 违例。正确姿势是只动最短路径(min path),EDA 工具的 hold fixing 也是按 min/max 角一起迭代收敛的。
误区三:「换个更慢的工艺角不就过了?」 恰恰相反,hold 最差角是 fast 角(低温、高压、快工艺),数据跑得最快、最容易冲掉旧值。慢角数据变慢反而裕量变大。signoff 时 hold 看 fast corner,setup 看 slow corner,别搞反。
误区四:「偏斜总是坏事。」 对 setup 而言正偏斜(capture 晚到)是帮忙的,对 hold 而言它正是元凶。时钟树综合(CTS)追求的是可控的、各路径一致的偏斜,而不是盲目追零,详见 时钟树综合。
误区五:「仿真过了就代表没有 hold 问题。」 功能仿真不带真实延迟,门级仿真只跑少数角。hold 是 STA 的地盘,靠约束和全角签核保证,约束写法见 SDC 约束基础。
五、真正该怎么修(速查)
| 手段 | 改的是 | 适用场景 | 代价 |
|---|---|---|---|
| 插 buffer / delay cell | 垫长 T_data | 绝大多数 min path 违例 | 面积、功耗微增 |
| 修时钟树偏斜 | 缩小 skew | 局部 skew 异常大 | CTS 迭代成本 |
| 换慢单元(降驱动/高 VT) | 垫长 T_cq/T_data | 少量违例、不想加 cell | 可能影响 setup 裕量 |
| 重布线拉开寄存器 | 垫长 T_data | 布局过近的直连触发器 | 布线资源 |
共同点:全部在改延迟项,没有一项改周期。这张表与第二节的公式一一对应——能把不等式左边垫大或右边减小的手段才有效。
延伸阅读
- 建立时间、保持时间与亚稳态——setup/hold 定义与亚稳态机理,本文的前置篇。
- 时钟树综合——skew 是怎么产生和被控制的。
- SDC 约束基础——min/max 延迟约束怎么写。
- 多周期路径与假路径——setup/hold 检查沿如何被约束移动。
一句话总结
保持时间违例为什么降频率修不好?因为 hold 检查的是同一个时钟沿上「数据到达」与「时钟到达」的相对先后,公式里没有周期项——数据来得太早是电路结构和偏斜决定的,把沿的间隔拉再大也改变不了同沿的赛跑结果,唯一有效的修法是把数据路径垫长或把偏斜修小。