14. 【RTL_Synthesis】Cell Characterization Data(cell特性数据)
🔬 单元特征化数据:从硅片物理到仿真数字的桥梁
今天我们来深入一个非常核心的话题——单元特征化数据。
你可能已经知道 Liberty 文件里存着标准单元的时序信息,但你知道这些数字是怎么来的吗?它们不是凭空编出来的,而是通过在硅片上实际测量得到的。这个过程叫单元特征化——就像给每个标准单元做一次全面“体检”,然后把体检结果变成一张张查表,供 EDA 工具使用。
理解这些数据的含义,是读懂时序报告、解决时序违例的关键。这一讲,我们就一起揭开时序数据的“黑盒子”。
1. 时序弧(Timing Arc)—— 时序分析的“最小单位”
1.1 什么是时序弧?
想象你有一条管道,水从一头流入(输入引脚),从另一头流出(输出引脚)。水流过管道需要时间,而且水流的速度(输入信号变化快慢)和管道的粗细(输出负载大小)都会影响出水的时间。
时序弧就是描述这种“从某个输入引脚到某个输出引脚的信号传播关系”的抽象。每个时序弧都包含:
- 哪个输入引脚影响哪个输出引脚
- 输出响应是上升还是下降(或者两者都有)
- 在不同条件下的延迟和输出转换时间
1.2 Liberty 中的时序弧表示
一个简单的反相器,只有一个时序弧:从 A 到 Y。
cell (INV_X1) {
pin (A) { direction : input; capacitance : 0.0015; }
pin (Y) { direction : output; function : "!A"; }
timing () {
related_pin : "A"; // 哪个输入引脚
timing_sense : negative_unate; // 输出与输入反相
timing_type : combinational; // 组合逻辑弧
/* 当输入上升,输出下降的延迟表 */
cell_fall (delay_template_5x5) { ... }
/* 当输入下降,输出上升的延迟表 */
cell_rise (delay_template_5x5) { ... }
/* 输出转换时间表(上升/下降)*/
rise_transition (delay_template_5x5) { ... }
fall_transition (delay_template_5x5) { ... }
}
}
1.3 多输入门的多个时序弧
对于 NAND2 门,有两个输入引脚 A 和 B,每个引脚到输出 Y 都有一个独立的时序弧。而且,一个弧是否“活跃”可能取决于另一个输入的状态。
cell (NAND2_X1) {
pin (A) { direction : input; capacitance : 0.0018; }
pin (B) { direction : input; capacitance : 0.0018; }
pin (Y) { direction : output; function : "!(A & B)"; }
timing () {
related_pin : "A";
timing_sense : negative_unate;
when : "B"; // 只有当 B 为高电平时,A 的变化才能传到 Y
/* 延迟表... */
}
timing () {
related_pin : "B";
timing_sense : negative_unate;
when : "A"; // 只有当 A 为高电平时,B 的变化才能传到 Y
/* 延迟表... */
}
}
为什么需要多个弧? 因为 A 和 B 在晶体管中的位置不同,延迟可能不一样。时序分析工具需要分别计算,才能准确知道最坏情况。
2. 时序 sense(Timing Sense)—— 输出变化的方向
- positive_unate:输出变化方向与输入相同。例如缓冲器:输入上升 → 输出上升。
- negative_unate:输出变化方向与输入相反。例如反相器:输入上升 → 输出下降。
- non_unate:输出变化方向依赖于其他输入状态。例如 XOR 门:A 上升,Y 可能上升也可能下降,取决于 B。
3. 时序单元(触发器/锁存器)的时序特性
顺序单元比组合门复杂得多。它们有三个关键时序参数:建立时间、保持时间、时钟到输出延迟。
3.1 建立时间(Setup Time)——“数据要早到”
物理含义:在时钟沿到来之前,数据必须稳定一段时间,让触发器内部的主锁存器能够可靠地采样。
Liberty 表示:
ff ("IQ", "IQN") {
next_state : "D";
clocked_on : "CP";
}
timing () {
related_pin : "D";
timing_type : setup_rising; // 上升沿触发的建立时间
rise_constraint (setup_template_5x5) {
index_1 ("0.01, 0.05, 0.1, 0.2, 0.4"); // 数据转换时间
index_2 ("0.01, 0.05, 0.1, 0.2, 0.4"); // 时钟转换时间
values ( \
"0.085, 0.090, 0.098, 0.114, 0.146", \
"0.083, 0.088, 0.096, 0.112, 0.144", \
"0.079, 0.084, 0.092, 0.108, 0.140", \
"0.071, 0.076, 0.084, 0.100, 0.132", \
"0.055, 0.060, 0.068, 0.084, 0.116" \
);
}
/* 还有 fall_constraint 用于数据下降沿 */
}
关键点:建立时间不是常数,而是随数据转换时间和时钟转换时间变化。通常,数据转换越快,需要的建立时间越大(因为内部节点切换剧烈,需要更多时间稳定)。
3.2 保持时间(Hold Time)——“数据不能走太快”
物理含义:时钟沿之后,数据必须稳定一段时间,让主锁存器完成捕获。如果数据变化太快,可能还没来得及锁存就变了。
Liberty 表示:
timing () {
related_pin : "D";
timing_type : hold_rising;
rise_constraint (hold_template_5x5) {
index_1 ("0.01, 0.05, 0.1, 0.2, 0.4");
index_2 ("0.01, 0.05, 0.1, 0.2, 0.4");
values ( \
"0.042, 0.038, 0.031, 0.017, -0.015", \
"0.044, 0.040, 0.033, 0.019, -0.013", \
"0.048, 0.044, 0.037, 0.023, -0.009", \
"0.056, 0.052, 0.045, 0.031, -0.001", \
"0.072, 0.068, 0.061, 0.047, 0.015" \
);
}
}
注意负值:负的保持时间意味着数据可以在时钟沿之前就开始变化,仍然能被正确捕获。这是良好设计的体现。
致命问题:保持时间违例无法通过降低时钟频率修复,只能修改物理设计(添加缓冲器延迟)。所以保持时间必须用最快的角(FF)验证。
3.3 时钟到输出延迟(Clock-to-Q Delay)——“输出响应时间”
物理含义:时钟沿触发后,输出 Q 需要多长时间才反映出新数据。
Liberty 表示:
timing () {
related_pin : "CP";
timing_type : rising_edge;
timing_sense : non_unate; // 输出变化方向取决于数据
cell_rise (delay_template_5x5) {
index_1 ("0.01, 0.05, 0.1, 0.2, 0.4"); // 时钟转换时间
index_2 ("0.01, 0.05, 0.1, 0.2, 0.4"); // 输出负载
values ( \
"0.156, 0.168, 0.192, 0.240, 0.336", \
"0.160, 0.172, 0.196, 0.244, 0.340", \
"0.168, 0.180, 0.204, 0.252, 0.348", \
"0.184, 0.196, 0.220, 0.268, 0.364", \
"0.216, 0.228, 0.252, 0.300, 0.396" \
);
}
cell_fall (delay_template_5x5) { ... }
rise_transition (...)
fall_transition (...)
}
4. 传播延迟的二维查表模型
无论是组合门还是时序单元的时钟到输出,延迟都不是一个固定值,而是 输入转换时间 和 输出负载 的函数。
4.1 为什么是这两个变量?
- 输入转换时间(input transition):输入信号变化得越慢,内部节点在“线性区”停留的时间越长,输出变化越慢,延迟越大。
- 输出负载(output load):负载电容越大,需要充放的电荷越多,输出变化越慢,延迟越大。
4.2 非线性的关系
这些关系不是线性的。比如,负载从 0.01pF 增加到 0.02pF,延迟可能增加 20%;从 0.2pF 增加到 0.4pF,延迟可能增加 50%。所以不能用一个简单公式,必须用二维查表。
4.3 为什么上升和下降延迟不同?
NMOS 和 PMOS 天生不对称:NMOS 电子迁移率高,通常比 PMOS 强。所以反相器输出下降(NMOS 导通)通常比输出上升(PMOS 导通)快。在 Liberty 中,分别用 cell_fall 和 cell_rise 表格表示。
5. 转换时间(Slew)——“信号爬坡速度”
5.1 定义
转换时间(也称 slew)指信号在逻辑 0 和逻辑 1 之间变化所需的时间。通常定义为从 20% 到 80% VDD 的时间(也可能 10%-90% 或 30%-70%)。
5.2 为什么重要
- 传递性:一个门的输出转换时间,就是下一个门的输入转换时间。所以必须逐级传播,才能准确计算后续门的延迟。
- 信号完整性:太慢的转换(大 slew)使信号易受噪声干扰,可能引起多次误翻转;太快的转换(小 slew)会引发地弹、EMI 问题。
- 约束检查:库中通常有
max_transition限制,超过此限制,特性数据可能无效,需加强驱动或加缓冲器。
Liberty 中用 rise_transition 和 fall_transition 表格描述输出转换时间,索引同样是输入转换时间和输出负载。
6. 电容值 —— 决定负载的关键
6.1 输入电容
每个输入引脚都有电容,它是驱动这个引脚所必须充放的负载。不同驱动强度的单元,输入电容不同:INV_X1 输入电容 0.0015pF,INV_X4 可能 0.0060pF(因为晶体管更大)。
6.2 输出电容
输出引脚本身也有寄生电容,通常比输入小得多,但也会计入总负载。
6.3 最大电容约束
每个输出引脚都有 max_capacitance 限制。超出此限制,可能无法达到有效的逻辑电平。工具会在综合时避免扇出过大,或在布局布线后插入缓冲器。
6.4 总负载计算
总负载 = 输出引脚寄生电容 + 线电容 + 所有扇出单元的输入电容之和
这个总负载就是用来查延迟表的 index_2。
7. 一个完整的时序计算例子
让我们跟随一个简单路径,看看工具是怎么一步步计算时序的。
FF1/Q ──→ INV1/A ──→ INV1/Y ──→ NAND2/A ──→ NAND2/Y ──→ FF2/D
步骤 1:时钟到 Q 延迟(FF1)
- 时钟转换时间:0.05 ns
- 输出负载(到 INV1 输入 + 线电容):0.025 pF
- 查表得到时钟到 Q 延迟:0.168 ns
- 输出转换时间:0.040 ns(成为 INV1 的输入转换时间)
步骤 2:反相器 INV1 延迟
- 输入转换时间:0.040 ns
- 输出负载(到 NAND2 输入 + 线电容):0.030 pF
- 查表得到反相器延迟(从 A 到 Y):0.058 ns
- 输出转换时间:0.045 ns(成为 NAND2 的输入转换时间)
步骤 3:NAND2 延迟
- 输入转换时间:0.045 ns
- 输出负载(到 FF2 输入 + 线电容):0.020 pF
- 查表得到 NAND2 延迟:0.063 ns
- 输出转换时间:0.038 ns(成为 FF2 的数据转换时间)
步骤 4:FF2 建立时间检查
- 数据转换时间:0.038 ns
- 时钟转换时间:0.05 ns
- 查表得到建立时间要求:0.090 ns
总路径延迟 = 0.168 + 0.058 + 0.063 = 0.289 ns
所需时钟周期 ≥ 0.289 + 0.090 = 0.379 ns → 最高频率 ≈ 2.64 GHz
这就是时序分析工具在做的事——对每条路径重复成百上千万次这样的查表和计算。
8. 常见陷阱与最佳实践
陷阱 1:超出表格范围
如果设计中的输入转换时间或输出负载超过了表格的最大索引,工具会进行外推(线性外推),但实际特性是非线性的,外推结果可能严重不准。
解决办法:通过设计约束(如 set_max_transition、set_max_capacitance)确保所有信号落在表征范围内。
陷阱 2:忽略转换时间
只看延迟,不检查转换时间约束(max_transition),可能导致后续级延迟计算错误,甚至信号完整性问题。
解决办法:在时序签核时同时检查 max_transition 和 max_capacitance。
陷阱 3:混淆建立时间和保持时间的角
- 建立时间(setup)检查必须用最慢的角(SS,高电压?等等,SS 配低电压高温),因为最大延迟路径发生在慢工艺、低电压、高温下。
- 保持时间(hold)检查必须用最快的角(FF,高电压、低温),因为最小延迟路径发生在快工艺、高电压、低温下。
常见错误:用同一个角检查 setup 和 hold,会漏掉违规。
陷阱 4:单位混淆
Liberty 文件中 capacitive_load_unit (1, pf) 表示电容单位是皮法,但寄生提取工具可能输出飞法(fF)。1 pF = 1000 fF,搞错就是 1000 倍的误差。
解决办法:始终检查单位,必要时转换。
9. 集成到设计流程
- 综合阶段:工具用 Liberty 中的电容和延迟数据做面积/速度权衡,并控制扇出不超过
max_capacitance。 - 布局布线阶段:实际线电容被计算出来,工具重新计算延迟,插入缓冲器修复时序。
- 签核 STA:使用全套角库,对所有路径做建立/保持检查,并验证转换时间约束。
10. 总结
单元特征化数据是连接物理硅片与数字设计工具的桥梁:
- 时序弧定义了信号从一个引脚到另一个引脚的传播路径。
- 建立/保持时间是触发器的“安全窗口”,必须严格满足。
- 传播延迟和输出转换时间都是二维查表函数,取决于输入转换时间和输出负载。
- 电容值决定了负载大小,直接影响延迟和功耗。
- 理解这些数据,你才能读懂时序报告,知道违例是真实问题还是假象,才能正确指导后端工程师优化设计。
记住:你的芯片最终要在硅片上工作,而 Liberty 文件中的每一个数字,都是物理世界的一次精确测量。尊重这些数字,就是尊重物理规律。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)