2. 时序分析基础与Vivado报告解读

时序收敛的第一步不是改约束,而是能读懂工具给出的时序报告。Vivado 的 report_timing_summary 把建立时间(Setup)、保持时间(Hold)、脉冲宽度(Pulse Width)三类检查汇总在一张表里,但真正决定“能不能收敛”的信息,往往藏在 WNS、TNS、WHS、THS 这几个字段以及它们背后的路径细节中。本节先建立时序分析的基本概念,再逐字段拆解报告,最后给出一个可复用的解读流程。

建立时间与保持时间:两个方向相反的约束

建立时间要求数据在时钟有效沿到来之前已经稳定一段时间。以触发器为例,若时钟上升沿在 t=10ns 到达,数据必须在 10ns − tsu 之前就稳定,其中 tsu 是器件固有的建立时间。保持时间则相反,要求数据在时钟沿之后继续保持稳定至少 th,防止新数据过早冲入。两者共同定义了数据到达窗口:数据到达时间必须落在 [时钟沿 + th, 下一个时钟沿 − tsu] 之内。

在 Vivado 中,建立检查的裕量(Slack)计算为:

Setup Slack = (要求时间 Required Time) − (到达时间 Arrival Time)
            = (捕获沿时刻 + 时钟路径延迟 − t_su − 不确定性)
              − (发射沿时刻 + 时钟路径延迟 + 数据路径延迟)

保持检查的裕量方向相反:

Hold Slack = (到达时间 Arrival Time) − (要求时间 Required Time)
           = (发射沿时刻 + 时钟路径延迟 + 数据路径延迟)
             − (捕获沿时刻 + 时钟路径延迟 + t_h + 不确定性)

Slack 为正表示满足,为负表示违例。注意建立与保持的“到达/要求”定义是互换的,这是初学者最容易混淆的地方。

时钟偏斜、抖动与不确定性

时钟偏斜(Skew)是同一时钟到达两个触发器时钟端的延迟差。若发射触发器时钟比捕获触发器早到 Δt,则建立裕量减少 Δt,保持裕量增加 Δt。偏斜本身不是错误,但会同时挤压建立和保持窗口。

抖动(Jitter)是时钟沿相对理想位置的随机偏移,通常用峰峰值或 RMS 描述。Vivado 把抖动、偏斜余量、时钟树延迟等统一折算为 Clock Uncertainty,在约束中通过 set_clock_uncertainty 指定。例如:

set_clock_uncertainty -setup 0.15 [get_clocks clk_pll]
set_clock_uncertainty -hold  0.08 [get_clocks clk_pll]

不确定性越大,可用裕量越小。工程上常把 PLL 输出抖动、板级时钟源抖动和时钟树偏斜余量合并估算,而不是逐项精确建模。

时序路径类型

Vivado 把路径分为四类:Setup(建立)、Hold(保持)、Recovery/Removal(异步复位恢复/移除)、Pulse Width(脉冲宽度)。其中 Setup 和 Hold 占绝大多数。路径的起点和终点可以是端口、触发器、RAM、DSP 等。跨时钟域路径若未做约束,会被归入 Timing Exception 或直接报为未约束路径,这是报告里最需要警惕的“假通过”。

建立/保持时间窗口与时钟不确定性示意 CLK 发射沿 捕获沿 数据稳定窗口 t_su t_h Uncertainty CLK' 时钟偏斜 Skew = 到达时间差 Setup Slack = (捕获沿 + 时钟延迟 − t_su − Uncertainty) − (发射沿 + 时钟延迟 + 数据延迟) Hold Slack = (发射沿 + 时钟延迟 + 数据延迟) − (捕获沿 + 时钟延迟 + t_h + Uncertainty) Slack ≥ 0 满足;Slack < 0 违例。建立与保持的到达/要求定义互换。

report_timing_summary 关键字段实战解读

执行 report_timing_summary -delay_type min_max -report_unconstrained -check_timing_verbose 后,报告开头是 Design Timing Summary 表。核心字段含义如下:

字段含义判读要点
WNS最差负裕量(Worst Negative Slack)所有建立路径中最差的一条;≥0 表示建立全部通过
TNS总负裕量(Total Negative Slack)所有违例路径裕量之和;反映违例规模
WHS最差保持裕量保持检查中最差的一条;≥0 表示保持全部通过
THS总保持裕量保持违例路径裕量之和
WPWS最差脉冲宽度裕量时钟高/低电平宽度是否满足最小要求
TNS Failing Endpoints违例终点数量定位需要修复的寄存器/端口数量

实战中先看 WNS 和 WHS 是否都为非负。若 WNS 为负而 WHS 为正,通常是组合逻辑过长或时钟频率过高;若 WHS 为负,则常见于数据路径过短、时钟偏斜过大或保持约束过紧。TNS 的绝对值越大,说明违例路径越多,修复优先级越高。

报告下半部分会列出每条违例路径的详细分解,包括:Source(起点)、Destination(终点)、Path Group(时钟组)、Path Type(Setup/Hold)、Requirement(要求时间)、Data Path Delay(数据路径延迟)、Logic Levels(逻辑级数)、Clock Path Skew(时钟偏斜)。其中 Logic Levels 和 Data Path Delay 是判断“是逻辑太深还是布线太长”的关键。

解读顺序建议:先确认 WNS/WHS 符号 → 再看违例终点数量 → 然后逐条打开最差路径 → 对比 Requirement 与 Data Path Delay 的差距 → 最后判断是逻辑级数问题、时钟问题还是约束问题。

一个可复用的解读示例

假设某设计在 100MHz 时钟下报告:WNS = −0.312ns,TNS = −1.845ns,WHS = 0.045ns,THS = 0.000ns,违例终点 7 个。这说明建立时间有 7 条路径违例,保持时间刚好通过。打开最差路径,看到 Data Path Delay = 10.42ns,Logic Levels = 14,Requirement = 10.00ns,Clock Path Skew = 0.18ns。计算可知:10.42 + 0.18 − 10.00 ≈ 0.60ns 的差距中,逻辑延迟占了主要部分。此时优先考虑插入流水线寄存器或优化组合逻辑,而不是先动时钟约束。

若同一设计 WHS = −0.02ns,则说明保持裕量不足。常见原因是数据路径过短(例如直连旁路)或时钟偏斜方向不利。可尝试增加数据路径延迟、调整时钟树约束,或在综合/实现策略中启用保持修复选项。注意保持违例通常不能靠降频解决,因为降频会同时放宽建立和保持的要求,但保持违例的根源往往在偏斜和短路径上。

常见误区:看到 WNS 为正就认为时序全部通过。若报告中存在未约束路径(Unconstrained Paths)或跨时钟域路径未做 set_false_path/set_clock_groups,这些路径不会计入 WNS,但实际硬件可能失效。务必用 report_unconstrained 和 check_timing 交叉验证。