文章目录
前言
该专题用于记录学习UVM芯片验证的过程,主要学习书籍为经典的《UVM实战》,同时也会去进行一些UVM的项目联系。
一、Driver驱动器
这段代码是用 SystemVerilog 编写的一个基于 UVM(Universal Verification Methodology)的驱动器(driver)组件,名为 my_driver。它继承自 uvm_driver 类,用于在验证环境中驱动 DUT(Design Under Test,被测设计)的输入信号。下面我将逐步解释这段代码的结构和功能。
1.1 整体结构
代码分为两个主要部分:
- 类定义部分:定义了 my_driver 类,包括构造函数和一个外部声明的任务(main_phase)。
- 任务实现部分:实现了 main_phase 任务,负责具体的信号驱动逻辑。
此外,代码使用 ifndef 和 define 宏来防止重复包含。
1.2 详细解释
1.2.1 宏定义保护
ifndef MY_DRIVER__SV
define MY_DRIVER__SV
检查是否已经定义了宏MY_DRIVER__SV。如果没有定义,则编译器会继续处理后面的代码。
最后,文件末尾的 endif 与开头的 ifndef 配对,结束条件编译块。
1.2.2 类定义
class my_driver extends uvm_driver;
function new(string name = "my_driver", uvm_component parent = null);
super.new(name, parent);
endfunction
extern virtual task main_phase(uvm_phase phase);
endclass
class my_driver extends uvm_driver:定义一个名为 my_driver 的类,并且表示 my_driver 继承自 UVM 提供的基类 uvm_driver。
uvm_driver 是 UVM 框架中的一个标准组件类,用于将事务级数据转换为 DUT 的引脚级信号。
事务级数据是指更高层次的抽象数据,通常以结构体或类的形式表示,而不是直接的硬件信号(0 和 1)。它描述的是“做什么”,而不是“怎么做”。
假设事务是一个 8 位数据 8’b10100101。
驱动器将其转换为:
top_tb.rxd <= 8’b10100101;(数据信号)
top_tb.rx_dv <= 1’b1;(有效信号)
并在 @(posedge top_tb.clk) 时更新这些信号。
function new:定义类的构造函数,用于创建 my_driver 对象。
super.new(name, parent):调用父类 uvm_driver 的构造函数,将 name 和 parent 参数传递给它。这是 UVM 中面向对象编程的标准做法,确保父类的初始化逻辑被执行。
extern:表示 main_phase 任务的实现不在类定义内部,而是在外部单独定义。
virtual:声明这是一个虚任务,允许子类重写(override)它。这是 UVM 中 phase 方法的常见做法。
task main_phase(uvm_phase phase):定义一个名为 main_phase 的任务,接收一个 uvm_phase 类型的参数 phase,表示 UVM 的仿真阶段(这里是 main_phase,通常用于主要的测试执行阶段)。
1.2.3 任务实现
task my_driver::main_phase(uvm_phase phase);
top_tb.rxd <= 8'b0;
top_tb.rx_dv <= 1'b0;
while(!top_tb.rst_n)
@(posedge top_tb.clk);
for(int i = 0; i < 256; i++)begin
@(posedge top_tb.clk);
top_tb.rxd <= $urandom_range(0, 255);
top_tb.rx_dv <= 1'b1;
`uvm_info("my_driver", "data is drived", UVM_LOW)
end
@(posedge top_tb.clk);
top_tb.rx_dv <= 1'b0;
endtask
my_driver::main_phase:明确指定这个任务是 my_driver 类的一部分。
这是 main_phase 的具体实现,负责驱动 DUT 的信号。
uvm_info(“my_driver”, “data is drived”, UVM_LOW):
UVM 提供的日志记录宏,打印信息。
my_driver:消息来源(组件名)。
data is drived:消息内容。
UVM_LOW:日志级别,表示低详细程度。
作用:在 256 个时钟周期内,连续向 DUT 的 rxd 输入随机数据,并将 rx_dv 置为 1,同时记录日志。
所谓类的定义,就是用编辑器写下:
class A ... endclass而所谓类的实例化指的是通过new创造出A的一个实例:
A a_list; a_list = new();
1.2.4 factory机制
factory机制的实现被集成在了一个宏中:uvm_component_utils。这个宏所做的事情非常多,其中之一就是将my_driver登记在UVM内部的一张表中,这张表是 factory 功能实现的基础。只要在定义一个新的类时使用这个宏,就相当于把这个类注册到了这张表中。
`uvm_component_utils(my_driver)
在给driver中加入factory机制后,还需要对top_tb做一些改动:
initial begin
run_test("my_driver");
end
但是输出的结果只有两个,没有执行后面的代码,关于这个问题,牵涉UVM的objection机制。
UVM_INFO my_driver.sv(8) @ 0: uvm_test_top [my_driver] new is called
UVM_INFO @ 0: reporter [RNTST] Running test my_driver...
UVM_INFO my_driver.sv(14) @ 0: uvm_test_top [my_driver] main_phase is called
1.2.4 objection机制
UVM中通过objection机制来控制验证平台的关闭。细心的读者可能发现,在上节的例子中,并没有如2.2.1节所示显式地调用 finish 语句来结束仿真。但是在运行上节例子时,仿真平台确实关闭了。在每个phase中,UVM会检查是否有objection被提起


2万+

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



