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约束对CTS优化目标的影响关系 SDC约束命令 create_clock 源点 / 周期 / 波形 create_generated_clock 分频 / 门控 / 源点 set_clock_groups 同步 / 异步分组 set_false_path 排除检查路径 set_multicycle_path 放宽周期数 CTS推导结果 时钟根位置 决定树起点 时钟域划分 决定平衡范围 平衡目标集合 决定优化对象 排除路径列表 决定忽略对象 优化优先级 决定缓冲力度 CTS结果与判断 正确:时钟树覆盖完整,偏斜达标 report_clock_tree 显示各域已平衡 错误1:源点错→树从中间断开 部分寄存器未被时钟树覆盖 错误2:漏生成时钟→域划分错 分频域被当作独立时钟 错误3:虚假路径过宽→漏检查 真实路径被排除,时序违例漏报 错误4:多周期漏hold→冲突 setup放宽但hold仍按单周期

五、常见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_timingsetup与hold成对出现,hold=setup-1
CTS后平衡report_clock_tree各时钟域寄存器数量与预期一致

把上述检查放在CTS之前执行,可以避免大部分因约束错误导致的时钟树返工。约束正确后,CTS的优化目标才与设计意图一致,后续的时序收敛才有可靠基础。