4. 时钟定义与约束
时钟是时序签核的“度量基准”。PrimeTime 里所有 setup/hold 检查、时钟偏斜、抖动、latency 的传播,最终都归结为对时钟波形的建模。如果时钟模型建得不准,即使路径本身没问题,报告出来的 slack 也会偏离真实硅片行为。本节围绕四个核心命令,说明如何从零构建一个可用于签核的时钟模型。
一、create_clock:定义时钟源与波形
create_clock 定义的是时钟的“源头”,即时钟进入设计边界或内部根节点时的理想波形。它描述周期、占空比、边沿位置,是后续所有时钟约束的起点。典型写法如下:
create_clock -name CLK -period 2.0 -waveform {0.0 1.0} [get_ports clk_in]
create_clock -name CLK_CORE -period 1.25 -waveform {0.0 0.625} [get_pins pll/CLKOUT]
这里 -period 是周期(ns),-waveform 给出上升沿和下降沿时刻。若省略 -waveform,默认上升沿在 0、下降沿在周期一半处。签核时要注意三点:一是时钟名要唯一且可读,便于后续引用;二是周期必须与设计规格一致,不能凭经验“留余量”;三是源点选择要正确——端口、PLL 输出 pin 或内部根节点,取决于时钟实际进入设计的位置。
对于多时钟域,每个时钟都要单独定义,并明确它们之间的相位关系。如果两个时钟来自同一源但经过不同分频,应使用 create_generated_clock 而不是再写一个 create_clock,否则 PrimeTime 会认为它们异步,导致跨域路径被错误地忽略或过度约束。
二、create_generated_clock:派生时钟的建模
分频器、倍频器、时钟门控、多路选择器输出的时钟,都属于“派生时钟”。它们与源时钟有确定的相位和频率关系,必须用 create_generated_clock 描述,才能让 PrimeTime 正确推导边沿和跨时钟检查。
create_generated_clock -name CLK_DIV2 -source [get_pins pll/CLKOUT] \
-divide_by 2 [get_pins div2/Q]
create_generated_clock -name CLK_GATED -source [get_pins clk_gen/CK] \
-combinational [get_pins gating_cell/Y]
-source 指向源时钟的根节点,-divide_by、-multiply_by 描述频率变换,-combinational 用于门控或组合逻辑产生的时钟。签核时最容易出错的是源点选错:如果 -source 指向了错误节点,派生时钟的相位会整体偏移,导致 setup/hold 同时恶化。另一个常见问题是门控时钟未加 -combinational,PrimeTime 会把它当成独立时钟,跨域路径被误判为异步。
三、set_clock_uncertainty:抖动与余量的统一表达
set_clock_uncertainty 把时钟抖动、PLL 相位误差、以及签核预留的余量合并成一个值,在 setup 和 hold 检查中分别扣除。它不改变时钟波形,只影响检查的严格程度。
set_clock_uncertainty -setup 0.08 [get_clocks CLK_CORE]
set_clock_uncertainty -hold 0.05 [get_clocks CLK_CORE]
set_clock_uncertainty -setup 0.10 -from [get_clocks CLK_CORE] -to [get_clocks CLK_DIV2]
签核时通常按“抖动 + 余量”拆分:例如 PLL 抖动 40ps、片上噪声 20ps、签核余量 20ps,setup uncertainty 取 80ps。hold 侧一般只取抖动和少量余量,因为 hold 检查对时钟边沿的敏感度不同。跨时钟域要单独设置,不能简单沿用单时钟值。注意 uncertainty 是“扣减”而非“加严”,值越大越保守,但过大会掩盖真实问题,导致过度修复。
四、set_clock_latency:从理想波形到实际到达时间
理想时钟假设边沿瞬间到达所有寄存器。真实时钟经过时钟树后会有延迟和偏斜,set_clock_latency 就是用来描述这个延迟的。它分两类:
- source latency:时钟从源点到设计时钟定义点的延迟,例如 PLL 到芯片端口、板级走线。
- network latency:时钟从定义点到寄存器时钟 pin 的延迟,即片上时钟树延迟。
set_clock_latency -source 0.35 [get_clocks CLK_CORE]
set_clock_latency 0.60 [get_clocks CLK_CORE]
set_clock_latency -late 0.75 [get_clocks CLK_CORE]
set_clock_latency -early 0.45 [get_clocks CLK_CORE]
在 CTS 之前,network latency 用估计值;CTS 之后,PrimeTime 会从时钟树提取实际延迟,此时应改用 set_propagated_clock,让工具自动传播,而不是继续手写 latency。签核阶段要区分 -early 和 -late:hold 检查用 early,setup 检查用 late,两者之差就是时钟偏斜的建模来源。如果只写一个值,工具会同时用于两侧,可能低估偏斜风险。
五、构建签核级时钟模型的顺序与检查
四个命令不是孤立的,签核时应按固定顺序建立模型,避免相互覆盖或遗漏。推荐流程是:先 create_clock 定义所有根时钟,再用 create_generated_clock 派生分频、门控时钟,然后设置 set_clock_latency 描述源延迟和网络延迟,最后用 set_clock_uncertainty 加入抖动和余量。CTS 完成后,把 network latency 切换为 set_propagated_clock,让工具从时钟树提取真实延迟。
检查模型是否合理,可以从三个角度入手。第一,用 report_clocks 确认每个时钟的周期、波形、源点和派生关系是否正确,特别检查是否有未定义的时钟或重复定义。第二,用 report_clock_timing -type latency 查看源延迟和网络延迟的分布,确认 early/late 值是否与时钟树预估一致。第三,跑一次 report_timing,观察 setup 和 hold 的 slack 是否在合理范围;如果某个时钟域 slack 异常好或异常差,往往说明 uncertainty 或 latency 设置有问题。
create_clock 定义派生时钟导致跨域检查丢失;门控时钟忘记加 -combinational;CTS 后仍使用手写 network latency 而未切换 set_propagated_clock;setup 和 hold 共用同一个 uncertainty 值。这些都会让签核结果偏离真实情况。
把四个命令按顺序落实,并用报告交叉验证,就能得到一个可签核、可复现、可追溯的时钟模型。后续的时序检查、跨域分析、OCV 设置,都建立在这个模型之上。