Innovus中_clock_gen skew group的隐藏陷阱:如何避免自动分组导致的时序问题
最近在做一个28nm工艺下的中规模SoC项目时,遇到了一个相当隐蔽的时序问题。在CTS阶段,所有指标看起来都很完美——skew控制在20ps以内,insertion delay也符合预期。然而到了post-CTS时序分析时,几个关键路径突然出现了严重的hold violation,最糟糕的地方达到了-80ps。更让人困惑的是,这些路径在pre-CTS阶段明明都是干净的。
排查过程相当曲折。起初怀疑是cell placement的问题,重新做了几次placement优化,结果依旧。接着检查了SDC约束,确认时钟定义和时序例外都正确无误。直到深入分析clock tree report时,才注意到工具自动生成了一批以_clock_gen开头的skew group。这些分组把设计中的分频寄存器和它的配置寄存器归到了一起,导致原本应该属于不同时钟域的寄存器被强行平衡时钟延迟——这正是问题的根源。
如果你也在使用Innovus进行时钟树综合,特别是设计中包含时钟分频电路,那么这篇文章可能会帮你避开一个相当耗时的陷阱。我将详细解释_clock_gen skew group的生成机制,它如何悄无声息地破坏你的时序收敛,以及如何通过精确控制来避免这种情况。
1. 理解skew group的本质与Innovus的自动分组逻辑
在深入探讨_clock_gen这个特定问题之前,我们需要先建立对skew group机制的基本理解。很多人把skew group简单理解为"需要平衡时钟延迟的一组sink",这种理解虽然没错,但过于表面了。
1.1 skew group的底层逻辑
从工具的角度看,skew group实际上定义了时钟延迟平衡的边界。工具会确保同一个skew group内的所有sink具有尽可能一致的clock insertion delay,但不同skew group之间的延迟差异则不受约束。这种设计原本是为了处理多时钟域、生成时钟等复杂场景,但自动分组机制有时会过度"热心"。
注意:skew group的划分直接影响CTS的优化目标。错误的划分会导致工具在不该平衡的地方花费大量精力,而在真正需要平衡的地方却缺乏约束。
Innovus默认的skew group生成规则基于时钟网络的结构关系。当工具检测到以下情况时,可能会创建额外的skew group:
- 时钟生成逻辑:如PLL输出、分频器、时钟门控单元
- 时钟复用结构:MUX选择不同时钟源的路径
- 时钟缓冲链:特别长的缓冲器链路上的节点
- 物理上隔离的区域:由于floorplan导致的物理隔离区域
1.2 _clock_gen skew group的触发条件
_clock_gen这个命名前缀已经暗示了它的来源——时钟生成电路。在实际项目中,我观察到以下几种典型场景会触发这种自动分组:
| 电路结构 | 触发原因 | 潜在问题 |
|---|---|---|
| 同步分频器 | 工具识别到分频寄存器与配置寄存器间的时序路径 | 破坏原始时钟域的平衡 |
| 可编程时钟发生器 | 配置总线与分频逻辑的交互 | 引入不必要的时钟延迟匹配 |
| 时钟门控使能链 | 使能信号生成逻辑与时钟门的连接 | 增加时钟树复杂度 |
最棘手的是第一种情况,也就是文章开头提到的分频电路问题。考虑下面这个典型的分频器设计:
// 典型的可配置分频器
module clk_divider (
input wire clk,
input wire rst_n,
input wire [3:0] div_ratio,
output wire clk_div
);
reg [3:0] counter;
reg div_reg;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
counter <= 4'd0;
div_reg <= 1'b0;
end else begin
if (counter == div_ratio - 1) begin
counter <= 4'd0;
div_reg <= ~div_reg;
end else begin
counter <= counter + 1;
end
end
end
assign clk_div = div_reg;
endmodule
在这个设计中,div_reg是分频输出的寄存器,而counter是分频计数器。Innovus的时序分析引擎会检测到从counter寄存器到div_reg的数据路径(在扫描链模式下尤为明显),然后"聪明"地认为这些寄存器应该共享相似的时钟延迟,于是将它们归入同一个_clock_gen skew group。
1.3 自动分组的利弊权衡
工具的这种行为并非bug,而是基于特定假设的设计选择。从理论上讲,将相关的时钟生成逻辑放在一起平衡有以下潜在好处:
- 改善局部时序:确保配置信号到分频寄存器的路径满足时序
- 降低功耗:通过局部平衡减少不必要的时钟缓冲
- 简化约束:对于简单设计,可以减少手动定义skew group的工作量
然而,在实际的复杂SoC设计中,这种自动分组往往弊大于利。主要问题在于:
- 破坏时钟域边界:分频器的配置寄存器通常属于主时钟域,而分频输出属于新的时钟域
- 增加时钟树复杂度:不必要的平衡约束可能导致时钟树过度缓冲
- 引入时序冲突:如文章开头案例所示,可能引发难以调试的hold violation
我曾经在一个图像处理芯片的项目中,就因为这个问题多花了近一周的调试时间。设计中有8个不同频率的时钟域,每个都由可编程分频器生成。Innovus为每个分频器都创建了_clock_gen skew group,结果导致时钟树变得异常复杂,最终不得不重新梳理整个时钟架构。
2. 问题定位:如何识别_clock_gen导致的时序问题
发现问题是解决问题的第一步。对于_clock_gen skew group引起的问题,症状往往比较隐蔽,需要系统的排查方法。
912




被折叠的 条评论
为什么被折叠?



