with one click
timing-analysis
静态时序分析技能 - 时序诊断、收敛优化、签收标准
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
静态时序分析技能 - 时序诊断、收敛优化、签收标准
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
物理设计全流程技能 - 从floorplan到GDSII,完整数字芯片物理设计指导
芯片架构设计技能 - 从需求定义到模块划分,完整指导芯片架构开发
EDA工具脚本开发技能 - TCL/Python/Makefile 自动化流程最佳实践
功能安全分析技能 - FMEDA 分析、安全机制设计、ISO 26262 符合
UVM 验证方法论技能 - 从验证计划到功能覆盖率,完整 UVM 验证平台开发
功耗分析和优化技能 - 功耗计算、IR降分析、电迁移分析、低功耗优化
| name | timing-analysis |
| description | 静态时序分析技能 - 时序诊断、收敛优化、签收标准 |
| description.zh | 静态时序分析技能 - 时序诊断、收敛优化、签收标准 |
| origin | ICER |
| categories | back-end |
当用户需要进行静态时序分析、时序诊断和时序收敛时,启用此技能。提供时序结果解读、问题诊断、优化策略。
| 参数 | 28nm | 16nm | 7nm | 说明 |
|---|---|---|---|---|
| 逻辑级数上限 | 8-10级 | 6-8级 | 4-6级 | 超过需流水线分割 |
| 典型单元延迟 | 50-80ps | 30-50ps | 15-30ps | NAND2_X1 |
| 典型线延迟/um | 0.5-1ps | 0.3-0.5ps | 0.2-0.3ps | M2层 |
| Setup Margin | 100-200ps | 50-100ps | 30-50ps | 签收裕量 |
| Hold Margin | 50-100ps | 30-50ps | 20-30ps | 保持裕量 |
| 参数 | 典型值 | 说明 |
|---|---|---|
| Clock Skew | < 100ps | 同时钟域内 |
| Clock Latency | 1-3ns | 取决于芯片大小 |
| Clock Transition | < 100ps | 时钟转换时间 |
| Clock Uncertainty | 50-150ps | 时钟不确定性 |
| 驱动类型 | 建议扇出 | 最大扇出 | 超过后果 |
|---|---|---|---|
| 时钟网络 | 8-16 | 32 | skew增大、转换时间变差 |
| 控制信号 | 4-8 | 16 | 延迟增大、时序违例 |
| 数据信号 | 4-6 | 8 | 延迟增大、负载过大 |
诊断步骤1:分析时序报告
# 获取详细时序信息
report_timing -max_paths 100 -slack_lesser_than 0 \
-input_pins -nets -caps -transition_time
# 分析延迟组成
report_delay_calculation -from [get_pins start/Q] -to [get_pins end/D]
判断标准:
| Cell Delay 占比 | Net Delay 占比 | 可能原因 | 诊断动作 |
|---|---|---|---|
| > 60% | < 40% | 逻辑级数过多/驱动不足 | 检查逻辑深度、单元驱动 |
| < 40% | > 60% | 线长过长/扇出过大 | 检查布局、扇出 |
| ≈ 50% | ≈ 50% | 综合问题 | 分析关键路径细节 |
诊断步骤2:检查约束正确性
# 验证时钟定义
report_clock -skew -latency
# 检查假路径
report_false_path
# 检查多周期路径
report_multicycle_path
# 检查输入输出延迟
report_port -delay
诊断步骤3:定位根本原因
| 根本原因 | 诊断特征 | 解决方案优先级 |
|---|---|---|
| 逻辑级数过多 | logic_depth > 10 | 1.流水线分割 2.逻辑重构 |
| 扇出过大 | fanout > 16 | 1.复制寄存器 2.插buffer |
| 线长过长 | net_length > 500um | 1.重新摆放 2.插buffer |
| 驱动不足 | slew > 100ps | 1.换大驱动 2.减负载 |
| 约束错误 | false path missing | 修正约束 |
现象: TNS >> WNS(如 WNS=-100ps, TNS=-10000ps)
诊断: 不只是几条路径有问题,而是模块级问题
| 可能原因 | 诊断方法 | 解决方案 |
|---|---|---|
| 模块时序预算不足 | 检查模块边界约束 | 调整时序预算 |
| 时钟质量问题 | 检查 CTS 报告 | 重做 CTS |
| 电源问题 | 检查 IR 降报告 | 修复电源网络 |
诊断步骤:
# 分析保持时间违例
report_timing -delay_type min -max_paths 50
# 检查时钟偏斜
report_clock_timing -type skew
根本原因分析:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 同一模块大量违例 | CTS 问题 | 检查时钟树、重做 CTS |
| 随机分布 | 局部时钟偏斜大 | 插入 delay buffer |
| 修复后反复出现 | 工艺角覆盖不全 | 检查所有工艺角 |
现象: SS 工艺角满足,FF 工艺角不满足(或相反)
诊断:
# 比较 SS 和 FF 工艺角
report_timing -max_paths 10 > timing_ss.rpt
current_scenario ff
report_timing -max_paths 10 > timing_ff.rpt
原因与解决方案:
| 矛盾情况 | 原因 | 解决方案 |
|---|---|---|
| SS 违例, FF OK | 建立时间问题 | 优化关键路径延迟 |
| FF 违例, SS OK | 保持时间问题 | 插入 delay buffer |
| 都违例 | 约束错误或设计问题 | 检查约束、重新评估 |
定义: 数据需要在下一个时钟沿之前稳定到达。
计算公式:
Setup Slack = Required Time - Arrival Time
= (Clock Period + Clock Skew) - (Launch Clock + Data Delay)
定义: 数据需要在时钟沿之后保持稳定,不能太快到达。
计算公式:
Hold Slack = Arrival Time - Required Time
= (Launch Clock + Data Delay) - (Capture Clock + Hold Time)
| 术语 | 含义 |
|---|---|
| WNS | Worst Negative Slack,最差的负 slack |
| TNS | Total Negative Slack,所有负 slack 总和 |
| NP | Number of Paths,违例路径数量 |
| OCV | On-Chip Variation,片上变化 |
| CPPR | Clock Path Pessimism Removal,去除时钟路径悲观 |
| Logic Depth | 逻辑深度,路径上逻辑单元数量 |
| Fanout | 扇出,一个信号驱动的负载数量 |
需要准备:
PrimeTime 示例:
# 读入库文件
set link_library [list *.lib]
# 读入网表
read_verilog design.v
# 链接设计
current_design design_name
link
# 读入约束
read_sdc constraints.sdc
# 读入寄生参数
read_parasitics design.spef
# 运行时序分析
update_timing
# 生成报告
report_timing -max_paths 100 -slack_lesser_than 0
report_timing -delay_type min -max_paths 100
report_constraint -all_violators
为什么需要 MMMC: 单一工艺角分析无法覆盖所有工作条件
# 创建场景
create_scenario -name func_ss_125c
create_scenario -name func_ff_-40c
create_scenario -name test_ss_125c
# 设置每个场景的操作条件
current_scenario func_ss_125c
set_operating_conditions -library slow_lib slow_125c
current_scenario func_ff_-40c
set_operating_conditions -library fast_lib fast_-40c
# 运行分析
report_timing -scenarios {func_ss_125c func_ff_-40c}
| 工艺角 | 晶体管速度 | 电压 | 温度 | 最容易出现 |
|---|---|---|---|---|
| FF | 快-快 | 高 | 低 | 保持时间违例 |
| SS | 慢-慢 | 低 | 高 | 建立时间违例 |
| TT | 典型 | 典型 | 典型 | 参考 |
| FS | 快N慢P | 典型 | 典型 | 混合偏差 |
| SF | 慢N快P | 典型 | 典型 | 混合偏差 |
第一步:看整体结果
Report: Timing Summary
WNS: -0.234 ns (Setup)
TNS: -12.567 ns (Setup)
NP: 156 paths
WNS: -0.045 ns (Hold)
TNS: -1.234 ns (Hold)
NP: 23 paths
解读方法:
| 指标 | 值 | 判断 |
|---|---|---|
| WNS | ≥ 0 | 满足 |
| WNS | -100ps ~ 0 | 接近收敛,小幅优化 |
| WNS | < -500ps | 严重问题,需要重构 |
| TNS/WNS | > 10 | 多条路径问题,模块级优化 |
| TNS/WNS | < 5 | 少数路径问题,针对性优化 |
第二步:分析关键路径详情
Startpoint: reg1/CK (rising edge-triggered flip-flop)
Endpoint: reg2/D (rising edge-triggered flip-flop)
Path Group: clk
Path Type: max
Point Incr Path
--------------------------------------------------
clock clk (rise edge) 0.000 0.000
clock network delay 0.200 0.200
reg1/CK 0.000 0.200 r
reg1/Q 0.150 0.350 f <- 检查转换时间
comb1/Z 0.300 0.650 f <- 延迟最大的单元
comb2/Z 0.250 0.900 f
comb3/Z 0.200 1.100 r
reg2/D 0.000 1.100 r
data arrival time 1.100
clock clk (rise edge) 1.000 1.000
clock network delay 0.200 1.200
clock uncertainty -0.050 1.150
reg2/setup time -0.050 1.100
data required time 1.100
--------------------------------------------------
slack 0.000
分析要点:
统计单元延迟
检查转换时间
检查线延迟
检查时钟路径
第三步:分类违例
| 分类 | 特征 | 策略 |
|---|---|---|
| 集中在某模块 | 模块时序预算不足 | 调整模块约束或重构 |
| 都是长路径 | 逻辑级数过多 | 流水线分割 |
| 都是高扇出 | 扇出过大 | 复制寄存器 |
| 随机分布 | 整体优化 | 综合优化 |
建立时间违例 = 路径太慢
建立时间违例
│
├── 逻辑级数 > 10?
│ ├── 是 → 流水线分割(最有效)
│ └── 否 → 检查延迟组成
│
├── Cell Delay > 60%?
│ ├── 是 → 检查驱动强度
│ │ ├── 驱动太小 → 换大驱动
│ │ └── 扇出太大 → 复制寄存器
│ └── 否 → 检查线延迟
│
├── Net Delay > 60%?
│ ├── 是 → 布局问题
│ │ ├── 线太长 → 重新摆放
│ │ └── 拥塞 → 优化布线
│ └── 否 → 继续分析
│
└── 接近收敛?
├── 是 → 有用偏斜
└── 否 → 重新评估设计
| 方法 | 效果 | 适用场景 | 操作 |
|---|---|---|---|
| 流水线分割 | 最大 | 逻辑级数 > 10 | 插入寄存器 |
| 换更大驱动 | 中等 | 负载大、转换时间差 | 替换单元 |
| 复制高扇出 | 中等 | 扇出 > 16 | 复制寄存器 |
| 重新摆放 | 中等 | 线太长 | 优化布局 |
| 有用偏斜 | 小 | 接近收敛 | 调整时钟 |
问题: 长组合逻辑路径延迟太大
// ❌ 问题:一级组合逻辑 32 级进位,延迟太大
always @(*) begin
for (i = 0; i < 32; i = i + 1) begin
c[i+1] = a[i] & b[i] | c[i] & (a[i] ^ b[i]);
end
end
解决: 分成两级流水
// ✅ 解决:分成两级流水
always @(posedge clk) begin
// 第一级:低 16 位
level1_c <= lower_16_bits_calculation;
end
always @(*) begin
// 第二级:高 16 位 + 第一级结果
final_result = upper_16_bits + level1_c;
end
# 分析关键路径
report_timing -max_paths 20 -input_pins -nets -caps
# 识别高扇出网络
report_net_fanout -threshold 16
# 分析延迟组成
report_delay_calculation -from [get_pins start/Q] -to [get_pins end/D]
# 自动优化建议
report_qor
保持时间违例 = 路径太快
| 方法 | 效果 | 操作 | 注意 |
|---|---|---|---|
| 插入延迟单元 | 最大 | 在快路径插入 buffer | 可能影响建立时间 |
| 调整有用偏斜 | 中等 | 调整发射时钟延迟 | 需要时钟树控制 |
| 换更小驱动 | 中等 | 减小驱动强度 | 选择有限 |
| 重新摆放 | 小 | 增加线长 | 效果不确定 |
问题路径:
reg1/Q -> [comb: 0.2ns] -> reg2/D
保持时间要求:0.3ns
Slack = 0.2 - 0.3 = -0.1ns(违例)
解决:插入 buffer
reg1/Q -> [comb: 0.2ns] -> [buffer: 0.15ns] -> reg2/D
Slack = 0.35 - 0.3 = 0.05ns(满足)
1. 分析保持时间违例路径
2. 计算需要的延迟量
3. 选择合适的 buffer
4. 插入 buffer
5. 重新检查建立时间(重要!)
6. 检查所有工艺角
⚠️ 重要提醒: 修复保持时间后,必须重新检查建立时间! 增加延迟会改善保持时间,但可能恶化建立时间。
同一芯片上,相同类型的单元速度也可能不同:
PrimeTime 示例:
# 设置 OCV 降额
set_timing_derate -early 0.90 -cell_delay
set_timing_derate -late 1.10 -cell_delay
# 打开 CPPR
set timing_remove_clock_reconvergence_pessimism true
# 运行分析
update_timing
report_timing -max_paths 100
| 工艺节点 | Early Derate | Late Derate | 说明 |
|---|---|---|---|
| 28nm | 0.92 | 1.08 | 标准值 |
| 16nm | 0.90 | 1.10 | 先进节点 |
| 7nm | 0.88 | 1.12 | 更大偏差 |
| 检查项 | 标准 | 说明 |
|---|---|---|
| Setup WNS | ≥ 0 | 所有工艺角 |
| Hold WNS | ≥ 0 | 所有工艺角 |
| TNS | = 0 | 无违例路径 |
| OCV | 满足 | OCV 分析通过 |
| CPPR | 已打开 | 去除悲观 |
# 生成所有工艺角汇总报告
report_timing -max_paths 100 -slack_lesser_than 0 > setup_violators.rpt
report_timing -delay_type min -max_paths 100 > hold_violators.rpt
report_constraint -all_violators > all_violators.rpt
report_timing_summary > timing_summary.rpt
report_clock_timing -type summary > clock_summary.rpt
# QoR 汇总
report_qor > qor_summary.rpt
背景:
问题现象:
Path 1: SLACK = -800ps (VIOLATED)
Startpoint: ddr_phy/data_out_reg
Endpoint: ddr_controller/din_reg
Path Group: clk_ddr
Data Path Delay: 1.2ns
Logic Levels: 12
诊断过程:
步骤1:分析延迟组成
Cell Delay: 400ps (33%)
Net Delay: 800ps (67%) <-- 异常高
结论:Net Delay 占比过高,问题在布线
步骤2:检查布局
ddr_phy 位置: (100, 100)
ddr_controller 位置: (800, 800)
距离: 约1mm
结论:模块距离过远,线长过大
步骤3:检查扇出
data_out_reg fanout: 48 <-- 异常高
结论:扇出过大,每个接收端负载过重
解决方案:
| 措施 | 效果 |
|---|---|
| 重新布局:将 ddr_controller 移至距 PHY 200um 处 | 线长减少 75% |
| 寄存器复制:将 data_out_reg 复制为 4 份 | 扇出降为 12 |
| 插入 buffer:在长线上插入 buffer 链 | 改善信号完整性 |
结果:
Path 1: SLACK = +50ps (MET)
Data Path Delay: 650ps
Logic Levels: 12
WNS 从 -800ps 改善到 +50ps,时序收敛。
经验总结:
# 正确设置派生时钟
create_generated_clock -name clk_div2 \
-source [get_pins pll/clk_out] \
-divide_by 2 \
[get_pins div/clk_out]
# 注意:派生时钟的 master clock 必须正确定义
# 设置异步时钟组
set_clock_groups -asynchronous \
-group [get_clocks clk_sys] \
-group [get_clocks clk_ddr] \
-group [get_clocks clk_peri]
# 或使用 false path
set_false_path -from [get_clocks clk_sys] -to [get_clocks clk_ddr]
# 输入延迟:外部芯片到本芯片的延迟
set_input_delay -max 2.0 -clock clk [get_ports data_in]
set_input_delay -min 0.5 -clock clk [get_ports data_in]
# 输出延迟:本芯片到外部芯片的延迟
set_output_delay -max 2.0 -clock clk [get_ports data_out]
set_output_delay -min 0.5 -clock clk [get_ports data_out]
| 工具 | 公司 | 用途 |
|---|---|---|
| PrimeTime | Synopsys | 工业界标准 |
| Tempus | Cadence | 主流 |
| OpenSTA | 开源 | 免费 |
❌ 只检查典型工艺角:TT 不代表最坏情况
❌ 忽略 CPPR:结果悲观,过度优化
❌ 修复保持后不检查建立:可能引入新问题
❌ 过度使用 false path:可能掩盖真正的问题
❌ 不看 TNS 只看 WNS:可能漏掉模块级问题
❌ 不分析延迟组成直接优化:可能选错优化方法
physical-design-engineer 代理进行物理设计实现timing-engineer 代理进行时序分析和优化power-engineer 进行功耗时序权衡基础时钟定义:
# 主时钟
create_clock -name clk -period 10 [get_ports clk]
# 多个主时钟
create_clock -name clk_sys -period 5 [get_ports clk_sys]
create_clock -name clk_ddr -period 2.5 [get_ports clk_ddr]
# 虚拟时钟(用于 I/O 约束)
create_clock -name virt_clk -period 10
派生时钟定义:
# 分频时钟
create_generated_clock -name clk_div2 \
-source [get_pins pll/clk_out] \
-divide_by 2 \
[get_pins div/clk_out]
# 倍频时钟
create_generated_clock -name clk_mul2 \
-source [get_pins pll/clk_out] \
-multiply_by 2 \
[get_pins pll/clk_mul]
# 门控时钟(不要创建为派生时钟)
# 门控时钟输出自动继承源时钟
# 时钟不确定性
set_clock_uncertainty -setup 0.2 [get_clocks clk]
set_clock_uncertainty -hold 0.1 [get_clocks clk]
# 时钟延迟
set_clock_latency -max 0.5 [get_clocks clk]
set_clock_latency -min 0.3 [get_clocks clk]
# 时钟转换时间
set_clock_transition 0.1 [get_clocks clk]
# 时钟理想网络(CTS 前)
set_ideal_network [get_ports clk]
set_ideal_network [get_nets clk_net]
# 时钟传播(CTS 后)
set_propagated_clock [get_clocks clk]
# 输入延迟
set_input_delay -max 2.0 -clock clk [all_inputs]
set_input_delay -min 0.5 -clock clk [all_inputs]
# 特定端口的输入延迟
set_input_delay -max 1.5 -clock clk [get_ports data_in]
set_input_delay -min 0.3 -clock clk [get_ports data_in]
# 输出延迟
set_output_delay -max 2.0 -clock clk [all_outputs]
set_output_delay -min 0.5 -clock clk [all_outputs]
# 相对于虚拟时钟的延迟
set_input_delay -max 2.0 -clock virt_clk [get_ports data_in]
# 方法1:设置异步时钟组
set_clock_groups -asynchronous \
-group [get_clocks clk_sys] \
-group [get_clocks clk_ddr] \
-group [get_clocks clk_peri]
# 方法2:设置假路径
set_false_path -from [get_clocks clk_sys] -to [get_clocks clk_ddr]
set_false_path -from [get_clocks clk_ddr] -to [get_clocks clk_sys]
# 异步复位
set_false_path -from [get_ports rst_n]
# 2 周期路径
set_multicycle_path 2 -setup -from [get_pins reg1/Q] -to [get_pins reg2/D]
set_multicycle_path 1 -hold -from [get_pins reg1/Q] -to [get_pins reg2/D]
# 路径组
set_multicycle_path 2 -setup -from [get_clocks clk_fast] -to [get_clocks clk_slow]
# 检查所有时钟已定义
report_clock
# 检查未定义时钟的端口
report_port -direction in -verbose
# 检查输入输出延迟
report_port -delay
# 检查假路径
report_false_path
# 检查多周期路径
report_multicycle_path
# 检查约束完整性
check_timing
时序分析结果
│
├── WNS < -500ps?
│ ├── 是 → 严重问题
│ │ ├── 逻辑级数 > 15? → RTL重构/流水线
│ │ ├── 扇出 > 32? → 复制寄存器
│ │ └── 线长异常? → 重新布局
│ └── 否 → 中等问题
│ ├── 拥塞热点? → 优化布局
│ └── CTS 问题? → 重做 CTS
│
├── WNS -100ps ~ 0?
│ └── 接近收敛
│ ├── 有用偏斜
│ └── 小规模优化
│
└── WNS ≥ 0?
└── 检查所有工艺角
├── SS 违例? → 建立时间修复
├── FF 违例? → 保持时间修复
└── 全部满足 → 签收
| WNS 范围 | 预期迭代次数 | 建议策略 |
|---|---|---|
| < -1ns | 5-10 次 | 重新评估设计 |
| -1ns ~ -500ps | 3-5 次 | 结构优化 |
| -500ps ~ -100ps | 2-3 次 | 局部优化 |
| -100ps ~ 0 | 1-2 次 | 微调优化 |
| 阶段 | 检查项 | 标准 |
|---|---|---|
| 综合后 | WNS < -200ps | 继续优化 |
| Placement 后 | WNS < -100ps | 继续优化 |
| CTS 后 | WNS < -50ps | 继续优化 |
| Route 后 | WNS ≥ 0 | 签收 |
| Signoff | 所有角 WNS ≥ 0 | 流片 |
# 生成 QoR 报告
report_qor > qor_report.rpt
# 关键指标
# - WNS (Setup/Hold)
# - TNS (Setup/Hold)
# - NP (违例路径数)
# - 面积
# - 功耗
| 版本 | 日期 | WNS(Setup) | WNS(Hold) | TNS | NP | 修改内容 |
|---|---|---|---|---|---|---|
| v1.0 | 01/01 | -500ps | 0 | -5ns | 50 | 初始 |
| v1.1 | 01/02 | -200ps | 0 | -2ns | 20 | 流水线分割 |
| v1.2 | 01/03 | -50ps | 0 | -0.5ns | 5 | 优化驱动 |
| v1.3 | 01/04 | 0 | 0 | 0 | 0 | 有用偏斜 |