shivakanta_kondapalli 4 месяцев назад
Родитель
Сommit
2166be2109
5 измененных файлов: 649 добавлений и 0 удалений
  1. +60
    -0
      axi_read_seq.sv
  2. +350
    -0
      axi_s_driver.sv
  3. +109
    -0
      axi_s_monitor.sv
  4. +86
    -0
      axi_scoreboard.sv
  5. +44
    -0
      axi_slave_agent.sv

+ 60
- 0
axi_read_seq.sv Просмотреть файл

@@ -0,0 +1,60 @@
// Class: axi_read_seq
//
class axi_read_seq#(D_WIDTH = 16, A_WIDTH = 16) extends uvm_sequence;
`uvm_object_param_utils(axi_read_seq#(D_WIDTH, A_WIDTH));
// Group: Variables
const int no_of_trans;
bit[7:0] id;
axi_transaction#(D_WIDTH, A_WIDTH) trans;
test_config test_cfg;
// Constructor: new
function new(string name = "axi_read_seq");
super.new(name);
if(!uvm_config_db#(test_config)::get(null, "uvm_test_top.seq", "config", test_cfg))
`uvm_fatal(get_name(), "config cannot be found in ConfigDB!")
no_of_trans = test_cfg.no_read_cases;
endfunction: new
// Task: body
// This is the user-defined task where the main sequence code resides.
extern virtual task body();
endclass: axi_read_seq
task axi_read_seq::body();
repeat(no_of_trans) begin
id++;
trans = axi_transaction#(D_WIDTH, A_WIDTH)::type_id::create("trans");
if(test_cfg.isAligned) begin
trans.addr_val_align.constraint_mode(1);
trans.addr_val_unalign.constraint_mode(0);
trans.addr_val.constraint_mode(0);
end
else if (!test_cfg.isAligned) begin
trans.addr_val_align.constraint_mode(0);
trans.addr_val_unalign.constraint_mode(1);
trans.addr_val.constraint_mode(0);
end
else begin
trans.addr_val_align.constraint_mode(0);
trans.addr_val_unalign.constraint_mode(0);
trans.addr_val.constraint_mode(1);
end
start_item(trans);
if(test_cfg.burst_type == 0)
assert(trans.randomize() with { b_type == FIXED; });
else if(test_cfg.burst_type == 1)
assert(trans.randomize() with { b_type == INCR; });
else if(test_cfg.burst_type == 2)
assert(trans.randomize() with { b_type == WRAP;addr==16'h80c6; write==0;});
else
assert(trans.randomize());
trans.id = {1, id};
finish_item(trans);
trans.print();
#10;
end
endtask: body

+ 350
- 0
axi_s_driver.sv Просмотреть файл

@@ -0,0 +1,350 @@
class axi_s_driver extends uvm_driver;
`uvm_component_utils(axi_s_driver)
// Components
virtual axi_intf#(.D_WIDTH(D_WIDTH), .A_WIDTH(A_WIDTH)).SDRV vif;
// Variables
axi_transaction#(D_WIDTH, A_WIDTH) s_wtrans, s_rtrans;
bit [7:0] mem [bit[A_WIDTH-1:0]];
bit [A_WIDTH-1:0] w_addr, r_addr;
bit w_done, r_done;
// Methods
extern task drive();
extern task read_write_address();
extern task read_read_address();
extern task read_write_data();
extern task send_read_data();
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_driver extends uvm_driver
function void axi_s_driver::build_phase(uvm_phase phase);
s_wtrans = new("s_wtrans");
s_rtrans = new("s_rtrans");
endfunction: build_phase
task axi_s_driver::run_phase(uvm_phase phase);
vif.s_drv_cb.AWREADY <= 1;
vif.s_drv_cb.ARREADY <= 1;
vif.s_drv_cb.WREADY <= 1;
// vif.s_drv_cb.BVALID <= 1;
// vif.s_drv_cb.RLAST <= 1;
vif.s_drv_cb.RVALID <= 1;
vif.s_drv_cb.RDATA <= 'b0;
forever begin
@(vif.s_drv_cb);
drive();
end
endtask: run_phase
task axi_s_driver::drive();
if(!vif.rstn) begin
vif.s_drv_cb.RVALID <= 0;
vif.s_drv_cb.BVALID <= 0;
return;
end
// fork
if(vif.s_drv_cb.WRITE)
begin
begin
// `uvm_info("DEBUG_S", $sformatf("w_addr(), w_done = %0d", w_done), UVM_HIGH)
//if(!s_wtrans.id[8])
begin
if(w_done) begin
w_done = 0;
read_write_address();
#5
read_write_data();
w_done = 1;
end
end
end
end
else if(!vif.s_drv_cb.WRITE)
begin
begin
// `uvm_info("DEBUG_S", $sformatf("r_addr(), r_done = %0d", r_done), UVM_HIGH)
// if(s_rtrans.id[8])
begin
if(r_done)
begin
r_done = 0;
$display("t is %t,enter read//////////",$time);
#10
read_read_address();
#20
send_read_data();
r_done = 1;
$display("t is %t,exit read//////////",$time);
end
end
end
end
// join_none
endtask: drive
task axi_s_driver::read_write_address();
`uvm_info("DEBUG_S", "Inside read_write_address", UVM_LOW)
wait(vif.s_drv_cb.AWVALID);
s_wtrans.id = vif.s_drv_cb.AWID;
s_wtrans.addr = vif.s_drv_cb.AWADDR;
s_wtrans.b_size = vif.s_drv_cb.AWSIZE;
s_wtrans.b_type = B_TYPE'(vif.s_drv_cb.AWBURST);
s_wtrans.b_len = vif.s_drv_cb.AWLEN;
s_wtrans.print();
endtask: read_write_address
task axi_s_driver::read_write_data();
int addr_1, addr_n, addr_align;
int lower_byte_lane, upper_byte_lane, upper_wrap_boundary, lower_wrap_boundary;
int no_bytes, total_bytes;
bit isAligned;
int c;
bit err, align_err;
`uvm_info("DEBUG_S", "Inside read_write_data", UVM_LOW)
vif.s_drv_cb.BVALID <= 0;
// Initial values and calculations
addr_1 = s_wtrans.addr;
no_bytes = 2**s_wtrans.b_size;
total_bytes = no_bytes * (s_wtrans.b_len+1);
addr_align = int'(addr_1/no_bytes)*no_bytes;
`uvm_info("DEBUG_S", $sformatf("Calculated aligned addr %0d,addr_1 %0d", addr_align,addr_1), UVM_LOW)
isAligned = addr_1 == addr_align;
// Calculate boundaries for WRAP Burst
if(s_wtrans.b_type == WRAP) begin
lower_wrap_boundary = int'(addr_1/total_bytes)*total_bytes;
upper_wrap_boundary = lower_wrap_boundary + total_bytes;
`uvm_info("DEBUG_S", $sformatf("Calculated Lower Wrap Boundary: %0d", lower_wrap_boundary), UVM_HIGH)
`uvm_info("DEBUG_S", $sformatf("Calculated Upper Wrap Boundary: %0d", upper_wrap_boundary), UVM_HIGH)
end
// check whether the wrap burst is alligned or not
if(s_wtrans.b_type == WRAP && !isAligned)
align_err = 1;
// Store data
err = 0;
for (int i=0; i<s_wtrans.b_len+1; i++) begin
`uvm_info("DEBUG_S", "Inside read_data_loop", UVM_LOW)
// addr_n = addr_align + i*no_bytes;
// Lane selection for the first transfer. In case of unaligned transfer the bytes b/w the
// start address and aligned address is not transferred. Thus for an unaligned burst, the
// first transfer has less bytes and the actual burst size;
// 'c' is a variable which stores which byte lane to select. In AXI, valid byte lane is used and
// selected dynamically using lower_byte_lane and upper_byte_lane, but we for simplicity, we are
// sending the data starting from WDATA[0:8*2**b_size], thus c converts the lower_byte_lane to
// such that it always select the data lines within the valid byte lanes, i.e. [0:8*2**b_size]
// This can be changed in future to match with proper AXI protocol
if(i==0 || s_wtrans.b_type == FIXED) begin
lower_byte_lane = addr_1-int'(addr_1/(D_WIDTH/8))*(D_WIDTH/8);
upper_byte_lane = addr_align+no_bytes-1-int'(addr_1/(D_WIDTH/8))*(D_WIDTH/8);
addr_n = addr_1;
$display("entering");
c = isAligned ? 0 : lower_byte_lane;
while (c>=no_bytes) begin
c -= no_bytes;
end
end
// For 2nd and all other transfers the address is always alligned and thus can read the entire
// valid byte lane, i.e, [0:8*2**b_size]; and thus c always start with 0
else begin
lower_byte_lane = addr_n-int'(addr_n/(D_WIDTH/8))*(D_WIDTH/8);
upper_byte_lane = lower_byte_lane + no_bytes-1;
c = 0;
end
`uvm_info("DEBUG_S", $sformatf("lower_byte_lane is %0d", lower_byte_lane), UVM_HIGH)
`uvm_info("DEBUG_S", $sformatf("upper_byte_lane is %0d", upper_byte_lane), UVM_HIGH)
`uvm_info("DEBUG_S", $sformatf("addr_n is %0d", addr_n), UVM_LOW)
wait(vif.s_drv_cb.WVALID);
`uvm_info("DEBUG_S", $sformatf("WVALID is %0d", vif.s_drv_cb.WVALID), UVM_LOW)
// Follows little endian
err = 0;
for (int j=lower_byte_lane; j<=upper_byte_lane; j++) begin
if(addr_n+j-lower_byte_lane >= 2**A_WIDTH)
err = 1;
if(err || align_err)
continue;
mem[addr_n+j-lower_byte_lane] = vif.s_drv_cb.WDATA[8*c+:8];
`uvm_info("DEBUG_S", $sformatf("c is %0d, addr is %0d, stored value is %h", c, addr_n+j-lower_byte_lane, mem[addr_n+j-lower_byte_lane]), UVM_HIGH)
c++;
c = c>=no_bytes ? 0:c;
end
// Update address
if(s_wtrans.b_type != FIXED) begin
if(isAligned) begin
addr_n = addr_n+no_bytes;
if(s_wtrans.b_type == WRAP) begin
`uvm_info("DEBUG_S", $sformatf("Updated addrn before boundary check: %0d", addr_n), UVM_HIGH)
addr_n = addr_n>=upper_wrap_boundary ? lower_wrap_boundary : addr_n;
`uvm_info("DEBUG_S", $sformatf("Updated addrn after boundary check: %0d", addr_n), UVM_HIGH)
end
end
else begin
addr_n = addr_align + no_bytes;
isAligned = 1;
end
end
@(vif.s_drv_cb);
end
vif.s_drv_cb.BID <= s_wtrans.id;
if(err || align_err)
vif.s_drv_cb.BRESP <= 2'b01;
else
vif.s_drv_cb.BRESP <= 2'b00;
@(vif.s_drv_cb);
vif.s_drv_cb.BVALID <= 1;
@(vif.s_drv_cb);
wait(vif.s_drv_cb.BREADY)
vif.s_drv_cb.BVALID <= 0;
endtask: read_write_data
task axi_s_driver::read_read_address();
`uvm_info("DEBUG_S", "Inside read_write_address", UVM_LOW)
// `uvm_info("DEBUG_S",$sformatf("ARVALID IS %b",vif.s_drv_cb.ARVALID) , UVM_LOW)
wait(vif.s_drv_cb.ARVALID);
// `uvm_info("DEBUG_S", $sformatf("ARVALID IS %b",vif.s_drv_cb.ARVALID), UVM_LOW)
s_rtrans.id = vif.s_drv_cb.ARID;
s_rtrans.addr = vif.s_drv_cb.ARADDR;
s_rtrans.b_size = vif.s_drv_cb.ARSIZE;
s_rtrans.b_type = B_TYPE'(vif.s_drv_cb.ARBURST);
s_rtrans.b_len = vif.s_drv_cb.ARLEN;
s_rtrans.print();
endtask: read_read_address
task axi_s_driver::send_read_data();
int addr_1, addr_n, addr_align;
int lower_byte_lane, upper_byte_lane, upper_wrap_boundary, lower_wrap_boundary;
int no_bytes, total_bytes;
bit isAligned;
int c;
bit err;
`uvm_info("DEBUG_S", "Inside send_read_data", UVM_LOW)
addr_1 = s_rtrans.addr;
no_bytes = 2**s_rtrans.b_size;
total_bytes = no_bytes * (s_rtrans.b_len+1);
// Calculate align address
addr_align = int'(addr_1/no_bytes)*no_bytes;
`uvm_info("DEBUG_S", $sformatf("Calculated aligned addr %0d", addr_align), UVM_HIGH)
isAligned = addr_1 == addr_align;
// If WRAP Burst then calculate the wrap boundary
if(s_rtrans.b_type == WRAP) begin
lower_wrap_boundary = int'(addr_1/total_bytes)*total_bytes;
upper_wrap_boundary = lower_wrap_boundary + total_bytes;
`uvm_info("DEBUG_S", $sformatf("Calculated Lower Wrap Boundary: %0d", lower_wrap_boundary), UVM_HIGH)
`uvm_info("DEBUG_S", $sformatf("Calculated Upper Wrap Boundary: %0d", upper_wrap_boundary), UVM_HIGH)
end
// Initial signals
vif.s_drv_cb.RLAST <= 0;
vif.s_drv_cb.RVALID <=0;
vif.s_drv_cb.RID <= s_rtrans.id;
// Store data
for (int i=0; i<s_rtrans.b_len+1; i++) begin
// `uvm_info("DEBUG_S", "Inside send_data_loop", UVM_LOW)
// addr_n = addr_align + i*no_bytes;
// Lane selection for the first transfer. In case of unaligned transfer the bytes b/w the
// start address and aligned address is not transferred. Thus for an unaligned burst, the
// first transfer has less bytes and the actual burst size;
// 'c' is a variable which stores which byte lane to select. In AXI, valid byte lane is used and
// selected dynamically using lower_byte_lane and upper_byte_lane, but we for simplicity, we are
// sending the data starting from WDATA[0:8*2**b_size], thus c converts the lower_byte_lane to
// such that it always select the data lines within the valid byte lanes, i.e. [0:8*2**b_size]
// This can be changed in future to match with proper AXI protocol
if(i==0 || s_rtrans.b_type == FIXED) begin
lower_byte_lane = addr_1-int'(addr_1/(D_WIDTH/8))*(D_WIDTH/8);
upper_byte_lane = addr_align+no_bytes-1-int'(addr_1/(D_WIDTH/8))*(D_WIDTH/8);
addr_n = addr_1;
c = isAligned ? 0 : lower_byte_lane;
while (c>=no_bytes) begin
c -= no_bytes;
end
end
// For 2nd and all other transfers the address is always alligned and thus can read the entire
// valid byte lane, i.e, [0:8*2**b_size]; and thus c always start with 0
else begin
lower_byte_lane = addr_n-int'(addr_n/(D_WIDTH/8))*(D_WIDTH/8);
upper_byte_lane = lower_byte_lane + no_bytes-1;
c = 0;
end
// @(vif.s_drv_cb);
`uvm_info("DEBUG_S", $sformatf("lower_byte_lane is %0d", lower_byte_lane), UVM_HIGH)
`uvm_info("DEBUG_S", $sformatf("upper_byte_lane is %0d", upper_byte_lane), UVM_HIGH)
`uvm_info("DEBUG_S", $sformatf("addr_n is %0d", addr_n), UVM_HIGH)
// Follows little endian
err = 0;
for (int j=lower_byte_lane; j<=upper_byte_lane; j++) begin
if(!mem.exists(addr_n+j-lower_byte_lane)) begin
err = 1;
vif.s_drv_cb.RDATA[8*c+:8] <= 'b0;
`uvm_info("DEBUG_S", $sformatf("c is %0d, addr is %0d, No data in location", c, addr_n+j-lower_byte_lane), UVM_HIGH)
end
else begin
vif.s_drv_cb.RDATA[8*c+:8] <= mem[addr_n+j-lower_byte_lane];
`uvm_info("DEBUG_S", $sformatf("c is %0d, addr is %0d, stored value is %h", c, addr_n+j-lower_byte_lane, mem[addr_n+j-lower_byte_lane]), UVM_HIGH)
end
c++;
c = c>=no_bytes ? 0:c;
end
if(i == s_rtrans.b_len) begin
vif.s_drv_cb.RLAST <= 1;
end
if(err)
vif.s_drv_cb.RRESP <= 2'b01;
else
vif.s_drv_cb.RRESP <= 2'b00;
@(vif.s_drv_cb);
vif.s_drv_cb.RVALID <= 1;
// Update address
if(s_rtrans.b_type != FIXED) begin
if(isAligned) begin
addr_n = addr_n+no_bytes;
if(s_rtrans.b_type == WRAP) begin
`uvm_info("DEBUG_S", $sformatf("Updated addrn before boundary check: %0d", addr_n), UVM_HIGH)
addr_n = addr_n>=upper_wrap_boundary ? lower_wrap_boundary : addr_n;
`uvm_info("DEBUG_S", $sformatf("Updated addrn after boundary check: %0d", addr_n), UVM_HIGH)
end
end
else begin
addr_n = addr_align + no_bytes;
isAligned = 1;
end
end
@(vif.s_drv_cb);
wait(vif.s_drv_cb.RREADY);
vif.s_drv_cb.RVALID <= 0;
end
endtask: send_read_data

+ 109
- 0
axi_s_monitor.sv Просмотреть файл

@@ -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

+ 86
- 0
axi_scoreboard.sv Просмотреть файл

@@ -0,0 +1,86 @@
`uvm_analysis_imp_decl(_master)
`uvm_analysis_imp_decl(_slave)
class axi_scoreboard extends uvm_scoreboard;
`uvm_component_utils(axi_scoreboard)
// Components
uvm_analysis_imp_master#(axi_transaction#(D_WIDTH, A_WIDTH), axi_scoreboard) m_ap_imp;
uvm_analysis_imp_slave#(axi_transaction#(D_WIDTH, A_WIDTH), axi_scoreboard) s_ap_imp;
// Variables
axi_transaction#(D_WIDTH, A_WIDTH) m_wtrans, m_rtrans, s_wtrans, s_rtrans;
bit [1:0] w_rcvd, r_rcvd;
int passCnt, failCnt;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction //new()
function void write_master(axi_transaction#(D_WIDTH, A_WIDTH) trans);
if(trans.id[8]) begin
m_rtrans = trans;
r_rcvd[0] = 1;
end
else begin
m_wtrans = trans;
w_rcvd[0] = 1;
end
check();
endfunction
function void write_slave(axi_transaction#(D_WIDTH, A_WIDTH) trans);
if(trans.id[8]) begin
s_rtrans = trans;
r_rcvd[1] = 1;
end
else begin
s_wtrans = trans;
w_rcvd[1] = 1;
end
check();
endfunction
function void check();
if(w_rcvd == 2'b11) begin
if(m_wtrans.compare(s_wtrans)) begin
`uvm_info("SCB", $sformatf("ID %0d: PASSED", m_wtrans.id), UVM_NONE)
passCnt++;
end
else begin
`uvm_error("SCB", $sformatf("ID %0d: FAILED", m_wtrans.id))
failCnt++;
end
w_rcvd = 2'b00;
end
if(r_rcvd == 2'b11) begin
if(m_rtrans.compare(s_rtrans)) begin
`uvm_info("SCB", $sformatf("ID %0d: PASSED", m_rtrans.id), UVM_NONE)
passCnt++;
end
else begin
`uvm_error("SCB", $sformatf("ID %0d: FAILED", m_rtrans.id))
failCnt++;
end
r_rcvd = 2'b00;
end
endfunction
// Function: build_phase
extern function void build_phase(uvm_phase phase);
endclass //axi_scoreboard extends uvm_scoreboard
function void axi_scoreboard::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);
m_ap_imp = new("m_ap_imp", this);
s_ap_imp = new("s_ap_imp", this);
endfunction: build_phase

+ 44
- 0
axi_slave_agent.sv Просмотреть файл

@@ -0,0 +1,44 @@
class axi_slave extends uvm_agent;
`uvm_component_utils(axi_slave)
// Components
axi_s_driver drv;
axi_s_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_slave extends uvm_agent
function void axi_slave::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_s_driver::type_id::create("drv", this);
mon = axi_s_monitor::type_id::create("mon", this);
drv.vif = env_cfg.intf;
mon.vif = env_cfg.intf;
ap = new("ap", this);
endfunction: build_phase
function void axi_slave::connect_phase(uvm_phase phase);
super.connect_phase(phase);
mon.ap.connect(ap);
endfunction: connect_phase

Загрузка…
Отмена
Сохранить