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,每一步都要考虑。我个人习惯,在项目开始的时候就制定好低功耗策略,然后每个阶段都检查一遍。
最后,送大家一句话:功耗问题,早发现早解决。拖到流片回来再改,成本高得吓人。
好了,这一章就聊到这儿。下一章我们讲讲低功耗验证,看看怎么确保你的低功耗设计真的能工作。