建立时间与保持时间:时序分析的基石
做数字芯片设计,说白了就是在跟时间赛跑。你想想看,一个触发器从时钟沿到来,到数据稳定输出,这中间有多少门道?我刚开始接触时序分析时,总觉得建立时间和保持时间就是两个参数,背下来就行了。直到有一次,一个项目在 28nm 工艺下跑 1GHz,死活收不拢时序,我才真正体会到——这两个时间,是芯片能不能正常工作的命根子。
建立时间(Setup Time)详解
建立时间,指的是在时钟有效沿到来之前,数据输入必须保持稳定的最短时间。说白了,就是数据得提前到场,等着时钟来“采样”。
核心定义: Tsetup = 数据在时钟沿前必须稳定的最小时间窗口
为什么要有这个要求?因为触发器内部是个模拟电路,数据需要时间把内部节点充放电到正确的逻辑电平。如果数据来得太晚,触发器可能采到个“中间值”,那就乱套了。
我在一个高速 SerDes 项目中遇到过这样的问题:数据路径上插了一堆缓冲器,结果建立时间裕量变成了负值。查了半天,发现是综合工具把缓冲器插得太密,路径延迟反而变大了。后来我手动调整了逻辑级数,才把时序救回来。
建立时间的检查公式很简单:
数据到达时间 + Tsetup ≤ 时钟到达时间 + 时钟周期
换个说法:
Tclk + Tclk_q + Tcomb_logic + Tsetup ≤ Tclk + Tperiod
化简一下:
Tclk_q + Tcomb_logic + Tsetup ≤ Tperiod
嗯,这里要注意,Tclk_q 是触发器的时钟到输出延迟,Tcomb_logic 是组合逻辑延迟。这两个加起来,再加上建立时间,必须小于时钟周期。
保持时间(Hold Time)详解
保持时间正好反过来——它指的是在时钟有效沿到来之后,数据输入必须保持稳定的最短时间。数据不能跑得太快,否则会把上一个时钟沿采到的值给冲掉。
核心定义: Thold = 数据在时钟沿后必须稳定的最小时间窗口
保持时间违规,我印象最深的是在一个低功耗项目中。为了省电,我们把很多寄存器的驱动强度调到了最低。结果保持时间全红了——数据路径太慢,但时钟路径因为用了 H 树,反而很快。数据还没到,时钟已经采完了,但保持时间窗口还没关,数据一过来就把旧值覆盖了。
保持时间的检查公式:
数据到达时间 ≥ 时钟到达时间 + Thold
展开写:
Tclk + Tclk_q + Tcomb_logic ≥ Tclk + Thold
化简:
Tclk_q + Tcomb_logic ≥ Thold
你发现没有?保持时间跟时钟周期无关。它只跟路径本身的延迟有关。所以保持时间违规,加时钟周期是没用的,只能加缓冲器或者换更大的驱动。
避坑指南: 我曾经在一个项目中,为了修建立时间违规,把路径上的缓冲器删了不少。结果建立时间修好了,保持时间全炸了。记住:修建立时间要减路径延迟,修保持时间要加路径延迟。这两个是矛盾的,需要平衡。
时序路径的组成
一条完整的时序路径,由三部分组成:
- 起点(Startpoint):通常是触发器的时钟引脚,或者是输入端口
- 组合逻辑网络(Combinational Logic):各种与门、或门、多路选择器、加法器等
- 终点(Endpoint):通常是触发器的数据输入引脚,或者是输出端口
说白了,就是数据从 A 点出发,经过一堆逻辑门,最后到达 B 点。STA 工具会检查这条路径上所有的时间约束。
我习惯把时序路径分成四类:
| 路径类型 | 起点 | 终点 | 典型场景 |
|---|---|---|---|
| 寄存器到寄存器 | 触发器时钟引脚 | 触发器数据引脚 | 最核心的路径,占 90% 以上 |
| 输入到寄存器 | 输入端口 | 触发器数据引脚 | 片外信号进入芯片 |
| 寄存器到输出 | 触发器时钟引脚 | 输出端口 | 芯片内部信号输出到片外 |
| 输入到输出 | 输入端口 | 输出端口 | 纯组合路径,很少见 |
下面这张图,把时序路径的结构画清楚了:
从图上你能看到,数据从起点触发器的 Q 端出发,经过组合逻辑,到达终点触发器的 D 端。时钟则从时钟源出发,分两条路分别到达两个触发器的时钟引脚。
个人经验: 我建议你在做时序约束时,先把所有寄存器到寄存器的路径列出来。这些路径占了芯片时序问题的 90%。如果这些路径都收得拢,剩下的输入输出路径一般不会太难搞。
建立时间与保持时间的关系
这两个时间,其实是触发器内部的两个“窗口”:
- 建立时间窗口:时钟沿之前,数据不能变
- 保持时间窗口:时钟沿之后,数据不能变
两个窗口加起来,就是数据必须稳定的总时间。你想想看,如果时钟沿在中间,数据得在前后各稳定一段时间。这个时间窗口越小,触发器能跑的速度就越快。
我记得有一次,工艺库里的标准触发器建立时间是 50ps,保持时间是 30ps。但有个特殊的高性能触发器,建立时间只要 20ps,保持时间 15ps。代价是什么?面积大了 3 倍,功耗多了 5 倍。所以选触发器也是个权衡。
注意: 建立时间和保持时间不是固定的。它们会随着 PVT(工艺、电压、温度)变化。一般来说,慢工艺、低电压、高温下建立时间最差;快工艺、高电压、低温下保持时间最差。做 STA 时,一定要在最差的 corner 下检查。
实际项目中的时序分析流程
我在项目中,一般按这个步骤做时序分析:
- 读入网表和约束:把综合后的门级网表和 SDC 约束文件读进 STA 工具
- 设置分析条件:选择最差的 PVT corner
- 运行建立时间检查:看所有路径的 setup slack
- 运行保持时间检查:看所有路径的 hold slack
- 分析违规路径:找出 slack 为负的路径,看是数据路径太长还是时钟偏斜太大
- 迭代优化:修改 RTL 或约束,重新综合,再跑 STA
这个流程,说白了就是“检查-分析-修改”的循环。我见过有些工程师,一看到 setup 违规就加 pipeline,一看到 hold 违规就插缓冲器。其实很多时候,调整一下时钟约束或者优化一下逻辑结构,效果更好。
关键指标:
- Setup Slack = 时钟周期 - (Tclk_q + Tcomb_logic + Tsetup) - 时钟偏斜
- Hold Slack = (Tclk_q + Tcomb_logic) - Thold - 时钟偏斜
- Slack 为正 → 时序满足;Slack 为负 → 时序违规
嗯,到这里,建立时间和保持时间的基本概念应该清楚了。记住一句话:建立时间管数据来得晚不晚,保持时间管数据跑得快不快。这两个搞明白了,时序分析就入门了。