4、低功耗设计流程:从RTL到GDSII,低功耗设计在传统数字后端流程中的嵌入

说实话,我刚入行那会儿,低功耗设计还是个「锦上添花」的活儿。项目紧张的时候,先把功能跑通再说,功耗嘛,后面再优化。结果呢?有一次流片回来,芯片在实验室里一跑,温度直接飙到85度,封装都快扛不住了。从那以后,我再也不敢把功耗问题拖到最后。

今天我们就聊聊,低功耗设计到底怎么嵌入到传统的数字后端流程里。说白了,就是从RTL到GDSII,每一步你都得想着「省电」这件事。

4.1 传统数字后端流程回顾

先简单回顾一下传统流程,这样我们才好说「嵌入」在哪儿。

  • RTL设计:写代码,做功能验证。
  • 逻辑综合:把RTL转成门级网表。
  • 布局规划:确定各个模块的位置。
  • 时钟树综合:把时钟信号送到每个触发器。
  • 布线:把所有的标准单元连起来。
  • 物理验证:DRC、LVS,确保能生产。
  • 时序签核:STA,确保能跑在目标频率。

嗯,这个流程本身没问题。但问题是,它默认所有模块都是「全速运行」的。你想想看,手机待机的时候,CPU根本不需要跑2GHz,对吧?

4.2 低功耗设计在RTL阶段的嵌入

我个人习惯,在RTL阶段就要开始想功耗了。不是等到综合才动手。

4.2.1 功耗意图文件(UPF/CPF)

低功耗设计的第一步,就是定义功耗意图。我们用UPF(Unified Power Format)或者CPF(Common Power Format)来描述。

举个例子,一个简单的UPF文件长这样:

# 定义电源域
create_power_domain PD_TOP -include_scope
create_power_domain PD_SLEEP -elements {u_sleep_block}

# 定义电源端口
create_supply_port VDD_TOP -domain PD_TOP
create_supply_port VDD_SLEEP -domain PD_SLEEP

# 定义电源网络
create_supply_net VDD_TOP_NET -domain PD_TOP
create_supply_net VDD_SLEEP_NET -domain PD_SLEEP

# 连接电源端口到网络
connect_supply_net VDD_TOP_NET -port VDD_TOP
connect_supply_net VDD_SLEEP_NET -port VDD_SLEEP

# 定义电平转换器
set_level_shifter LS1 -domain PD_TOP -applies_to outputs
set_level_shifter LS2 -domain PD_SLEEP -applies_to inputs

# 定义隔离单元
set_isolation ISO1 -domain PD_SLEEP -applies_to outputs
set_isolation_control ISO1 -isolation_signal iso_en -isolation_value 0

这段代码定义了三个东西:电源域、电平转换器、隔离单元。我在项目中遇到过,有人忘了加隔离单元,结果睡眠域断电后,输出信号浮空,把接收端的逻辑直接搞乱了。嗯,这种坑踩过一次就记住了。

4.2.2 时钟门控

时钟门控是RTL阶段最常用的低功耗手段。说白了,就是模块不用的时候,把时钟关掉。

RTL代码里,我们这样写:

// 不好的写法:时钟一直跑
always @(posedge clk) begin
  if (enable) begin
    data_out <= data_in;
  end
end

// 好的写法:用时钟门控
reg clk_gated;
assign clk_gated = clk & enable;

always @(posedge clk_gated) begin
  data_out <= data_in;
end

你可能会问:「直接用AND门不就行了吗?」嗯,这里要注意,直接用AND门会产生毛刺。所以实际项目中,我们用的是专用的时钟门控单元(ICG),它内部有锁存器,能保证时钟的完整性。

4.3 低功耗设计在逻辑综合阶段的嵌入

综合阶段,工具会根据UPF文件,自动插入电平转换器、隔离单元、以及电源开关。

4.3.1 多阈值电压库

综合的时候,工具会从库里面选单元。库里有三种单元:

类型 速度 漏电功耗 使用场景
HVT(高阈值) 非关键路径
RVT(标准阈值) 一般路径
LVT(低阈值) 关键路径

我建议,综合的时候先让工具尽量用HVT单元,只在时序紧张的地方换成LVT。这样能省不少漏电。我曾经有个项目,光靠这个技巧,漏电功耗就降了30%。

4.3.2 电源开关的插入

对于需要关断的电源域,综合阶段会插入电源开关(Power Switch)。这些开关像一个个小阀门,控制着电流的通断。

工具会自动把电源开关放在电源域的边界上,形成一圈「开关环」。嗯,这里要注意,开关的驱动能力要够,不然电压降会很大。

4.4 低功耗设计在布局规划阶段的嵌入

布局规划阶段,我们要把电源域在物理上分开。

4.4.1 电源域的物理划分

每个电源域都有自己的电源网络。比如,常开域用VDD_TOP,睡眠域用VDD_SLEEP。这两个网络在物理上是隔离的。

我在项目中遇到过,有人把两个域的电源网络画得太近,结果DRC报了一堆错。后来我们规定,不同电源域之间至少留5微米的间距。

4.4.2 电平转换器的放置

电平转换器要放在电源域的边界上。工具会自动识别跨域的信号,然后插入对应的电平转换器。

我个人习惯,在布局规划阶段就手动检查一下电平转换器的位置。如果放得太远,走线会很长,不仅影响时序,还会增加动态功耗。

4.5 低功耗设计在时钟树综合阶段的嵌入

时钟树综合阶段,我们要考虑时钟门的插入位置。

4.5.1 时钟门的层次化插入

时钟门可以放在时钟树的各个层级。比如,顶层时钟门控制整个模块,底层时钟门控制单个寄存器。

我建议,尽量把时钟门放在靠近时钟源的位置。这样关断时钟的时候,能省掉一大段时钟树的功耗。你想想看,时钟树上的buffer和inverter,每个都在耗电,关掉一个分支就能省一大片。

4.5.2 时钟树的功耗优化

时钟树综合的时候,工具会尽量用HVT的buffer和inverter。但有时候,为了满足时钟偏斜的要求,不得不用LVT的单元。

嗯,这里有个技巧:可以手动调整时钟树的结构,减少buffer的级数。级数越少,功耗越低。

4.6 低功耗设计在布线阶段的嵌入

布线阶段,主要关注的是电源网络的电阻和电容。

4.6.1 电源网络的IR Drop分析

布线完成后,要做IR Drop分析。说白了,就是检查电源网络上的电压降。如果某个区域的电压降太大,标准单元可能无法正常工作。

我曾经有个项目,睡眠域唤醒的时候,瞬间电流太大,导致电压降了0.2V。后来我们加宽了电源线,才把问题解决。

4.6.2 信号线的屏蔽

对于高频信号线,建议在旁边加一条地线做屏蔽。这样能减少信号翻转时的串扰,也能降低动态功耗。

4.7 低功耗设计在物理验证阶段的嵌入

物理验证阶段,除了常规的DRC和LVS,还要做低功耗相关的检查。

4.7.1 电源域隔离检查

检查每个电源域是否被正确隔离。比如,睡眠域的输出信号是否都经过了隔离单元。

4.7.2 电平转换器检查

检查跨域信号是否都经过了电平转换器。如果漏了一个,芯片可能直接烧掉。

⚠️ 警告: 电平转换器漏插是低功耗设计中最常见的错误之一。我曾经在项目中吃过这个亏,一个跨域信号没加电平转换器,结果芯片工作异常,查了整整两周才找到原因。所以,物理验证阶段一定要做电平转换器的覆盖率检查。

4.8 低功耗设计在时序签核阶段的嵌入

时序签核阶段,要同时考虑多种工作模式。

4.8.1 多模式多角分析

低功耗芯片有多种工作模式,比如:

  • 全速模式:所有域都上电,时钟全开。
  • 睡眠模式:部分域断电,时钟关断。
  • 唤醒模式:从睡眠模式切换到全速模式。

每种模式都要做STA。我建议,先做全速模式的时序分析,再做睡眠模式的。因为睡眠模式下,很多信号是固定的,时序约束相对简单。

4.8.2 电压降对时序的影响

IR Drop会导致标准单元的延迟增加。所以,STA的时候要加上IR Drop的影响。

嗯,这里有个坑:IR Drop分析的结果是静态的,但实际芯片工作的时候,电流是动态变化的。所以,我们一般会留10%的时序余量。

4.9 总结

低功耗设计不是最后才做的事,而是从RTL到GDSII,每一步都要考虑。我个人习惯,在项目开始的时候就制定好低功耗策略,然后每个阶段都检查一遍。

最后,送大家一句话:功耗问题,早发现早解决。拖到流片回来再改,成本高得吓人。

💡 小技巧: 如果你刚开始做低功耗设计,建议先从时钟门控和电源关断这两个技术入手。它们的效果最明显,实现起来也相对简单。等熟悉了,再尝试动态电压频率调整(DVFS)和衬底偏置这些高级技术。

好了,这一章就聊到这儿。下一章我们讲讲低功耗验证,看看怎么确保你的低功耗设计真的能工作。