4、输入输出延迟约束:set_input_delay、set_output_delay、set_load、set_drive

好,咱们今天聊聊IO约束。这玩意儿,说白了就是告诉工具:芯片外面那些信号,到底是怎么个来法、怎么个去法。

我刚开始做后端那会儿,总觉得IO约束是前端的事。后来吃过一次亏——有个项目,内部逻辑跑得飞快,结果芯片一上板,死活就是不稳定。查到最后,发现是输入路径的setup违例了。嗯,从那以后,我再也不敢小看这几条命令了。

4.1 set_input_delay:告诉工具信号啥时候到

你想想看,芯片外面有个信号,从时钟沿开始,经过PCB走线、经过另一个芯片的输出延迟,最后才到你的输入引脚。这个“从时钟沿到数据到达引脚”的时间,就是input delay。

命令长这样:

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对应setup分析,-min对应hold分析。我个人习惯,-max和-min都会给,哪怕只差一点点。为什么?因为工具需要知道最坏情况和最好情况,才能做准确的时序收敛。

核心理解:

  • input delay越大,留给内部逻辑的setup时间就越少
  • input delay越小,内部hold就越容易出问题
  • 说白了,input delay就是“外部已经消耗掉的时间”

我在项目中遇到过一种情况:前端给的input delay特别大,几乎把整个周期都占满了。我一看,这不对啊,内部逻辑根本没法做。后来跟前端一聊,发现他们用的是最差工况的估算,根本没考虑实际PCB走线。最后我们协商,把input delay拆成了两部分——芯片内部和PCB外部,这样才合理。

4.2 set_output_delay:告诉工具信号啥时候必须到

output delay正好反过来。它描述的是:数据从你的输出引脚出发,经过PCB走线、到达下一个芯片的输入,这中间需要多少时间。

set_output_delay -clock clk -max 3.0 [get_ports data_out]
set_output_delay -clock clk -min 1.2 [get_ports data_out]

注意看,output delay越大,留给内部逻辑把数据送到引脚的时间就越少。因为外部已经“预定”了这段时间。

我的小技巧:

做output delay约束时,我习惯先问清楚下一级芯片的setup/hold要求。很多新人直接抄上一版项目的数值,结果换了芯片就不灵了。每个项目的外部环境都不一样,别偷懒。

4.3 set_load:给输出引脚加点“负担”

这个命令,说白了就是告诉工具:你的输出引脚要驱动多大的负载。负载越大,信号上升越慢,延迟就越大。

set_load -pin_load 0.5 [get_ports data_out]

单位一般是pf(皮法)。一个标准单元的输入引脚负载大概在0.01~0.05pf左右,而一个PCB走线加一个芯片引脚的负载,可能到5~10pf。差距很大。

我记得有一次,一个同事没设set_load,工具默认用了0负载。结果综合出来的驱动能力根本不够,流片回来信号质量一塌糊涂。嗯,从那以后,我每次做IO约束,都会把set_load和set_output_delay一起检查。

避坑指南:

我曾经在一个项目中,把set_load设得太大了,导致工具拼命加大驱动单元,面积和功耗都爆了。后来发现,实际PCB走线没那么长,负载估算过于悲观。所以,set_load要跟后端物理设计的人对齐,别自己拍脑袋。

4.4 set_drive:描述外部驱动强度

set_drive描述的是:外部驱动你的输入引脚的信号,它的驱动能力有多强。驱动越强,信号上升越快,到达引脚的时间就越短。

set_drive -rise 0.5 [get_ports data_in]
set_drive -fall 0.5 [get_ports data_in]

单位是ns(纳秒)。数值越小,表示驱动越强。0表示理想驱动(信号瞬间跳变)。

实际项目中,我很少直接用set_drive。为什么?因为现在主流做法是用set_input_transition,它更直观、更贴近实际。但有些老项目或者特殊场景,还是会用到set_drive。你至少得知道它是什么意思。

set_drive vs set_input_transition:

命令 描述 常用场景
set_drive 指定外部驱动电阻值 老项目、库文件不完整时
set_input_transition 直接指定输入信号的转换时间 现代设计,更直观

4.5 四个命令的配合使用

你想想看,这四个命令其实是互相配合的:

  • 输入路径:set_input_delay + set_drive(或set_input_transition)
  • 输出路径:set_output_delay + set_load

输入路径上,外部驱动越强、input delay越小,内部时序就越宽松。输出路径上,负载越小、output delay越小,内部时序也越宽松。但现实世界哪有那么好的事?外部环境往往比我们想象的更恶劣。

我个人习惯,在做完IO约束后,会跑一遍report_timing,专门检查IO路径。看看setup和hold的slack是不是合理。如果发现某个IO路径的slack特别紧,我会回头检查对应的约束值,确认是不是太悲观了。

实战建议:

做IO约束时,别只看一个命令。把set_input_delay、set_output_delay、set_load、set_drive放在一起看,形成一个完整的“外部环境画像”。我曾经在一个项目中,把四个命令的数值整理成一个表格,跟前端和PCB工程师一起评审,效果非常好。

好了,这一章的内容就这些。记住,IO约束是芯片跟外部世界的“接口协议”,设错了,内部逻辑再牛也白搭。下一章,咱们聊聊时钟约束的进阶内容——generated clock和clock groups。