4. 创建时钟(create_clock):语法详解、主时钟与虚拟时钟、时钟的波形定义

时钟,是时序分析的“心跳”。

没有时钟,STA 就无从谈起。我见过不少新手,上来就写约束,结果忘了定义时钟——工具直接报一堆“unconstrained path”。嗯,那场面挺尴尬的。

今天我们就来聊聊 create_clock 这个命令。它看似简单,但里面有不少门道。

4.1 语法详解:create_clock 到底怎么写?

先看最基础的语法:

create_clock -name <clock_name> -period <period_value> [ -waveform <edge_list> ] [ <source_objects> ]

我来拆解一下:

  • -name:给时钟起个名字。比如 clk_sys、clk_ddr。我个人习惯用“模块名_时钟用途”来命名,方便后期排查。
  • -period:时钟周期,单位是 ns。比如 10ns 对应 100MHz。
  • -waveform:定义时钟的上升沿和下降沿位置。默认是 0 和 period/2,也就是 50% 占空比。
  • source_objects:时钟加在哪个端口或网络上。可以是 get_ports clk 或 get_pins ...。

举个例子:

create_clock -name sys_clk -period 10.0 [get_ports clk_in]

这条命令的意思是:在端口 clk_in 上创建一个名为 sys_clk 的时钟,周期 10ns,默认占空比 50%(上升沿在 0ns,下降沿在 5ns)。

小提示: 如果你不指定 -waveform,工具会自动认为上升沿在 0,下降沿在 period/2。但如果你要定义非 50% 占空比的时钟,就必须手动写 waveform。

4.2 主时钟 vs 虚拟时钟:别搞混了

这两个概念,我当年也迷糊过一阵子。

主时钟(Master Clock):就是物理存在的时钟。它加在芯片的输入端口上,或者由 PLL 输出引脚产生。说白了,你能在示波器上看到它的波形。

虚拟时钟(Virtual Clock):它没有物理端口,也没有网络。它只存在于 STA 工具的“脑海”里。用来干什么?用来约束那些与外部接口相关的路径,比如 input delay 和 output delay。

为什么要用虚拟时钟?

你想想看,外部芯片送来的数据,是跟着它自己的时钟走的。这个时钟并不在你的芯片内部。所以你需要创建一个虚拟时钟,来模拟外部时钟的行为。

举个例子:

# 创建虚拟时钟,代表外部芯片的时钟
create_clock -name vclk -period 10.0

# 设置输入延迟,参考虚拟时钟
set_input_delay -clock vclk -max 5.0 [get_ports data_in]

这里 vclk 没有加在任何端口上,它就是虚拟的。

注意: 虚拟时钟不能作为内部寄存器的时钟源。它只用于约束 I/O 接口。我曾经见过有人把虚拟时钟当成主时钟用,结果内部路径全乱套了。

4.3 时钟的波形定义:不只是 50% 占空比

很多芯片内部用的时钟是 50% 占空比,但接口协议不一定。比如 DDR 接口,它的时钟是 50% 占空比,但数据选通信号(DQS)可能是 45%/55%。

这时候就需要手动定义 waveform。

语法是这样的:

create_clock -name ddr_clk -period 5.0 -waveform {0 2.5} [get_ports clk_ddr]

-waveform 后面跟的是上升沿和下降沿的时间点列表。格式是 {上升沿1 下降沿1 上升沿2 下降沿2 ...}。

默认情况下,一个周期内只有两个沿:上升沿在 0,下降沿在 period/2。但你可以定义多个沿,比如:

# 定义占空比为 40% 的时钟(上升沿在0,下降沿在4)
create_clock -name custom_clk -period 10.0 -waveform {0 4}

甚至你可以定义非单调的波形?不行。工具会检查波形是否合理。比如上升沿必须在下降沿之前,且所有沿必须在 0 到 period 之间。

核心要点:
  • waveform 列表中的时间点,是相对于 0 时刻的偏移。
  • 第一个时间点必须是上升沿。
  • 如果只给两个值,就是单脉冲波形。如果给四个值,就是双脉冲(比如 DDR 时钟)。

4.4 知识体系图:时钟创建的核心逻辑

下面这张图,是我自己总结的。它把 create_clock 的整个知识脉络串起来了。

create_clock 知识体系 create_clock 语法详解 主时钟 虚拟时钟 -name -period -waveform source_objects 物理端口/网络 PLL输出引脚 内部寄存器时钟 可被示波器观测 无物理端口/网络 用于I/O约束 模拟外部时钟 波形定义:-waveform {上升沿 下降沿 ...} 默认:{0 period/2} | 可自定义占空比

4.5 避坑指南:我踩过的那些坑

讲几个真实案例吧。

案例一:忘记加 -name

有一次我写约束,图省事没加 -name。结果工具自动用端口名作为时钟名。后来那个端口名改了,整个约束文件全废了。从那以后,我每个时钟都手动加 -name,哪怕只有一个时钟。

案例二:虚拟时钟和主时钟重名

虚拟时钟的名字不能和主时钟重复。我见过有人把虚拟时钟也叫 sys_clk,结果工具报错说“时钟已存在”。嗯,改个名字就好了。

案例三:waveform 写反了

我曾经把 -waveform {5 0} 写成了 {0 5} 的反向。工具没报错,但时序分析结果完全不对。因为上升沿和下降沿的顺序反了,工具认为时钟是负脉冲。检查了半天才发现。

避坑总结:
  • 始终使用 -name 显式命名时钟。
  • 虚拟时钟和主时钟不要重名。
  • waveform 的第一个值必须是上升沿,第二个是下降沿。
  • 创建完时钟后,用 report_clocks 检查一下波形是否正确。

4.6 实战小练习

给你留个思考题:

假设你有一个输入端口 clk_50m,频率 50MHz,占空比 60%。请写出对应的 create_clock 命令。

答案:

create_clock -name clk_50m -period 20.0 -waveform {0 12} [get_ports clk_50m]

50MHz 对应周期 20ns。60% 占空比意味着高电平占 12ns,低电平占 8ns。所以上升沿在 0,下降沿在 12。

嗯,就是这么简单。但细节决定成败。


可可精品资料库