| name | vivado-constraints |
| description | 当用户需要为 Vivado FPGA 设计编写 XDC/SDC 时序或物理约束时使用此技能。这包括时钟定义(create_clock、create_generated_clock、虚拟时钟)、I/O 延迟约束(set_input_delay、set_output_delay、DDR 时序)、时序异常(set_false_path、set_multicycle_path、set_max_delay、set_min_delay)、时钟域交叉(CDC)约束(set_clock_groups、set_bus_skew)、时钟不确定性/抖动/延迟、物理约束(IOSTANDARD、PACKAGE_PIN、LOC、Pblock、布局、布线)、XDC 优先级规则、约束作用域(SCOPED_TO_REF)、约束排序优化或约束调试(check_timing、report_exceptions、report_clock_interaction)。当用户提及 XDC、SDC、时序约束、时钟约束、IO 延迟、false path、multicycle path、clock groups 或物理引脚分配时触发。如需时序报告解释和分析使用 vivado-analysis。 |
Vivado XDC 约束决策指南
基于 UG903(v2025.2)。完整语法示例请参阅 REFERENCE.md。
XDC 文件管理
综合 vs 实现约束
# 工程模式:设置在 XDC 文件对象上
set_property USED_IN_SYNTHESIS TRUE [get_files timing.xdc]
set_property USED_IN_IMPLEMENTATION TRUE [get_files timing.xdc]
set_property USED_IN_SYNTHESIS FALSE [get_files physical.xdc] ;# 仅实现
# 非工程模式:按适当顺序读取
read_xdc timing.xdc ;# 综合和实现都用
read_xdc physical.xdc ;# 仅综合后读取
约束作用域(用于 IP / 子模块)
# 工程模式
set_property SCOPED_TO_REF uart_tx_ctl [get_files uart_tx_ctl.xdc]
set_property SCOPED_TO_CELLS uart_tx_i0/uart_tx_ctl_i0 [get_files uart_tx_ctl.xdc]
# 非工程模式
read_xdc -ref uart_tx_ctl uart_tx_ctl.xdc
read_xdc -cells uart_tx_i0/uart_tx_ctl_i0 uart_tx_ctl.xdc
对象命名规则
- 单比特寄存器
myReg → 实例名称:myReg_reg
- 多比特寄存器
myBus[2:0] → myBus_reg[0]、myBus_reg[1]、myBus_reg[2]
- 查询多比特:
get_cells myBus_reg[*](不是 myBus_reg[2:0])
- 层次名称:使用明确的
/ 分隔符,而非带 -hierarchical 的通配符
- 推荐: 使用
get_cells inst_A/inst_B/*_reg 不带 -hierarchical
时钟定义指南
主时钟
# 板级时钟在输入端口(推荐)
create_clock -period 10 [get_ports sysclk]
# 带自定义波形的命名时钟(25% 占空比,90° 相移)
create_clock -name devclk -period 10 -waveform {2.5 5} [get_ports ClkIn]
# 差分时钟 — 仅在正引脚上定义
create_clock -name sysclk -period 3.33 [get_ports SYS_CLK_clk_p]
# GT 恢复时钟
create_clock -name rxclk -period 3.33 [get_pins gt0/RXOUTCLK]
# 虚拟时钟(无网表对象 — 用于 I/O 延迟参考)
create_clock -name clk_virt -period 10
规则:
- 在输入端口上定义主时钟,而非 BUFG 输出
- 必须首先定义主时钟——其他约束引用它们
- 虚拟时钟必须在使用它们的 set_input_delay/set_output_delay 之前定义
生成时钟
# MMCM/PLL 输出 → 自动派生,无需手动约束
# 用户逻辑分频器 → 必须手动定义:
create_generated_clock -name clkdiv2 -source [get_ports clkin] -divide_by 2 [get_pins REGA/Q]
# 使用 -edges(主时钟的边沿索引)
create_generated_clock -name clkdiv2 -source [get_pins REGA/C] -edges {1 3 5} [get_pins REGA/Q]
# 占空比变化 + 相移通过 -edges 和 -edge_shift
create_generated_clock -name clkshift -source [get_pins mmcm0/CLKIN] \
-edges {1 2 3} -edge_shift {2.5 0 2.5} [get_pins mmcm0/CLKOUT]
# 乘以 + 除以(用于 MMCM 手动定义)
create_generated_clock -name clk43 -source [get_pins mmcm0/CLKIN] \
-multiply_by 4 -divide_by 3 [get_pins mmcm0/CLKOUT]
# 仅组合路径(MUX 输出)
create_generated_clock -name clkout -source [get_pins mmcm0/CLKIN] \
-combinational [get_pins MUX/O]
# 重命名自动派生时钟(仅名称 + source_object)
create_generated_clock -name clk_rx [get_pins clk_gen_i0/clk_core_i0/inst/mmcm_adv_inst/CLKOUT0]
规则:
-source 仅接受引脚/端口,不接受时钟对象
- MMCM/PLL 输出自动派生——仅在需要自定义设置时才手动定义
- 自动派生时钟仅可在 CMB 输出引脚上重命名
- 使用
get_clocks -of_objects [get_pins <pin>] 查询自动派生时钟名称
时钟组
# 异步时钟(最常见 — 独立振荡器)
set_clock_groups -name async_clk0_clk1 -asynchronous \
-group {clk0 usrclk itfclk} -group {clk1 gtclkrx gtclktx}
# 带 -include_generated_clocks(自动包含派生时钟)
set_clock_groups -name async_grp -asynchronous \
-group [get_clocks -include_generated_clocks clk0] \
-group [get_clocks -include_generated_clocks clk1]
# 互斥时钟(BUFGMUX — 一次仅一个活跃)
set_clock_groups -name exclusive_clk0_clk1 -physically_exclusive \
-group clk0 -group clk1
规则:
set_clock_groups 在时序异常中具有最高优先级
- 无法被
-reset_path 覆盖
- 对于异步 CDC,优先使用
set_clock_groups 而非两个 set_false_path
-logically_exclusive 和 -physically_exclusive 对 AMD FPGA 等效
时钟延迟、抖动、不确定性
# 源延迟(板级延迟,FPGA 外部)
set_clock_latency -source -early 0.2 [get_clocks sysClk]
set_clock_latency -source -late 0.5 [get_clocks sysClk]
# 输入抖动(仅主时钟,每个时钟)
set_input_jitter [get_clocks -of_objects [get_ports clkin]] 0.1
# 系统抖动(全局,所有时钟)
set_system_jitter 0.05
# 额外时钟不确定性(额外时序裕量)
set_clock_uncertainty 0.5 [get_clocks clk1]
# 跨时钟不确定性(必须定义两个方向)
set_clock_uncertainty 2.0 -from [get_clocks clk1] -to [get_clocks clk2]
set_clock_uncertainty 2.0 -from [get_clocks clk2] -to [get_clocks clk1]
I/O 延迟模板
SDR 输入
# 基本(min 和 max)
set_input_delay -clock sysClk 2 [get_ports DIN]
# 分开 min/max
set_input_delay -clock sysClk -max 4 [get_ports DIN]
set_input_delay -clock sysClk -min 1 [get_ports DIN]
# 相对于虚拟时钟
create_clock -name clk_port_virt -period 10
set_input_delay -clock clk_port_virt 2 [get_ports DIN]
DDR 输入
create_clock -name clk_ddr -period 6 [get_ports DDR_CLK_IN]
set_input_delay -clock clk_ddr -max 2.1 [get_ports DDR_IN]
set_input_delay -clock clk_ddr -max 1.9 [get_ports DDR_IN] -clock_fall -add_delay
set_input_delay -clock clk_ddr -min 0.9 [get_ports DDR_IN]
set_input_delay -clock clk_ddr -min 1.1 [get_ports DDR_IN] -clock_fall -add_delay
SDR 输出
set_output_delay -clock sysClk 6 [get_ports DOUT]
# 分开 min/max
set_output_delay -clock sysClk -max 6 [get_ports DOUT]
set_output_delay -clock sysClk -min 1 [get_ports DOUT]
DDR 输出
create_clock -name clk_ddr -period 6 [get_ports DDR_CLK_IN]
set_output_delay -clock clk_ddr -max 2.1 [get_ports DDR_OUT]
set_output_delay -clock clk_ddr -max 1.9 [get_ports DDR_OUT] -clock_fall -add_delay
set_output_delay -clock clk_ddr -min 0.9 [get_ports DDR_OUT]
set_output_delay -clock clk_ddr -min 1.1 [get_ports DDR_OUT] -clock_fall -add_delay
组合路径(输入到输出)
create_clock -name sysClk -period 10
set_input_delay -clock sysClk 4 [get_ports DIN]
set_output_delay -clock sysClk 1 [get_ports DOUT]
# 有效预算:10 - 4 - 1 = 5 ns
关键规则:
-clock 在 Vivado 中是必需的(在 SDC 标准中可选)
-clock_fall 指的是时钟边沿,而非数据边沿
- 第二个约束在同一端口上需要
-add_delay(DDR)
- 使用虚拟时钟来模拟不同的抖动/源延迟场景
时序异常
多周期路径 — 决策表
| 场景 | 约束 |
|---|
| 相同频率同相位 | set_multicycle_path N -setup -from CLK1 -to CLK2 |
| set_multicycle_path N-1 -hold -from CLK1 -to CLK2 |
| SLOW → FAST | set_multicycle_path N -setup -from CLK1 -to CLK2 |
| set_multicycle_path N-1 -hold -end -from CLK1 -to CLK2 |
| FAST → SLOW | set_multicycle_path N -setup -start -from CLK1 -to CLK2 |
| set_multicycle_path N-1 -hold -from CLK1 -to CLK2 |
关键规则:
-setup 默认:移动目标(capture)时钟边沿 → 使用 -start 移动源端
-hold 默认:移动源端(launch)时钟边沿 → 使用 -end 移动目标端
-start 和 -end 在相同时钟域内无效
- 始终配对 setup + hold 多周期约束
False Path
# 异步时钟域之间(优先使用 set_clock_groups)
set_false_path -from [get_clocks CLKA] -to [get_clocks CLKB]
set_false_path -from [get_clocks CLKB] -to [get_clocks CLKA]
# 复位信号
set_false_path -from [get_ports reset] -to [all_registers]
# 通过特定路径(-through 顺序很重要!)
set_false_path -through [get_pins MUX1/a0] -through [get_pins MUX2/a1]
# 仅 setup 或仅 hold
set_false_path -setup -from [get_clocks CLKA] -to [get_clocks CLKB]
注意: -through 无 -from 或 -to 会移除通过该引脚/网络的所有路径。
最大/最小延迟
# 覆盖 setup 要求
set_max_delay 5 -from [get_pins FD1/C] -to [get_pins FD2/D]
# 覆盖 hold 要求
set_min_delay 1 -from [get_pins FD1/C] -to [get_pins FD2/D]
# CDC 路径带 -datapath_only(无时钟 skew,hold 自动 false-pathed)
set_max_delay -datapath_only -from [get_cells src_reg*] -to [get_cells dst_reg*] 10.0
-datapath_only 差异:
| set_max_delay | set_max_delay -datapath_only |
|---|
| 时钟 skew | 包含 | 从不包含 |
| hold 要求 | 不变 | 自动 false-pathed |
| -from | 可选 | 必需 |
Case 分析
set_case_analysis <value> <pins_or_ports>
# 值:0, 1, zero, one, rise, rising, fall, falling
# rise/rising/fall/falling → 仅分析指定转换
# 示例:通过 BUFGMUX 选择 clk_2
set_case_analysis 1 [get_pins clock_sel/S]
禁用时序
# 禁用单元时序弧
set_disable_timing -from WCLK -to O [get_cells inst_fifo_gen/gdm.dm/gprl.dout_i_reg[*]]
# 检查所有禁用的弧
report_disable_timing -file disabled_arcs.rpt
XDC 优先级规则
异常优先级(高 → 低)
- set_clock_groups — 无法覆盖
- set_false_path
- set_max_delay / set_min_delay
- set_multicycle_path
对象特异性(高 → 低)
- 端口、引脚、单元(单元解析为引脚)
- 时钟
过滤特异性(高 → 低)
-from -through -to
-from -to
-from -through
-from
-through -to
-to
-through
-reset_path 可以覆盖 false_path/max_delay/multicycle 优先级,但不能覆盖 clock_groups。
相同约束(相同类型、相同特异性)以最后约束获胜。
CDC 约束
异步 CDC
# 选项 1:set_clock_groups(推荐 — 覆盖两个方向)
set_clock_groups -asynchronous -group [get_clocks clkA] -group [get_clocks clkB]
# 选项 2:set_false_path(需要两个方向)
set_false_path -from [get_clocks clkA] -to [get_clocks clkB]
set_false_path -from [get_clocks clkB] -to [get_clocks clkA]
带 max delay 约束的 CDC
# 限制 CDC 路径延迟(使用同步器 + set_false_path 时)
set_max_delay -datapath_only -from [get_cells src_reg*] -to [get_cells dst_sync_reg*] 10.0
多位 CDC 带总线 skew
# CE 控制的 CDC(握手):skew = N_sync_stages * dst_period
set_bus_skew -from [get_cells src_hsdata_ff_reg*] -to [get_cells dest_hsdata_ff_reg*] 10.000
# Gray 编码 FIFO:skew = dst_period
set_bus_skew -from [get_cells src_gray_ff_reg*] -to [get_cells {dest_graysync_ff_reg[0]*}] 2.500
# set_bus_skew 需要:-from 和 -to,至少 2 个起点 + 2 个终点
# 值应 > 0.5 * min(src_period, dst_period)
性能约束排序
按此顺序编写 XDC 部分以最小化运行时间影响:
| 顺序 | 命令 | 原因 |
|---|
| 1 | set_disable_timing、set_case_analysis | 首先剪枝时序图 |
| 2 | create_clock、create_generated_clock、set_clock_sense | 引用前定义时钟 |
| 3 | set_clock_latency、set_propagated_clock、set_clock_uncertainty、set_input_jitter、set_system_jitter | 时钟属性 |
| 4 | set_input_delay、set_output_delay | I/O 时序 |
| 5 | set_clock_groups、set_false_path、set_min_delay、set_max_delay、set_multicycle_path、set_bus_skew | 时序异常 |
| 6 | set_max_time_borrow、set_external_delay | 很少使用 |
性能提示:
- 对于大型查询使用
get_cells 而非 get_pins
- 将重复查询缓存在 Tcl 变量中
- 避免
all_fanin/all_fanout 与 set_disable_timing 结合使用
- 在可能的地方用
get_clocks clk1 替换 all_registers -clock clk1
约束验证命令
# 检查未约束路径
check_timing -file check_timing.rpt
# 审查时序异常覆盖、冲突、被忽略的约束
report_exceptions -coverage -file exceptions_coverage.rpt
report_exceptions -ignored -file exceptions_ignored.rpt
report_exceptions -scope_override -file exceptions_scope.rpt
report_exceptions -ignored_objects -file exceptions_ignored_obj.rpt
# 时钟域交互矩阵
report_clock_interaction -file clock_interaction.rpt
# 方法学检查(大型约束集合的 XDCV-1、XDCV-2)
report_methodology -file methodology.rpt