静态时序分析(STA)入门

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

STA 跟动态仿真不一样。动态仿真你得给激励、看波形,跑一次可能几小时甚至几天。STA 呢?它把所有可能的路径都检查一遍,不需要输入向量。你想想看,这效率差距有多大。

核心观点:STA 是签核(Sign-off)前的最后一道防线。它不测功能,只测时序。功能对不对是仿真的事,能不能按时跑到目标频率,那是 STA 的事。

STA 的基本概念

STA 的输入有三个东西:网表、时序库、约束。网表就是你的电路连接,时序库告诉你每个单元有多快,约束告诉工具你的目标是什么。

我个人习惯把 STA 理解成「查时刻表」。火车什么时候到站、什么时候发车,晚点了没有——STA 就是在查数字电路里每个信号什么时候到达、什么时候需要到达。

STA 要素 对应含义 我的理解
网表 电路连接关系 铁路网
时序库 单元延迟参数 列车速度表
约束 时钟、输入输出延迟 时刻表
报告 检查结果 晚点通知

时序路径:起点与终点

STA 把电路拆成一条一条的路径来分析。每条路径都有起点和终点。

起点可以是:

  • 触发器的时钟引脚(CK)
  • 输入端口(Input Port)

终点可以是:

  • 触发器的数据输入引脚(D)
  • 输出端口(Output Port)

路径从起点到终点,中间经过组合逻辑。STA 会计算这条路径上的总延迟,然后跟约束要求做比较。

我的经验:刚学 STA 时我总搞不清路径怎么算。后来我画了个图:时钟沿从起点出发,经过组合逻辑,到达终点。路径延迟 = 时钟到起点的时间 + 组合逻辑延迟 + 线延迟。就这么简单。

路径类型主要有四种:

  • 输入到寄存器:从输入端口到触发器的 D 端
  • 寄存器到寄存器:从触发器 CK 到下一个触发器 D 端
  • 寄存器到输出:从触发器 CK 到输出端口
  • 输入到输出:从输入端口到输出端口(纯组合路径)

其中寄存器到寄存器路径是最常见的,也是我们最需要关注的。

时序路径结构图 触发器 FF1 CK → Q 起点 组合逻辑 AND + OR + INV 触发器 FF2 D → Q 终点 时钟 CLK 路径延迟 = T_clk2q(FF1) + T_combo + T_wire 检查条件:路径延迟 ≤ T_clk - T_setup(FF2)

建立时间检查

建立时间(Setup Time)是触发器在时钟沿到来之前,数据必须保持稳定的最短时间。如果数据到得太晚,触发器就可能采到错误的值。

检查公式:

数据到达时间 ≤ 数据要求时间
即:T_launch + T_clk2q + T_combo ≤ T_capture + T_clk_period - T_setup

我在项目中遇到过一个问题:一条路径的建立时间违例了 50ps。查了半天,发现是综合时没设对时钟 uncertainty。加上 uncertainty 后,路径就过了。所以啊,约束一定要写对。

注意:建立时间违例是硬伤。如果 setup 不满足,芯片在目标频率下一定会出错。没有侥幸的可能。

保持时间检查

保持时间(Hold Time)是时钟沿之后,数据必须保持稳定的最短时间。如果数据变化太快,触发器也可能采错。

检查公式:

数据到达时间 ≥ 数据要求时间
即:T_launch + T_clk2q + T_combo ≥ T_capture + T_hold

保持时间违例通常发生在短路径上。比如两个触发器直接相连,中间没有组合逻辑。数据从 FF1 的 Q 端出来,几乎同时就到了 FF2 的 D 端。如果时钟偏斜(Clock Skew)比较大,就可能出问题。

检查类型 检查什么 违例后果 修复方法
建立时间 数据不能太晚 频率上不去 降频、优化逻辑、加流水线
保持时间 数据不能太早 功能错误 加缓冲、加延迟单元

避坑指南:我曾经在一个项目中只做了 setup 检查,没做 hold 检查。结果流片回来,低温下芯片功能就不对。后来一查,是 hold 违例。从那以后,我每次跑 STA 都会把 setup 和 hold 都跑一遍,一个都不能少。

建立时间与保持时间的关系

建立时间和保持时间是一对矛盾。你优化 setup,可能会让 hold 变差;你修 hold,又可能让 setup 变差。为什么?

修 setup 要减少路径延迟,比如换更快的单元。但更快的单元输出跳变更快,对下一级来说,数据到达时间更早,hold 裕量就变小了。

修 hold 要增加路径延迟,比如加缓冲。但加了缓冲,路径总延迟变大,setup 裕量就变小了。

所以 STA 工程师得在两者之间找平衡。我个人习惯是先修 setup,再修 hold。因为 setup 跟频率直接相关,是性能指标。hold 是功能正确性,虽然也重要,但通常可以通过加延迟来修,代价相对小一些。

关键点:STA 不是跑一次就完事的。每修一次路径,都要重新跑一遍,看看有没有引入新的违例。迭代是常态。

STA 工具的工作流程

实际项目中,STA 工具(比如 PrimeTime)的工作流程大致如下:

  1. 读入网表:把综合后的门级网表读进来
  2. 读入库:读入标准单元库、IO 库、宏单元库
  3. 读入约束:读入 SDC 约束文件
  4. 提取寄生参数:读入 RC 参数(SPEF 文件)
  5. 计算延迟:工具自动计算每条路径的延迟
  6. 检查时序:逐条路径检查 setup 和 hold
  7. 生成报告:输出违例路径、裕量、关键路径等信息

嗯,这里要注意:寄生参数提取的准确性直接影响 STA 结果。如果 RC 参数不准,STA 就是白跑。我建议在 sign-off 阶段用最准确的寄生参数,不要省那点时间。

STA 入门其实不难,难的是在实际项目中灵活运用。多跑几次,多看看报告,慢慢就有感觉了。