4. 保持时间违例分析

保持时间违例,说实话,是时序分析里最让人头疼的问题之一。建立时间违例你还能通过降频、加流水线来补救,但保持时间违例一旦出现,基本就是动电路结构了。我刚开始做后端时,就被一个保持时间违例折腾了两周,最后发现是时钟偏斜搞的鬼。

4.1 保持时间公式推导

先来推公式。保持时间检查,说白了就是看数据能不能稳定地待在触发器里。

对于发射触发器(launch flop)和捕获触发器(capture flop),保持时间要满足:

数据到达时间 > 数据要求时间

数据到达时间:

Data_arrival = T_clk_launch + T_ck2q + T_data_path

数据要求时间:

Data_required = T_clk_capture + T_hold

保持时间余量:

Hold_slack = Data_arrival - Data_required
           = (T_clk_launch + T_ck2q + T_data_path) - (T_clk_capture + T_hold)

这里有个关键点——时钟偏斜。我们把时钟偏斜定义为:

T_skew = T_clk_capture - T_clk_launch

代入公式:

Hold_slack = T_ck2q + T_data_path - T_hold - T_skew

核心结论:保持时间违例和时钟周期无关!它只取决于数据路径延迟、时钟偏斜和触发器的保持时间要求。

嗯,这里要注意。建立时间检查看的是最慢路径,保持时间检查看的是最快路径。为什么?因为数据到达得越早,越容易破坏上一个数据的保持时间要求。

4.2 违例原因分析

我在项目中遇到过三种最常见的保持时间违例原因,一个一个说。

4.2.1 时钟偏斜

时钟偏斜对保持时间的影响,说白了就是「成也萧何,败也萧何」。

如果捕获时钟比发射时钟晚到(正偏斜),保持时间余量会变小:

Hold_slack = T_ck2q + T_data_path - T_hold - T_skew

你看,T_skew 越大,余量越小。我曾经在一个项目中,时钟树综合没做好,导致两个相邻触发器之间的时钟偏斜达到了 200ps。结果保持时间违例一片一片的,修得我头皮发麻。

避坑指南:我曾经遇到过一种情况——时钟偏斜看起来不大,但数据路径几乎为零(两个触发器背靠背放置),结果保持时间还是违例了。所以,时钟偏斜要结合数据路径一起看。

4.2.2 数据路径过短

这是保持时间违例最常见的原因。数据路径太短,数据嗖的一下就过去了,捕获触发器还没准备好。

什么情况下数据路径会过短?

  • 两个触发器直接相连——中间没有任何组合逻辑
  • 使用了低驱动强度的单元——但路径长度本身很短
  • 扫描链上的保持时间违例——扫描链通常路径很短

我记得有一次做低功耗设计,用了很多低阈值电压的单元。结果保持时间违例报表一出来,好家伙,几百条。原因就是低阈值单元速度太快,数据路径延迟太小。

个人经验:我建议在综合阶段就检查保持时间。虽然保持时间通常在布局布线后修,但综合阶段可以提前发现那些「数据路径过短」的极端情况,提前插入缓冲器。

4.2.3 工艺角影响

工艺角对保持时间的影响,和建立时间正好相反。

工艺角 对建立时间的影响 对保持时间的影响
慢工艺角(SS) 最差(路径延迟最大) 最好(路径延迟最大)
快工艺角(FF) 最好(路径延迟最小) 最差(路径延迟最小)
典型工艺角(TT) 中等 中等

所以,保持时间分析要在最快工艺角下做。你想想看,芯片在低温、高电压下,晶体管开关速度最快,数据路径延迟最小,这时候保持时间最容易违例。

我有个血的教训。一次流片回来,芯片在常温下跑得好好的,一到低温就出问题。查了半天,就是保持时间在低温工艺角下违例了。从那以后,我每次做保持时间分析,都会把快工艺角作为重点检查对象。

关键点:保持时间违例的修复,通常是在数据路径上插入缓冲器(buffer)或延迟单元(delay cell)。但要注意,插入缓冲器会增加功耗和面积,而且可能影响建立时间。所以,这是一个权衡的过程。

4.3 保持时间违例的典型场景

我总结了几种常见的保持时间违例场景,你在实际项目中大概率会遇到:

  1. 扫描链保持时间违例——扫描链路径短,而且通常跨模块,时钟偏斜大
  2. 时钟门控单元的保持时间违例——时钟门控使能信号路径短
  3. 异步复位同步器的保持时间违例——复位信号和时钟之间的时序关系复杂
  4. 多bit总线之间的保持时间违例——不同bit的路径延迟差异大

嗯,这里要特别说一下扫描链。我做过一个项目,扫描链上有上千个触发器,保持时间违例占了三分之一。最后怎么修的?在扫描链上逐级插入延迟单元,每修一条就重新跑一遍STA,折腾了整整一周。

实用技巧:我建议在布局布线阶段,对保持时间违例的路径设置较高的权重。这样布线工具会自动在数据路径上插入缓冲器,减少后续的手动修复工作。

4.4 保持时间违例的修复策略

修复保持时间违例,说白了就是让数据走慢一点。常用的方法有:

  • 插入缓冲器——在数据路径上串入缓冲器,增加延迟
  • 使用延迟单元——专门的延迟单元,延迟大、面积小
  • 调整时钟偏斜——让捕获时钟提前到达(负偏斜),但这会影响建立时间
  • 优化工艺角——在快工艺角下修复,确保在所有工艺角下都满足

我个人习惯是优先使用延迟单元。为什么?因为延迟单元的延迟大,插入一个就能解决很多问题,而且对功耗的影响比缓冲器小。

但要注意,延迟单元也有坑。我曾经用过一种延迟单元,在慢工艺角下延迟太大,反而导致了建立时间违例。所以,修复保持时间违例时,一定要同时检查建立时间。

重要提醒:修复保持时间违例后,一定要重新做STA验证。而且要在所有工艺角、所有温度、所有电压下都验证一遍。不要只盯着快工艺角看。

保持时间违例分析框架 保持时间违例 公式推导 违例原因分析 修复策略 Hold_slack = T_ck2q + T_data - T_hold - T_skew 与时钟周期无关 时钟偏斜(正偏斜恶化) 数据路径过短 工艺角影响(FF最差) 插入缓冲器/延迟单元 调整时钟偏斜 优化工艺角 核心:保持时间违例修复 = 增加数据路径延迟 同时检查建立时间,避免引入新违例

保持时间违例的分析,说白了就是一场和时间的赛跑。数据不能跑得太快,也不能跑得太慢。我做了这么多年芯片设计,最大的体会就是:时序分析没有捷径,只有踏踏实实地理解每一个公式、每一个工艺角的影响,才能在项目中出现问题时快速定位、快速修复。