3.9 学习UVM中的uvm_env类分为几步?
文章目录
- 前言
- 1. 定义
- 2. 核心功能
- 3. 适用场景
- 4. 使用方法
- 5. 完整代码示例
- 5.1 事务类定义
- 5.2 Monitor 类定义
- 5.3 Scoreboard 类定义
- 5.4 Agent 类定义
- 5.5 Env 类定义
- 5.6 测试平台
- 6. 代码说明
- 7. 总结
前言
以下是关于 UVM 中 uvm_env
的详细解释、核心功能、适用场景、使用方法以及一个完整的代码示例:
1. 定义
uvm_env
是 UVM(Universal Verification Methodology)中的一个重要组件类,用于封装验证环境的顶层结构。它是一个容器类,用于组织和管理验证环境中的其他组件(如 uvm_agent
、uvm_scoreboard
、uvm_subscriber
等)。uvm_env
是验证环境的最高层次,通常包含多个 uvm_agent
和其他功能组件。
uvm_env
的主要特点:
- 是验证环境的顶层容器。
- 封装了验证环境中的所有组件。
- 支持层次化结构,可以嵌套其他
uvm_env
。
2. 核心功能
uvm_env
提供了以下核心功能:
- 组件组织:将验证环境中的组件(如
uvm_agent
、uvm_scoreboard
等)组织在一起。 - 配置管理:通过配置对象(configuration object)配置验证环境的行为。
- 层次化结构:支持嵌套其他
uvm_env
,构建复杂的验证环境。 - 测试平台集成:与
uvm_test
配合使用,构建完整的测试平台。
3. 适用场景
uvm_env
通常用于以下场景:
- 顶层验证环境:用于构建验证环境的顶层结构。
- 复杂验证环境:在复杂的验证环境中,嵌套多个
uvm_env
以管理不同的功能模块。 - 配置管理:通过配置对象管理验证环境的行为。
- 组件复用:封装通用的验证环境,便于在不同测试中复用。
4. 使用方法
使用 uvm_env
的步骤如下:
- 定义类:从
uvm_env
派生一个类,并定义其属性和方法。 - 构建组件:在
build_phase
中创建和配置子组件(如uvm_agent
、uvm_scoreboard
等)。 - 连接组件:在
connect_phase
中连接子组件的端口和接口。 - 配置环境:通过配置对象设置验证环境的行为。
- 集成测试:在
uvm_test
中实例化并运行uvm_env
。
5. 完整代码示例
以下是一个完整的代码示例,展示如何使用 uvm_env
构建验证环境。
5.1 事务类定义
// 定义一个从 uvm_sequence_item 派生的事务类
class my_transaction extends uvm_sequence_item;
bit [7:0] data;
bit [3:0] addr;
bit valid;
// 注册类到 UVM 工厂
`uvm_object_utils(my_transaction)
// 构造函数
function new(string name = "my_transaction");
super.new(name);
endfunction
// 实现 print 方法
virtual function void do_print(uvm_printer printer);
printer.print_field("data", this.data, 8);
printer.print_field("addr", this.addr, 4);
printer.print_field("valid", this.valid, 1);
endfunction
endclass
5.2 Monitor 类定义
// 定义一个从 uvm_monitor 派生的监控类
class my_monitor extends uvm_monitor;
// 定义 analysis port
uvm_analysis_port #(my_transaction) ap;
// 虚拟接口(用于访问 DUT 信号)
virtual my_interface vif;
// 注册类到 UVM 工厂
`uvm_component_utils(my_monitor)
// 构造函数
function new(string name, uvm_component parent);
super.new(name, parent);
ap = new("ap", this);
endfunction
// 实现 run_phase
virtual task run_phase(uvm_phase phase);
forever begin
my_transaction tx;
// 等待信号有效
@(posedge vif.clock iff vif.valid);
// 创建事务对象
tx = my_transaction::type_id::create("tx");
// 捕捉信号并转换为事务
tx.data = vif.data;
tx.addr = vif.addr;
tx.valid = vif.valid;
// 打印事务
`uvm_info("MONITOR", $sformatf("Captured transaction: data=0x%0h, addr=0x%0h, valid=%b",
tx.data, tx.addr, tx.valid), UVM_LOW)
// 通过 analysis port 广播事务
ap.write(tx);
end
endtask
endclass
5.3 Scoreboard 类定义
// 定义一个从 uvm_scoreboard 派生的记分板类
class my_scoreboard extends uvm_scoreboard;
// 预期事务队列
my_transaction expected_queue[$];
// 注册类到 UVM 工厂
`uvm_component_utils(my_scoreboard)
// 构造函数
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
// 实现 write 方法(用于接收事务)
virtual function void write(my_transaction tx);
my_transaction expected_tx;
// 检查预期队列是否为空
if (expected_queue.size() == 0) begin
`uvm_error("SCOREBOARD", "Unexpected transaction received")
return;
end
// 获取预期事务
expected_tx = expected_queue.pop_front();
// 比较事务
if (!tx.compare(expected_tx)) begin
`uvm_error("SCOREBOARD", "Transaction mismatch")
`uvm_info("SCOREBOARD", $sformatf("Expected: data=0x%0h, addr=0x%0h, valid=%b",
expected_tx.data, expected_tx.addr, expected_tx.valid), UVM_LOW)
`uvm_info("SCOREBOARD", $sformatf("Received: data=0x%0h, addr=0x%0h, valid=%b",
tx.data, tx.addr, tx.valid), UVM_LOW)
end else begin
`uvm_info("SCOREBOARD", "Transaction matched", UVM_LOW)
end
endfunction
// 添加预期事务
function void add_expected(my_transaction tx);
expected_queue.push_back(tx);
endfunction
endclass
5.4 Agent 类定义
// 定义一个从 uvm_agent 派生的 agent 类
class my_agent extends uvm_agent;
my_monitor monitor;
my_scoreboard scoreboard;
// 注册类到 UVM 工厂
`uvm_component_utils(my_agent)
// 构造函数
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
// 构建组件
virtual function void build_phase(uvm_phase phase);
monitor = my_monitor::type_id::create("monitor", this);
scoreboard = my_scoreboard::type_id::create("scoreboard", this);
endfunction
// 连接组件
virtual function void connect_phase(uvm_phase phase);
monitor.ap.connect(scoreboard.write);
endfunction
endclass
5.5 Env 类定义
// 定义一个从 uvm_env 派生的 env 类
class my_env extends uvm_env;
my_agent agent;
// 注册类到 UVM 工厂
`uvm_component_utils(my_env)
// 构造函数
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
// 构建组件
virtual function void build_phase(uvm_phase phase);
agent = my_agent::type_id::create("agent", this);
endfunction
endclass
5.6 测试平台
// 测试平台
module testbench;
initial begin
// 创建测试类
class my_test extends uvm_test;
my_env env;
// 注册类到 UVM 工厂
`uvm_component_utils(my_test)
// 构造函数
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
// 构建组件
virtual function void build_phase(uvm_phase phase);
env = my_env::type_id::create("env", this);
endfunction
// 运行测试
virtual task run_phase(uvm_phase phase);
my_transaction tx;
phase.raise_objection(this);
// 添加预期事务
tx = my_transaction::type_id::create("tx");
tx.data = 8'hAA;
tx.addr = 4'h1;
tx.valid = 1;
env.agent.scoreboard.add_expected(tx);
#100; // 模拟测试运行时间
phase.drop_objection(this);
endtask
endclass
// 启动测试
initial begin
run_test("my_test");
end
end
endmodule
6. 代码说明
- 事务类:
my_transaction
定义了事务的属性和方法。 - Monitor 类:
my_monitor
监控 DUT 的信号并转换为事务。 - Scoreboard 类:
my_scoreboard
接收事务并与预期事务进行比较。 - Agent 类:
my_agent
封装了uvm_monitor
和uvm_scoreboard
。 - Env 类:
my_env
封装了uvm_agent
,是验证环境的顶层容器。 - 测试平台:
my_test
类用于构建和运行测试环境。
7. 总结
uvm_env
是 UVM 中用于构建验证环境顶层结构的关键组件。它封装了验证环境中的所有组件,并支持层次化结构和配置管理。以上示例展示了如何定义和使用 uvm_env
,适用于实际的验证场景。