4、电源门控:电源门控(Power Gating)架构设计,休眠保持寄存器(Retention Register)的使用,电源域划分与隔离策略。
各位做嵌入式的老铁,咱们接着聊低功耗。前面几章讲了动态电压频率调节和时钟门控,说白了都是在「运行中」省电。但有个问题——当某个模块完全没事干的时候,你光把时钟关了,漏电流还在那哗哗地流。这就好比人睡着了,灯还开着,空调还打着,你说浪费不浪费?
所以这一章,咱们聊聊真正的「断舍离」——电源门控。我做了这么多年低功耗设计,可以负责任地告诉你:电源门控是降低静态功耗最狠的手段,没有之一。但狠归狠,用不好容易翻车。咱们慢慢拆解。
4.1 电源门控的基本思想
电源门控,说白了就是把暂时不用的模块的电源彻底切断。不是降频,不是关时钟,是直接把电断了。这样漏电流就归零了。
你可能会问:「直接断电,那模块里的寄存器状态不就丢了吗?」
没错,这就是电源门控的核心矛盾——省电 vs 保状态。我早期做的一个物联网项目,为了省电把整个射频前端都断电了,结果每次唤醒都要重新初始化,那叫一个慢。后来才明白,不是所有模块都适合粗暴断电。
电源门控的基本架构,通常包含这几个要素:
- 电源开关(Power Switch):一般是高阈值的PMOS或NMOS管,用来控制电源通断
- 隔离单元(Isolation Cell):防止断电模块输出浮空,把不确定信号传到工作区
- 状态保持单元(Retention Register):在断电时保存关键状态,唤醒后快速恢复
- 电源域控制器(Power Controller):管理上电/断电时序的有限状态机
核心原则:电源门控不是「一刀切」,而是「按需断」。断得越细,省电越多,但控制逻辑越复杂,面积开销也越大。
4.2 休眠保持寄存器(Retention Register)的使用
好,咱们先解决那个最头疼的问题——状态保存。
我记得第一次做带电源门控的芯片时,架构师跟我说:「小张,这个模块断电后,你让它在100微秒内恢复工作。」我当时就懵了——100微秒,连重新加载固件都不够啊!
后来才知道,有一样神器叫「休眠保持寄存器」。它长什么样呢?
// 简化版的保持寄存器结构(Verilog描述)
module retention_ff (
input clk, d, rst_n,
input save_n, // 保存使能,低有效
input retain_n, // 保持使能,低有效
input vdd_sw, // 可关断电源
input vdd_ret, // 常开电源(保持用)
output q
);
// 主寄存器,由可关断电源供电
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
main_q <= 1'b0;
else
main_q <= d;
end
// 保持寄存器,由常开电源供电
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
ret_q <= 1'b0;
else if (!save_n)
ret_q <= main_q; // 保存主寄存器值
end
// 输出选择
assign q = retain_n ? main_q : ret_q;
endmodule
看到没?这个寄存器有两个电源轨:vdd_sw是可关断的,vdd_ret是常开的。正常工作时,主寄存器干活,保持寄存器待命。断电前,把主寄存器的值「快照」到保持寄存器里。唤醒后,再把值恢复回去。
这里有个关键点——保持寄存器用的是高阈值晶体管,漏电流极低。我测过一个0.18微米工艺的保持寄存器,保持电流只有几十纳安。你想想看,一个芯片里几百个保持寄存器,总漏电也就几微安,完全可以接受。
我的经验:不是所有寄存器都需要保持。我一般只保持「状态机状态」、「配置寄存器」、「关键数据指针」这三类。像FIFO里的数据、流水线里的中间结果,丢了就丢了,重新跑一遍就行。保持太多,面积和漏电都受不了。
4.3 电源域划分与隔离策略
电源域划分,说白了就是「谁跟谁一起断电」。这活儿看着简单,其实门道很深。
我见过一个团队,把CPU核和L1缓存放在同一个电源域里。结果CPU休眠时缓存也得跟着断,醒来后缓存全失效,性能一落千丈。这就是典型的划分失误。
电源域划分的几个原则,我总结一下:
- 功能相关性:经常一起工作的模块,放在同一个域。比如DMA和它的描述符存储器。
- 唤醒频率匹配:频繁唤醒的模块,不要和很少唤醒的模块绑在一起。否则每次唤醒都要带上一堆「累赘」。
- 电压域一致性:同一个电源域内的模块,工作电压应该相同。否则电平转换器又是一笔开销。
- 物理布局紧凑:电源域内的模块在版图上尽量挨着,减少电源走线的IR Drop。
隔离策略这块,我重点说说「隔离单元」的选择。常见的隔离方式有三种:
| 隔离方式 | 输出状态 | 适用场景 | 面积开销 |
|---|---|---|---|
| AND型隔离 | 输出钳位到0 | 控制信号、使能信号 | 小 |
| OR型隔离 | 输出钳位到1 | 复位信号、高有效信号 | 小 |
| 锁存型隔离 | 保持断电前最后一拍的值 | 数据总线、地址总线 | 中 |
我个人习惯,控制信号用AND型隔离,数据总线用锁存型隔离。为什么?因为控制信号通常低有效,断电后钳位到0最安全。数据总线如果钳死,可能会让接收端误以为有数据,所以保持最后一拍的值更稳妥。
避坑指南:我曾经在一个项目里,把隔离单元放在了断电域内部。结果断电后隔离单元自己先没电了,输出直接浮空,把隔壁工作域的信号全拉乱了。正确的做法是——隔离单元必须放在常开域,或者用常开电源供电。这个坑我踩过,你们别踩了。
4.4 电源门控的时序与唤醒流程
电源门控最容易被忽视的,就是时序控制。上电和断电不是瞬间完成的,中间有一系列步骤。
一个典型的唤醒流程是这样的:
- 请求唤醒:电源控制器收到唤醒信号(比如中断、定时器)
- 开启电源开关:先打开粗栅开关,再打开细栅开关,防止电流浪涌
- 等待电源稳定:等电压上升到90%以上,一般需要几十到几百微秒
- 释放隔离:把隔离单元从钳位状态切回正常状态
- 恢复寄存器:从保持寄存器把状态恢复到主寄存器
- 释放复位:模块开始正常工作
这里每一步都有讲究。比如开启电源开关时,如果一下子全打开,瞬间电流可能把电源轨拉垮。我一般建议分两步:先开20%的开关,让电容慢慢充电;等电压稳定了,再开剩下的80%。
断电流程相对简单:
- 保存关键寄存器到保持单元
- 使能隔离单元,把输出钳位
- 关闭电源开关
断电比上电快得多,因为不需要等电源稳定。但要注意——断电前一定要确保所有总线事务已经完成,否则数据可能丢失。
关键指标:唤醒时间 = 电源稳定时间 + 寄存器恢复时间。我做过一个28nm的芯片,唤醒时间控制在50微秒以内,基本不影响用户体验。如果唤醒时间超过1毫秒,用户就能感觉到卡顿了。
4.5 实际项目中的权衡
说了这么多,你可能觉得电源门控很美好。但现实是——它是有代价的。
代价一:面积。每个保持寄存器比普通寄存器大30%-50%,电源开关管也要占面积。我算过一笔账,一个中等规模的SoC,做电源门控大概要多花5%-10%的芯片面积。
代价二:设计复杂度。电源域之间的跨域信号处理、时序约束、物理验证,都比单电源域复杂得多。我记得第一次做多电源域的后端设计,光电源网络就画了三天。
代价三:唤醒延迟。这个前面说过了,有些实时性要求高的场景,等不起那几十微秒。
所以我的建议是:先评估,再动手。如果模块的静态功耗只占总功耗的10%以下,做电源门控的意义不大。但如果静态功耗占比超过30%,那就值得投入。
嗯,这一章的内容就到这里。电源门控是个好东西,但用好了是利器,用不好是累赘。下一章咱们聊聊「动态电压频率调节」的实战技巧,那个更刺激。