时序路径分析:FPGA中的四种时序路径
做FPGA设计这么多年,我越来越觉得时序分析就像是在给芯片做体检。你得知道信号从哪来、到哪去、路上花了多少时间。说白了,时序路径就是信号在FPGA内部走过的路。今天咱们就把这四条路彻底聊透。
四种时序路径概览
FPGA里的时序路径,按起点和终点来分,一共就四种。我习惯把它们记成「从外到内、从内到外、内部循环、外部直通」。来,先看这张图,一目了然:
路径①:输入到寄存器
这条路径从芯片的输入引脚开始,经过IO缓冲和布线,最终到达第一个寄存器的数据输入端。嗯,这里有个坑——外部信号到达FPGA引脚的时间是不受你控制的。
我在项目中遇到过这样的情况:一块板子上有两个FPGA互相通信,发送端的数据在时钟上升沿之后才到达接收端。查了半天,原来是输入延迟约束没设对。你想想看,外部信号从PCB走线到FPGA引脚,这段延迟如果不告诉工具,它怎么知道该不该优化?
关键约束: set_input_delay
这个约束告诉工具:外部信号相对于时钟,到底晚到了多少。设小了,工具会过度优化,设大了又浪费资源。
我个人习惯的做法是:先看芯片手册里IO缓冲的典型延迟,再留20%的余量。比如手册说最大5ns,我就设6ns。宁可多报一点,别让工具太乐观。
路径②:寄存器到寄存器
这是FPGA里最常见的路径,也是我们最需要关注的。说白了,就是两个寄存器之间通过组合逻辑传递数据。这条路径的延迟决定了你的系统能跑多快。
我曾经接手过一个项目,系统只能跑到80MHz,但需求是100MHz。打开时序报告一看,最长的路径就是两个寄存器之间的一堆加法器。怎么解决的?在中间插了一级流水线,把组合逻辑拆成两段。频率直接飙到120MHz。
注意: 寄存器到寄存器的路径,必须满足建立时间和保持时间。建立时间不满足,可以降频或者加流水线。保持时间不满足,那就麻烦了——加延迟都救不了,只能改设计。
路径③:寄存器到输出
这条路径从内部寄存器的时钟端开始,经过输出缓冲,最终到达芯片的输出引脚。它决定了你的FPGA输出信号到达外部器件时,是否还在有效窗口内。
我记得有一次调试一个DDR接口,数据总是偶尔出错。用示波器一看,数据在时钟边沿附近跳变。这就是典型的输出延迟没约束好。后来加了set_output_delay,把数据提前半个周期输出,问题就解决了。
关键约束: set_output_delay
这个约束告诉工具:外部器件需要数据在时钟边沿之前多久就稳定下来。说白了,就是给外部器件留出建立时间。
路径④:输入到输出
这条路径比较特殊,它直接从输入引脚到输出引脚,中间不经过任何寄存器。说白了就是纯组合逻辑路径。这种路径在时序分析里最让人头疼,因为它完全不受时钟控制。
我建议你尽量避免这种路径。为什么?因为它的延迟完全由布线决定,工具很难优化。而且一旦芯片温度变化或者电压波动,这条路径的延迟会变得很不稳定。
| 路径类型 | 起点 | 终点 | 约束方式 | 常见问题 |
|---|---|---|---|---|
| 输入到寄存器 | 输入引脚 | 寄存器D端 | set_input_delay | 外部信号延迟不匹配 |
| 寄存器到寄存器 | 寄存器Q端 | 寄存器D端 | create_clock | 组合逻辑过长 |
| 寄存器到输出 | 寄存器Q端 | 输出引脚 | set_output_delay | 输出信号建立时间不足 |
| 输入到输出 | 输入引脚 | 输出引脚 | set_max_delay | 延迟不可控 |
建立时间与保持时间
聊完路径,咱们得说说两个核心概念:建立时间和保持时间。这两个东西,你搞不清楚,时序分析就白做了。
建立时间(Setup Time): 时钟有效沿到来之前,数据必须保持稳定的最短时间。说白了,就是数据得提前到,让寄存器有时间「看清楚」。
保持时间(Hold Time): 时钟有效沿到来之后,数据必须保持稳定的最短时间。嗯,这个也好理解——时钟来了之后,数据不能马上变,得让寄存器把值「锁住」。
我见过太多新手只关注建立时间,忽略了保持时间。结果呢?综合通过,布局布线也通过,但芯片一上电就随机出错。保持时间违例的典型表现就是:有时候对,有时候错,温度一变更明显。
怎么检查?看时序报告里的Slack值。建立时间的Slack如果是负数,说明路径太长了。保持时间的Slack如果是负数,说明路径太短了。路径太短听起来是好事?不对,太短意味着数据跑得太快,把上一个时钟的数据覆盖了。
我曾经在一个项目中遇到保持时间违例,查了半天发现是时钟偏斜(clock skew)太大。解决办法是在短路径上手动插入缓冲器,让数据走慢一点。嗯,这招虽然土,但管用。
实战建议
说了这么多,总结几条我自己的经验:
- 先约束再综合: 别等到布局布线完了才加约束,那时候改起来成本太高。
- 看最差路径: 时序报告里找最差的几条路径,优先优化它们。
- 留余量: 我习惯留10%-20%的时序余量,别卡着极限做设计。
- 避免纯组合路径: 输入到输出的路径,能加寄存器就加寄存器。
好了,这四种路径和建立保持时间的关系,你心里应该有数了。下次做时序约束的时候,先想想你的信号走的是哪条路,再对症下药。
公众号:蓝海资料掘金营,微信deep3321