4. 时钟定义与约束检查
时钟树综合(CTS)的输入不只是版图和工艺库,更关键的是SDC约束。CTS工具会根据SDC推导出哪些寄存器属于同一个时钟域、哪些路径需要平衡、哪些路径可以忽略。如果SDC写错,CTS会朝着错误的目标优化:该平衡的时钟没有平衡,不该约束的路径被强行约束,最终导致建立时间或保持时间无法收敛。本节围绕五类最影响CTS的SDC命令展开,并给出常见错误的识别与修正方法。
一、create_clock:时钟树的根定义
create_clock定义时钟的源点、周期和波形。CTS最关心的是源点位置和周期。源点通常指向时钟输入端口或PLL输出端口,周期决定目标偏斜和插入延迟的优化力度。
create_clock -name clk_core -period 2.0 -waveform {0 1.0} [get_ports clk_in]
create_clock -name clk_ddr -period 1.25 [get_ports ddr_clk]
常见错误有三类。第一,源点写成寄存器时钟引脚而非端口,导致CTS把该寄存器当作时钟根,时钟树从中间断开。第二,周期单位与库不一致,例如库以ns为单位而约束写成ps数值,CTS会按错误周期计算目标。第三,漏写-waveform时默认占空比50%,若设计实际需要非50%占空比,上升沿与下降沿的平衡目标就会偏差。修正方法是:源点统一指向端口或PLL输出;周期与库单位核对;对非50%占空比显式写出波形。
二、create_generated_clock:分频与门控时钟的传递
当设计内部存在分频器、时钟门控或时钟选择器时,必须用create_generated_clock描述生成时钟与源时钟的关系。CTS需要知道生成时钟的源点,才能把源时钟树和生成时钟树作为一个整体来平衡。
create_generated_clock -name clk_div2 \
-source [get_ports clk_in] -divide_by 2 \
[get_pins u_div/clk_out]
常见错误是只写了create_clock而漏掉生成时钟,CTS会把分频后的寄存器当作独立时钟域,导致源时钟与分频时钟之间的路径不被平衡。另一种错误是-source指向了错误的节点,例如指向分频器输入而非源端口,CTS推导出的时钟树拓扑就会错位。修正时先用report_clocks确认每个时钟的源点和生成关系,再检查分频比、门控条件是否与RTL一致。
三、时钟组:告诉CTS哪些时钟需要平衡
默认情况下,CTS会尝试平衡所有时钟。但异步时钟域之间不需要平衡,强行平衡会浪费资源并可能引入不必要的缓冲。用set_clock_groups把异步时钟分组,CTS就会跳过组间平衡。
set_clock_groups -asynchronous \
-group {clk_core} \
-group {clk_ddr} \
-group {clk_usb}
常见错误是把本应同步的时钟设为异步,导致CTS不再平衡它们,跨域路径的建立时间检查被跳过,实际硅片上却存在时序关系。另一种错误是漏设时钟组,CTS对异步时钟也做平衡,插入大量缓冲,面积和功耗上升。修正原则是:只有确认无固定相位关系的时钟才设为异步;同一PLL输出的不同分频时钟通常应保持同步关系。
四、虚假路径与多周期路径:影响CTS的优化边界
set_false_path告诉工具某条路径不需要时序检查,CTS会将其从平衡目标中排除。set_multicycle_path则放宽路径的周期数,CTS会相应降低该路径的优化优先级。
set_false_path -from [get_clocks clk_core] -to [get_clocks clk_ddr]
set_multicycle_path 2 -setup -from [get_pins u_ctrl/reg_a/CK] \
-to [get_pins u_dsp/reg_b/D]
常见错误是把虚假路径设得过宽,例如用-from [get_clocks clk_core]覆盖了整个时钟域,结果该域内真正需要检查的路径也被排除。多周期路径的常见错误是只设了setup而漏设hold,导致保持时间检查仍按单周期执行,CTS在优化时产生冲突。修正方法是:虚假路径尽量精确到具体引脚或时钟对;多周期路径同时设置setup和hold,且hold值通常为setup值减一。
五、常见SDC问题的识别与修正流程
在Innovus中,CTS前应执行一次约束检查。常用命令包括report_clocks查看所有时钟定义,check_timing检查未约束路径和冲突约束,report_clock_tree在CTS后确认各时钟域是否被正确平衡。
report_clocks
check_timing -verbose
report_clock_tree -summary
一个典型的排查顺序是:先看report_clocks确认每个时钟的源点和生成关系是否与RTL一致;再用check_timing找出未约束的端点、被虚假路径覆盖的路径、以及多周期路径的setup/hold配对情况;最后在CTS后看report_clock_tree,如果某个时钟域的寄存器数量明显偏少,往往说明该域的时钟根定义有误或生成时钟漏写。
需要特别注意:set_false_path和set_multicycle_path会直接改变CTS的优化目标。在CTS前修改这两类约束,必须重新运行CTS,不能只做时序分析。否则时钟树仍然是按旧约束构建的,新约束下的时序结果不可信。
六、约束检查清单
| 检查项 | 命令 | 判断标准 |
|---|---|---|
| 时钟源点 | report_clocks | 源点指向端口或PLL输出,非寄存器引脚 |
| 生成时钟 | report_clocks | 分频/门控时钟均有generated_clock定义 |
| 时钟组 | check_timing | 异步时钟已分组,同步时钟未误分组 |
| 虚假路径 | check_timing -verbose | 无过宽false_path覆盖真实路径 |
| 多周期路径 | check_timing | setup与hold成对出现,hold=setup-1 |
| CTS后平衡 | report_clock_tree | 各时钟域寄存器数量与预期一致 |
把上述检查放在CTS之前执行,可以避免大部分因约束错误导致的时钟树返工。约束正确后,CTS的优化目标才与设计意图一致,后续的时序收敛才有可靠基础。