第二章 静态时序分析基础

静态时序分析,说白了就是检查你的芯片能不能跑在目标频率上。我刚开始做设计时总觉得这步可有可无,直到有一次流片回来芯片死活上不了高频……嗯,从那以后我再也不敢跳过 STA 了。

2.1 STA 的基本概念

静态时序分析是一种穷举式的时序验证方法。它不需要输入激励,而是遍历所有可能的时序路径,检查每条路径是否满足时序要求。我个人习惯把 STA 比作「芯片的体检报告」——它告诉你哪里虚、哪里堵、哪里可能出问题。

核心思想:STA 不关心功能对不对,只关心时序够不够。功能验证是仿真的事,时序验证是 STA 的事,两者分工明确。

STA 的输入有三个要素:

  • 网表——综合后的门级电路
  • 时序库——标准单元的延迟信息(.lib 文件)
  • 约束文件——你告诉工具时钟长什么样、输入输出怎么走(SDC 文件)

输出呢?就是一份时序报告,告诉你哪些路径通过了,哪些没通过。我在项目中遇到过一种情况:STA 报告全是绿的,但芯片跑起来就是不稳定。后来发现是约束写得太松了——嗯,约束不是越松越好,要实事求是。

2.2 建立时间与保持时间

这两个概念是 STA 的基石。你想想看,一个寄存器要正确采样数据,得满足两个条件:

建立时间(Setup Time)

数据必须在时钟有效沿到来之前稳定下来。这个「之前」的时间窗口,就是建立时间。为什么要有这个要求?因为寄存器内部需要时间把数据「锁住」。我见过新手把建立时间理解成「数据要提前到」,其实更准确的说法是「数据要提前稳定」。

我的经验:建立时间违例通常发生在路径太长、组合逻辑太多的时候。解决办法要么是插流水线,要么是优化逻辑深度。

保持时间(Hold Time)

数据在时钟有效沿之后还要保持一段时间不变。这个「之后」的时间窗口,就是保持时间。为什么会这样?因为寄存器锁存数据需要时间,如果数据变化太快,锁进去的可能是个错误值。

注意:保持时间违例比建立时间违例更难修。建立时间不够可以降频,保持时间不够降频也没用。我曾经在一个 28nm 项目上遇到保持时间违例,最后不得不手动插 buffer,那叫一个痛苦。

用公式表达就是:

建立时间检查:T_data_arrival + T_setup <= T_clock_period + T_clock_skew
保持时间检查:T_data_arrival >= T_hold + T_clock_skew

嗯,公式看着复杂,其实核心就一句话:数据不能来得太晚(setup),也不能变得太快(hold)。

2.3 时序路径的分类

STA 把路径分成四类。我个人觉得这个分类特别重要,因为不同路径的约束写法、优化方法都不一样。

路径类型 起点 终点 典型约束
reg2reg 寄存器时钟端 寄存器数据端 create_clock
reg2out 寄存器时钟端 输出端口 set_output_delay
in2reg 输入端口 寄存器数据端 set_input_delay
in2out 输入端口 输出端口 set_max_delay

reg2reg 路径

这是最常见的路径,也是 STA 默认会检查的路径。两个寄存器之间通过组合逻辑连接。我建议你重点关注这条路径,因为大部分时序违例都出在这里。

reg2out 路径

从寄存器到芯片输出端口。这条路径的约束取决于外部芯片的要求。比如外部芯片要求数据在时钟沿之后 5ns 内必须稳定,那你就得设 set_output_delay -max 5。

in2reg 路径

从输入端口到内部寄存器。同样,约束取决于外部芯片。我记得有一次,客户给的输入延迟约束写错了,导致我调了三天时序都没调通——后来发现是约束本身有问题。

in2out 路径

纯组合路径,从输入直接到输出。这种路径在数字芯片里不多见,但模拟接口或者一些特殊模块里会有。约束一般用 set_max_delay 搞定。

避坑指南:我曾经在 reg2out 路径上吃过亏。当时只设了 output_delay,忘了设 output_delay -clock。结果工具默认用了虚拟时钟,时序分析完全不对。嗯,从那以后我每次写约束都会 double-check 时钟关联。

2.4 小结

静态时序分析不是什么玄学。它就是把每条路径的延迟算出来,然后跟时钟周期比一比。建立时间看数据到得早不早,保持时间看数据变得快不快。路径分四类,每类的约束写法不同。

你想想看,掌握了这些基础,后面再学时序优化就轻松多了。下一章我会讲时序约束怎么写,包括那些容易踩坑的细节——比如 false_path 和 multicycle_path 到底什么时候用。

一句话总结:STA 不是用来「过」的,是用来「看」的。看懂报告,才能知道芯片到底行不行。