2、时序分析基础:建立时间与保持时间、时钟抖动与时钟偏移、时序路径分类
好,咱们进入正题。时序分析,说白了就是看你的芯片能不能在规定的时钟频率下稳定工作。我见过不少新手,上来就怼代码,结果流片回来发现跑不到目标频率,那叫一个头疼。所以,这一章咱们把地基打牢。
2.1 建立时间与保持时间:寄存器的“脾气”
每个寄存器都有它的“脾气”。你要在时钟沿到来之前,把数据稳稳地送到它的输入端,并且保持一段时间。这两个时间,就是建立时间(Setup Time)和保持时间(Hold Time)。
- 建立时间(Tsu):时钟沿到来之前,数据必须稳定的最短时间。
- 保持时间(Th):时钟沿到来之后,数据必须稳定的最短时间。
违反这两个时间,寄存器就会进入“亚稳态”——输出不确定,整个电路逻辑就乱了。我在项目中遇到过,一个高速接口的保持时间违例,查了三天,最后发现是时钟树综合时没处理好。
核心公式(STA检查):
// 建立时间检查
Tclk + Tskew >= Tcq + Tcomb + Tsu
// 保持时间检查
Tcq + Tcomb >= Th + Tskew
其中:Tclk是时钟周期,Tskew是时钟偏移,Tcq是寄存器输出延迟,Tcomb是组合逻辑延迟。
我的小技巧: 做STA时,我习惯先看建立时间,因为它跟频率直接相关。保持时间违例通常可以通过插入延迟单元(Buffer)解决,但建立时间违例往往要动架构。
2.2 时钟抖动与时钟偏移:理想很丰满,现实很骨感
你想想看,时钟信号在芯片里传输,怎么可能完全同步?这里有两个概念必须分清:抖动和偏移。
- 时钟抖动(Jitter):时钟沿在时间轴上的随机波动。说白了,就是时钟沿“晃了一下”。
- 时钟偏移(Skew):同一个时钟信号到达不同寄存器的延迟差异。说白了,就是时钟沿“到得早晚不一样”。
为什么会这样?抖动主要来自电源噪声、热噪声;偏移主要来自时钟树的不平衡。我曾经在一个项目中,因为时钟偏移太大,导致建立时间余量不足,最后不得不重新做时钟树综合。
避坑指南: 我曾经以为抖动和偏移可以忽略,结果在高速设计中吃了大亏。记住:抖动会吃掉你的建立时间余量,偏移会同时影响建立和保持时间。做时序分析时,一定要把这两项留够余量。
| 特性 | 时钟抖动 | 时钟偏移 |
|---|---|---|
| 本质 | 时间上的随机变化 | 空间上的延迟差异 |
| 影响 | 主要影响建立时间 | 同时影响建立和保持时间 |
| 解决方法 | 低抖动PLL、去耦电容 | 平衡时钟树、H-tree结构 |
2.3 时序路径分类:STA的“地图”
做STA,你得知道你要检查哪些路径。我把它们分成四类,就像地图上的四条主干道:
- 输入到寄存器路径:从芯片输入端口到第一个寄存器的D端。
- 寄存器到寄存器路径:从上一个寄存器的时钟端到下一个寄存器的D端。这是最常见的路径。
- 寄存器到输出路径:从最后一个寄存器的时钟端到芯片输出端口。
- 输入到输出路径:从芯片输入端口直接到输出端口(纯组合逻辑路径)。
嗯,这里要注意:第四类路径在同步设计中很少见,但异步接口里经常遇到。我建议你重点检查前两类,它们占了90%以上的时序违例。
实际项目中的检查顺序:
1. 先跑所有寄存器到寄存器的路径(最核心)
2. 再跑输入到寄存器的路径(看IO约束是否合理)
3. 最后跑寄存器到输出的路径(看输出延迟是否满足)
4. 输入到输出路径(如果有,单独处理)
我个人习惯,在综合阶段就先把寄存器到寄存器的路径跑一遍。如果这里都有问题,那后面的步骤基本白费。你想想看,芯片内部都跑不顺,IO再优化也没用。
经验之谈: 做STA时,别只看最差情况(Worst Case)。我建议你同时看最好情况(Best Case)和最差情况,因为保持时间违例往往在最好情况下暴露。嗯,这个坑我踩过。
好了,时序分析的基础就这些。记住:建立时间和保持时间是根本,抖动和偏移是现实,路径分类是地图。下一章咱们聊聊怎么用工具做STA,以及那些让人头疼的约束怎么写。