4. 输入输出延迟约束实战

在完成时钟约束之后,I/O 时序约束是时序收敛中最容易被忽视、也最容易出错的一环。FPGA 内部逻辑的时序由时钟周期和路径延迟决定,而接口时序则取决于外部器件的建立/保持要求、PCB 走线延迟以及 FPGA 引脚到内部寄存器的延迟。set_input_delay 和 set_output_delay 的本质,就是把"外部世界"的时序要求翻译成 FPGA 内部可以检查的约束。本节围绕三类典型接口——系统同步、源同步和 DDR 接口,说明约束的计算方法和板级参数的提取思路。

一、先明确参照系:延迟是相对哪个时钟沿定义的

set_input_delay 和 set_output_delay 的数值,都是相对于某个参考时钟沿而言的。这个参考时钟通常是接口时钟,通过 create_clock 或 create_generated_clock 定义在 FPGA 的时钟输入引脚或恢复时钟上。约束中的 -clock 参数指定参考时钟,-max/-min 分别对应建立和保持检查。理解这一点非常关键:如果参考时钟定义错了,延迟数值再精确也没有意义。

另一个必须统一的约定是延迟的正负号。Vivado 中,set_input_delay 表示数据到达 FPGA 引脚相对于参考时钟沿的延迟;set_output_delay 表示数据从 FPGA 引脚出发后,到达外部器件捕获沿之前所需的延迟。正号表示数据在时钟沿之后到达(或需要更晚发出),负号表示数据在时钟沿之前到达。全文和图示都遵循这一约定。

二、系统同步接口:延迟来自外部器件的 Tco 与走线

系统同步接口的特点是:发送端和接收端使用同一个系统时钟,时钟在板上以独立走线分发。以 FPGA 作为接收端为例,外部器件在时钟沿之后经过 Tco 输出数据,数据再经过 PCB 走线到达 FPGA 引脚。因此:

set_input_delay -max = Tco_max + Tpcb_max
set_input_delay -min = Tco_min + Tpcb_min

假设外部器件手册给出 Tco 范围为 1.5 ns 到 3.2 ns,PCB 走线延迟经提取为 0.4 ns 到 0.6 ns,则 -max 为 3.8 ns,-min 为 1.9 ns。这两个值分别用于建立和保持检查。如果 FPGA 是发送端,则 set_output_delay 的数值来自外部器件的建立时间 Tsu 和保持时间 Th:

set_output_delay -max = Tsu_ext + Tpcb_max
set_output_delay -min = -Th_ext + Tpcb_min

注意保持时间对应的 -min 通常为负值,因为外部器件要求数据在时钟沿之后还要保持一段时间,相当于要求 FPGA 更早发出数据。系统同步接口的板级参数主要来自器件数据手册和 PCB 走线延迟,走线延迟可用 IBIS 仿真或经验值(约 6~7 ps/mm)估算。

三、源同步接口:时钟随数据一起传输

源同步接口中,时钟由发送端随数据一起发出,接收端用这个随路时钟采样数据。此时参考时钟不再是系统时钟,而是随路时钟。以 FPGA 接收 DDR 源同步数据为例,数据在随路时钟的两个边沿都可能变化,因此需要分别约束上升沿和下降沿:

set_input_delay -clock [get_clocks rx_clk] -max 1.2 [get_ports data_in*]
set_input_delay -clock [get_clocks rx_clk] -min 0.3 [get_ports data_in*]
set_input_delay -clock [get_clocks rx_clk] -max 1.2 [get_ports data_in*] -clock_fall -add_delay
set_input_delay -clock [get_clocks rx_clk] -min 0.3 [get_ports data_in*] -clock_fall -add_delay

源同步接口的关键板级参数是数据与时钟之间的偏斜(skew)。这个偏斜包括发送端输出偏斜、PCB 走线长度差以及接收端引脚延迟差。实际提取时,应测量数据走线与时钟走线的长度差,再乘以单位长度延迟。例如数据线比时钟线长 8 mm,按 6.5 ps/mm 计算,偏斜约 52 ps。这个偏斜要分别叠加到 -max 和 -min 上。

四、DDR 接口:双边沿采样与更严格的偏斜控制

DDR 接口在时钟的上升沿和下降沿都传输数据,因此有效数据窗口只有半个时钟周期。约束时必须同时覆盖两个边沿,并且 -max 和 -min 的差值直接决定了数据有效窗口。以 FPGA 输出 DDR 数据为例:

set_output_delay -clock [get_clocks ddr_clk] -max 0.8 [get_ports dq*]
set_output_delay -clock [get_clocks ddr_clk] -min -0.2 [get_ports dq*]
set_output_delay -clock [get_clocks ddr_clk] -max 0.8 [get_ports dq*] -clock_fall -add_delay
set_output_delay -clock [get_clocks ddr_clk] -min -0.2 [get_ports dq*] -clock_fall -add_delay

DDR 接口的板级参数提取比 SDR 更严格:除了走线延迟,还要考虑 DQS 与 DQ 之间的偏斜、FPGA 内部 PHY 的延迟以及外部存储器的建立/保持窗口。实际项目中,通常先用 IBIS 仿真得到引脚处的时序,再反推约束值。如果约束值与仿真结果偏差超过 100 ps,就需要重新检查走线模型或参考时钟定义。

板级参数提取的通用流程:从器件手册获取 Tco/Tsu/Th,从 PCB 工具导出走线长度,用单位延迟换算成时间,再按接口类型组合成 -max/-min。所有参数都应记录来源和版本,便于后续复核。
三类接口的延迟约束计算与板级参数来源 系统同步接口 参考时钟:系统时钟(独立走线) 外部器件 FPGA 引脚 Tco+Tpcb 输入:-max = Tco_max + Tpcb_max 输入:-min = Tco_min + Tpcb_min 输出:-max = Tsu_ext + Tpcb_max 输出:-min = -Th_ext + Tpcb_min 参数来源:器件手册 + PCB 走线 源同步接口 参考时钟:随路时钟(与数据同走) 发送端 接收端 数据 时钟 -max = 数据偏斜_max + 建立余量 -min = 数据偏斜_min - 保持余量 双边沿需加 -clock_fall -add_delay 关键参数:数据与时钟走线长度差 参数来源:PCB 长度差 × 单位延迟 DDR 接口 参考时钟:DQS / 随路时钟 FPGA PHY 外部 DDR DQ DQS -max = Tsu_ext + Tpcb_max + 偏斜 -min = -Th_ext + Tpcb_min - 偏斜 上升沿与下降沿分别约束 有效窗口 = 半周期 - 偏斜 - 抖动 参数来源:IBIS 仿真 + 手册 板级参数提取与约束生成流程 器件手册 Tco / Tsu / Th PCB 走线 长度 / 单位延迟 IBIS 仿真 引脚处时序 参考时钟定义 create_clock 约束值 -max/-min 校验要点: ① 参考时钟是否与接口实际采样时钟一致;② -max/-min 是否覆盖所有边沿;③ 约束值与 IBIS 仿真偏差是否在 100 ps 以内;④ 是否使用 -add_delay 保留多组约束。

五、约束编写中的常见陷阱

第一,参考时钟定义错误。源同步接口如果误用系统时钟作为参考,约束会完全失效。第二,忘记 -clock_fall。DDR 和双边沿接口必须为下降沿单独添加约束,否则下降沿路径不会被检查。第三,-max 和 -min 写反。建立检查用 -max,保持检查用 -min,写反会导致时序报告出现虚假违例或漏报。第四,没有使用 -add_delay。当同一端口需要同时约束上升沿和下降沿时,必须加 -add_delay,否则后一条约束会覆盖前一条。

板级参数提取时,务必区分"典型值"和"最坏值"。时序约束应使用最坏值(max 用最大值,min 用最小值),而不是典型值。如果手册只给出典型值,需要根据工艺角和温度范围做合理裕量估计,并在约束注释中说明假设条件。

六、一个可复用的参数提取记录表

为了让约束值可追溯、可复核,建议为每个接口建立一份参数提取记录。以下是一个示例结构,字段可根据项目实际情况调整:

参数来源数值单位备注
Tco_max器件手册3.2ns最坏值
Tco_min器件手册1.5ns最坏值
Tpcb_maxPCB 走线0.6ns长度 × 6.5 ps/mm
Tpcb_minPCB 走线0.4ns长度 × 6.5 ps/mm
set_input_delay -max计算3.8nsTco_max + Tpcb_max
set_input_delay -min计算1.9nsTco_min + Tpcb_min

这张表的价值在于:当接口出现时序违例时,可以快速定位是器件参数、走线参数还是约束写法出了问题。同时,它也是团队交接和设计复用的重要依据。约束不是一次写对就结束的工作,而是需要随着板级参数更新、器件替换和时钟方案调整持续维护的工程资产。