3. UPF电源意图描述实战

UPF(Unified Power Format)文件是低功耗验证的“电源意图说明书”。它不描述RTL功能,而是告诉VCS:芯片里有哪些电源域、谁给谁供电、什么时候断电、断电时信号怎么处理。本节以一个典型的SoC子系统为例,从零编写一份可被VCS加载的UPF,并说明如何检查语法与语义。

一、先建立电源域与供电网络

假设设计包含三个模块:CPU子系统(cpu_core)、外设控制器(peri_ctrl)和常开逻辑(aon_logic)。供电策略是:CPU可独立关断,外设可独立关断,常开逻辑始终供电。首先定义电源域和供电端口:

# 定义电源域
create_power_domain PD_CPU -elements {u_cpu} \
    -supply {primary VDD_CPU}
create_power_domain PD_PERI -elements {u_peri} \
    -supply {primary VDD_PERI}
create_power_domain PD_AON -elements {u_aon} \
    -supply {primary VDD_AON}

# 定义供电端口与网络
create_supply_port VDD_CPU
create_supply_port VDD_PERI
create_supply_port VDD_AON
create_supply_net VDD_CPU -domain PD_CPU
create_supply_net VDD_PERI -domain PD_PERI
create_supply_net VDD_AON -domain PD_AON

# 连接供电端口到供电网络
connect_supply_net VDD_CPU -ports {VDD_CPU}
connect_supply_net VDD_PERI -ports {VDD_PERI}
connect_supply_net VDD_AON -ports {VDD_AON}

这里的关键是-domain参数:每个供电网络必须归属到某个电源域,否则VCS在elaboration阶段会报“supply net not associated with domain”的语义错误。电源域划分的粒度直接影响后续隔离和电平转换的插入位置,通常按“可独立关断的电压区域”来划分。

二、电源开关:控制域的上电与断电

CPU域需要支持关断,因此要插入电源开关(power switch)。开关由常开域的控制信号pwr_en_cpu驱动,输出供电网络VDD_CPU_SW给CPU域使用:

create_power_switch sw_cpu \
    -domain PD_CPU \
    -input_supply_port {vin VDD_AON} \
    -output_supply_port {vout VDD_CPU_SW} \
    -control_port {sleep_ctrl pwr_en_cpu} \
    -on_state {on_state vin {!sleep_ctrl}} \
    -off_state {off_state {sleep_ctrl}}

connect_supply_net VDD_CPU_SW -ports {u_cpu/VDD}

注意-on_state和-off_state的布尔表达式:!sleep_ctrl表示控制信号为低时开关导通。如果写反,VCS不会报语法错,但仿真中CPU域会在应该上电时断电,属于典型的语义陷阱。建议在UPF中用注释标明控制极性。

三、隔离与电平转换:跨域信号的安全处理

CPU域断电后,其输出信号会浮空,必须插入隔离单元(isolation cell),把浮空值钳位到确定电平。同时,CPU域(0.9V)与外设域(1.2V)之间电压不同,需要电平转换器(level shifter)。

# 隔离:CPU域输出到常开域
set_isolation iso_cpu2aon \
    -domain PD_CPU \
    -isolation_power_net VDD_AON \
    -isolation_ground_net VSS \
    -clamp_value 0 \
    -applies_to outputs \
    -source VDD_CPU_SW \
    -sink VDD_AON

# 电平转换:CPU域到外设域
set_level_shifter ls_cpu2peri \
    -domain PD_CPU \
    -applies_to outputs \
    -rule low_to_high \
    -location self

# 电平转换:外设域到CPU域
set_level_shifter ls_peri2cpu \
    -domain PD_PERI \
    -applies_to outputs \
    -rule high_to_low \
    -location self

-clamp_value 0表示隔离期间输出钳位为低电平;-location self表示电平转换器放在源域一侧。隔离和电平转换的插入位置必须与RTL中的实际单元或综合脚本一致,否则VCS会报“isolation cell not found”或“level shifter location mismatch”。

四、状态保持:断电前保存关键寄存器

CPU域中有若干配置寄存器需要在断电期间保持,重新上电后恢复。使用set_retention指定保持寄存器和保持供电网络:

set_retention ret_cpu \
    -domain PD_CPU \
    -retention_power_net VDD_AON \
    -retention_ground_net VSS \
    -elements {u_cpu/cfg_reg[*] u_cpu/state_reg[*]}

set_retention_control ret_cpu \
    -domain PD_CPU \
    -save_signal {save_ff high} \
    -restore_signal {restore_ff high}

保持寄存器的保存/恢复由save_ff和restore_ff控制,这两个信号必须来自常开域。VCS在仿真中会检查:断电前是否有效拉高save、上电后是否有效拉高restore,否则保持数据会丢失。

UPF电源意图结构:域、开关、隔离、电平转换、保持 PD_AON(常开域) VDD_AON 始终供电 pwr_en_cpu / save_ff restore_ff 电源开关 sw_cpu vin=VDD_AON vout=VDD_CPU_SW PD_CPU(可关断) VDD_CPU_SW cfg_reg[*] / state_reg[*] 保持寄存器 PD_PERI(可关断) VDD_PERI 1.2V 外设控制器 VDD_AON VDD_CPU_SW pwr_en_cpu(控制开关) 隔离单元 clamp_value=0 iso_cpu2aon 电平转换器 ls_cpu2peri low_to_high CPU输出 隔离后 CPU输出 1.2V 状态保持 ret_cpu save/restore 保持供电 VDD_AON 供电/信号 控制信号 保持路径

五、用VCS加载并检查语法与语义

UPF写完后,用VCS加载验证。基本命令如下:

vcs -full64 -sverilog \
    -upf top.upf \
    -power=upf \
    -debug_access+all \
    -lca \
    rtl/top.sv rtl/cpu_core.sv rtl/peri_ctrl.sv rtl/aon_logic.sv \
    -o simv_upf

VCS在编译阶段会做两轮检查。第一轮是语法检查:UPF命令拼写、参数名、括号匹配、命令顺序。常见错误如create_power_domain写成create_power_domian,或-elements写成-element,会直接报“unknown command”或“invalid option”。第二轮是语义检查:供电网络是否连接到域、隔离/电平转换的源和目的域是否存在、保持控制信号是否来自常开域、电源开关的on/off状态是否覆盖所有控制组合。语义错误通常以“UPF-xxx”编号出现,例如“UPF-201: supply net VDD_CPU_SW not found in domain PD_CPU”。

建议在编译时加-upf_verbose查看UPF解析详情,并用-report_upf生成电源意图报告。如果只想检查UPF而不跑仿真,可以用vcs -upf top.upf -power=upf -upf_only做快速语法语义扫描。

实战建议:UPF文件按“域→供电网络→开关→隔离→电平转换→保持”的顺序编写,VCS对命令顺序有依赖。先定义域和供电网络,再定义开关和隔离,最后定义保持。如果顺序颠倒,VCS可能报“domain not defined”或“supply net not found”。另外,所有跨域信号都要显式声明隔离或电平转换,否则VCS在仿真中会给出“unprotected crossing”警告,这个警告在低功耗验证中通常意味着功能风险。
常见语义陷阱:电源开关的-on_state布尔表达式如果写反,语法检查不会报错,但仿真中域会在错误的时间上电/断电。隔离单元的-clamp_value如果设为1而RTL期望0,会导致下游逻辑误触发。保持寄存器的save_ff和restore_ff如果来自可关断域,断电后控制信号丢失,保持功能失效。这三类问题都只能通过语义检查和仿真波形发现,不能只靠语法检查。

完成上述UPF编写和VCS加载后,可以用simv_upf运行一个简单的上电、断电、保持、恢复序列,在波形中观察VDD_CPU_SW的电压变化、隔离输出是否钳位、保持寄存器数据是否在断电后保留。如果波形与UPF描述一致,说明电源意图描述正确,可以进入后续的低功耗仿真验证阶段。