3、时序约束入门:什么是SDC?创建时钟、设置输入延迟、设置输出延迟
时序约束,说白了就是告诉工具你的芯片要在什么条件下工作。没有约束,综合工具就像蒙着眼睛走路——它不知道你的时钟多快,不知道数据从外面进来花了多久,也不知道输出要给下游留多少时间。
我刚开始做数字设计时,觉得约束就是随便写几条时钟,跑通就行。结果第一次流片回来,芯片在低温下死活跑不到目标频率……嗯,从那以后我再也不敢轻视SDC了。
3.1 SDC是什么?
SDC全称是Synopsys Design Constraints,是工业界最通用的时序约束格式。几乎所有主流EDA工具——Synopsys的DC、PT,Cadence的Genus、Tempus——都支持SDC。
说白了,SDC就是一份给工具的“说明书”。它告诉工具:
- 时钟长什么样(周期、波形、抖动)
- 数据从外部进来花了多少时间
- 数据输出到外部需要留多少时间
- 哪些路径是假的(false path),不需要分析
- 哪些路径有多周期关系(multicycle path)
核心原则:没有约束就没有分析。工具默认认为所有路径都是单周期路径,且输入输出延迟为零——这在实际芯片中根本不存在。
我个人习惯把SDC分成三类:
| 类别 | 命令 | 作用 |
|---|---|---|
| 时钟约束 | create_clock, create_generated_clock |
定义时钟源和衍生时钟 |
| 输入约束 | set_input_delay |
描述外部到芯片输入端的延迟 |
| 输出约束 | set_output_delay |
描述芯片输出端到外部的延迟 |
3.2 创建时钟——一切约束的起点
时钟是时序分析的基准。没有时钟,STA根本不知道拿什么去衡量路径延迟。
最基本的时钟约束长这样:
create_clock -name clk -period 10.0 [get_ports clk_in]
这条命令的意思是:在端口clk_in上创建一个名为clk的时钟,周期10ns(对应100MHz)。
你想想看,工具拿到这个约束后,就知道所有以clk为时钟的寄存器,数据必须在10ns内从上一个寄存器传到下一个寄存器。
实际项目中,时钟往往没那么简单。比如:
- 波形定义:默认占空比50%,但有些时钟不是。可以用
-waveform {0 5}指定上升沿在0ns,下降沿在5ns。 - 时钟抖动:用
set_clock_uncertainty加上抖动值。我一般给50ps~100ps,具体看PLL规格。 - 衍生时钟:分频、倍频、门控时钟都要用
create_generated_clock定义。
小技巧:我习惯在创建时钟后立即加一条set_clock_uncertainty -setup 0.1 [get_clocks clk]。这0.1ns的余量,帮我挡过好几次PVT corner下的时序违例。
3.3 设置输入延迟——告诉工具数据从哪来
芯片不是孤岛。数据从外部芯片(比如上一级FPGA或SoC)进来,经过PCB走线,再到你的芯片输入引脚。这段路径上的延迟,就是输入延迟。
命令格式:
set_input_delay -clock clk -max 2.5 [get_ports data_in]
这条命令告诉工具:数据data_in相对于时钟clk的上升沿,最大延迟是2.5ns。
为什么会分-max和-min?
- -max:用于建立时间(setup)分析,数据最晚到达的情况
- -min:用于保持时间(hold)分析,数据最早到达的情况
我在项目中遇到过一个问题:只设了-max没设-min,结果工具默认-min为0。实际PCB走线有延迟,hold分析过于乐观,流片回来发现采样出错……
避坑指南:我曾经吃过一次亏——输入延迟的参考时钟必须是芯片内部时钟,而不是外部时钟。如果你用外部时钟做参考,记得先创建内部时钟,再用set_input_delay引用它。
3.4 设置输出延迟——告诉工具数据去哪
输出延迟和输入延迟是对称的。它描述的是:数据从芯片输出引脚,经过PCB走线,到下游芯片的输入引脚,这段路径上的延迟。
命令格式:
set_output_delay -clock clk -max 4.0 [get_ports data_out]
这条命令告诉工具:数据data_out必须在时钟上升沿之前4.0ns就准备好,否则下游芯片来不及采样。
你想想看,输出延迟越大,留给芯片内部路径的时间就越少。所以:
- 输出延迟设得太大 → 内部路径难收敛,setup容易违例
- 输出延迟设得太小 → 下游芯片可能采不到数据
我个人习惯的做法是:先和板级工程师沟通,拿到PCB走线延迟和下游芯片的建立/保持时间,然后算出合理的输出延迟值。
| 参数 | 输入延迟 | 输出延迟 |
|---|---|---|
| 参考时钟 | 芯片内部时钟 | 芯片内部时钟 |
| -max 含义 | 外部数据最晚到达 | 内部数据必须最早准备好 |
| -min 含义 | 外部数据最早到达 | 内部数据必须最晚准备好 |
| 影响 | 影响芯片内部setup/hold | 影响芯片内部setup/hold |
3.5 知识体系总览
下面这张图把SDC的核心脉络画出来了。你可以看到,时钟是根,输入输出延迟是枝叶,它们共同构成了时序分析的完整框架。
3.6 实战建议
写SDC不是一次性的事。我通常的做法是:
- 先写时钟:把所有时钟、衍生时钟、时钟分组写清楚。这是基础,错了后面全白搭。
- 再写IO延迟:根据芯片规格书和板级设计,逐条加上输入输出延迟。
- 跑一次STA:看看有没有unconstrained path(未约束路径)。如果有,说明漏了约束。
- 迭代优化:根据STA报告调整约束值,直到所有路径都收敛。
个人习惯:我会在SDC文件开头加一段注释,写明芯片名称、版本、时钟频率、IO接口类型。半年后回头看,这些注释能帮你省下大量时间。