第二章:静态时序分析入门
静态时序分析,说白了就是检查你的芯片能不能跑在目标频率上。我刚开始做设计时总觉得这步可有可无,直到有一次流片回来芯片死活上不了高频……嗯,从那以后我再也不敢跳过 STA 了。
这一章,我们聊聊 STA 的基本流程、SDC 约束怎么写,以及怎么读懂那份让人头疼的时序报告。
2.1 STA 基本流程:三步走
STA 的流程其实不复杂,我习惯把它拆成三步:
- 读入设计:把综合后的网表和库文件加载进来
- 施加约束:告诉工具时钟长什么样、输入输出延迟多少
- 分析报告:工具算出所有路径的时序裕量,你挑出违例的修
你想想看,这跟做菜有点像。先备好食材(网表),再定好火候(约束),最后尝尝咸淡(看报告)。
核心逻辑:STA 不跑仿真,它用数学方法穷举所有路径。所以它快,但不检查功能对不对。
下面这张图是我自己画的 STA 流程框架,你看一眼就明白了:
我的习惯:每次跑 STA 前,先确认库文件版本对不对。我在项目中遇到过因为库文件混用导致时序分析完全不准的情况,折腾了两天才发现是 .lib 版本不匹配。
2.2 SDC 约束文件编写
SDC 是 Synopsys Design Constraints 的缩写。说白了,它就是告诉工具你的设计想跑多快、输入信号什么时候到、输出信号什么时候要。
我个人习惯把 SDC 分成三块来写:
2.2.1 时钟约束
时钟是时序分析的基准。没有时钟,STA 就没法玩。
# 创建一个 100MHz 的时钟,占空比 50%
create_clock -name clk -period 10.0 [get_ports clk]
# 生成时钟(从分频器出来的)
create_generated_clock -name clk_div2 \
-source [get_ports clk] -divide_by 2 \
[get_pins u_divider/Q]
嗯,这里要注意:时钟的 period 单位是纳秒。100MHz 对应 10ns,200MHz 对应 5ns。别搞反了,我见过有人把 10ns 写成 10MHz 的……
2.2.2 输入输出延迟
芯片不是孤岛,它要跟外部打交道。输入延迟告诉工具数据从片外到片内要多久,输出延迟告诉工具数据从片内到片外要多久。
# 输入延迟:数据在时钟沿之后 2ns 到达
set_input_delay -clock clk -max 2.0 [get_ports data_in]
# 输出延迟:数据需要在时钟沿之前 1.5ns 稳定
set_output_delay -clock clk -max 1.5 [get_ports data_out]
避坑指南:我曾经把输入延迟设得太乐观,结果芯片流片回来发现接口时序不满足。后来学乖了,输入输出延迟一定要留余量,至少 10%-20%。
2.2.3 时序例外
有些路径不需要严格检查,比如跨时钟域的同步器路径、异步复位路径。这时候要用 set_false_path 或 set_multicycle_path。
# 跨时钟域路径,不检查
set_false_path -from [get_clocks clk_a] -to [get_clocks clk_b]
# 多周期路径:数据需要 2 个时钟周期才稳定
set_multicycle_path -setup 2 -from [get_pins u_slow/A] -to [get_pins u_fast/B]
你想想看,如果不设 false path,工具会拼命去优化那些不需要优化的路径,浪费你的时间。
2.3 时序报告解读
跑完 STA 后,工具会吐出一堆报告。新手看到那密密麻麻的数字就头大。我教你一个方法:只看关键信息。
2.3.1 报告结构
一份典型的时序报告长这样:
********************************************************************************
Startpoint: u_reg1/Q (rising edge-triggered flip-flop)
Endpoint: u_reg2/D (rising edge-triggered flip-flop)
Path Group: clk
Path Type: max (setup)
********************************************************************************
Point Incr Path
---------------------------------------------------------------- -----------
clock clk (rise edge) 0.00 0.00
clock network delay (propagated) 0.50 0.50
u_reg1/Q (reg) 0.30 0.80
u_comb/A (AND2) 0.15 0.95
u_comb/Z (AND2) 0.20 1.15
u_reg2/D (reg) 0.00 1.15
data arrival time 1.15
clock clk (rise edge) 10.00 10.00
clock network delay (propagated) 0.50 10.50
clock uncertainty -0.20 10.30
u_reg2/D (setup time) -0.10 10.20
data required time 10.20
---------------------------------------------------------------- -----------
slack (MET) 9.05
********************************************************************************
我一般先看最下面那行 slack。正数表示满足,负数表示违例。然后看 data arrival time 和 data required time 的差值,就知道差了多少。
2.3.2 关键指标速查表
| 指标 | 含义 | 正常值 | 违例信号 |
|---|---|---|---|
| slack | 时序裕量 | ≥ 0 | 负数 |
| data arrival time | 数据实际到达时间 | 越小越好 | 接近 required time |
| data required time | 数据最晚必须到达时间 | 越大越好 | 小于 arrival time |
| clock uncertainty | 时钟抖动和余量 | 通常 0.1~0.3ns | 过大说明时钟质量差 |
| setup time | 寄存器建立时间要求 | 库文件给定 | 过大说明选库有问题 |
我的经验:看到 slack 为负别慌。先看是 setup 违例还是 hold 违例。setup 违例可以降频或优化组合逻辑,hold 违例通常加 buffer 就能解决。我在项目中遇到过最离谱的一次,slack 负了 5ns,最后发现是时钟约束写错了……
2.3.3 常见违例及对策
- setup 违例:路径太长,数据跑不过去。对策:插流水线、优化组合逻辑、降低频率。
- hold 违例:数据跑得太快,把上一拍的数据冲掉了。对策:加 buffer 延迟路径。
- transition 违例:信号上升/下降时间太长。对策:加大驱动强度、减少扇出。
- clock gating 检查失败:门控时钟的使能信号不稳定。对策:加同步器或调整门控逻辑。
嗯,其实大部分违例都是 setup 和 hold。你只要把这两个搞明白,STA 就算入门了。
小技巧:看报告时,我习惯先按 slack 排序,从最差的开始修。修完一条路径,重新跑 STA,再看下一条。别想一口气把所有违例都修完,那会把自己搞崩溃。
好了,这一章就聊到这儿。STA 入门不难,难的是经验积累。多跑几次、多读报告,慢慢就上手了。
可可精品资料库