3、输入输出延迟约束:set_input_delay、set_output_delay、最大最小延迟约束、系统同步与源同步接口

各位同学,今天我们来聊聊时序约束里最“接地气”的部分——输入输出延迟约束。说实话,这块内容在项目里天天都要打交道。你想想看,FPGA不是孤岛,它要和外面的芯片、传感器、总线打交道。数据从外部进来,或者从FPGA发出去,这中间的延迟怎么算?怎么约束?这就是我们今天要解决的问题。

3.1 为什么需要输入输出延迟约束?

先问大家一个问题:FPGA内部的时序,我们可以通过时钟周期、组合逻辑路径来约束。但数据从外部引脚进来,到第一个寄存器,这段路我们管得了吗?

答案是:管不了,但我们可以告诉工具“这段路大概有多长”。这就是set_input_delay和set_output_delay存在的意义。

我个人习惯把输入输出延迟约束比作“给工具画个圈”。你不画这个圈,工具就不知道外部信号什么时候来,什么时候走。结果就是——综合出来的电路可能根本没法用。

核心思想:输入输出延迟约束,本质上是把外部器件的时序特性“翻译”成FPGA工具能理解的约束语言。

3.2 set_input_delay:告诉工具数据什么时候来

set_input_delay定义的是:相对于时钟边沿,数据到达FPGA引脚的时间。

公式很简单:

set_input_delay -clock [get_clocks clk] -max 2.5 [get_ports data_in]
set_input_delay -clock [get_clocks clk] -min 1.0 [get_ports data_in]

这里-max和-min分别对应最大延迟和最小延迟。最大延迟决定了建立时间(setup)的裕量,最小延迟决定了保持时间(hold)的裕量。

我在项目中遇到过一件事:有个同事只给了-max约束,没给-min。结果板子跑起来偶尔出错,查了三天才发现是保持时间违例。嗯,从那以后我每次都会把-max和-min都写上,哪怕-min设成0也行。

小技巧:如果外部器件的数据手册只给了最大延迟,没给最小延迟,可以把最小延迟设为0。但最好还是问清楚,或者实测一下。

3.3 set_output_delay:告诉工具数据什么时候被取走

set_output_delay正好反过来:它定义的是数据从FPGA输出后,到外部器件采样时钟边沿之间的时间。

set_output_delay -clock [get_clocks clk] -max 3.0 [get_ports data_out]
set_output_delay -clock [get_clocks clk] -min 0.5 [get_ports data_out]

这里要注意一个容易搞混的点:set_output_delay的值,其实是“外部器件需要的建立/保持时间”。你想想看,外部器件采样数据需要时间,这个时间就是FPGA必须保证的。

我曾经犯过一个错误:把set_output_delay设成了PCB走线延迟,而不是外部器件的建立时间。结果仿真全过,上板就挂。后来才明白,set_output_delay描述的是“外部世界的需求”,不是“FPGA到外部的路径延迟”。

注意:set_output_delay的值通常为正数。如果外部器件是DDR接口或者有特殊的采样窗口,可能会出现负值。但初学者先别碰负值,容易把自己绕晕。

3.4 最大延迟与最小延迟约束

刚才提到的-max和-min,其实就是最大延迟约束和最小延迟约束。它们分别对应setup和hold检查。

约束类型 检查内容 对应参数
最大延迟(-max) 建立时间(setup) 数据最晚到达时间
最小延迟(-min) 保持时间(hold) 数据最早到达时间

说白了,最大延迟约束保证数据不会来得太晚,最小延迟约束保证数据不会走得太早。两者缺一不可。

我建议你在写约束时,先确定-max,再确定-min。因为-max通常来自数据手册,比较容易拿到。-min往往需要额外分析,比如考虑时钟抖动、温度变化等因素。

3.5 系统同步与源同步接口

这部分是很多人的盲区。系统同步和源同步,其实是两种不同的接口时序模型。

系统同步(System Synchronous)

系统同步是指:FPGA和外部器件共用同一个时钟源。时钟从外部进来,同时供给FPGA和外部芯片。

这种接口的约束比较简单:你只需要考虑时钟偏斜(clock skew)和PCB走线延迟。set_input_delay的值通常等于外部器件的Tco(时钟到输出延迟)加上PCB走线延迟。

# 系统同步接口示例
set_input_delay -clock [get_clocks sys_clk] -max 2.0 [get_ports data_in]
set_input_delay -clock [get_clocks sys_clk] -min 0.5 [get_ports data_in]

源同步(Source Synchronous)

源同步是指:数据发送方同时发送数据和时钟。比如DDR接口、LVDS接口、MIPI接口等。

源同步的约束要复杂一些。因为时钟和数据是同步发送的,但到达FPGA时可能会有相位差。你需要考虑的是“时钟和数据之间的相对延迟”,而不是延迟。

我记得第一次做DDR3接口时,被源同步的约束搞得很头疼。后来总结了一个经验:源同步接口的set_input_delay,通常等于数据相对于时钟的skew。这个值可以从数据手册的“数据有效窗口”里找到。

关键区别:

  • 系统同步:关注延迟(数据相对于系统时钟的到达时间)
  • 源同步:关注相对延迟(数据相对于随路时钟的相位关系)

3.6 实战经验:如何快速确定约束值?

很多同学拿到数据手册就懵了,不知道从哪下手。我分享一个自己的方法:

  1. 先找时钟信息:确定接口是系统同步还是源同步
  2. 再找Tco或Tsu/Th:系统同步看Tco,源同步看数据有效窗口
  3. 加上PCB走线延迟:一般每英寸约150-200ps,具体看板材
  4. 留出余量:我习惯在计算值上加10%-20%的余量

举个例子:某ADC芯片输出数据,Tco最大2.5ns,最小1.0ns,PCB走线延迟0.3ns。那么:

set_input_delay -max = 2.5 + 0.3 = 2.8ns
set_input_delay -min = 1.0 + 0.3 = 1.3ns

当然,这只是理论值。实际项目中,我建议你做完约束后跑一下时序分析,看看setup和hold的裕量。如果裕量太小,就要考虑调整约束值或者优化PCB布局。

避坑指南:我曾经遇到过一个问题:约束值设得太紧,导致工具为了满足时序疯狂插入buffer,结果面积和功耗都超标。后来我学会了“适度宽松”——在满足数据手册要求的前提下,给工具留一点呼吸空间。

3.7 本章小结

输入输出延迟约束,说白了就是“告诉工具外部世界的时序特性”。set_input_delay管输入,set_output_delay管输出,-max和-min分别对应setup和hold。系统同步和源同步的区别在于时钟的来源和约束的侧重点。

最后送大家一句话:约束不是越紧越好,也不是越松越好。恰到好处,才是高手。

输入输出延迟约束知识体系 IO延迟约束 set_input_delay set_output_delay 最大延迟(-max) / 最小延迟(-min) 系统同步接口 源同步接口 setup/hold检查 共用时钟源 随路时钟+数据 核心:将外部器件时序特性“翻译”为FPGA约束语言

可可精品资料库