3. 验证环境搭建基础
验证环境搭建是数字验证项目交付的第一道工程关口。一个可复用的UVM验证平台,不只是把driver、monitor、scoreboard堆在一起,而是要让组件之间的连接关系、编译仿真流程和目录版本管理形成稳定闭环。本节围绕UVM平台架构、VCS编译仿真流程、目录结构规范与版本管理集成四个部分展开,重点说明实际工程中如何组织这些内容。
UVM验证平台架构:从组件到连接
UVM验证平台的核心是分层结构。最上层是uvm_test,它负责配置环境、启动sequence;其下是uvm_env,用于封装agent、scoreboard、coverage collector等组件;agent内部通常包含sequencer、driver和monitor,分别负责激励产生、信号驱动和总线采样。对于需要主动激励的接口,使用uvm_active_agent;对于只做监测的接口,使用uvm_passive_agent,此时不实例化driver和sequencer。
组件之间的连接通过TLM端口完成。monitor通过analysis_port把采样到的transaction发送给scoreboard和coverage collector;scoreboard通过analysis_export接收数据,并与reference model的输出进行比较。sequence通过start()方法挂载到sequencer上,sequencer再通过seq_item_port把item交给driver。这个连接关系决定了平台能否正确运行,也是调试时最常检查的部分。
配置方面,UVM提供了uvm_config_db机制。典型用法是在test层通过uvm_config_db#(virtual my_if)::set(this, "env.agent.drv", "vif", vif)把虚拟接口传递给driver,driver在build_phase中通过get()获取。这种机制避免了全局变量,也让不同test可以复用同一套env。
Synopsys VCS编译仿真流程
VCS的编译仿真流程分为三步:分析(analysis)、精化(elaboration)和仿真(simulation)。实际工程中通常用一条命令完成前三步,再单独运行仿真。一个典型的编译命令如下:
vcs -full64 -sverilog -ntb_opts uvm-1.2 \
-timescale=1ns/1ps \
-f filelist.f \
-top tb_top \
-l compile.log \
-debug_access+all \
-o simv
其中-full64表示64位编译,-sverilog支持SystemVerilog,-ntb_opts uvm-1.2指定UVM库版本,-f filelist.f读取文件列表,-top tb_top指定顶层模块,-debug_access+all为后续DVE/Verdi调试保留信号可见性。编译成功后生成simv可执行文件。
仿真阶段常用命令为:
./simv -l sim.log +UVM_TESTNAME=my_test +UVM_VERBOSITY=UVM_LOW
其中+UVM_TESTNAME指定要运行的test,+UVM_VERBOSITY控制打印级别。仿真结束后,VCS会输出UVM报告摘要,包括UVM_ERROR和UVM_FATAL数量。判断仿真是否通过,首先看UVM_ERROR是否为0,再看scoreboard是否报告比较失败,最后检查覆盖率是否达到收敛目标。
目录结构规范
一个可维护的验证项目目录通常按功能划分,而不是把所有文件堆在根目录。推荐结构如下:
proj_uvm/
├── rtl/ # DUT RTL源码
├── tb/
│ ├── env/ # env、agent、scoreboard
│ ├── seq/ # sequence库
│ ├── test/ # test用例
│ ├── if/ # interface定义
│ └── top/ # tb_top、时钟复位
├── sim/
│ ├── filelist.f # 编译文件列表
│ ├── Makefile # 编译仿真入口
│ └── run/ # 仿真日志与波形
├── cov/ # 覆盖率配置与报告
├── reg/ # 寄存器模型
└── doc/ # 验证计划与说明
这种结构让编译文件列表、仿真脚本和源码分离,便于在CI中复用。filelist.f中应使用相对路径或+incdir+指定include目录,避免绝对路径导致换机器后无法编译。
版本管理集成
验证代码和RTL应放在同一个版本库中,但通过分支策略区分。推荐使用Git,主分支保护,功能开发在feature分支进行。每次提交前,应在本地运行一次编译和冒烟测试。一个简单的Makefile目标可以这样写:
compile:
vcs -full64 -sverilog -ntb_opts uvm-1.2 \
-f filelist.f -top tb_top -l compile.log -o simv
sim:
./simv -l sim.log +UVM_TESTNAME=smoke_test
regress:
./simv -l sim.log +UVM_TESTNAME=regression_test
clean:
rm -rf simv* csrc *.log ucli.key
在CI流水线中,每次push触发make compile和make sim,只有编译通过且UVM_ERROR为0才允许合并。覆盖率报告和仿真日志作为构建产物归档,便于回溯。对于多人协作项目,建议在.gitignore中排除simv*、csrc/、*.log、ucli.key等生成文件,只提交源码、脚本和配置。
综合来看,UVM平台架构决定了验证环境能否正确运行,VCS编译仿真流程决定了能否快速得到结果,目录结构规范决定了项目能否长期维护,版本管理集成决定了团队协作能否稳定推进。四者缺一不可,建议在项目启动阶段就确定好这些规范,而不是等到环境膨胀后再重构。