1.2 时序路径:延迟账本的记账单元 本节摘要:时序路径是 STA 数延迟的基本单位——从起点(时钟沿或输入端口)到终点(捕获沿或输出端口)的一条有向通路。本节拆解四类路径与三段构成(时钟路径、数据路径、捕获时钟路径),说明时序弧如何串成路径,为后面所有延迟累加提供计数对象。 别以为"路径"是个可以随口一说的词。在 STA 里,一条时序路径(timing path)有严格的起点与终点约定:起点要么是启动触发器的时钟引脚,要么是输入端口;终点要么是捕获触发器的数据引脚,要么是输出端口。凡是既不在任何路径起点上、也不在任何路径终点上的延迟,都不进入建立保持的账本。理解这个约定,你就理解了为什么有些人优化了半天逻辑,违例数字却纹丝不动——他改的电路根本不在报告的那条路径上。
本节摘要:时序路径是 STA 数延迟的基本单位——从起点(时钟沿或输入端口)到终点(捕获沿或输出端口)的一条有向通路。本节拆解四类路径与三段构成(时钟路径、数据路径、捕获时钟路径),说明时序弧如何串成路径,为后面所有延迟累加提供计数对象。
别以为"路径"是个可以随口一说的词。在 STA 里,一条时序路径(timing path)有严格的起点与终点约定:起点要么是启动触发器的时钟引脚,要么是输入端口;终点要么是捕获触发器的数据引脚,要么是输出端口。凡是既不在任何路径起点上、也不在任何路径终点上的延迟,都不进入建立保持的账本。理解这个约定,你就理解了为什么有些人优化了半天逻辑,违例数字却纹丝不动——他改的电路根本不在报告的那条路径上。
按起点与终点的类型组合,路径分四类。寄存器到寄存器(reg2reg)是频率的骨架,全芯片最严的建立检查几乎都落在这里;输入到寄存器(in2reg)考验的是外部环境与片内第一级的配合,依赖输入延迟约束;寄存器到输出(reg2out)同理,依赖输出延迟约束;输入到输出(in2out)是纯组合通路,只在定义了 max_delay 这类约束时才被检查。四类路径的检查公式并不相同——第二章会看到,in2reg 与 reg2out 的公式里混合了外部时间,这也是它们经常被约束错误坑害的原因。

图上的每条边叫一个时序弧。单元弧(cell arc)发生在单元内部,比如反相器从输入引脚到输出引脚、触发器从 CLK 到 Q——它们的方向与极性由电路结构决定,一个触发器有两条最基本的单元弧:CLK 到 Q 的输出弧(带正负沿两种)与 D 到内部锁存的建立要求。互连弧(net arc)是引脚之间的连线,方向一律从驱动引脚指向负载引脚。路径就是这些弧首尾相接串成的链,延迟账本上每一行 Increment,对应的就是一段弧的延迟——这个对应关系在 2.4 解读报告时会变得非常具体。
有一点新手容易误解:路径在中途会"断开重续"。STA 的路径分段规则是,遇到时序元件(触发器、锁存器)就把路径截断——上一段的终点是触发器的 D 端,下一段的起点是同一个触发器的 CLK 端。因此"从时钟源到捕获触发器"从来不是一条路径,而是"启动时钟路径 + 数据路径"的组合,两段分别累加、分别参与公式。组合逻辑无论多长,只要中间不撞上时序元件,就始终是同一条路径——这正是某些深组合块成为噩梦的原因:逻辑级数越多,可优化的空间越小。
每个触发器的 D 端都同时挂着两本账:上一拍发出、本拍要被采样的数据(建立账,起点在启动 FF,终点在捕获 FF 的 D 端);本拍刚发出、正准备冲向下一级的数据(保持账,起点与终点同建立账一样,但比较对象是同一个时钟沿)。同一个物理结构,在两本账里的延迟取数不同:建立账用慢延迟(max delay),保持账用快延迟(min delay)——因为建立怕慢,保持怕快。这也是为什么工艺角要分慢角与快角(第五章):同一套网表,在两个角下是两套完全不同的数字。
| 账目要素 | 建立账 | 保持账 |
|---|---|---|
| 比较的时钟沿 | 下一个捕获沿 | 同一个捕获沿 |
| 延迟取数 | 最慢路径(max) | 最快路径(min) |
| 怕什么 | 怕数据迟到 | 怕数据抢跑 |
| 典型工艺角 | 慢角(低压高温慢工艺) | 快角(高压低温快工艺) |
| 违例后果 | 该拍数据采错,功能出错 | 竞争冒险,亚稳态扩散 |
| 修复方向 | 缩短延迟或拉长周期 | 加大延迟或前移捕获沿 |
路径分段规则还有两个工程推论值得写进肌肉记忆。推论一是"伪路径的最小单元是段而不是路径":一条从 A 到 D 的物理通路如果穿过触发器 B,那么它实际上是 A 到 B、B 到 D 两段检查——给整条通路声明伪路径时,锚点必须覆盖你要豁免的那一段,写错锚点的例外会命中零条路径(4.3 审计抓的就是它)。推论二是"路径条数的膨胀是组合级的":扇出为 2 的逻辑链走 20 级,路径条数是 2 的 20 次方量级——STA 报告的"最差路径"是按终点聚合后的代表,同一终点可能有千万条物理通路在背后被取过最坏值。这解释了为什么修复一条报告路径后,同终点的 slack 常常只改善一点:你修的是代表,背后的通路群各有各的最坏分支。
下面是一段典型的路径报告骨架(简化,完整解读留给 2.4)。注意看每一行的 Increment 如何对应一段弧:
Startpoint: u_reg_ctrl/clk (上升沿触发的触发器) Endpoint: u_datapath/u_cnt_reg[7] Path Group: clk Path Type: max ; 建立账用慢延迟 Point Incr Path ---------------------------------------------------- clock clk (rise edge) 0.000 0.000 ; 启动时钟路径起点 clock network delay 0.036 0.036 ; 时钟树到 launch CLK u_reg_ctrl/CK 0.000 0.036 ; 时钟弧到达 u_reg_ctrl/Q (INVX1 之后) 0.082 0.118 ; CLK 到 Q 的单元弧 u_nand_a/Y (NAND2X1) 0.045 0.163 ; 组合单元弧 u_net_172 (wire) 0.021 0.184 ; 互连弧 u_mux_b/Z (MUX2X1) 0.068 0.252 ; 组合单元弧 u_datapath/u_cnt_reg[7]/D 0.000 0.252 ; 数据路径终点 data arrival time 0.252
从这个骨架已经能读出本节的核心:路径是弧的序列,账本是弧延迟的累加。启动时钟路径、数据路径、捕获时钟路径三段各自累加,然后在公式里各就各位——公式的完整形态,就是下一章 2.1 的主角。带着这张"记账单元"的地图去读任何时序报告,你都不会迷路。
路径模型建好了,还差最后一个变量:时钟沿本身在时间轴上的位置并不像纸面上那样整齐。下一节把时钟树、偏斜与不确定度这三个修正项讲透,公式里的每个减项从此都有出处。