定义了用于验证 MCDF 总线(可能是模块或协议名称)的 UVM 组件,包括数据传输类、序列器、监控器、驱动器和 agent。
class mcdf_bus_trans extends uvm_sequence_item; // 定义 MCDF 总线事务类,继承自 uvm_sequence_item
rand bit[1:0] cmd; // 事务命令,随机化
rand bit[7:0] addr; // 事务地址,随机化
rand bit[31:0] wdata; // 写入数据,随机化
bit[31:0] rdata; // 读取数据
`uvm_object_utils_begin(mcdf_bus_trans) // 使用 `uvm_object_utils_begin` 宏定义字段
... // 此处省略了字段定义
`uvm_object_utils_end // 使用 `uvm_object_utils_end` 宏结束字段定义
... // 此处省略了其他方法定义
endclass
class mcdf_bus_sequencer extends uvm_sequencer; // 定义 MCDF 总线序列器类,继承自 uvm_sequencer
virtual mcdf_if vif; // 与 MCDF 接口的虚拟接口
`uvm_component_utils(mcdf_bus_sequencer) // 使用 `uvm_component_utils` 宏定义字段
... // 此处省略了其他方法定义
function void build_phase(uvm_phase phase);
if(!uvm_config_db#(virtual mcdf_if)::get(this, "", "vif", vif)) begin // 从配置数据库获取虚拟接口
`在这里插入代码片` `uvm_error("GETVIF", "no virtual interface is assigned") // 如果获取失败则报错
end
endfunction
endclass
class mcdf_bus_monitor extends uvm_monitor; // 定义 MCDF 总线监控器类,继承自 uvm_monitor
virtual mcdf_if vif; // 与 MCDF 接口的虚拟接口
uvm_analysis_port#(mcdf_bus_trans) ap; // 分析端口,用于发送事务到分析器
`uvm_component_utils(mcdf_bus_monitor) // 使用 `uvm_component_utils` 宏定义字段
... // 此处省略了其他方法定义
function void build_phase(uvm_phase phase);
if(!uvm_config_db#(virtual mcdf_if)::get(this, "", "vif", vif)) begin // 从配置数据库获取虚拟接口
`uvm_error("GETVIF", "no virtual interface is assigned") // 如果获取失败则报错
end
ap = new("ap", this); // 创建分析端口
endfunction
task run_phase(uvm_phase phase);
forever begin // 循环监控事务
mon_trans();
end
endtask
task mon_trans(); // 监控事务任务
mcdf_bus_trans t;
@(posedge vif.clk); // 等待时钟上升沿
if(vif.cmd == `WRITE) begin // 如果是写入操作
t = new(); // 创建事务对象
t.cmd = `WRITE;
t.addr = vif.addr;
t.wdata = vif.wdata;
ap.write(t); // 将事务写入分析端口
end
else if(vif.cmd == `READ) begin // 如果是读取操作
t = new(); // 创建事务对象
t.cmd = `READ;
t.addr = vif.addr;
fork // 并行执行读取操作和发送事务
begin
@(posedge vif.clk); // 等待时钟上升沿
#10ns; // 延迟 10ns
t.rdata = vif.rdata; // 读取数据
ap.write(t); // 将事务写入分析端口
end
join_none
end
endtask
endclass
class mcdf_bus_driver extends uvm_driver; // 定义 MCDF 总线驱动器类,继承自 uvm_driver
virtual mcdf_if vif; // 与 MCDF 接口的虚拟接口
`uvm_component_utils(mcdf_bus_driver) // 使用 `uvm_component_utils` 宏定义字段
... // 此处省略了其他方法定义
function void build_phase(uvm_phase phase);
if(!uvm_config_db#(virtual mcdf_if)::get(this, "", "vif", vif)) begin // 从配置数据库获取虚拟接口
`uvm_error("GETVIF", "no virtual interface is assigned") // 如果获取失败则报错
end
endfunction
task run_phase(uvm_phase phase);
REQ tmp; // 临时变量
mcdf_bus_trans req, rsp; // 事务对象
reset_listener(); // 启动复位监听器
forever begin // 循环驱动事务
seq_item_port.get_next_item(tmp); // 从序列器获取下一条事务
void'($cast(req, tmp)); // 将事务转换为 mcdf_bus_trans 类型
`uvm_info("DRV", $sformatf("got a item \n %s", req.sprint()), UVM_LOW) // 打印信息
void'($cast(rsp, req.clone())); // 克隆事务
rsp.set_sequence_id(req.get_sequence_id()); // 设置序列 ID
rsp.set_transaction_id(req.get_transaction_id()); // 设置事务 ID
driver_bus(rsp); // 驱动总线
seq_item_port.item_done(rsp); // 通知序列器事务完成
`uvm_info("DRV", $sformatf("sent a item \n %s", req.sprint()), UVM_LOW) // 打印信息
end
endtask
task reset_listener(); // 复位监听器任务
fork
forever begin
@(negedge vif.rstn) driver_idle(); // 当复位信号有效时进入空闲状态
end
join_none
endtask
task drive_bus(mcdf_bus_trans t); // 驱动总线任务
case(t.cmd) // 根据命令类型执行不同的驱动操作
`WRITE: drive_write(t); // 写入操作
`READ: drive_read(t); // 读取操作
`IDLE: drive_idle(t); // 空闲状态
default: `uvm_error("DRIVE", "invalid mcdf command type received!") // 非法命令类型,报错
endcase
endtask
task drive_write(mcdf_bus_trans t); // 写入驱动任务
@(posedge vif.clk); // 等待时钟上升沿
vif.cmd <= t.cmd; // 写入命令
vif.addr <= t.addr; // 写入地址
vif.wdata <= t.wdata; // 写入数据
endtask
task drive_read(mcdf_bus_trans t); // 读取驱动任务
@(posedge vif.clk); // 等待时钟上升沿
vif.cmd <= t.cmd; // 写入命令
vif.addr <= t.addr; // 写入地址
@(posedge vif.clk); // 等待时钟上升沿
#10ns; // 延迟 10ns
t.rdata = vif.rdata; // 读取数据
endtask
task drive_idle(bit is_sync=0); // 空闲驱动任务
if(is_sync) @(posedge vif.clk); // 如果是同步操作,则等待时钟上升沿
@(posedge vif.clk); // 等待时钟上升沿
vif.cmd <= 'h0; // 写入空闲命令
vif.addr <= 'h0; // 写入空闲地址
vif.wdata <= 'h0; // 写入空闲数据
endtask
endclass
class mcdf_bus_agent extends uvm_agent; // 定义 MCDF 总线 agent 类,继承自 uvm_agent
mcdf_bus_driver driver; // 驱动器对象
mcdf_bus_sequencer sequencer; // 序列器对象
mcdf_bus_monitor monitor; // 监控器对象
`uvm_component_utils(mcdf_bus_agent) // 使用 `uvm_component_utils` 宏定义字段
... // 此处省略了其他方法定义
function void build_phase(uvm_phase phase);
driver = mcdf_bus_driver::type_id::create("driver", this); // 创建驱动器对象
sequencer = mcdf_bus_sequencer::type_id::create("sequencer", this); // 创建序列器对象
monitor = mcdf_bus_monitor::type_id::create("monitor", this); // 创建监控器对象
endfunction
function void connect_phase(uvm_phase phase);
driver.seq_item_port.connect(sequencer.seq_item_export); // 将驱动器的 seq_item_port 连接到序列器的 seq_item_export
endfunction
endclass
代码功能:
mcdf_bus_trans 类定义了 MCDF 总线上的数据传输结构,包括命令、地址、写入数据和读取数据。
mcdf_bus_sequencer 类定义了 MCDF 总线的序列器,负责生成和发送事务。
mcdf_bus_monitor 类定义了 MCDF 总线的监控器,负责捕获总线上的事务并将其发送到分析器。
mcdf_bus_driver 类定义了 MCDF 总线的驱动器,负责将事务发送到 DUT 并接收响应。
mcdf_bus_agent 类定义了 MCDF 总线的 agent,将驱动器、序列器和监控器组合在一起,并进行连接。
代码优势:
使用 UVM 组件,可以方便地创建和管理测试平台。
使用虚拟接口,可以方便地与 DUT 进行交互。
使用分析端口,可以方便地将事务发送到分析器进行分析。
使用随机化,可以方便地生成测试用例。