3、输入输出延迟约束:set_input_delay、set_output_delay、虚拟时钟、外部路径建模

好,咱们今天聊聊输入输出延迟约束。说实话,这块儿是综合约束里最容易出问题的地方之一。我见过太多工程师,内部逻辑跑得飞起,结果一上板子就挂,查到最后发现是IO约束没给对。

为什么会这样?因为芯片不是孤岛。它要和外面的世界打交道——可能是另一颗芯片,也可能是一个接口器件。你得告诉工具:外面的信号到底什么时候来,又什么时候走。这就是set_input_delay和set_output_delay干的事。

3.1 set_input_delay:告诉工具信号什么时候到

先看输入延迟。说白了,就是时钟沿之后,数据到底多久才能稳定到你的芯片引脚上。

我个人习惯这样理解:输入延迟 = 外部器件的Tco + 走线延迟。你想想看,外部器件在时钟沿之后发出数据,经过PCB走线,再到你的芯片引脚,这中间肯定有延迟。

# 典型用法
set_input_delay -clock clk -max 2.5 [get_ports data_in]
set_input_delay -clock clk -min 0.8 [get_ports data_in]

这里-max和-min分别对应最坏和最好情况。嗯,这里要注意:max对应建立时间分析,min对应保持时间分析。我刚开始做的时候老搞反,后来吃了亏才记住。

核心要点:

  • 输入延迟是相对于时钟沿的
  • max值越大,留给内部逻辑的建立时间越少
  • min值越小,保持时间越容易出问题

3.2 set_output_delay:告诉工具信号什么时候被取走

输出延迟正好反过来。它描述的是:你的芯片输出数据后,外部器件需要多久才能稳定地采到它。

我曾经在一个DDR接口项目里吃过亏。当时只给了输出延迟,没考虑外部器件的建立时间窗口,结果仿真全过,实测就是采不到数据。后来加上外部器件的setup/hold时间,问题才解决。

# 典型用法
set_output_delay -clock clk -max 3.0 [get_ports data_out]
set_output_delay -clock clk -min 1.2 [get_ports data_out]

注意:输出延迟是从你的时钟沿开始算的。max值越大,意味着外部器件要求数据越早到达,你的内部逻辑就得跑得越快。

约束类型 分析对象 max影响 min影响
set_input_delay 输入路径 内部建立时间 内部保持时间
set_output_delay 输出路径 内部建立时间 内部保持时间

3.3 虚拟时钟:没有时钟域的时钟

虚拟时钟这东西,说白了就是一个不连任何物理引脚的时钟。它只用来做约束参考。

什么时候用?最常见的就是异步接口。比如你的芯片用100MHz时钟工作,但外部器件用的是50MHz时钟。这时候你没法直接约束跨时钟域路径,就得靠虚拟时钟。

# 创建虚拟时钟
create_clock -name vclk -period 20.0

# 用虚拟时钟约束输入
set_input_delay -clock vclk -max 5.0 [get_ports async_data]

我个人习惯:虚拟时钟的名字一定要起得有意义。别用vclk1、vclk2这种,回头自己都看不懂。我一般用ext_clk_50m这种格式,一看就知道是外部50MHz时钟。

小技巧:虚拟时钟的周期和波形,要和你实际的外部时钟一致。别瞎编一个周期,那约束就没意义了。

3.4 外部路径建模:把外面的世界画清楚

外部路径建模,其实就是把芯片外面的时序路径也描述清楚。工具只看得到芯片内部,外面的东西你得告诉它。

我一般用set_load和set_drive来做外部建模。set_load描述输出引脚要驱动多大的电容,set_drive描述输入引脚的外部驱动强度。

# 输出负载建模
set_load -pin_load 5.0 [get_ports data_out]

# 输入驱动建模
set_drive -rise 0.5 [get_ports data_in]
set_drive -fall 0.5 [get_ports data_in]

这里有个坑:set_drive的值越小,代表驱动越强。0.5ns的上升时间比1.0ns快。我曾经有个同事搞反了,结果综合出来的电路驱动能力严重不足。

警告:外部路径建模不能太理想化。我建议留10%-20%的余量。因为PCB走线、连接器、温度变化都会影响实际延迟。你想想看,流片一次几百万,多花点时间把约束做扎实,值不值?

3.5 知识体系总览

下面这张图,是我自己总结的输入输出延迟约束的完整流程。你看一遍,应该能有个整体概念。

输入输出延迟约束知识体系 外部器件 Tco + 走线延迟 驱动强度 / 负载电容 set_input_delay 芯片内部 组合逻辑 + 寄存器 建立时间检查 保持时间检查 set_output_delay 外部器件 建立时间要求 保持时间要求 虚拟时钟(异步接口场景) create_clock -name ext_clk -period 20.0 用于跨时钟域路径约束,不连任何物理引脚 外部路径建模 set_load → 输出负载电容 | set_drive → 输入驱动强度 留10%-20%余量,考虑PCB走线、温度、连接器影响

这张图把整个流程串起来了。从左到右:外部器件发出数据 → 经过输入延迟约束 → 芯片内部处理 → 经过输出延迟约束 → 到达外部器件。虚拟时钟和外部路径建模是辅助手段,帮你把约束做完整。

总结一下我的经验:

  • 输入输出延迟约束,核心是站在外部器件的角度思考
  • 虚拟时钟用于异步场景,名字要起好
  • 外部路径建模别太理想,留余量
  • 每次做完约束,跑一遍STA看看有没有violation

好了,这一章就到这儿。记住一句话:IO约束做得好,流片回来不烦恼。

可可精品资料库