3、电压域基础概念:电压域定义、电源状态表、always_on buffer的作用
各位同学,今天我们聊聊多电压域设计里最基础、也最绕不开的几个概念。说实话,我刚入行那会儿,觉得电压域不就是把芯片分成几块,各供各的电嘛,有什么好讲的?后来被现实狠狠教育了一顿——有一次项目都快 tape out 了,发现某个模块在睡眠模式下漏电严重,查了三天,最后发现是电压域划分时少考虑了一个 always_on buffer。嗯,从那以后,我再也不敢小看这些基础概念了。
3.1 电压域(Voltage Domain)到底是什么?
电压域,说白了就是芯片上一块独立的供电区域。你可以把它想象成一座大楼里的不同房间——每个房间都有自己的空调开关,想开就开,想关就关。在芯片里,每个电压域有自己独立的电源网络,可以工作在相同或不同的电压下。
我个人习惯把电压域分成三类:
- 常开域(Always-On Domain):永远不掉电,负责系统唤醒、电源管理等关键功能
- 可关断域(Power-Gated Domain):可以完全断电,省电效果最明显
- 电压缩放域(Voltage-Scaled Domain):电压可动态调整,性能与功耗之间找平衡
你想想看,一个 SoC 里可能有十几个电压域。每个域都有自己的电源开关、电平转换器和隔离单元。这些组件怎么配合?靠的就是我们接下来要讲的电源状态表。
核心要点:电压域划分不是拍脑袋决定的。我在项目中见过有人为了省事,把所有逻辑塞进一个域里,结果漏电功耗高得离谱。合理的划分要综合考虑功能模块的独立性、功耗目标、物理布局和时序要求。
3.2 电源状态表(Power State Table)——多电压域的“交通规则”
电源状态表,简称 PST。它定义了芯片在不同工作模式下,每个电压域应该处于什么状态。没有这张表,各个电压域就像没有红绿灯的十字路口——乱成一锅粥。
一个典型的电源状态表长这样:
| 工作模式 | CPU域 | GPU域 | 内存域 | 外设域 | Always-On域 |
|---|---|---|---|---|---|
| 高性能模式 | 1.0V | 1.0V | 1.2V | 0.9V | 0.9V |
| 低功耗模式 | 0.7V | OFF | 1.0V | 0.7V | 0.9V |
| 睡眠模式 | OFF | OFF | 保留 | OFF | 0.9V |
| 深度睡眠 | OFF | OFF | OFF | OFF | 0.9V |
注意看,Always-On 域在所有模式下都保持供电。这就是它的名字由来——永远在线。
在 Synopsys 工具链里,电源状态表通常用 UPF(Unified Power Format)来描述。举个例子:
create_power_domain PD_CPU -elements {cpu_core}
create_power_domain PD_GPU -elements {gpu_core}
create_power_domain PD_ALWAYS_ON -elements {wakeup_ctrl}
add_port_state VDD_CPU -state {ON 1.0} -state {OFF off}
add_port_state VDD_GPU -state {ON 1.0} -state {OFF off}
create_pst pst_chip -supplies {VDD_CPU VDD_GPU VDD_AO}
add_pst_state high_perf -pst pst_chip -state {ON ON ON}
add_pst_state low_power -pst pst_chip -state {ON OFF ON}
add_pst_state sleep -pst pst_chip -state {OFF OFF ON}
这段代码定义了三个电压域和它们的电源状态。你可能会问:为什么 CPU 和 GPU 都断电了,还要给 Always-On 域供电?因为唤醒逻辑、实时时钟、电源管理控制器都在这个域里。它们得活着,才能把其他域叫醒。
我的经验:写电源状态表时,一定要和系统架构师反复确认。我曾经遇到过一个 case,架构师说某个模式不需要 GPU,结果 tape out 后发现 GPU 域在低功耗模式下还有 DMA 传输没做完。嗯,从那以后我养成了一个习惯——每个电源状态都要标注“哪些模块还在干活”。
3.3 always_on buffer——跨电压域的“信使”
好,现在问题来了。假设 CPU 域断电了,但 Always-On 域里的唤醒逻辑需要给 CPU 域发一个信号。这个信号怎么传过去?直接连?不行。断电域的信号线是浮空的,电平不确定,可能会让 Always-On 域的逻辑误判。
这时候就需要 always_on buffer 出场了。
always_on buffer 是一种特殊的 buffer,它的供电来自 Always-On 域,但它的输入输出可以连接到其他电压域。说白了,它是个“两边都吃电”的中间人——自己永远有电,帮两边传话。
它的主要作用有三个:
- 信号隔离:防止断电域的信号干扰常开域的逻辑
- 电平保持:当某个域断电时,always_on buffer 能保持输出为确定值(通常是 0 或 1)
- 唤醒路径保证:确保唤醒信号在任何情况下都能正确传递
在 UPF 里,我们这样指定 always_on buffer:
set_isolation iso_cpu_wake -domain PD_ALWAYS_ON -applies_to inputs
set_isolation_control iso_cpu_wake -isolation_signal wake_en -isolation_value 0
set_level_shifter ls_cpu_to_ao -domain PD_ALWAYS_ON -applies_to inputs
set_level_shifter_control ls_cpu_to_ao -level_shifter_signal ls_en
这段代码给 Always-On 域的输入端口加了隔离和电平转换。注意那个 -isolation_value 0——当 CPU 域断电时,输入信号被强制拉低到 0,避免浮空。
避坑指南:我曾经在一个项目中,always_on buffer 的供电网络画错了,结果 buffer 跟着断电域一起掉了电。唤醒信号传不过去,整个芯片睡死了就醒不过来。查了整整一周才找到问题。所以,布局布线时一定要检查 always_on buffer 的电源连接——它必须接在常开域的电源网络上,不能接错。
3.4 三个概念之间的关系
最后,我帮你理一理这三个概念的关系:
- 电压域是物理基础——你把芯片分成几块,各供各的电
- 电源状态表是行为规范——每个域在什么模式下该干什么
- always_on buffer是通信保障——让断电域和常开域还能正常对话
三者缺一不可。没有电压域,你没法精细控制功耗;没有电源状态表,各个域各自为政,系统乱套;没有 always_on buffer,跨域通信全是坑。
我记得刚带新人时,有个小伙子问我:“老师,always_on buffer 是不是越多越好?”我说不是。每个 always_on buffer 都在消耗静态功耗,用多了反而得不偿失。合理的做法是:只在关键的唤醒路径和控制信号上使用,数据路径尽量用电平转换器。
好了,这一章的内容就到这里。下一章我们聊聊电平转换器的选型——这东西选错了,轻则时序违例,重则芯片功能失效。到时候我给你们讲讲我踩过的那个“1.8V 转 0.9V 结果烧了芯片”的坑。