从仿真到上板的时序收敛方法 - 第2节
时序分析基础:建立时间与保持时间
各位同学,今天我们来聊聊时序分析最核心的两个概念——建立时间与保持时间。说实话,我刚入行那会儿,觉得这两个概念就是背背定义的事。直到有一次,我负责的一个高速接口项目在仿真时跑得好好的,上了板子却频繁出错。折腾了两周,最后发现是一个寄存器的保持时间违例。从那以后,我再也不敢小看这两个基础概念了。
建立时间(Setup Time)
建立时间,说白了就是数据在时钟有效沿到来之前,必须提前稳定下来的最短时间。你想想看,寄存器内部需要时间去采样数据,如果数据来得太晚,采样结果就不确定。
定义:在时钟有效沿到达之前,数据输入必须保持稳定的最小时间窗口。
我在项目中遇到过这样一个案例:一个 200MHz 的设计,综合报告显示建立时间违例了 0.3ns。当时我以为是综合工具没优化好,后来仔细一查,是组合逻辑路径太长,数据传播延迟过大。解决办法其实不复杂——在关键路径上插入一级流水线,问题就解决了。
保持时间(Hold Time)
保持时间呢,刚好反过来。它要求数据在时钟有效沿之后,还要再稳定一段时间。为什么要这样?因为时钟沿过去之后,寄存器内部的锁存器还需要一点时间来完成数据捕获。如果数据变化太快,采样结果同样会出错。
定义:在时钟有效沿到达之后,数据输入必须保持稳定的最小时间窗口。
注意:保持时间违例比建立时间违例更难调试。建立时间违例通常可以通过降低频率来验证,但保持时间违例与频率无关,即使降频也可能存在。
我曾经在一个低功耗项目中遇到过保持时间问题。为了省电,我们用了很慢的时钟,结果保持时间反而违例了。为什么?因为数据路径太短,时钟偏斜又比较大。解决办法是在短路径上插入缓冲器,人为增加延迟。
建立时间与保持时间的对比
| 对比项 | 建立时间 | 保持时间 |
|---|---|---|
| 关注点 | 数据来得太晚 | 数据变化太快 |
| 与频率关系 | 频率越高越容易违例 | 与频率无关 |
| 常见原因 | 组合逻辑路径过长 | 数据路径过短或时钟偏斜 |
| 修复方法 | 插入流水线、优化逻辑 | 插入缓冲器、调整时钟树 |
| 仿真可见性 | 功能仿真通常可见 | 功能仿真难以发现 |
时序路径的分类
搞清楚了建立时间和保持时间,我们再来看看时序路径。时序分析说白了就是检查所有可能的路径,确保每条路径上的建立时间和保持时间都满足要求。按照起点和终点的不同,时序路径可以分为四类。
寄存器到寄存器路径
这是最常见的一类路径,也是我们平时分析最多的。起点是一个寄存器的输出,经过组合逻辑,终点是另一个寄存器的输入。这类路径的时序分析相对直观,因为起点和终点都有时钟控制。
经验之谈:我建议你在做综合之前,先手动检查一下关键路径的级数。如果组合逻辑超过 15 级,大概率会有建立时间问题。提前规划流水线,比事后修 timing 要高效得多。
输入到寄存器路径
这类路径从芯片的输入端口开始,到内部寄存器结束。难点在于,输入信号什么时候到达,我们并不完全确定。这需要我们在约束中指定输入延迟。
我记得有个项目,客户提供的输入延迟约束写错了,导致我们综合出来的设计在实测时频频出错。后来花了三天时间,用示波器实测信号时序,才把正确的约束反推出来。嗯,从那以后,我每次都要和客户反复确认输入延迟的数值。
寄存器到输出路径
这类路径从内部寄存器出发,到芯片的输出端口结束。和输入路径类似,我们需要约束输出延迟,告诉工具外部器件需要多长时间来采样我们的输出数据。
输入到输出路径
这类路径比较特殊——它没有经过任何寄存器,直接从输入端口到输出端口。说白了就是纯组合逻辑路径。这类路径的时序分析需要特别注意,因为没有时钟来同步,延迟完全由组合逻辑决定。
避坑指南:我曾经在一个设计中,为了省一个寄存器,把输入到输出路径做成了纯组合逻辑。结果上板后发现,输出信号毛刺严重,导致后端模块误触发。最后老老实实加了一级寄存器,问题才解决。我的建议是:除非对延迟有极苛刻的要求,否则尽量在输入到输出路径上插入寄存器。
四种路径的约束要点
| 路径类型 | 需要约束的内容 | 常见问题 |
|---|---|---|
| 寄存器到寄存器 | 时钟周期、时钟偏斜 | 组合逻辑过深导致建立时间违例 |
| 输入到寄存器 | 输入延迟(set_input_delay) | 输入延迟约束不准确 |
| 寄存器到输出 | 输出延迟(set_output_delay) | 外部器件时序要求不明确 |
| 输入到输出 | 最大/最小延迟(set_max_delay/set_min_delay) | 纯组合路径,无时钟同步 |
好了,这一章的内容就到这里。建立时间和保持时间是时序分析的基石,四种路径分类是后续所有时序约束的基础。你把这些概念吃透了,后面的内容学起来就会轻松很多。