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,否则保持数据会丢失。
五、用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做快速语法语义扫描。
-on_state布尔表达式如果写反,语法检查不会报错,但仿真中域会在错误的时间上电/断电。隔离单元的-clamp_value如果设为1而RTL期望0,会导致下游逻辑误触发。保持寄存器的save_ff和restore_ff如果来自可关断域,断电后控制信号丢失,保持功能失效。这三类问题都只能通过语义检查和仿真波形发现,不能只靠语法检查。
完成上述UPF编写和VCS加载后,可以用simv_upf运行一个简单的上电、断电、保持、恢复序列,在波形中观察VDD_CPU_SW的电压变化、隔离输出是否钳位、保持寄存器数据是否在断电后保留。如果波形与UPF描述一致,说明电源意图描述正确,可以进入后续的低功耗仿真验证阶段。