4. 时序约束入门:时钟定义、输入延迟、输出延迟、时序例外
时序约束,说白了就是给芯片设计定规矩。你告诉工具:信号什么时候来,什么时候走,哪些路径可以慢一点。没有约束,综合工具就像没头苍蝇,做出来的网表可能根本跑不起来。
我个人习惯,写RTL之前先把约束框架搭好。别等到代码写完了再补,那时候发现问题就晚了。好,咱们直接进入正题。
4.1 时钟定义——设计的“心跳”
时钟是时序逻辑的基准。没有时钟,寄存器就不知道什么时候采样数据。定义时钟,是约束的第一步。
最基本的时钟用 create_clock 命令。举个例子:
create_clock -name clk_sys -period 10 [get_ports clk]
这条命令告诉工具:端口 clk 上有一个时钟,周期10ns,也就是100MHz。嗯,这里要注意,周期单位默认是纳秒。
如果时钟来自PLL或者内部逻辑,用 create_generated_clock:
create_generated_clock -name clk_div2 -source [get_ports clk] -divide_by 2 [get_pins u_pll/clk_out]
我在项目中遇到过,有人忘了定义生成时钟,结果工具把分频后的路径当异步路径分析,时序报告全是乱的。所以,每个时钟节点都要明确告诉工具。
- 主时钟用
create_clock,生成时钟用create_generated_clock - 时钟名要规范,别用默认的
clk这种名字,容易混淆 - 虚拟时钟(
-name不带[get_ports])用于输入输出延迟约束
4.2 输入延迟——数据从片外来
数据从外部芯片进来,经过PCB走线,到达你的芯片引脚。这个过程中,数据相对于时钟有延迟。你需要告诉工具这个延迟范围。
输入延迟用 set_input_delay 定义:
set_input_delay -clock clk_sys -max 2.5 [get_ports data_in]
set_input_delay -clock clk_sys -min 1.0 [get_ports data_in]
这里 -max 是最大延迟,-min 是最小延迟。为什么要有两个值?因为外部芯片的时序有波动,温度、电压都会影响。
我曾经踩过一个坑:只设了最大延迟,没设最小延迟。结果工具认为数据可以提前很多到达,hold检查全过,但实际芯片就是跑不稳。后来加上最小延迟,问题才解决。
t_co(时钟到输出延迟)加上PCB走线延迟,就是你的输入延迟。
4.3 输出延迟——数据要去片外
输出延迟和输入延迟是对称的。你的芯片输出数据,外部芯片要在时钟沿附近采样。你需要告诉工具,外部芯片的建立时间和保持时间要求。
命令是 set_output_delay:
set_output_delay -clock clk_sys -max 3.0 [get_ports data_out]
set_output_delay -clock clk_sys -min 0.5 [get_ports data_out]
你想想看,输出延迟的本质是什么?是外部芯片的建立时间加上PCB走线延迟。所以,-max 对应外部建立时间,-min 对应外部保持时间。
我个人习惯,输出延迟留一点余量。比如外部芯片要求建立时间2ns,我设2.5ns。这样即使PCB走线有点偏差,也能兜住。
-clock_fall 选项。
4.4 时序例外——打破常规
不是所有路径都需要严格的时序检查。有些路径天生就慢,有些路径根本不需要检查。这时候就要用时序例外。
4.4.1 False Path(伪路径)
False path,就是不需要检查的路径。比如跨时钟域的同步器路径,或者测试模式下的路径。
set_false_path -from [get_clocks clk_a] -to [get_clocks clk_b]
这条命令告诉工具:从 clk_a 到 clk_b 的所有路径,都不用检查时序。
我记得有一次,一个同事把异步FIFO的跨时钟路径设成了false path。结果工具没检查,但实际电路因为格雷码同步延迟太大,偶尔丢数据。所以,false path要慎用。只有确定数据不会影响功能,才设false path。
- 异步复位信号
- 测试模式(scan_enable)路径
- 跨时钟域的同步器(但要注意,同步器本身要检查)
- 上电初始化阶段的信号
4.4.2 Multicycle Path(多周期路径)
有些路径不需要在一个时钟周期内完成。比如,一个使能信号每4个周期才有效一次,那这条路径就可以放宽到4个周期。
set_multicycle_path -setup 4 -from [get_pins u_reg_a/Q] -to [get_pins u_reg_b/D]
set_multicycle_path -hold 3 -from [get_pins u_reg_a/Q] -to [get_pins u_reg_b/D]
这里 -setup 4 表示建立时间检查放宽到4个周期。-hold 3 是保持时间检查的偏移量。为什么hold要设3?因为默认hold检查是在setup检查的前一个沿,设了多周期后,hold也要跟着调整。
我在项目中遇到过,有人只设了 -setup 没设 -hold,结果hold检查还是按单周期来,导致大量hold违例。所以,多周期路径一定要成对出现。
4.5 知识体系总览
下面这张图,把时序约束的核心逻辑串起来了。你看一遍,心里就有谱了。
这张图把四个核心知识点串起来了。时钟是基础,输入输出延迟是接口约束,时序例外是特殊处理。你写约束的时候,按这个顺序来,基本不会漏。
好了,时序约束入门就讲到这里。记住,约束不是写一次就完事的。综合后要看时序报告,发现问题就回来调。多调几次,你就有感觉了。
- 时钟定义:create_clock 和 create_generated_clock 是基础
- 输入延迟:set_input_delay 要设 max 和 min
- 输出延迟:set_output_delay 对应外部芯片的建立/保持时间
- False path:只用于真正不需要检查的路径
- Multicycle path:setup 和 hold 要成对设置
可可精品资料库