每次看到UPF文档里密密麻麻的create_supply_net和set_domain_supply_net命令就头疼?作为数字IC验证工程师,我完全理解这种感受。三年前我第一次接触UPF时,对着官方手册死记硬背了两周,结果在实际项目中还是频频出错。直到后来通过搭建完整的验证环境,才真正理解了每个命令的实际意义。本文将带你用VCS仿真工具,从RTL设计开始,一步步构建包含多级电源域的可运行验证环境——不是语法手册,而是让你在仿真波形中亲眼看到电源管理如何工作。
我们先定义一个简单的验证对象:包含顶层(TOP)和计算单元(pd1)的两级系统。顶层工作电压1.0V,计算单元支持0.8V低功耗模式。用以下RTL代码建立基础结构:
verilog复制module top (
input logic clk,
input logic rst_n,
output logic [7:0] data_out
);
logic [7:0] core_data;
dhm_core u_dhm_core (
.clk (clk),
.rst_n (rst_n),
.data_out (core_data)
);
always_ff @(posedge clk) begin
data_out <= core_data;
end
endmodule
module dhm_core (
input logic clk,
input logic rst_n,
output logic [7:0] data_out
);
// 核心计算逻辑
endmodule
创建基础的仿真脚本run_vcs.sh,注意添加UPF支持参数:
bash复制#!/bin/bash
vcs -full64 \
-sverilog \
-debug_access+all \
-upf power_plan.upf \
-l vcs.log \
top.sv
关键提示:VCS 2020版本后必须使用
-upf替代旧的-lpwr选项,否则会报语法解析错误
在项目根目录创建power_plan.upf文件,首先定义电源域层级:
tcl复制# 顶层电源域
create_power_domain TOP -include_scope
create_power_domain pd1 -elements {u_dhm_core}
接着构建物理供电网络。注意电源端口(Port)与网络(Net)的区别:
tcl复制# 顶层电源端口声明(类似RTL中的端口声明)
create_supply_port VDD # 主电源
create_supply_port VDDL # 低电压电源
create_supply_port VSS # 地
# 顶层电源网络布线(类似PCB走线)
create_supply_net VDD -domain TOP
create_supply_net VDDL -domain TOP
create_supply_net VSS -domain TOP
# 子模块电源网络复用
create_supply_net VDDL -domain pd1 -reuse
create_supply_net VSS -domain pd1 -reuse
create_supply_net VDDLS1 -domain pd1 # 子模块特有电源
完成物理连接并设置工作电压,这是最易出错的环节:
tcl复制# 连接端口到网络(类似RTL中的连线)
connect_supply_net VDD -ports {VDD}
connect_supply_net VDDL -ports {VDDL}
connect_supply_net VSS -ports {VSS}
# 设置各域供电关系
set_domain_supply_net TOP \
-primary_power_net VDD \
-primary_ground_net VSS
set_domain_supply_net pd1 \
-primary_power_net VDDLS1 \
-primary_ground_net VSS
常见陷阱:忘记设置
-primary_ground_net会导致仿真时出现"undefined supply net"警告
在pd1域添加电源开关,实现低功耗模式切换:
tcl复制create_power_switch psw_pd1 \
-domain pd1 \
-input_supply_port {in VDDL} \
-output_supply_port {out VDDLS1} \
-control_port {ctrl u_dhm_core.pwr_ctrl} \
-on_state {on_state in out !ctrl} \
-off_state {off_state {} out ctrl}
对应的RTL需要增加控制信号:
verilog复制module dhm_core (
input logic clk,
input logic rst_n,
output logic [7:0] data_out,
output logic pwr_ctrl // 新增电源控制信号
);
//...
endmodule
创建power_state_table.pst定义工作模式:
tcl复制add_pst_state NORMAL -supply {TOP/VDD 1.0 TOP/VSS 0}
add_pst_state LP_MODE -supply {TOP/VDDL 0.8 TOP/VSS 0}
set_design_attributes -elements {u_dhm_core} \
-attribute lp_power_aware \
-value true
运行仿真后,在DVE中需要特别关注这些信号:
| 信号类型 | 路径示例 | 正常特征 |
|---|---|---|
| 主电源网络 | TOP/VDD | 稳定直流1.0V |
| 低功耗电源 | pd1/VDDLS1 | 随开关控制变化 |
| 电源控制信号 | u_dhm_core.pwr_ctrl | 明确的高低电平切换 |
遇到仿真失败时,按此流程检查:
语法错误
连接性问题
report_supply_net检查网络连接状态冲突
tcl复制# 调试命令示例
report_power_domain -verbose
check_power_management -all
当设计包含多个电压域时,需要特别注意电平转换器件的建模。在UPF中添加:
tcl复制create_level_shifter ls_inst \
-domain pd1 \
-applies_to inputs \
-location self \
-input_supply {VDDLS1 VSS} \
-output_supply {VDD VSS}
对应的仿真参数需要更新:
bash复制vcs -full64 \
-sverilog \
-debug_access+all \
-upf power_plan.upf \
-power_top top \
-l vcs.log \
top.sv level_shifters.sv
最后分享一个实用技巧:在大型项目中,我习惯将UPF文件按功能拆分为多个子文件(如power_domains.tcl、switches.tcl等),然后用主UPF文件包含它们。这样既便于团队协作,也方便版本管理。