跳转到内容
新建笔记

XDC 约束与时序收敛

目标:把真实系统翻译成 STA 模型

跳转到“目标:把真实系统翻译成 STA 模型”

XDC 不是为了“消除红色数字”,而是向 Vivado 描述真实硬件环境:

  1. 时钟从哪里来,周期、波形、相位和抖动是什么。
  2. FPGA 外部器件何时发出数据,何时采样数据。
  3. 哪些路径必须在一个周期内完成,哪些路径确实有特殊协议。
  4. 顶层端口连接到哪个封装引脚,使用什么电气标准。
flowchart LR
A["原理图与器件手册"] --> B["时钟 / 接口时序模型"]
B --> C["XDC"]
C --> D["对象命中与覆盖检查"]
D --> E["STA 报告"]
E --> F["修改 RTL / 约束 / 物理实现"]
F --> D

一份合格的 XDC 必须同时满足三件事:数值有物理来源、命令命中正确对象、报告证明没有漏约束或误切路径。

典型寄存器到寄存器路径:

launch clock -> source register -> combinational path -> destination register <- capture clock
检查直观问题Slack
Setup / max delay新数据能否在目标采样边沿前稳定required time - arrival time
Hold / min delay旧数据能否在目标采样边沿后保持足够久arrival time - required time

Slack 大于等于 0 表示该项通过。Vivado 还会分析 input-to-register、register-to-output、input-to-output、异步控制恢复/移除和时钟脉宽等路径。

约束不能修复功能错误。异步输入没有同步器、握手协议错误、总线撕裂或复位释放不可靠时,即使时序报告全绿,设计仍可能失败。

字段示例来源
名称sys_clk工程命名
物理来源板载 100 MHz 晶振原理图
FPGA 端口/引脚sys_clk / E3顶层 RTL、原理图
周期与占空比10 ns / 50%振荡器手册
抖动0.08 ns振荡器、PLL 手册
衍生关系MMCM 输出 200 MHzClocking Wizard 配置
与其他时钟关系同源、异步或互斥系统架构
字段输入接口示例输出接口示例
数据端口adc_data[7:0]dac_data[7:0]
参考时钟ADC 转发 adc_dcoFPGA 转发 dac_clk
采样边沿双边沿上升沿
外部参数tCO(min/max)tSU、tH
数据走线min/max 延迟min/max 延迟
时钟走线min/max 延迟min/max 延迟
电压与引脚Bank、VCCO、IOSTANDARD、PACKAGE_PIN同左

没有这两张表时,不要凭经验填写 set_input_delay、set_output_delay 或时序例外。

接口类型典型例子时钟模型主要约束
单一板载时钟驱动内部逻辑MCU/控制 FPGA端口上的 primary clockcreate_clock
System-synchronousFPGA 与外设共享板级参考时钟物理时钟 + 同波形 virtual clockinput/output delay
Source-synchronous 输入ADC DCO、RGMII RX数据随外部转发时钟进入端口 clock + input delay,DDR 时双边沿
Source-synchronous 输出DAC、RGMII TXFPGA 输出数据和转发时钟generated forwarded clock + output delay
完全异步控制按键、中断、UART RX与内部时钟无固定相位CDC 结构 + 精确例外
异步多位数据双时钟 FIFO、Gray pointer两个独立时钟域CDC/FIFO + 必要的 max delay/bus skew
多工作模式调试/运行时钟 MUX每个模式的真实时钟exclusive clock group 或逐模式 case analysis

小型工程可以使用一个 top.xdc。大型工程按职责拆分:

constraints/
00_clocks.xdc # 主时钟、虚拟时钟、生成时钟、抖动
10_io_timing.xdc # input/output delay
20_exceptions.xdc # CDC、false path、multicycle、max delay
30_io_physical.xdc # 引脚、电气标准、DRIVE、SLEW

约束按顺序解释,引用时钟前必须先创建时钟。Non-Project Mode 应显式按顺序 read_xdc;Project Mode 应检查 Constraints Sources 的处理顺序。不要仅依赖文件名排序。

每个 XDC 文件只约束一个明确边界。板卡固定引脚可单独维护,IP 自带 XDC 不要复制到顶层后再重复约束。

第一原则:先保证对象匹配正确

跳转到“第一原则:先保证对象匹配正确”

Vivado XDC 使用 Tcl 对象集合,不是简单字符串。.xdc 采用受限的 Tcl/SDC 命令集,不支持把任意 Tcl 程序都写进去;例如 Vivado 2020.2 会拒绝 XDC 内的自定义 proc。复杂检查应放到综合后执行的独立 .tcl 脚本。

查询对象范围常见用途
get_ports顶层端口时钟输入、I/O delay、封装引脚
get_pins实例引脚生成时钟源、寄存器 D/C 引脚
get_cells层次实例/综合网表单元同步器、特定寄存器组
get_nets网表连线少数物理或调试场景
get_clocks已创建/自动推导的时钟I/O delay、时钟组、报告

在 Tcl Console 或综合后验证脚本中,可先观察匹配结果。总线和通配模式必须用大括号保护,避免 [] 被 Tcl 当作命令替换:

set adc_data [get_ports -quiet {adc_data[*]}]
set sync_ff1 [get_cells -quiet -hier -filter {NAME =~ */sync_ff1_reg[*]}]

还要区分层级搜索与完整路径:get_cells -hierarchical 在逐层搜索时对每一级的名称匹配,普通 pattern 不应再带 u_slow/ 这样的层级前缀。已知相对于当前实例的完整路径时,使用 get_cells {u_slow/src_reg[*]};需要跨层筛选时,用 -hierarchical -filter {NAME =~ ...} 或经核对的 -regexp。get_pins 的层级匹配同样须按命令规则处理。下面带完整实例路径的例子假定 current_instance 为顶层,不再混用 -hier。见 Vivado 2020.2 get_cells。

不要在正式 XDC 中普遍使用 -quiet,否则空集合更难发现。关键对象应在综合后的验证 Tcl 中主动检查:

proc require_objects {label objects} {
if {[llength $objects] == 0} {
error "XDC: no objects matched for $label"
}
return $objects
}
set sys_clk_port [require_objects sys_clk [get_ports -quiet sys_clk]]
set adc_data [require_objects adc_data [get_ports -quiet {adc_data[*]}]]

运行方式:先 synth_design 或 open_run synth_1,再 source scripts/validate_constraints.tcl。XDC 本身保持为直接约束命令;构建脚本应把 Critical Warning、验证脚本异常和约束报告失败视为构建失败。

顶层端口名通常稳定;综合后的寄存器名可能因优化改变。对内部对象施加例外时,应保持清晰层次、给同步器加 ASYNC_REG 属性,并在每次综合后用 get_* 和 report_exceptions 复核命中范围。

主时钟:定义真实入口

跳转到“主时钟:定义真实入口”

100 MHz、50% 占空比:

create_clock -name sys_clk -period 10.000 [get_ports sys_clk]

125 MHz、非 50% 波形,第一上升沿为 0 ns、下降沿为 3 ns:

create_clock -name eth_clk -period 8.000 -waveform {0.000 3.000} \
[get_ports eth_clk]
  • 周期和波形单位默认是 ns。
  • create_clock 应放在时钟进入 FPGA 的根端口或合法根引脚。
  • 不要为了“让报告有时钟”在普通数据网上随意 create_clock。
  • 不要用更宽松的周期掩盖设计达不到目标频率的事实。
set_input_jitter [get_clocks sys_clk] 0.080
set_clock_uncertainty -setup 0.100 [get_clocks sys_clk]

set_input_jitter 描述输入时钟源的随机/周期抖动。set_clock_uncertainty 是额外的不确定性预算;不要重复计算工具已传播的抖动,也不要把它当作随意“加保险”的数字。

虚拟时钟:描述 FPGA 外部参考

跳转到“虚拟时钟:描述 FPGA 外部参考”

虚拟时钟没有连接到设计端口,适合作为外部器件 I/O 时序的参考:

create_clock -name ext_sys_clk -period 10.000

系统同步接口中,板级同一个时钟源可能分别送到 FPGA 和外部器件。物理 sys_clk 驱动 FPGA 内部逻辑,虚拟 ext_sys_clk 表示外部器件边界。二者的周期、波形和相位必须来自同一个真实关系。

虚拟时钟不是“异步时钟”的同义词。不要把它放进异步时钟组,除非外部参考与 FPGA 时钟确实无固定关系。

生成时钟:保留来源和相位关系

跳转到“生成时钟:保留来源和相位关系”

Vivado 通常能从 MMCM、PLL、BUFR 等专用资源自动推导输出时钟。先查看报告,再决定是否补充或重命名:

report_clocks
report_clock_networks

普通分频逻辑或工具无法自动推导的时钟,用 create_generated_clock:

create_generated_clock -name clk_div2 \
-source [get_ports sys_clk] \
-divide_by 2 \
[get_pins u_clk_div/clk_div_reg/Q]

-source 是主时钟经过的源端口/引脚,最后一个对象是生成时钟实际出现的位置。复杂相位关系可用 -edges、-edge_shift、-invert;一个源上存在多个主时钟时需要 -master_clock 和 -add。

不要在分频输出上另建无关的 create_clock。那样会丢失父时钟插入延迟和抖动传播,工具也无法正确分析跨时钟路径。

I/O delay:把板外路径放进时序分析

跳转到“I/O delay:把板外路径放进时序分析”

set_input_delay 描述数据到达 FPGA 输入端口的时间,相对于指定参考时钟边沿。set_output_delay 描述 FPGA 输出必须为外部接收器预留的时间。

定义:

符号含义
tCO_min/max外部发送器从时钟边沿到数据输出的最小/最大延迟
tSU、tH外部接收器的 setup/hold 要求
Ddata_min/max数据在选定板级参考点之间的最小/最大延迟
Dclk_min/max参考时钟在同一组参考点之间的最小/最大延迟
Smin/max数据相对参考时钟的板级 skew:Ddata - Dclk

先保证 data path 和 clock path 使用相同起点/终点,再计算最坏相对 skew:

Smax = Ddata_max - Dclk_min
Smin = Ddata_min - Dclk_max

在时钟和数据使用兼容采样边沿的前提下:

约束计算式
input -maxtCO_max + Smax
input -mintCO_min + Smin
output -maxtSU + Smax
output -min-tH + Smin

-min 可以为负数,这是时钟/数据相对关系的正常结果,不应强行改成 0。

示例计算:

# 外部发送器:tCO=0.6..2.4 ns
# 数据走线:0.35..0.55 ns;时钟走线:0.25..0.40 ns
# input_max = 2.4 + 0.55 - 0.25 = 2.70 ns
# input_min = 0.6 + 0.35 - 0.40 = 0.55 ns
set_input_delay -clock [get_clocks ext_sys_clk] -max 2.700 \
[get_ports {rx_data[*]}]
set_input_delay -clock [get_clocks ext_sys_clk] -min 0.550 \
[get_ports {rx_data[*]}]
# 外部接收器:tSU=1.8 ns,tH=0.4 ns
# 数据走线:0.30..0.50 ns;时钟走线:0.20..0.35 ns
# output_max = 1.8 + 0.50 - 0.20 = 2.10 ns
# output_min = -0.4 + 0.30 - 0.35 = -0.45 ns
set_output_delay -clock [get_clocks ext_sys_clk] -max 2.100 \
[get_ports {tx_data[*]}]
set_output_delay -clock [get_clocks ext_sys_clk] -min -0.450 \
[get_ports {tx_data[*]}]

这些公式假设参考点和边沿定义一致。Source-synchronous 接口通常从发送器引脚量到接收器引脚;共同振荡器分叉的 system-synchronous 接口必须把两个时钟分支的相对延迟都纳入 Smin/Smax。若器件在相反边沿采样、时钟经过移相或接口规范直接给出窗口,应按真实时序图重新推导,不能只套公式。

外部器件把时钟与数据一起送入 FPGA,例如 ADC 的 DCO:

create_clock -name adc_dco -period 5.000 [get_ports adc_dco]
set_input_delay -clock [get_clocks adc_dco] -max 0.850 \
[get_ports {adc_data[*]}]
set_input_delay -clock [get_clocks adc_dco] -min -0.150 \
[get_ports {adc_data[*]}]

数值描述数据相对 ADC 时钟到达 FPGA 边界的窗口,应包含器件 skew 和板级 data-to-clock skew。若接口在 FPGA 内使用 IDELAY/ISERDES 居中采样,还要把实际延迟设置和采样相位纳入分析。

DDR 需要同时约束参考时钟上升沿和下降沿:

set adc_ports [get_ports {adc_data[*]}]
set adc_clock [get_clocks adc_dco]
set_input_delay -clock $adc_clock -max 0.850 $adc_ports
set_input_delay -clock $adc_clock -min -0.150 $adc_ports
set_input_delay -clock $adc_clock -clock_fall -max 0.900 \
-add_delay $adc_ports
set_input_delay -clock $adc_clock -clock_fall -min -0.100 \
-add_delay $adc_ports

-clock_fall 选择参考时钟下降沿,-rise/-fall 选择数据转换方向,两者不是一回事。对同一端口保留第二组边沿约束时使用 -add_delay,否则可能覆盖已有约束。

FPGA 同时输出数据和转发时钟时,先让转发时钟保持与内部源时钟的关系:

create_generated_clock -name dac_fwd_clk \
-source [get_pins u_dac_clk_oddr/C] \
-divide_by 1 \
[get_ports dac_clk]
set_output_delay -clock [get_clocks dac_fwd_clk] -max 1.200 \
[get_ports {dac_data[*]}]
set_output_delay -clock [get_clocks dac_fwd_clk] -min -0.300 \
[get_ports {dac_data[*]}]

转发时钟通常通过 ODDR 和专用时钟资源输出。不要用普通逻辑翻转信号代替转发时钟。

异步输入不是 I/O delay 问题

跳转到“异步输入不是 I/O delay 问题”

按键、外部中断和 UART RX 等与内部时钟没有固定相位关系。不要为它们编造相对于 sys_clk 的 input delay。正确流程是:

  1. 在 RTL 中使用合适的同步器、脉冲同步或异步 FIFO。
  2. 标记同步器寄存器,例如 (* ASYNC_REG = "TRUE" *)。
  3. 只对异步端口到第一级同步器的路径施加精确例外。
  4. 对同步器之后的逻辑继续执行正常同步时序分析。
set_false_path -from [get_ports async_irq] \
-to [get_pins u_irq_sync/sync_ff1_reg/D]

时序例外:默认不使用,证明后再使用

跳转到“时序例外:默认不使用,证明后再使用”

例外会减少或改变分析范围。每一条例外都应附带协议理由、起点、终点和验证方法。

需求优先考虑不能解决的问题
两个时钟完全无固定相位关系正确 CDC 结构,再按范围异步分组/切路径亚稳态、丢脉冲、总线撕裂
某条功能路径永不采样精确 set_false_path错误模式控制或错误握手
接收端按协议每 N 周期采样setup/hold 成对的 multicycle组合逻辑本来就太深
异步总线还需限制传播/偏斜set_max_delay -datapath_only、set_bus_skew缺少 Gray/握手/FIFO 协议
不同工作模式选择不同路径set_case_analysis,分别分析各模式实际硬件中的动态切换错误
set_clock_groups -asynchronous \
-group [get_clocks {sys_clk}] \
-group [get_clocks {adc_dco}]

这会双向切断两个时钟组之间的普通时序分析,适合组内关系明确、组间确实异步且所有 CDC 已审核的场景。

set_clock_groups 范围很大,且会压过同一路径上的普通 set_max_delay 等低优先级时序例外。若某个 CDC 总线仍需要最大数据路径限制,不要先用宽泛的异步时钟组把它完全切掉;改为缩小切路径范围。set_bus_skew 是独立的总线偏斜检查,但也必须用报告确认实际覆盖对象和最终有效约束。

-logically_exclusive 和 -physically_exclusive 用于互斥时钟模式,不等于异步。只有硬件保证时钟不会同时作用于相关路径时才使用。

set src_regs [get_cells -hier -filter {NAME =~ */status_src_reg[*]}]
set sync_d [get_pins -hier -filter {NAME =~ */status_sync_ff1_reg[*]/D}]
set_false_path -from $src_regs -to $sync_d

优先约束到第一级同步器 D 引脚,不要用 -through 一个常见网名切掉大量未知路径。set_false_path -from [get_clocks A] -to [get_clocks B] 只切一个方向;双向无关时钟可使用经过审核的 set_clock_groups -asynchronous。

若同一时钟域内,目标寄存器按协议每 3 个周期才采样一次:

set src_regs [get_cells {u_slow/src_reg[*]}]
set dst_regs [get_cells {u_slow/dst_reg[*]}]
set_multicycle_path 3 -setup -from $src_regs -to $dst_regs
set_multicycle_path 2 -hold -from $src_regs -to $dst_regs

常见同周期场景中,N 周期 setup 对应 N-1 周期 hold 修正。若源/目的时钟周期不同,必须重新确认 -start/-end 的边沿移动规则,不能机械套用。

只有 RTL 中存在真实、可验证的采样使能或协议保证时才能设置 multicycle。单纯因为路径时序失败而设置多周期,会把硬件错误隐藏起来。

异步总线的最大延迟与偏斜

跳转到“异步总线的最大延迟与偏斜”

Gray 计数器等 CDC 总线不仅需要功能协议,还可能需要限制各位到达时间:

set gray_src [get_cells {u_fifo/wgray_reg[*]}]
set gray_dst [get_pins {u_fifo/wgray_sync_ff1_reg[*]/D}]
set_max_delay 4.000 -datapath_only -from $gray_src -to $gray_dst
set_bus_skew 1.000 -from $gray_src -to $gray_dst

具体上限应由源端更新速率、源和目的时钟周期、Gray 协议以及实现预算共同推导,不能只看接收周期。Vivado 2020.2 的 set_bus_skew 帮助给出以两域较短周期为参考的常见选择,并以源时钟周期的 set_max_delay -datapath_only 辅助限制寄存器距离;这些仍需按实际协议确定。这里的 4 ns 与 1 ns 仅演示语法,不是任意 FIFO 的通用数值。set_bus_skew 限制各位到达时间之差,不等于限制整条路径的绝对延迟,两者用途不同。

异步复位应采用“异步置位/复位、同步释放”的结构。不要对所有复位路径一刀切后忽略 recovery/removal 风险。

若外部复位只连接到同步释放电路的异步控制端,可精确约束该已审核边界;同步释放后的复位网络仍按各时钟域正常分析。复位策略见 时钟、复位与 CDC。

set_property -dict { \
PACKAGE_PIN E3 \
IOSTANDARD LVCMOS33 \
} [get_ports sys_clk]
set_property -dict { \
PACKAGE_PIN H5 \
IOSTANDARD LVCMOS33 \
DRIVE 8 \
SLEW SLOW \
} [get_ports status_led]

差分输入示例:

set_property PACKAGE_PIN K4 [get_ports refclk_p]
set_property PACKAGE_PIN K3 [get_ports refclk_n]
set_property IOSTANDARD LVDS_25 [get_ports {refclk_p refclk_n}]
set_property DIFF_TERM TRUE [get_ports refclk_p]
属性决定依据
PACKAGE_PIN原理图、封装和 PCB 连接
IOSTANDARD外部电平标准与 Bank VCCO
DRIVE负载、边沿和信号完整性预算
SLEWEMI、串扰、时序与信号完整性权衡
PULLUP/PULLDOWN板级上拉/下拉与上电状态
DIFF_TERM差分接口拓扑和终端方案

不要从其他开发板复制引脚。IOSTANDARD 必须与目标 Bank 电压和器件规则一致,最后运行 report_drc。

下面的骨架适用于“一个系统时钟、一个同步外设接口、一个异步输入”的起点。先替换所有参数和对象名,再根据接口类型删减,不要原样照搬数值。

# ----------------------------------------------------------------------------
# 0. Primary and virtual clocks
# ----------------------------------------------------------------------------
create_clock -name sys_clk -period 10.000 [get_ports sys_clk]
create_clock -name ext_sys_clk -period 10.000
set_input_jitter [get_clocks sys_clk] 0.080
# ----------------------------------------------------------------------------
# 1. Board-level I/O timing (replace with calculated values)
# ----------------------------------------------------------------------------
set_input_delay -clock [get_clocks ext_sys_clk] -max 2.700 \
[get_ports {rx_data[*]}]
set_input_delay -clock [get_clocks ext_sys_clk] -min 0.550 \
[get_ports {rx_data[*]}]
set_output_delay -clock [get_clocks ext_sys_clk] -max 2.100 \
[get_ports {tx_data[*]}]
set_output_delay -clock [get_clocks ext_sys_clk] -min -0.450 \
[get_ports {tx_data[*]}]
# ----------------------------------------------------------------------------
# 2. Reviewed asynchronous boundary
# ----------------------------------------------------------------------------
set_false_path -from [get_ports async_irq] \
-to [get_pins u_irq_sync/sync_ff1_reg/D]
# ----------------------------------------------------------------------------
# 3. Physical pins (replace from schematic)
# ----------------------------------------------------------------------------
set_property PACKAGE_PIN E3 [get_ports sys_clk]
set_property IOSTANDARD LVCMOS33 [get_ports sys_clk]
# Add every used top-level I/O pin and its verified IOSTANDARD here.

不要把上面的 proc 对象检查写回 .xdc。配套的 validate_constraints.tcl 在综合后执行:

proc require_objects {label objects expected_min} {
set count [llength $objects]
if {$count < $expected_min} {
error "Constraint validation: $label matched $count object(s)"
}
puts "Constraint validation: $label matched $count object(s)"
return $objects
}
require_objects sys_clk_port [get_ports -quiet sys_clk] 1
require_objects rx_data [get_ports -quiet {rx_data[*]}] 1
require_objects tx_data [get_ports -quiet {tx_data[*]}] 1
require_objects irq_sync_d \
[get_pins -quiet u_irq_sync/sync_ff1_reg/D] 1
if {[llength [get_clocks -quiet sys_clk]] != 1} {
error "Constraint validation: sys_clk was not created exactly once"
}
report_exceptions -summary
report_exceptions -coverage
report_exceptions -ignored
check_timing -verbose

总线宽度已知时,应把 expected_min 改为精确数量判断,例如 rx_data 必须正好命中 8 个端口。若外设不是 system-synchronous,应替换虚拟时钟和 I/O delay 部分:source-synchronous 使用转发时钟;异步控制使用 CDC;没有采样关系的静态配置端口不要伪造周期约束。

每次构建都要验证约束

跳转到“每次构建都要验证约束”

综合后至少运行:

report_clocks
report_clock_networks
check_timing -verbose
report_clock_interaction
report_exceptions -summary
report_exceptions -coverage
report_exceptions -ignored
report_timing_summary -delay_type min_max \
-report_unconstrained -check_timing_verbose
report_drc
检查合格标准
report_clocks所有预期时钟存在,周期、波形和 generated source 正确
check_timing -verbose无意外 no_clock、partial I/O delay、multiple clock、unconstrained endpoint
report_clock_interaction时钟关系与架构一致,每个不安全交互都有 CDC 解释
report_exceptions -coverage每条例外命中预期起点/终点,没有过宽覆盖
report_exceptions -ignored没有因对象缺失或高优先级约束而被忽略的关键例外
report_timing_summarysetup/hold 均检查,无未约束关键路径,WNS/TNS/WHS/THS 达标
report_drc无未解决的时钟、I/O、电气和实现 DRC

如果设计使用了 set_bus_skew,实现完成后还应单独执行 report_bus_skew,核对每组起终点、requirement、actual 与 slack;不能用 report_timing_summary 代替它。报告中没有相应路径也不是通过,需先检查约束是否命中正确对象。这一独立签核要求可查 AMD UG906 的 Report Bus Skew 说明。

对某个接口做点对点检查:

report_timing -from [get_ports {rx_data[*]}] \
-to [get_cells {u_rx/data_reg[*]}] \
-delay_type min_max -max_paths 20
report_timing -from [get_cells {u_tx/data_reg[*]}] \
-to [get_ports {tx_data[*]}] \
-delay_type min_max -max_paths 20

只看到 WNS >= 0 不足以签核:路径可能根本没有被约束,或被错误 false path 切掉。

按以下顺序拆解,而不是立即更换实现策略:

  1. 确认 startpoint、endpoint、launch/capture clock 正确。
  2. 确认 path requirement、I/O delay 和时序例外来自真实协议。
  3. 分开查看 data path、clock path、logic delay、route delay 和 clock skew。
  4. 判断是 setup、hold、恢复/移除还是脉宽问题。
  5. 找出重复出现的逻辑结构、扇出源和物理区域,而不是只修最差一条路径。

常见信号:

报告特征优先怀疑
逻辑级数很深RTL 组合链、优先级选择、大比较/算术
routing delay 占比高高扇出、拥塞、跨区域/SLR、宏单元距离
大负 clock skew时钟拓扑、跨区域、时钟资源或约束关系
input/output 路径失败外部时序模型、IOB 寄存器、IDELAY/ODELAY、板级 skew
hold 大量失败时钟偏斜、生成时钟关系、过短数据路径或错误 min delay
路径 requirement 异常小时钟波形/相位、错误 generated clock、错误边沿或例外
  1. 修正漏约束、错误时钟关系和不可信例外。
  2. 确认路径确实应该在当前采样边沿完成。
  3. 减少逻辑级数、串行优先级、宽运算和不必要转换。
  4. 在自然边界增加流水级,并同步延迟 valid、地址和标签。
  5. 复制或分层驱动高扇出控制信号,避免一个源跨全芯片。
  6. 检查 BRAM/DSP/URAM 是否启用合适内部寄存器。
  7. 检查拥塞、跨区域/SLR 距离和关键 IP 的相对位置。
  8. 最后再尝试综合/实现 directive、phys_opt_design 或增量实现。

架构修复通常比反复更换策略稳定。若每次实现结果波动很大,应先处理拥塞、高扇出和物理距离。

  1. 检查 generated clock、时钟相位、I/O -min 和 multicycle hold 是否正确。
  2. 确认没有把本应异步的路径误当同步,或把同源时钟误分异步。
  3. 检查异常 clock skew、专用时钟资源使用和物理跨区。
  4. 让实现工具进行合法的 hold 修复,并复查 setup 是否退化。

不要在 RTL 中插入组合延迟链或依赖门延迟修 hold。FPGA 逻辑和布线延迟会随器件、PVT 和实现变化,无法作为可靠功能延迟。

错误做法后果正确做法
给所有输入输出填同一个 delay板外模型失真按接口和器件手册分别计算 min/max
get_ports adc_data[*] 不加大括号Tcl 可能解释 []使用 [get_ports {adc_data[*]}]
在 XDC 中定义任意 procVivado 拒绝不受支持命令,后续约束可能失效XDC 只放约束;对象断言放综合后 Tcl
get_* -quiet 后不检查空集合约束看似执行但没有命中在验证 Tcl 中对关键集合检查 llength
用 create_clock 描述内部分频时钟丢失父时钟相位、延迟和抖动关系使用自动推导或 create_generated_clock
对异步时钟只设 false pathCDC 电路仍可能错误先实现同步器/FIFO/握手,再约束
为失败路径直接设 multicycle隐藏真实单周期违例证明接收协议确实隔 N 周期采样
只写 multicycle setuphold 检查边沿错误同周期场景配套 N-1 hold
对时钟组全局 asynchronous 后再限 Gray 总线高优先级切路径可能让后续约束无效缩小切路径范围并查 ignored/coverage
只检查 WNS可能存在 hold 或未约束路径同时查 WNS/TNS/WHS/THS 和 unconstrained
从其他开发板复制 pin/IOSTANDARD引脚或 Bank 电压错误以当前原理图、封装、VCCO 为准
  • 每个时序单元都有预期时钟。
  • primary、virtual、generated clock 的来源、周期、波形和关系正确。
  • MMCM/PLL 自动生成时钟已在 report_clocks 中核对。
  • 异步、逻辑互斥和物理互斥没有混用。
  • 每个同步接口都有独立的 min/max 计算记录。
  • SDR/DDR 的参考边沿和 -add_delay 使用正确。
  • 异步输入使用了匹配协议的 CDC 结构。
  • 每个已使用端口的引脚、电平标准和 Bank 电压一致。
  • 每条例外有协议依据、精确对象和审核人可理解的注释。
  • multicycle setup/hold 成对且边沿含义已验证。
  • report_exceptions -ignored 无意外结果,coverage 不过宽。
  • false path 没有切掉应该分析的同步逻辑。
  • check_timing -verbose 无未解释问题。
  • setup、hold、恢复/移除和脉宽检查均通过。
  • 无未约束关键路径,时钟交互与 CDC 设计一致。
  • 关键 timing、DRC、utilization 报告进入构建产物并可追溯。

Vivado 终端化运行方式见 Vivado 终端命令与 Tcl 批处理,完整实现阶段见 Vivado 从 RTL 到上板。