二、工艺库与电压域:多阈值单元库、不同电压下的单元特性、库文件配置

好,咱们接着聊。上一章我讲了多电压域的基本概念,说白了就是芯片里不同模块各跑各的电压。但光有概念不行,你得有东西去实现它。什么东西?就是工艺库。

工艺库这东西,你想想看,它就像是设计师的「食材」。你要做一道菜,食材不对,再好的厨艺也白搭。多电压域设计也一样,库选不对,后面全是坑。

2.1 多阈值单元库:为什么要有高阈值和低阈值?

先问大家一个问题:一个晶体管的阈值电压 Vt 高一点好,还是低一点好?

嗯,这个问题没有标准答案。我当年刚入行时也这么想,后来被老工程师一句话点醒了——「高阈值省电但跑得慢,低阈值跑得快但漏电大」。说白了,这就是个 trade-off。

所以工艺厂会提供三种类型的标准单元库:

  • 高阈值(HVT):漏电最小,速度最慢。适合放在常开域或者对性能不敏感的地方。
  • 标准阈值(SVT / RVT):折中方案。大部分逻辑用这个就行。
  • 低阈值(LVT / ULVT):速度最快,但漏电也最大。只用在关键路径上。

核心原则:能用 HVT 的地方绝不用 LVT。我见过不少新手,一上来全用 LVT,结果芯片静态功耗爆炸,流片回来根本没法用。

我在一个 28nm 的项目里就吃过这个亏。当时为了赶时序,把整个模块都换成了 LVT 库。结果呢?时序是过了,但芯片待机电流比预期大了三倍。后来不得不重新做 ECO,把非关键路径全部换回 HVT。那次教训让我记住了——多阈值混合使用才是正道

2.2 不同电压下的单元特性

同一个标准单元,在不同的电压下表现完全不一样。你想想看,这就像一个人,吃饱了和饿着肚子干活,效率能一样吗?

具体来说,电压对单元的影响主要体现在三个方面:

特性参数 高电压(1.1V) 低电压(0.7V)
延迟 小(快) 大(慢)
动态功耗 大(P ∝ V²)
漏电功耗
噪声容限

这里有个关键点:延迟和电压不是线性关系。我做过实测,电压从 1.0V 降到 0.8V,延迟可能增加 50% 以上。所以做低电压设计时,时序分析一定要留够余量。

我的个人习惯:在做多电压域设计时,我会先跑一遍所有电压角下的时序。如果某个电压域在 0.8V 下时序紧张,我会提前考虑插入一些 LVT 单元,而不是等到最后再救火。

2.3 库文件配置:Liberty 文件里到底有什么?

好,到了实操环节。工艺库在 EDA 工具里是以 Liberty(.lib)文件的形式存在的。你打开一个 .lib 文件,里面密密麻麻全是表格和参数。我刚开始看的时候也是一头雾水。

其实核心就几个东西:

  • 电压定义:库文件头部会声明这个库适用的电压范围。
  • 时序弧(Timing Arc):每个单元的输入到输出的延迟查表(NLDM 或 CCS 模型)。
  • 功耗模型:内部功耗、漏电功耗、短路功耗等。
  • 约束条件:建立时间、保持时间、最小脉冲宽度等。

举个例子,一个简单的反相器在 .lib 里的描述大概长这样:

cell (INV_X1) {
  area : 0.5;
  pin (A) {
    direction : input;
    capacitance : 0.002;
  }
  pin (Y) {
    direction : output;
    function : "(!A)";
    timing () {
      related_pin : "A";
      timing_sense : negative_unate;
      cell_rise (delay_template_7x7) {
        index_1 ("0.1, 0.3, 0.5, 0.7, 0.9, 1.1, 1.3");
        index_2 ("0.01, 0.02, 0.05, 0.1, 0.2, 0.4, 0.8");
        values ( \
          "0.05, 0.08, 0.12, 0.18, 0.25, 0.35, 0.50", \
          ...
        );
      }
    }
  }
}

看到那个 delay_template_7x7 了吗?这就是一个 7×7 的查找表。横轴是输入转换时间,纵轴是输出负载电容。工具会根据实际值查表插值得到延迟。

注意:不同电压域要用对应的库文件。你不能把 1.0V 的库用在 0.8V 的域里。我曾经见过有人把库配错了,结果 STA 报出来的时序全是错的,查了两天才发现是库文件版本不对。

2.4 多电压域下的库配置策略

在实际项目中,我们通常会给每个电压域单独指定库文件。比如:

  • Core 域(1.0V):使用 tcbn28hpcplus_ccs_1v0.lib
  • IO 域(1.8V):使用 tcbn28hpcplus_ccs_1v8.lib
  • SRAM 域(0.9V):使用 tcbn28hpcplus_ccs_0v9.lib

在 Synopsys 工具链里,配置方式是这样的:

set target_library "tcbn28hpcplus_ccs_1v0.lib tcbn28hpcplus_ccs_0v9.lib"
set link_library "* $target_library tcbn28hpcplus_ccs_1v8.lib"

# 为每个电压域指定库
set_voltage_domain -name CORE -voltage 1.0
set_voltage_domain -name SRAM -voltage 0.9
set_voltage_domain -name IO -voltage 1.8

# 将库关联到电压域
set_domain_library -domain CORE -library tcbn28hpcplus_ccs_1v0.lib
set_domain_library -domain SRAM -library tcbn28hpcplus_ccs_0v9.lib
set_domain_library -domain IO -library tcbn28hpcplus_ccs_1v8.lib

这里有个容易踩的坑:不同电压域的库,其 PVT(工艺-电压-温度)角必须匹配。你不能 Core 域用 worst-case 库,SRAM 域却用 best-case 库。那样分析出来的结果毫无意义。

避坑指南:我建议在项目初期就把所有电压域的库文件清单整理好,做成一个配置文件。每次跑流程前先检查一遍库文件版本和 PVT 角是否一致。这个习惯救过我很多次。

2.5 小结

嗯,这一章内容不少。总结一下:

  • 多阈值库(HVT/SVT/LVT)是平衡性能和功耗的关键工具
  • 电压降低会显著影响单元延迟和功耗,设计时要留余量
  • 库文件配置要仔细,不同电压域用不同的库,PVT 角要一致

下一章我会讲电平转换单元(Level Shifter)和隔离单元(Isolation Cell)的设计与插入策略。这些东西是连接不同电压域的桥梁,搞不好就会出大问题。咱们下回见。