1. 初识UVM寄存器模型的内建sequence:你的验证“瑞士军刀”
如果你正在做芯片验证,尤其是用UVM(Universal Verification Methodology)这套方法学,那你肯定绕不开寄存器模型。它就像是DUT(待测设计)里所有寄存器和存储器的一个“软件镜像”,让你能方便地读写和检查。但光有模型还不够,你怎么能确信这个“镜像”和真实的硬件行为完全一致呢?万一模型建错了,或者硬件实现有偏差,那后续的所有验证工作都可能建立在错误的基础上。
这时候,UVM寄存器模型自带的一套内建sequence(built-in sequence)就该登场了。你可以把它们理解为一套开箱即用的、功能强大的“自动化测试脚本”。它们不是让你手动去写一堆读写操作,而是封装好了几种最经典、最必需的寄存器检查场景。我刚接触时,觉得这玩意儿太方便了,简直就是验证工程师的“瑞士军刀”,能帮你快速完成寄存器模型正确性的“体检”。
这套内建sequence主要分为两大类:一类是针对寄存器(uvm_reg)的,另一类是针对存储器(uvm_mem)的。今天咱们重点聊聊寄存器相关的这几个。它们各自有明确的职责:
uvm_reg_hw_reset_seq:检查上电复位后的默认值。uvm_reg_access_seq和uvm_reg_single_access_seq:检查基本的读写通路是否畅通。uvm_reg_bit_bash_seq和uvm_reg_single_bit_bash_seq:对寄存器的每一位进行“暴力”读写,确保每个bit都独立可控。uvm_reg_shared_access_seq:专门对付那些有多个地址映射的“共享寄存器”。
用好它们,你就能在项目初期快速建立起对寄存器模型的信心,把基础打牢,避免后期因为寄存器问题而返工,那可是相当痛苦的。下面,我就带你一个一个拆解,看看它们具体怎么用,以及在实际项目中会遇到哪些坑,怎么绕过去。
2. 复位值检查官:uvm_reg_hw_reset_seq
2.1 核心功能与使用场景
uvm_reg_hw_reset_seq,顾名思义,就是硬件复位序列。它的任务非常单纯且关键:验证DUT在上电复位后,所有寄存器的硬件复位值是否与寄存器模型中定义的复位值(reset value)完全一致。
为什么这个检查如此重要?想象一下,一个控制模块的使能寄存器,复位后本应该是0(关闭状态),但如果硬件实现成了1,一上电模块就开始乱跑,这绝对是灾难性的。这个sequence就是防止这种低级但致命错误的第一道防线。
它的工作原理很直观:sequence启动后,会遍历寄存器模型中的每一个寄存器,通过前门访问(即通过总线接口)去读取DUT中该寄存器的实际值,然后将这个读回来的值与模型里预设的reset值进行比较。如果全都匹配,测试通过;只要有一个不匹配,就会报错。
在实际项目中,我通常会在验证环境刚搭建好、寄存器模型初步集成后,第一个就跑这个sequence。它能快速告诉你模型的基础定义(特别是复位值)和硬件实现是否对得上,是一个很好的“冒烟测试”。
2.2 如何跳过特定寄存器的检查
但是,现实项目往往没那么理想。有时候,某些寄存器在复位后就是不确定的(比如一些由模拟电路初始化的寄存器),或者当前测试平台暂时不支持对其复位值进行读取。这时候,我们并不希望整个测试因为这些寄存器而失败。
UVM提供了一个非常灵活的机制来跳过检查:uvm_resource_db。你可以在启动sequence之前,像“贴标签”一样,给不想检查的寄存器设置一个“免检”资源。
具体怎么做呢?有两种资源名可以设置,效果是等价的:
// 方法一:使用通用的“NO_REG_TESTS”标签
// 这个标签比较霸道,会跳过所有内建sequence对这个寄存器的检查,不光是hw_reset
function void my_test::build_phase(uvm_phase phase);
super.build_phase(phase);
// 假设rm是寄存器模型顶层,invert是其中一个寄存器
uvm_resource_db#(bit)::set({"REG::", rm.invert.get_full_name(), ".*"}, "NO_REG_TESTS", 1, this);
endfunction
// 方法二:使用专用的“NO_REG_HW_RESET_TEST”标签


3179

被折叠的 条评论
为什么被折叠?



