这段代码是一个 UVM 验证平台的片段,用于测试 APB 总线。它包含了环境类、测试类和测试序列类,分别负责搭建测试环境、运行测试和产生测试激励。代码使用了随机化和约束来生成各种测试用例,并包含了数据校验功能。 apb_pkg 包含了具体的 APB 总线事务定义和 agent 实现。 该代码实现了单事务和 burst 事务的测试。 local:: 用于访问局部变量。
// 防止头文件重复包含
`ifndef APB_TESTS_SV
`define APB_TESTS_SV
// 导入 apb_pkg 包中的所有内容, apb_pkg 包含了 APB 总线相关的定义和类
import apb_pkg::*;
// 定义 APB 环境类,继承自 UVM 环境类
class apb_env extends uvm_env;
// 定义 master agent 和 slave agent
apb_master_agent mst;
apb_slave_agent slv;
// UVM 宏,用于生成一些常用的函数,例如 new() 和 build()
`uvm_component_utils(apb_env)
// 构造函数
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
// build 阶段函数,用于创建 master agent 和 slave agent
function void build_phase(uvm_phase phase);
super.build_phase(phase);
mst = apb_master_agent::type_id::create("mst", this);
slv = apb_slave_agent::type_id::create("slv", this);
endfunction
endclass
// 定义 APB 基类测试类,继承自 UVM 测试类
class apb_base_test extends uvm_test;
// 定义 APB 环境
apb_env env;
// UVM 宏,用于生成一些常用的函数
`uvm_component_utils(apb_base_test)
// 构造函数
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
// build 阶段函数,用于创建 APB 环境
function void build_phase(uvm_phase phase);
super.build_phase(phase);
env = apb_env::type_id::create("env", this);
endfunction
endclass
// 定义 APB 基类测试序列类,继承自 UVM 序列类,参数化 apb_transfer
class apb_base_test_sequence extends uvm_sequence #(apb_transfer);
// 定义一个动态数组,用于存储内存数据
bit[31:0] mem[bit[31:0]];
// UVM 宏,用于生成一些常用的函数
`uvm_object_utils(apb_base_test_sequence)
// 构造函数
function new(string name="");
super.new(name);
endfunction : new
// 函数用于检查内存数据是否正确
function bit check_mem_data(bit[31:0] addr, bit[31:0] data);
if(mem.exists(addr)) begin // 检查地址是否存在于mem数组中
if(data != mem[addr]) begin // 检查读取的数据是否与存储的数据一致
`uvm_error("CMPDATA", $sformatf("addr 32'h%8x, READ DATA expected 32'h%8x != actual 32'h%8x", addr, mem[addr], data))
return 0; // 返回 0 表示数据不一致
end
else begin
`uvm_info("CMPDATA", $sformatf("addr 32'h%8x, READ DATA 32'h%8x comparing success!", addr, data), UVM_LOW)
return 1; // 返回 1 表示数据一致
end
end
else begin // 地址不存在于mem数组中
if(data != 0) begin // 检查读取的数据是否为 0
`uvm_error("CMPDATA", $sformatf("addr 32'h%8x, READ DATA expected 32'h00000000 != actual 32'h%8x", addr, data))
return 0; // 返回 0 表示数据不为 0
end
else begin
`uvm_info("CMPDATA", $sformatf("addr 32'h%8x, READ DATA 32'h%8x comparing success!", addr, data), UVM_LOW)
return 1; // 返回 1 表示数据为 0
end
end
endfunction: check_mem_data
// 任务,等待复位释放
task wait_reset_release();
@(negedge apb_tb.rstn); // 等待复位信号下降沿
@(posedge apb_tb.rstn); // 等待复位信号上升沿
endtask
// 任务,等待指定数量的时钟周期
task wait_cycles(int n);
repeat(n) @(posedge apb_tb.clk); // 等待 n 个时钟上升沿
endtask
// 函数,获取随机地址
function bit[31:0] get_rand_addr();
bit[31:0] addr;
void'(std::randomize(addr) with {addr[31:12] == 0; addr[1:0] == 0;}); // 随机化地址,高12位为0,低2位为0
return addr;
endfunction
endclass
// 定义 APB 单事务测试序列类,继承自 apb_base_test_sequence
class apb_single_transaction_sequence extends apb_base_test_sequence;
// 定义单次写、单次读和写后读序列
apb_master_single_write_sequence single_write_seq;
apb_master_single_read_sequence single_read_seq;
apb_master_write_read_sequence write_read_seq;
// 测试次数
rand int test_num = 100;
// 约束,测试次数为 100
constraint cstr{
soft test_num == 100;
}
// UVM 宏,用于生成一些常用的函数
`uvm_object_utils(apb_single_transaction_sequence)
// 构造函数
function new(string name="");
super.new(name);
endfunction : new
// 测试任务
task body();
bit[31:0] addr;
this.wait_reset_release(); // 等待复位释放
this.wait_cycles(10); // 等待 10 个时钟周期
// 测试连续写事务
`uvm_info(get_type_name(), "TEST continous write transaction...", UVM_LOW)
repeat(test_num) begin
addr = this.get_rand_addr(); // 获取随机地址
`uvm_do_with(single_write_seq, {addr == local::addr; data == local::addr;}) // 执行单次写事务,地址和数据相同
mem[addr] = addr; // 将数据写入内存
end
// 测试连续读事务
`uvm_info(get_type_name(), "TEST continous read transaction...", UVM_LOW)
repeat(test_num) begin
addr = this.get_rand_addr(); // 获取随机地址
`uvm_do_with(single_read_seq, {addr == local::addr;}) // 执行单次读事务
void'(this.check_mem_data(addr, single_read_seq.data)); // 检查读取的数据
end
// 测试写后读事务
`uvm_info(get_type_name(), "TEST read transaction after write transaction...", UVM_LOW)
repeat(test_num) begin
addr = this.get_rand_addr(); // 获取随机地址
`uvm_do_with(single_write_seq, {addr == local::addr; data == local::addr;}) // 执行单次写事务
mem[addr] = addr; // 将数据写入内存
`uvm_do_with(single_read_seq, {addr == local::addr;}) // 执行单次读事务
void'(this.check_mem_data(addr, single_read_seq.data)); // 检查读取的数据
end
// 测试写后立即读事务
`uvm_info(get_type_name(), "TEST read transaction immediately after write transaction", UVM_LOW)
repeat(test_num) begin
addr = this.get_rand_addr(); // 获取随机地址
`uvm_do_with(write_read_seq, {addr == local::addr; data == local::addr;}) // 执行写后立即读事务
mem[addr] = addr; // 将数据写入内存
void'(this.check_mem_data(addr, write_read_seq.data)); // 检查读取的数据
end
this.wait_cycles(10); // 等待 10 个时钟周期
endtask
endclass: apb_single_transaction_sequence
// 定义 APB 单事务测试类,继承自 apb_base_test
class apb_single_transaction_test extends apb_base_test;
// UVM 宏,用于生成一些常用的函数
`uvm_component_utils(apb_single_transaction_test)
// 构造函数
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
// run 阶段任务,用于启动测试序列
task run_phase(uvm_phase phase);
apb_single_transaction_sequence seq = new(); // 创建测试序列
phase.raise_objection(this); // 提出异议,阻止仿真结束
super.run_phase(phase); // 调用父类的 run_phase 函数
seq.start(env.mst.sequencer); // 启动测试序列
phase.drop_objection(this); // 放弃异议,允许仿真结束
endtask
endclass: apb_single_transaction_test
// 定义 APB burst 事务测试序列类,继承自 apb_base_test_sequence
class apb_burst_transaction_sequence extends apb_base_test_sequence;
// 定义 burst 写和 burst 读序列
apb_master_burst_write_sequence burst_write_seq;
apb_master_burst_read_sequence burst_read_seq;
// 测试次数
rand int test_num = 100;
// 约束,测试次数为 100
constraint cstr{
soft test_num == 100;
}
// UVM 宏,用于生成一些常用的函数
`uvm_object_utils(apb_burst_transaction_sequence)
// 构造函数
function new(string name="");
super.new(name);
endfunction : new
// 测试任务
task body();
bit[31:0] addr;
this.wait_reset_release(); // 等待复位释放
this.wait_cycles(10); // 等待 10 个时钟周期
// 测试连续 burst 写事务
repeat(test_num) begin
addr = this.get_rand_addr(); // 获取随机地址
`uvm_do_with(burst_write_seq, {addr == local::addr;}) // 执行 burst 写事务
foreach(burst_write_seq.data[i]) begin // 将数据写入内存
mem[addr+(i<<2)] = burst_write_seq.data[i];
end
`uvm_do_with(burst_read_seq, {addr == local::addr; data.size() == burst_write_seq.data.size();}) // 执行 burst 读事务
foreach(burst_read_seq.data[i]) begin // 检查读取的数据
void'(this.check_mem_data(addr+(i<<2), burst_write_seq.data[i]));
end
end
this.wait_cycles(10); // 等待 10 个时钟周期
endtask
endclass: apb_burst_transaction_sequence
// 定义 APB burst 事务测试类,继承自 apb_base_test
class apb_burst_transaction_test extends apb_base_test;
// UVM 宏,用于生成一些常用的函数
`uvm_component_utils(apb_burst_transaction_test)
// 构造函数
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
// run 阶段任务,用于启动测试序列
task run_phase(uvm_phase phase);
apb_burst_transaction_sequence seq = new(); // 创建测试序列
phase.raise_objection(this); // 提出异议
super.run_phase(phase); // 调用父类的 run_phase 函数
seq.start(env.mst.sequencer); // 启动测试序列
phase.drop_objection(this); // 放弃异议
endtask
endclass: apb_burst_transaction_test
// 结束条件编译
`endif // APB_TESTS_SV