@@ -0,0 +1,40 @@ | |||||
class axi_env extends uvm_env; | |||||
`uvm_component_utils(axi_env) | |||||
// Components | |||||
axi_master master; | |||||
axi_slave slave; | |||||
axi_scoreboard scb; | |||||
env_config env_cfg; | |||||
// | |||||
function new(string name, uvm_component parent); | |||||
super.new(name, parent); | |||||
endfunction //new() | |||||
// Function: build_phase | |||||
extern function void build_phase(uvm_phase phase); | |||||
// Function: connect_phase | |||||
extern function void connect_phase(uvm_phase phase); | |||||
endclass //axi_env extends uvm_env | |||||
function void axi_env::build_phase(uvm_phase phase); | |||||
/* note: Do not call super.build_phase() from any class that is extended from an UVM base class! */ | |||||
/* For more information see UVM Cookbook v1800.2 p.503 */ | |||||
//super.build_phase(phase); | |||||
master = axi_master::type_id::create("master", this); | |||||
slave = axi_slave::type_id::create("slave", this); | |||||
scb = axi_scoreboard::type_id::create("scb", this); | |||||
endfunction: build_phase | |||||
function void axi_env::connect_phase(uvm_phase phase); | |||||
super.connect_phase(phase); | |||||
master.ap.connect(scb.m_ap_imp); | |||||
slave.ap.connect(scb.s_ap_imp); | |||||
endfunction: connect_phase | |||||
@@ -0,0 +1,108 @@ | |||||
class axi_m_monitor extends uvm_monitor; | |||||
`uvm_component_utils(axi_m_monitor) | |||||
// Components | |||||
uvm_analysis_port#(axi_transaction#(D_WIDTH, A_WIDTH)) ap; | |||||
virtual axi_intf#(.D_WIDTH(D_WIDTH), .A_WIDTH(A_WIDTH)).SMON vif; | |||||
// variables | |||||
axi_transaction#(D_WIDTH, A_WIDTH) w_trans, r_trans; | |||||
bit w_done, r_done; | |||||
int b_size; | |||||
// Methods | |||||
extern task run_mon(uvm_phase phase); | |||||
extern task write_monitor(); | |||||
extern task read_monitor(); | |||||
function new(string name, uvm_component parent); | |||||
super.new(name, parent); | |||||
w_done = 1; | |||||
r_done = 1; | |||||
endfunction //new() | |||||
// Function: build_phase | |||||
extern function void build_phase(uvm_phase phase); | |||||
// Function: run_phase | |||||
extern task run_phase(uvm_phase phase); | |||||
endclass //axi_m_monitor extends uvm_monitor | |||||
function void axi_m_monitor::build_phase(uvm_phase phase); | |||||
ap = new("ap", this); | |||||
endfunction: build_phase | |||||
task axi_m_monitor::run_phase(uvm_phase phase); | |||||
forever begin | |||||
run_mon(phase); | |||||
@(vif.mon_cb); | |||||
end | |||||
endtask: run_phase | |||||
task axi_m_monitor::run_mon(uvm_phase phase); | |||||
fork | |||||
if(w_done) begin | |||||
phase.raise_objection(this); | |||||
w_done = 0; | |||||
write_monitor(); | |||||
w_done = 1; | |||||
phase.drop_objection(this); | |||||
end | |||||
if(r_done) begin | |||||
phase.raise_objection(this); | |||||
r_done = 0; | |||||
read_monitor(); | |||||
r_done = 1; | |||||
phase.drop_objection(this); | |||||
end | |||||
join_none | |||||
endtask: run_mon | |||||
task axi_m_monitor::write_monitor(); | |||||
if(vif.mon_cb.AWVALID && vif.mon_cb.AWREADY) begin | |||||
w_trans = axi_transaction#(D_WIDTH, A_WIDTH)::type_id::create("w_trans"); | |||||
w_trans.addr = vif.mon_cb.AWADDR; | |||||
w_trans.id = vif.mon_cb.AWID; | |||||
w_trans.b_size = vif.mon_cb.AWSIZE; | |||||
w_trans.b_len = vif.mon_cb.AWLEN; | |||||
w_trans.b_type = B_TYPE'(vif.mon_cb.AWBURST); | |||||
w_trans.data = new [w_trans.b_len+1]; | |||||
for (int i=0; i<w_trans.b_len+1; i++) begin | |||||
@(vif.mon_cb); | |||||
wait(vif.mon_cb.WVALID && vif.mon_cb.WREADY); | |||||
w_trans.data[i] = new [D_WIDTH/8]; | |||||
for (int j=0; j<D_WIDTH/8; j++) begin | |||||
w_trans.data[i][j] = vif.mon_cb.WDATA[8*j+:8]; | |||||
end | |||||
end | |||||
wait(vif.mon_cb.BVALID); | |||||
w_trans.b_resp = vif.mon_cb.BRESP; | |||||
ap.write(w_trans); | |||||
`uvm_info("MMON", $sformatf("WTRANS %s", w_trans.convert2string()), UVM_HIGH) | |||||
end | |||||
endtask: write_monitor | |||||
task axi_m_monitor::read_monitor(); | |||||
if(vif.mon_cb.ARVALID && vif.mon_cb.ARREADY) begin | |||||
r_trans = axi_transaction#(D_WIDTH, A_WIDTH)::type_id::create("r_trans"); | |||||
r_trans.addr = vif.mon_cb.ARADDR; | |||||
r_trans.id = vif.mon_cb.ARID; | |||||
r_trans.b_size = vif.mon_cb.ARSIZE; | |||||
r_trans.b_len = vif.mon_cb.ARLEN; | |||||
r_trans.b_type = B_TYPE'(vif.mon_cb.ARBURST); | |||||
r_trans.data = new [r_trans.b_len+1]; | |||||
r_trans.r_resp = new [r_trans.b_len+1]; | |||||
for (int i=0; i<r_trans.b_len+1; i++) begin | |||||
@(vif.mon_cb); | |||||
wait(vif.mon_cb.RVALID && vif.mon_cb.RREADY); | |||||
r_trans.data[i] = new [D_WIDTH/8]; | |||||
for (int j=0; j<D_WIDTH/8; j++) begin | |||||
r_trans.data[i][j] = vif.mon_cb.RDATA[8*j+:8]; | |||||
end | |||||
r_trans.r_resp[i] = vif.mon_cb.RRESP; | |||||
end | |||||
ap.write(r_trans); | |||||
`uvm_info("MMON", $sformatf("RTRANS %s", r_trans.convert2string()), UVM_HIGH) | |||||
end | |||||
endtask: read_monitor |
@@ -0,0 +1,50 @@ | |||||
class axi_master extends uvm_agent; | |||||
`uvm_component_utils(axi_master) | |||||
// Components | |||||
uvm_sequencer#(axi_transaction#(D_WIDTH, A_WIDTH)) w_seqr; | |||||
uvm_sequencer#(axi_transaction#(D_WIDTH, A_WIDTH)) r_seqr; | |||||
axi_m_driver drv; | |||||
axi_m_monitor mon; | |||||
uvm_analysis_port#(axi_transaction#(D_WIDTH, A_WIDTH)) ap; | |||||
// Variables | |||||
env_config env_cfg; | |||||
function new(string name, uvm_component parent); | |||||
super.new(name, parent); | |||||
endfunction //new() | |||||
// Function: build_phase | |||||
extern function void build_phase(uvm_phase phase); | |||||
// Function: connect_phase | |||||
extern function void connect_phase(uvm_phase phase); | |||||
endclass //axi_master extends uvm_agent | |||||
function void axi_master::build_phase(uvm_phase phase); | |||||
env_cfg = new("env_cfg"); | |||||
assert (uvm_config_db#(env_config)::get(this, "", "config", env_cfg)) begin | |||||
`uvm_info(get_name(), "vif has been found in ConfigDB.", UVM_LOW) | |||||
end else `uvm_fatal(get_name(), "vif cannot be found in ConfigDB!") | |||||
drv = axi_m_driver::type_id::create("drv", this); | |||||
mon = axi_m_monitor::type_id::create("mon", this); | |||||
w_seqr = uvm_sequencer#(axi_transaction#(D_WIDTH, A_WIDTH))::type_id::create("w_seqr", this); | |||||
r_seqr = uvm_sequencer#(axi_transaction#(D_WIDTH, A_WIDTH))::type_id::create("r_seqr", this); | |||||
drv.vif = env_cfg.intf; | |||||
mon.vif = env_cfg.intf; | |||||
ap = new("ap", this); | |||||
endfunction: build_phase | |||||
function void axi_master::connect_phase(uvm_phase phase); | |||||
super.connect_phase(phase); | |||||
drv.seq_item_port.connect(w_seqr.seq_item_export); | |||||
drv.seq_item_port2.connect(r_seqr.seq_item_export); | |||||
mon.ap.connect(ap); | |||||
endfunction: connect_phase | |||||
@@ -0,0 +1,109 @@ | |||||
class axi_s_monitor extends uvm_monitor; | |||||
`uvm_component_utils(axi_s_monitor) | |||||
// Components | |||||
uvm_analysis_port#(axi_transaction#(D_WIDTH, A_WIDTH)) ap; | |||||
virtual axi_intf#(.D_WIDTH(D_WIDTH), .A_WIDTH(A_WIDTH)).SMON vif; | |||||
// variables | |||||
axi_transaction#(D_WIDTH, A_WIDTH) w_trans, r_trans; | |||||
bit w_done, r_done; | |||||
int b_size; | |||||
// Methods | |||||
extern task run_mon(uvm_phase phase); | |||||
extern task write_monitor(); | |||||
extern task read_monitor(); | |||||
function new(string name, uvm_component parent); | |||||
super.new(name, parent); | |||||
w_done = 1; | |||||
r_done = 1; | |||||
endfunction //new() | |||||
// Function: build_phase | |||||
extern function void build_phase(uvm_phase phase); | |||||
// Function: run_phase | |||||
extern task run_phase(uvm_phase phase); | |||||
endclass //axi_s_monitor extends uvm_monitor | |||||
function void axi_s_monitor::build_phase(uvm_phase phase); | |||||
ap = new("ap", this); | |||||
endfunction: build_phase | |||||
task axi_s_monitor::run_phase(uvm_phase phase); | |||||
forever begin | |||||
run_mon(phase); | |||||
@(vif.mon_cb); | |||||
end | |||||
endtask: run_phase | |||||
task axi_s_monitor::run_mon(uvm_phase phase); | |||||
fork | |||||
if(w_done) begin | |||||
phase.raise_objection(this); | |||||
w_done = 0; | |||||
write_monitor(); | |||||
w_done = 1; | |||||
phase.drop_objection(this); | |||||
end | |||||
if(r_done) begin | |||||
phase.raise_objection(this); | |||||
r_done = 0; | |||||
read_monitor(); | |||||
r_done = 1; | |||||
phase.drop_objection(this); | |||||
end | |||||
join_none | |||||
endtask: run_mon | |||||
task axi_s_monitor::write_monitor(); | |||||
if(vif.mon_cb.AWVALID && vif.mon_cb.AWREADY) begin | |||||
w_trans = axi_transaction#(D_WIDTH, A_WIDTH)::type_id::create("w_trans"); | |||||
w_trans.addr = vif.mon_cb.AWADDR; | |||||
w_trans.id = vif.mon_cb.AWID; | |||||
w_trans.b_size = vif.mon_cb.AWSIZE; | |||||
w_trans.b_len = vif.mon_cb.AWLEN; | |||||
w_trans.b_type = B_TYPE'(vif.mon_cb.AWBURST); | |||||
w_trans.data = new [w_trans.b_len+1]; | |||||
for (int i=0; i<w_trans.b_len+1; i++) begin | |||||
@(vif.mon_cb); | |||||
wait(vif.mon_cb.WVALID && vif.mon_cb.WREADY); | |||||
w_trans.data[i] = new [D_WIDTH/8]; | |||||
for (int j=0; j<D_WIDTH/8; j++) begin | |||||
w_trans.data[i][j] = vif.mon_cb.WDATA[8*j+:8]; | |||||
end | |||||
end | |||||
wait(vif.mon_cb.BVALID); | |||||
w_trans.b_resp = vif.mon_cb.BRESP; | |||||
ap.write(w_trans); | |||||
`uvm_info("SMON", $sformatf("WTRANS %s", w_trans.convert2string()), UVM_HIGH) | |||||
end | |||||
endtask: write_monitor | |||||
task axi_s_monitor::read_monitor(); | |||||
if(vif.mon_cb.ARVALID && vif.mon_cb.ARREADY) begin | |||||
r_trans = axi_transaction#(D_WIDTH, A_WIDTH)::type_id::create("r_trans"); | |||||
r_trans.addr = vif.mon_cb.ARADDR; | |||||
r_trans.id = vif.mon_cb.ARID; | |||||
r_trans.b_size = vif.mon_cb.ARSIZE; | |||||
r_trans.b_len = vif.mon_cb.ARLEN; | |||||
r_trans.b_type = B_TYPE'(vif.mon_cb.ARBURST); | |||||
r_trans.data = new [r_trans.b_len+1]; | |||||
r_trans.r_resp = new [r_trans.b_len+1]; | |||||
for (int i=0; i<r_trans.b_len+1; i++) begin | |||||
@(vif.mon_cb); | |||||
wait(vif.mon_cb.RVALID && vif.mon_cb.RREADY); | |||||
r_trans.data[i] = new [D_WIDTH/8]; | |||||
for (int j=0; j<D_WIDTH/8; j++) begin | |||||
r_trans.data[i][j] = vif.mon_cb.RDATA[8*j+:8]; | |||||
end | |||||
r_trans.r_resp[i] = vif.mon_cb.RRESP; | |||||
end | |||||
ap.write(r_trans); | |||||
`uvm_info("SMON", $sformatf("RTRANS %s", r_trans.convert2string()), UVM_HIGH) | |||||
end | |||||
endtask: read_monitor |
@@ -0,0 +1,128 @@ | |||||
interface axi_if(input bit aclk,arst); | |||||
//write address channel | |||||
logic[31:0]awaddr; | |||||
bit[3:0]awid; | |||||
logic[3:0]awlen; | |||||
logic[2:0]awsize; | |||||
logic[1:0]awburst; | |||||
logic[3:0]awcache; | |||||
logic[2:0]awprot; | |||||
logic[1:0]awlock; | |||||
logic awvalid;' | |||||
logic awready; | |||||
//write data channel | |||||
bit[3:0]wid; | |||||
logic[3:0]wstrb; | |||||
logic[31:0]wdata[$]; | |||||
logic wlast; | |||||
logic wvalid; | |||||
logic wready; | |||||
//write response channel | |||||
bit[3:0]bid; | |||||
logic[1:0]bresp; | |||||
logic bvalid; | |||||
logic bready; | |||||
//read address channel | |||||
logic[31:0]araddr; | |||||
bit[3:0]arid; | |||||
logic[3:0]arlen; | |||||
logic[2:0]arsize; | |||||
logic[1:0]arburst; | |||||
logic[3:0]arcache; | |||||
logic[2:0]arprot; | |||||
logic[1:0]arlock; | |||||
logic arvalid; | |||||
logic arready; | |||||
//read data channel | |||||
bit[3:0]rid; | |||||
logic[31:0]rdata[$]; | |||||
logic rlast; | |||||
logic[1:0]rresp; | |||||
logic rvalid; | |||||
logic rready; | |||||
clocking drv_cb @(posedge aclk); | |||||
default input #1 output #0; | |||||
output awid; //write address channel | |||||
output awaddr; | |||||
output awlen; | |||||
output awsize; | |||||
output awburst; | |||||
output awprot; | |||||
output awcache; | |||||
output awlock; | |||||
output awvalid; | |||||
input awready; | |||||
output wid; //write data channel | |||||
output wdata; | |||||
output wstrb; | |||||
output wlast; | |||||
output wvalid; | |||||
input wready; //write response channel | |||||
input bid; | |||||
input bresp; | |||||
input bvalid; | |||||
output bready; | |||||
output arid; //read address channel | |||||
output araddr; | |||||
output arlen; | |||||
output arsize; | |||||
output arburst; | |||||
output arprot; | |||||
output arcache; | |||||
output arlock; | |||||
output arvalid; | |||||
input arready; | |||||
input rid; //read response channel | |||||
input rdata; | |||||
input rresp; | |||||
input rlast; | |||||
input rvalid; | |||||
output rready; | |||||
endclocking | |||||
clocking mon_cb @(posedge clk); | |||||
default input #1 output #0; | |||||
input awid; //write address channel | |||||
input awaddr; | |||||
input awlen; | |||||
input awsize; | |||||
input awburst; | |||||
input awprot; | |||||
input awcache; | |||||
input awlock; | |||||
input awvalid; | |||||
input awready; | |||||
input wid; //write data channel | |||||
input wdata; | |||||
input wstrb; | |||||
input wlast; | |||||
input wvalid; | |||||
input wready; //write response channel | |||||
input bid; | |||||
input bresp; | |||||
input bvalid; | |||||
input bready; | |||||
input arid; //read address channel | |||||
input araddr; | |||||
input arlen; | |||||
input arsize; | |||||
input arburst; | |||||
input arprot; | |||||
input arcache; | |||||
input arlock; | |||||
input arvalid; | |||||
input arready; | |||||
input rid; //read data channel | |||||
input rdata; | |||||
input rresp; | |||||
input rlast; | |||||
input rvalid; | |||||
input rready; | |||||
endclocking | |||||
modport drv_mod(clocking drv_cb,arst); | |||||
modport mon_mod(clocking mon_cb,arst); | |||||
endinterface | |||||