一、chnl_pkg
好戏开始:
//要写chnl_pkgt,所以先写大标题
package chnl_pkg;
//需要用到UVM验证方法,得引入两句话
import uvm_pkg::*;
`include "uvm_macros.svh"
//正片开始,从小到大写,首先item
class chnl_trans extends uvm_sequence_item;
//声明随机变量,包的成员变量
rand bit[31:0] data[];//动态数组表示,32 位
rand int ch_id;//通道号
rand int pkt_id;//包号
rand int data_nidles;//间隔位数
rand int pkt_nidles;
bit rsp;//发送完毕的单比特标志位rsp
//做约束,初始化
constraint cnst {
//data的随机化按照chnl_id左移8位+id
soft data.size inside {[4:32]};
foreach(data[i]) data[i] == 'hC000_0000 + (this.ch_id<<24) + (this.t<<8) + i;
soft ch_id = 0;
soft pkt_id = 0;
soft data_nidles inside {[0:2]};
soft pk_nidles inside {[1:10]};//发包时序
};//注意分号
//做注册和域的自动化
`uvm_object_utils_begin(chnl_trans)
`uvm_field_array_int(data, UVM_ALL_ON)
`uvm_field_int(chnl_id, UVM_ALL_ON)
`uvm_field_int(pkt_id, UVM_ALL_ON)
`uvm_field_int(data_idle, UVM_ALL_ON)
`uvm_field_int(pk_idle, UVM_ALL_ON)
`uvm_object_utils_end
//new()函数,创建新的对象,item继承与事务类transaction,又继承于object,所以新建的时候只有一个参数name
function new (string name = "chnl_trans");
super.new(name);
endfunction
endclass: chnl_trans
//2.driver 负责从sequencer中拿到刚刚写的item,解析,设置通道和包的id之后返回给sequencer一个rsp并点亮rsp
//通信采用TLM通信,即seq_item_port和export端口。
//构建driver类
class chnl_driver extends uvm_driver #(chnl_trans);
声明本地虚拟通道接口 intf,加上local和virtual
local virtual chnl_intf intf;
`uvm_component_utils(chnl_driver)
//创建new()函数
function new(string name = "chnl_driver", uvm_parent parent);
super.new(new, parent);
endfunction
//连通接口
function void set_interface(virtual intf intf);
// 如果 intf 为空,输出错误信息
if (intf == null)
$error("interface handle is null!");
// 否则将传入的 intf 赋值给本地变量
else
this.intf = intf;
endfunction
//run_phase()中有两个线程
task run_phase(uvm_phase phase);
fork
this.do_drive();
this.do_reset();
join
endtask
//第二个线程
function do_reset();
forever begin
// 在 intf.rstn 的下降沿等待
@(negedge intf.rstn);
intf.ch_valid<=0;
intf.ch_data<=0;
end
endtask
//定义第一个线程
task do_drive();
// 声明 chnl_trans 类型的 req 和 rsp 两个变量
chnl_trans req, rsp;
@(posedge intf.rstn);
forever begin
// 从 seq_item_port 中获取下一个 seq item 并赋值给 req
seq_item_port.get_next_item(req);
//将req的数据通过chnl_write任务传递到接口
this.chnl_write(req);
//动态转换// 将 req 的克隆体转换为 rsp
void'($cast(rsp, req.clone));
// 将 rsp 的 rsp 字段赋值为 1
rsp.rsp = 1;
// 将 rsp 的 sequence id 设置为 req 的 sequence id
rsp.set_sequence_id(req.get_sequence_id());
// 通过 seq_item_port 将 rsp 标记为完成
seq_item_port.item_done(rsp);
end
endtask
task chnl_write(input chnl_trans t);
forever(t.data[i]) begin
@