Порівняти коміти

...

Немає спільних комітів. 'master' та 'main' мають різну історію.
master ... main

15 змінених файлів з 1507 додано та 2 видалено
  1. +0
    -2
      README.md
  2. +23
    -0
      assertion.sv
  3. +45
    -0
      axi_config_objs.svh
  4. +40
    -0
      axi_env.sv
  5. +211
    -0
      axi_master_driver.sv
  6. +60
    -0
      axi_read_seq.sv
  7. +350
    -0
      axi_s_driver.sv
  8. +109
    -0
      axi_s_monitor.sv
  9. +86
    -0
      axi_scoreboard.sv
  10. +85
    -0
      axi_sequnce.sv
  11. +44
    -0
      axi_slave_agent.sv
  12. +42
    -0
      axi_tb_top.sv
  13. +166
    -0
      axi_test.sv
  14. +185
    -0
      axi_transaction.sv
  15. +61
    -0
      axi_write_seq.sv

+ 0
- 2
README.md Переглянути файл

@@ -1,2 +0,0 @@
# shivakanta_project


+ 23
- 0
assertion.sv Переглянути файл

@@ -0,0 +1,23 @@
module axi_asserttions;


////// handshaking for awvalid & awready

property pro;

@(posedge clk)
disable iff(reset)

(awvalid && !awready) |=> (awvalid && awready) ##1 (!awvalid && !awready);


endproperty


property pro_n;
disable iff(reset)

!($isunknown({awaddr,awlen,awsize,awburst,awvalid})& awburst=2'b 10) |-> (awaddr%(2**awsize)==0)


endproperty

+ 45
- 0
axi_config_objs.svh Переглянути файл

@@ -0,0 +1,45 @@
import uvm_pkg::*;
/* Configuration object to configure the environment of Test Bench.
Configurable fields:
1. intf: Virtual Interface for the agents
2. active: To set the agent as active or passive */
class env_config#(parameter A_WIDTH = 16, D_WIDTH = 16) extends uvm_object;
`uvm_object_utils(env_config)
// variables
virtual axi_intf#(.D_WIDTH(D_WIDTH), .A_WIDTH(A_WIDTH)) intf;
// Master and Slave are active or passive
uvm_active_passive_enum active = UVM_ACTIVE;
function new(string name = "env_config");
super.new(name);
endfunction //new()
endclass //env_config extends uvm_object
// Configuration object which configures the sequence item generation
class test_config extends uvm_object;
`uvm_object_utils(test_config)
// Vartiables
int no_write_cases = 2;
int no_read_cases = 2;
// Set whether to produce aligned address or unalinged address
// -1: produce both aligned and unaligned randomly
// 0: produce unaligned adresses for all bursts
// 1: produce alligned adress for all bursts
byte isAligned = -1;
// Set the specific burst type for a test
// -1: produce all the burst type randomly
// 0: produce fixed bursts
// 1: produce incr bursts
// 2: produce wrap bursts
byte burst_type = -1;
function new(string name = "test_config");
super.new(name);
endfunction //new()
endclass //test_config extends uvm_object

+ 40
- 0
axi_env.sv Переглянути файл

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

+ 211
- 0
axi_master_driver.sv Переглянути файл

@@ -0,0 +1,211 @@
class axi_driver extends uvm_driver#(axi_seq_item);
`uvm_component_utils(axi_driver)

virtual intf vif;
axi_seq_item tx;
int temp[];
int burst_len;
int burst_size;
int total_tr;
int wrap_lower_boundary;
int wrap_upper_boundary;

function new(string name="axi_driver",uvm_component_parent);
super.new(name,parent);
endfunction

function void build_phase(uvm_phase phase);
super.new();
tx=axi_seq_item::type_id::create("tx",this);

if(!uvm_config_db#(virtual intf)::get("this",*,"intf",vif)
`uvm_error(get_type_name(),$sformatf("failed for get vif"))
endfunction

task run_phase(uvm_phase phase)
forever begin
seq_item_port.get_next_item(tx);

drive();

seq_item_port.item_done(tx);
end
endtask

task drive();

if(tx.wr_rd)
begin

write_address();
write_data();
write_response();

end

else

read_address();

endtask
////////write address///////
task write_adress();
@(posedge vif.clk)

tx.awvalid<=1;
vif.awvalid<=tx.awvalid;


vif.awid<=tx.awid;
//vif.awaddr<=tx.awaddr;
vif.awsize<=tx.awsize;
vif.awlen<=tx.awlen;
vif.awburst<=tx.awburst;
//////////fixed burst////////////

if(tx.awburst==2'b00)

vif.awaddr<=tx.awaddr;

////////increament burst////////
else if(awburst==2'b01)begin

vif.awaddr<=tx.awaddr;
for(i=0;i<awlen;i++)
vif.awaddr<=(tx.awaddr+(2**awsize));
end
////////wrap burst/////////
else if(tx.awburst=2'b10)begin
begin
if(((tx.awaddr)%2**awsize)==0)begin
burst_len=tx.awlen+1;
burst_size=2**(tx.awsize);
total_tr=burst_len*burst_size;
wrap_lower_boundary=int'((tx.awaddr)/(total_tr))*total_tr;
wrap_upper_boundary=wrap_lower_boundary+total_tr;
end




vif.awlock<=tx.awlock;

@(posedge vif.clk)
wait(vif.awready)


@(posedge vif.clk)
tx.awvalid<=0;
vif.awvalid<=tx.awvalid;

endtask
//////write data///////////
task write_data();
@posedge vif.clk)
tx.wvalid<=1;
vif.wvalid<=tx.wvalid;
vif.wid<=tx.wid;

foreach(tx.wdata[i,j])
begin
temp[i][8*i+:8]<=tx.wdata[i][j];
end

for(i=0;i<awlen+1;i++);
begin
vif.wdata<=temp[i];
tx.wvalid<=1;
vif.wvalid<=tx.wvalid;

vif.wlast<=awlen==i?1:0;
end
wait(vif.wready);

//endtask
@posedge vif.clk)
tx.wvalid<=0;
vif.wvalid<=tx.wvalid;
endtask

//////////write response //////////

task write_response();

@posedge vif.clk)
vif.bid<=tx.bid;
vif.bresp<=tx.bresp;
tx.bvalid<=1;
vif.bvalid<=tx.bvalid;

@posedge vif.clk)
wait(vif.bready);


@posedge vif.clk)
tx.bvalid<=0;
vif.bvalid<=tx.bvalid;

endtask

/////////read address/////////

task read_adress();
@(posedge vif.clk)

tx.arvalid<=1;
vif.arvalid<=tx.arvalid;


vif.arid<=tx.arid;
//vif.araddr<=tx.araddr;
vif.arsize<=tx.arsize;
vif.arlen<=tx.arlen;
vif.arburst<=tx.arburst;
//////////fixed burst////////////

if(tx.arburst==2'b00)

vif.araddr<=tx.araddr;

vif.arid<=tx.arid;
////////increament burst////////

else if(arburst==2'b01)begin

vif.araddr<=tx.araddr;
for(i=0;i<arlen;i++)
begin
vif.arid<=tx.arid;

vif.araddr<=(tx.araddr+(2**arsize));
end
////////wrap burst/////////
else if(tx.arburst=2'b10)begin
begin
if(((tx.araddr)%2**arsize)==0)begin

vif.arid<=tx.arid;
burst_len=tx.arlen+1;
burst_size=2**(tx.arsize);
total_tr=burst_len*burst_size;
wrap_lower_boundary=int'((tx.araddr)/(total_tr))*total_tr;
wrap_upper_boundary=wrap_lower_boundary+total_tr;
end

vif.arlock<=tx.arlock;

@(posedge vif.clk)
wait(vif.arready)


@(posedge vif.clk)
tx.arvalid<=0;

vif.arvalid<=tx.arvalid;

endtask


endclass



+ 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

+ 85
- 0
axi_sequnce.sv Переглянути файл

@@ -0,0 +1,85 @@
// axi write sequence

class axi_write_sequence extends uvm_sequence#(axi_seq_item);

`uvm_object_utils(axi_write_sequence);

function new(string name="axi_write_sequence");
super.new(name);
endfunction

task body();
req=axi_seq_item::type_id::create(req);

start_item(req);

assert(req.randomize()with{req.wr_rd==1;req.awaddr==0x08;req.awburst==2'b 10;req.awlen==3;req.awsize==2;req.wdata==0x22fb;});

finish_item(req);
endtask

endclass


// axi_read_sequence


class axi_read_sequence extends uvm_sequence#(axi_seq_item);

`uvm_object_utils(axi_read_sequence);

function new(string name="axi_read_sequence");
super.new(name);
endfunction

task body();
req=axi_seq_item::type_id::create(req);

start_item(req);
assert(req.randomize()with{req.wr_rd==0;req.araddr==0x08;arlen==3;arburst==2'b 10;});
finish_item(req);
endtask

endclass

// axi aligned sequence

class axi_aligned_sequence extends uvm_sequence#(axi_seq_item);

`uvm_object_utils(axi_aligned_sequence);

function new(string name="axi_aligned_sequence");
super.new(name);
endfunction

task body();

req=axi_seq_item::type_id::create(req);

start_item(req);
assert(req.randomize()with{req.wr_rd==1;req.awaddr==0x08;req.awsize==3;req.awburst==2'b 10;req.wdata==0xfa30;});
finish_item(req);
endtask
endclass

// write followed by read


class write_read_sequence extends uvm_sequence#(axi_seq_item);
`uvm_object_utils(write_read_sequence);

axi_write_sequence axi_wr_seq;
axi_read_sequence axi_rd_seq;

function new(string name="write_read_sequence");
super.new(name);
endfunction

task body();
`uvm_do(axi_wr_seq);
`uvm_do(axi_rd_seq);
end
endclass




+ 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

+ 42
- 0
axi_tb_top.sv Переглянути файл

@@ -0,0 +1,42 @@
// `include "uvm_pkg.sv"
import uvm_pkg::*;
`include "uvm_macros.svh"
`include "axi_config_objs.svh"
`include "axi_interface.sv"
`include "axi_transaction.sv"
`include "axi_write_seq.sv"
`include "axi_read_seq.sv"
`include "axi_m_driver.sv"
`include "axi_m_monitor.sv"
`include "axi_master_agent.sv"
`include "axi_s_driver.sv"
`include "axi_s_monitor.sv"
`include "axi_slave_agent.sv"
`include "axi_scoreboard.sv"
`include "axi_env.sv"
`include "axi_test.sv"
`include "uvm_pkg.sv"
// parameter A_WIDTH = 8; // Address bus width
// parameter D_WIDTH = 128; // Data bus width
module top;
bit clk, rstn;
always #5 clk = ~clk;
initial rstn = 1;
axi_intf#(.A_WIDTH(A_WIDTH), .D_WIDTH(D_WIDTH)) intf(clk, rstn);
env_config env_cfg;
initial begin
env_cfg = new();
env_cfg.intf = intf;
uvm_config_db#(env_config)::set(null, "uvm_test_top", "config", env_cfg);
uvm_config_db#(env_config)::set(null, "uvm_test_top.env.master", "config", env_cfg);
uvm_config_db#(env_config)::set(null, "uvm_test_top.env.slave", "config", env_cfg);
run_test("axi_base_test");
end
endmodule

+ 166
- 0
axi_test.sv Переглянути файл

@@ -0,0 +1,166 @@
class axi_base_test extends uvm_test;
`uvm_component_utils(axi_base_test)
// Components
axi_env env;
axi_write_seq#(.D_WIDTH(D_WIDTH), .A_WIDTH(A_WIDTH)) wr_seq;
axi_read_seq#(.D_WIDTH(D_WIDTH), .A_WIDTH(A_WIDTH)) rd_seq;
// variables
env_config env_cfg;
test_config test_cfg;
function new(string name, uvm_component parent);
super.new(name, parent);
test_cfg = new("test_cfg");
test_cfg.no_write_cases = 1;
test_cfg.no_read_cases = 1;
endfunction //new()
// Function: build_phase
extern function void build_phase(uvm_phase phase);
// Function: end_of_elaboration_phase
extern function void end_of_elaboration_phase(uvm_phase phase);
// Function: run_phase
extern task run_phase(uvm_phase phase);
endclass //axi_base_test extends uvm_test
function void axi_base_test::build_phase(uvm_phase phase);
test_cfg.burst_type = 2;
uvm_config_db#(test_config)::set(null, "uvm_test_top.seq", "config", test_cfg);
wr_seq = new("wr_seq");
rd_seq = new("rd_seq");
env = axi_env::type_id::create("env", this);
endfunction: build_phase
function void axi_base_test::end_of_elaboration_phase(uvm_phase phase);
super.end_of_elaboration_phase(phase);
uvm_top.print_topology();
endfunction: end_of_elaboration_phase
task axi_base_test::run_phase(uvm_phase phase);
phase.raise_objection(this);
fork
wr_seq.start(env.master.w_seqr);
#200
rd_seq.start(env.master.r_seqr);
// end
join
phase.drop_objection(this);
endtask: run_phase
// ****************************************************************************************
// Directed Test Cases
// ****************************************************************************************
class axi_write_test extends axi_base_test;
`uvm_component_utils(axi_write_test)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction //new()
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction: build_phase
function void end_of_elaboration_phase(uvm_phase phase);
super.end_of_elaboration_phase(phase);
endfunction: end_of_elaboration_phase
task run_phase(uvm_phase phase);
phase.raise_objection(this);
wr_seq.start(env.master.w_seqr);
phase.drop_objection(this);
endtask: run_phase
endclass //write_test extends axi_base_test
class axi_read_test extends axi_base_test;
`uvm_component_utils(axi_read_test)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction //new()
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction: build_phase
function void end_of_elaboration_phase(uvm_phase phase);
super.end_of_elaboration_phase(phase);
endfunction: end_of_elaboration_phase
task run_phase(uvm_phase phase);
phase.raise_objection(this);
wr_seq.start(env.master.w_seqr);
// rd_seq.start(env.master.r_seqr);
phase.drop_objection(this);
endtask: run_phase
endclass //write_test extends axi_base_test
class axi_fixed_test extends axi_base_test;
`uvm_component_utils(axi_fixed_test)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction //new()
function void build_phase(uvm_phase phase);
test_cfg.burst_type = 0;
uvm_config_db#(test_config)::set(null, "uvm_test_top.seq", "config", test_cfg);
wr_seq = new("wr_seq");
rd_seq = new("rd_seq");
env = axi_env::type_id::create("env", this);
endfunction: build_phase
task run_phase(uvm_phase phase);
super.run_phase(phase);
endtask: run_phase
endclass //axi_fixed_test extends axi_base_test
class axi_incr_test extends axi_base_test;
`uvm_component_utils(axi_incr_test)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction //new()
function void build_phase(uvm_phase phase);
test_cfg.burst_type = 1;
uvm_config_db#(test_config)::set(null, "uvm_test_top.seq", "config", test_cfg);
wr_seq = new("wr_seq");
rd_seq = new("rd_seq");
env = axi_env::type_id::create("env", this);
endfunction: build_phase
task run_phase(uvm_phase phase);
super.run_phase(phase);
endtask: run_phase
endclass //axi_fixed_test extends axi_base_test
class axi_wrap_test extends axi_base_test;
`uvm_component_utils(axi_wrap_test)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction //new()
function void build_phase(uvm_phase phase);
test_cfg.burst_type = 2;
uvm_config_db#(test_config)::set(null, "uvm_test_top.seq", "config", test_cfg);
wr_seq = new("wr_seq");
rd_seq = new("rd_seq");
env = axi_env::type_id::create("env", this);
endfunction: build_phase
task run_phase(uvm_phase phase);
super.run_phase(phase);
endtask: run_phase
endclass //axi_fixed_test extends axi_base_test

+ 185
- 0
axi_transaction.sv Переглянути файл

@@ -0,0 +1,185 @@
import uvm_pkg::*;
typedef enum bit[1:0] { FIXED, INCR, WRAP } B_TYPE;
// Class: axi_transaction
//
class axi_transaction#(d_width = 16, a_width = 16) extends uvm_sequence_item;
typedef axi_transaction#(d_width, a_width) this_type_t;
`uvm_object_param_utils(axi_transaction#(d_width, a_width));
// Group: Variables
bit [8:0] id;
rand bit [a_width-1:0] addr;
rand bit write;
rand bit [7:0] data [][];
rand bit [2:0] b_size;
rand bit [3:0] b_len;
rand B_TYPE b_type;
bit b_last;
bit [1:0] b_resp;
bit [1:0] r_resp [];
// Group: Constraints
constraint b_size_val { 8*(2**b_size) <= d_width; }
constraint data_size {
/* solve order constraints */
solve b_len before data;
solve b_size before data;
/* rand variable constraints */
data.size() == b_len+1;
foreach (data[i] )
data[i].size() == 2**b_size;
}
constraint b_len_val {
/* solve order constraints */
solve b_type before b_len;
/* rand variable constraints */
if(b_type == FIXED)
b_len inside { 0, 1 };
else if(b_type == WRAP)
b_len inside { 1, 3, 7, 15 };
}
constraint addr_val {
/* solve order constraints */
solve b_type before addr;
solve b_size before addr;
/* rand variable constraints */
if(b_type == WRAP)
addr == int'(addr/2**b_size) * 2**b_size;
}
constraint addr_val_align {
/* solve order constraints */
solve b_size before addr;
/* rand variable constraints */
addr == int'(addr/2**b_size) * 2**b_size;
}
constraint addr_val_unalign {
/* solve order constraints */
solve b_size before addr;
/* rand variable constraints */
addr != int'(addr/2**b_size) * 2**b_size;
}
// Constructor: new
function new(string name = "axi_transaction");
super.new(name);
endfunction: new
// Function: do_copy
extern function void do_copy(uvm_object rhs);
// Function: do_compare
extern function bit do_compare(uvm_object rhs, uvm_comparer comparer);
// Function: convert2string
extern function string convert2string();
// Function: do_print
extern function void do_print(uvm_printer printer);
// Function: do_record
// extern function void do_record(uvm_recorder recorder);
// Function: do_pack
// extern function void do_pack();
// Function: do_unpack
// extern function void do_unpack();
endclass: axi_transaction
/*----------------------------------------------------------------------------*/
/* Functions */
/*----------------------------------------------------------------------------*/
function void axi_transaction::do_print(uvm_printer printer);
/* chain the print with parent classes */
super.do_print(printer);
/* list of local properties to be printed: */
printer.print_field("ID", id, $bits(id), UVM_UNSIGNED);
printer.print_field("Addr", addr, $bits(addr), UVM_HEX);
printer.print_generic("Data", "dynamic array", 8*2**b_size*(b_len+1), $sformatf("%u", data));
printer.print_field("Burst Size", b_size, $bits(b_size), UVM_UNSIGNED);
printer.print_field("Burst Length", b_len+1, $bits(b_len), UVM_UNSIGNED);
printer.print_generic("Burst Type", "B_TYPE", $bits(b_len), b_type.name());
endfunction: do_print
function string axi_transaction::convert2string();
string s;
/* chain the convert2string with parent classes */
s = super.convert2string();
/* list of local properties to be printed: */
// guide 0---4---8--12--16--20--24--28--32--36--40--44--48--
s = {s, $sformatf("ID : %0d\n", id)};
s = {s, $sformatf("Addr : 0x%0h\n", addr)};
s = {s, $sformatf("Data : 0x%0u\n", data)};
s = {s, $sformatf("Busrt Type : %s\n", b_type.name())};
s = {s, $sformatf("Burst Size : %0d\n", b_size)};
s = {s, $sformatf("Busrt Length : %0d\n", b_len+1)};
s = {s, $sformatf("Busrt resp : 0x%0h\n", b_resp)};
s = {s, $sformatf("Read resp : %0u\n", r_resp)};
return s;
endfunction: convert2string
function void axi_transaction::do_copy(uvm_object rhs);
this_type_t rhs_;
if (!$cast(rhs_, rhs)) begin
`uvm_error({this.get_name(), ".do_copy()"}, "Cast failed!");
return;
end
// `uvm_info({this.get_name(), ".do_copy()"}, "Cast succeded.", UVM_HIGH);
/* chain the copy with parent classes */
super.do_copy(rhs);
/* list of local properties to be copied */
this.id = rhs_.id;
this.addr = rhs_.addr;
this.data = rhs_.data;
this.b_type = rhs_.b_type;
this.b_size = rhs_.b_size;
this.b_len = rhs_.b_len;
this.b_resp = rhs_.b_resp;
this.r_resp = rhs_.r_resp;
endfunction: do_copy
function bit axi_transaction::do_compare(uvm_object rhs, uvm_comparer comparer);
this_type_t rhs_;
if (!$cast(rhs_, rhs)) begin
`uvm_error({this.get_name(), ".do_compare()"}, "Cast failed!");
return 0;
end
// `uvm_info({this.get_name(), ".do_compare()"}, "Cast succeded.", UVM_HIGH);
/* chain the compare with parent classes */
do_compare = super.do_compare(rhs, comparer);
/* list of local properties to be compared: */
do_compare &= (
this.id == rhs_.id &&
this.addr == rhs_.addr &&
this.b_type == rhs_.b_type &&
this.b_size == rhs_.b_size &&
this.b_len == rhs_.b_len &&
this.b_resp == rhs_.b_resp
);
foreach(data[i,j]) begin
do_compare &= this.data[i][j] == rhs_.data[i][j];
end
foreach ( r_resp[i] ) begin
do_compare &= this.r_resp[i] == rhs_.r_resp[i];
end
endfunction: do_compare

+ 61
- 0
axi_write_seq.sv Переглянути файл

@@ -0,0 +1,61 @@
// Class: axi_write_seq
//
class axi_write_seq#(D_WIDTH = 16, int A_WIDTH = 16) extends uvm_sequence;
`uvm_object_param_utils(axi_write_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_write_seq");
super.new(name);
test_cfg = new("test_cfg");
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_write_cases;
endfunction: new
// Task: body
// This is the user-defined task where the main sequence code resides.
extern virtual task body();
endclass: axi_write_seq
task axi_write_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==1;});
else
assert(trans.randomize());
trans.id = {1'b0, id};
finish_item(trans);
trans.print();
#10;
end
endtask: body

Завантаження…
Відмінити
Зберегти