2. Quartus时序分析基础
在Quartus Prime的时序收敛流程中,TimeQuest Timing Analyzer(简称TimeQuest)是唯一被官方推荐的静态时序分析引擎。它不依赖仿真激励,而是通过读取综合与布局布线后的网表、延迟模型以及SDC约束,穷举所有时序路径并给出裕量(Slack)报告。理解TimeQuest的核心概念,是后续编写约束、定位违例、迭代收敛的前提。
建立时间与保持时间:时序检查的两把尺子
建立时间(Setup Time,tsu)指时钟有效沿到来之前,数据必须保持稳定的最短时间;保持时间(Hold Time,th)指时钟有效沿到来之后,数据仍需保持稳定的最短时间。二者共同定义了触发器对数据窗口的要求。TimeQuest对每条寄存器到寄存器的路径同时做这两项检查:
- 建立检查:要求数据到达时间(Data Arrival)早于数据需求时间(Data Required)。裕量 Slack = Required − Arrival,Slack ≥ 0 表示满足。
- 保持检查:要求数据在时钟沿后保持足够久,裕量 Slack = Arrival − Required,同样要求 ≥ 0。
以一条典型路径为例:源寄存器在 100 MHz 时钟(周期 10 ns)下发送数据,经过组合逻辑延迟 4.2 ns,目的寄存器 tsu = 0.35 ns、th = 0.12 ns,时钟偏斜为 +0.25 ns。建立检查中,数据需求时间为 10 − 0.35 + 0.25 = 9.90 ns,到达时间为 4.2 ns,建立裕量约 5.70 ns;保持检查中,到达时间 4.2 ns 远大于需求时间 0.12 + 0.25 = 0.37 ns,保持裕量约 3.83 ns。上述数值为教学示例,实际值由器件模型与布局布线决定。
时钟不确定性、偏斜与抖动
理想时钟是同时到达所有寄存器的完美方波,但真实时钟存在三类偏差,TimeQuest将它们统一纳入分析:
- 时钟偏斜(Clock Skew):同一时钟到达不同寄存器时钟端的延迟差。偏斜会同时影响建立与保持裕量,方向相反。
- 时钟抖动(Clock Jitter):时钟周期或边沿位置的随机波动,通常用峰峰值或RMS表示。抖动直接压缩可用时序窗口。
- 时钟不确定性(Clock Uncertainty):在SDC中通过
set_clock_uncertainty声明,用于覆盖抖动、PLL相位误差、板上时钟源偏差等无法精确建模的余量。
三者关系可概括为:偏斜是确定性的空间差异,抖动是随机性的时间波动,不确定性是工程师主动预留的保守量。TimeQuest在计算需求时间时会扣除不确定性,因此约束值设置过大会直接导致虚假违例。
SDC约束的基本语法
SDC(Synopsys Design Constraints)是TimeQuest的输入语言,本质是一组Tcl命令。Quartus工程中通常创建 .sdc 文件,并在编译流程中由TimeQuest读取。最核心的约束包括时钟定义、输入输出延迟、时钟不确定性、多周期与伪路径。
# 1. 定义主时钟,周期10ns,占空比50%
create_clock -name clk_sys -period 10.000 [get_ports {clk}]
# 2. 定义PLL输出时钟(示例:100MHz)
create_generated_clock -name clk_core -source [get_pins {pll_inst|inclk[0]}] \
-divide_by 1 -multiply_by 2 [get_pins {pll_inst|clk[0]}]
# 3. 输入延迟:数据相对时钟沿提前2ns到达
set_input_delay -clock clk_sys -max 2.000 [get_ports {data_in[*]}]
set_input_delay -clock clk_sys -min 0.500 [get_ports {data_in[*]}]
# 4. 输出延迟
set_output_delay -clock clk_sys -max 3.000 [get_ports {data_out[*]}]
# 5. 时钟不确定性:预留0.15ns给抖动与PLL误差
set_clock_uncertainty -setup 0.150 [get_clocks clk_sys]
set_clock_uncertainty -hold 0.100 [get_clocks clk_sys]
# 6. 伪路径:跨时钟域异步路径不做时序检查
set_false_path -from [get_clocks clk_sys] -to [get_clocks clk_aux]
# 7. 多周期路径:组合逻辑较深,允许2个周期
set_multicycle_path -setup 2 -from [get_clocks clk_sys] -to [get_clocks clk_sys]
语法要点:get_ports、get_pins、get_clocks 是对象查询命令,返回集合;-max 与 -min 分别对应建立与保持分析;-setup 与 -hold 用于区分不确定性类型。约束文件中的时间单位默认与Quartus工程设置一致,通常为纳秒。
report_clocks 与 report_sdc,确认时钟与约束被正确识别,再运行 report_timing 查看路径裕量。若出现“No clocks defined”警告,说明SDC未被读取或时钟名不匹配。从约束到报告:一次完整的检查闭环
实际工程中,推荐按以下顺序推进:首先用 create_clock 定义所有输入时钟,用 create_generated_clock 描述PLL与分频器输出;其次用 set_input_delay / set_output_delay 约束器件边界;然后设置合理的 set_clock_uncertainty,一般先取时钟周期的3%~5%作为初始值;最后对异步跨时钟域路径使用 set_false_path,对慢速逻辑使用 set_multicycle_path。完成约束后,在TimeQuest中依次执行 update_timing_netlist、report_timing -setup、report_timing -hold,观察最差路径的Slack值。若建立裕量为负,优先检查组合逻辑级数与时钟频率;若保持裕量为负,通常需要插入缓冲或调整布局,而非简单降低频率。
set_false_path 掩盖真实的同步路径违例。伪路径仅适用于异步跨时钟域或上电后不再变化的配置信号,滥用会导致时序问题被隐藏到板级调试阶段。