静态时序分析(STA)原理

静态时序分析,说白了就是给芯片的每一条逻辑路径做“体检”。我刚开始接触数字设计时,总觉得STA是后端的活儿,直到自己负责的一个模块在流片后死活跑不到目标频率——翻看时序报告才发现是保持时间违规,但后端说这该前端管。那次之后我才明白,STA是前后端都要盯死的环节。

STA分析流程

STA的核心是枚举所有时序路径,然后检查每条路径上数据信号能否在时钟沿前后稳定建立和保持。流程大概分三步:

  • 读入网表与约束:把综合后的门级网表和SDC时序约束喂给STA工具。
  • 路径枚举与延迟计算:工具会找出所有起点(通常是时钟引脚)到终点(通常是寄存器数据端)的路径,然后根据标准单元库和互连寄生参数算出每段延迟。
  • 建立/保持检查:用算出来的延迟去验证是否违反setup和hold要求。

这里有个容易忽略的点:路径必须覆盖所有四种类型——输入到寄存器、寄存器到寄存器、寄存器到输出、输入到输出。我曾经在一个项目中漏配了输入到寄存器的约束,结果STA报告全绿,流片回来IO时序全崩。

我的个人习惯:在跑STA前,先用命令 report_analysis_coverage 看看路径覆盖率是不是100%。如果低于98%,大概率漏约束了。

建立时间与保持时间检查公式

建立时间和保持时间的检查公式是STA的数学基础。很多人背公式却不懂物理含义,我建议你把它想象成“数据必须在寄存器采样窗口内稳定”。

检查类型 公式 物理含义
建立时间 T_data_path + T_setup ≤ T_clock_period + T_clock_skew 数据必须在下一个时钟沿之前到达并稳定
保持时间 T_data_path ≥ T_hold + T_clock_uncertainty 数据不能在当前时钟沿之后变化太快

你想想看,建立时间违规通常是路径太长,保持时间违规往往是路径太短。在HS‑TTA这种高吞吐架构里,流水线级数多,保持时间违规更隐蔽——因为大量路径的延迟都很接近,稍微一点工艺偏差就可能违例。

时序报告解读

拿到STA报告后,我一般先看 slack 列。slack是负值的地方就是违规点。但光看这一个数字不够,得逐层拆报告。

典型的report_timing输出长这样:

Startpoint: u_ff_a_reg/CK
Endpoint:   u_ff_b_reg/D
Path Type:  setup
Slack:      -0.12ns

Data Path:
  u_ff_a_reg/Q         0.00ns
  U1/A                 0.15ns
  U2/Z                 0.28ns
  u_ff_b_reg/D         0.43ns

Clock Path:
  clk (rise edge)      0.00ns
  u_ff_a_reg/CK        0.05ns
  u_ff_b_reg/CK        0.08ns

关键字段解读:

  • Slack:负值表示时序余量不足,值就是欠了多少时间。
  • Data Path:从起点Q端到终点D端的实际延迟。
  • Clock Path:时钟从源点到起点和终点的延迟差(skew在这里体现)。

如果看到建立时间违例,而我确定代码逻辑没问题,那我会先检查时钟是否太慢——哦不对,是时钟周期是否足够。如果是保持时间违例,我曾经被一个假路径骗过:报告里显示一条路径slack为‑0.01ns,我以为是边缘违例,加了两个Buffer才跑通。后来发现那是异步时钟域间的路径,应该在约束里设false_path。所以看报告前,一定要确认路径的约束类型。

我曾经踩过的坑:有一次报告里所有setup违例都集中在同一个模块的输出端口。我盯着数据路径看了半天,最后发现是输出端口没有设output_delay。所以读报告时先看 Path Type,再看 Startpoint/Endpoint 是不是和自己预期的输入输出端口匹配。

STA在HS‑TTA中的特殊考量

HS‑TTA架构里经常有多周期路径和流水线握手信号。这些东西在STA里需要额外标注。比如一个数据需要两个周期才能到达终点,你就得在SDC里写set_multicycle_path -setup 2。不然工具会按单周期检查,报一堆假违例。

另外,HS‑TTA的时钟分布对jitter要求很高。我建议你在约束里加入合理的clock_uncertainty值,别用默认的0。真实项目中我曾因为uncertainty设得过小,导致上板测试时偶尔时序跑飞。

下面这张图总结了STA的核心路径分类:

STA时序路径分类 STA路径分类 输入→寄存器 检查输入端口到寄存器 输入延迟必须满足建立/保持 寄存器→寄存器 最核心的路径类型 数据路径延迟≤周期−建立时间 寄存器→输出 检查寄存器到输出端口 输出延迟必须满足外部要求 输入→输出 纯组合逻辑路径 延迟不能超过周期减IO延时

对应到我们HS‑TTA项目里,寄存器到寄存器的路径往往占85%以上。我在调试setup违例时,会优先看这条路径上有没有插不必要的Buffer,或者能不能通过retiming把逻辑移到相邻级。

STA报告解读是门手艺活。我的经验是:先看总违例数,再看最差违例路径的slack,接着看路径类型。如果全是同一个类型的违例,比如全是寄存器到输出,那大概率是输出约束配错了。

注意:不要一上来就调代码或插Buffer。先确认约束本身是否正确——我曾经花了两天优化一条路径,最后发现是时钟周期设错了。正确的调试顺序永远是:确认约束 → 验证路径 → 分析延迟 → 修改设计。