|
|
|
@@ -1,125 +1,185 @@ |
|
|
|
`include "uvm_macros.svh" |
|
|
|
import uvm_pkg::*; |
|
|
|
|
|
|
|
class axi_seq_item extends uvm_seq_item; |
|
|
|
//'uvm_object_utils(axi_seq_item); |
|
|
|
|
|
|
|
function new(string name="axi_seq_item") |
|
|
|
super.new(name); |
|
|
|
endfunction |
|
|
|
//write adress channel signals |
|
|
|
|
|
|
|
rand bit wr_rd; |
|
|
|
|
|
|
|
rand bit [3:0] awid; |
|
|
|
rand logic[31:0] awaddr; |
|
|
|
rand logic[2:0] awsize; |
|
|
|
rand logic[3:0] awlen; |
|
|
|
rand logic[1:0] awburst; |
|
|
|
rand logic[1:0] awlock; |
|
|
|
|
|
|
|
logic awvalid; |
|
|
|
logic awready; |
|
|
|
|
|
|
|
|
|
|
|
//write data channel |
|
|
|
|
|
|
|
rand bit [3:0] wid; |
|
|
|
rand logic[31:0] wdata[][]; |
|
|
|
logic[3:0] wstrb; |
|
|
|
logic wlast; |
|
|
|
logic wvalid; |
|
|
|
logic wready; |
|
|
|
|
|
|
|
// write response channel |
|
|
|
rand bit []3:0]bid; |
|
|
|
logic[1:0] bresp; |
|
|
|
|
|
|
|
logic bvalid; |
|
|
|
logic bready; |
|
|
|
|
|
|
|
// read adress channel |
|
|
|
|
|
|
|
rand bit [3:0] arid; |
|
|
|
|
|
|
|
rand logic[31:0] araddr; |
|
|
|
rand logic[2:0] arsize; |
|
|
|
rand logic[3:0] arlen; |
|
|
|
rand logic[1:0] arburst; |
|
|
|
rand logic[1:0] arlock; |
|
|
|
logic arvalid; |
|
|
|
logic arready; |
|
|
|
|
|
|
|
// read data channel |
|
|
|
|
|
|
|
|
|
|
|
rand bit [3:0] rid; |
|
|
|
logic[31:0] rdata; |
|
|
|
logic[3:0]rresp; |
|
|
|
logic rlast; |
|
|
|
logic rvalid; |
|
|
|
logic rready; |
|
|
|
|
|
|
|
|
|
|
|
`uvm_object_utils_begin(axi_seq_item) |
|
|
|
|
|
|
|
`uvm_field_int(awid,UVM_ALL_ON) |
|
|
|
`uvm_field_int(awaddr,UVM_ALL_ON) |
|
|
|
`uvm_field_int(awsize,UVM_ALL_ON) |
|
|
|
`uvm_field_int(awlen,UVM_ALL_ON) |
|
|
|
`uvm_field_int(awburst,UVM_ALL_ON) |
|
|
|
`uvm_field_int(awlock,UVM_ALL_ON) |
|
|
|
`uvm_field_int(awvalid,UVM_ALL_ON) |
|
|
|
`uvm_field_int(awready,UVM_ALL_ON) |
|
|
|
|
|
|
|
`uvm_field_int(wid,UVM_ALL_ON) |
|
|
|
`uvm_field_int(wdata,UVM_ALL_ON) |
|
|
|
`uvm_field_int(wlast,UVM_ALL_ON) |
|
|
|
`uvm_field_int(wstrb,UVM_ALL_ON) |
|
|
|
`uvm_field_int(wvalid,UVM_ALL_ON) |
|
|
|
`uvm_field_int(wready,UVM_ALL_ON) |
|
|
|
|
|
|
|
`uvm_field_int(bid,UVM_ALL_ON) |
|
|
|
`uvm_field_int(bresp,UVM_ALL_ON) |
|
|
|
`uvm_field_int(bvalid,UVM_ALL_ON) |
|
|
|
`uvm_field_int(bready,UVM_ALL_ON) |
|
|
|
|
|
|
|
`uvm_field_int(arid,UVM_ALL_ON) |
|
|
|
`uvm_field_int(araddr,UVM_ALL_ON) |
|
|
|
`uvm_field_int(arsize,UVM_ALL_ON) |
|
|
|
`uvm_field_int(arlen,UVM_ALL_ON) |
|
|
|
`uvm_field_int(arsize,UVM_ALL_ON) |
|
|
|
`uvm_field_int(arburst,UVM_ALL_ON) |
|
|
|
`uvm_field_int(arlock,UVM_ALL_ON) |
|
|
|
`uvm_field_int(arvalid,UVM_ALL_ON) |
|
|
|
`uvm_field_int(arready,UVM_ALL_ON) |
|
|
|
|
|
|
|
`uvm_field_int(rid,UVM_ALL_ON) |
|
|
|
`uvm_field_int(rdata,UVM_ALL_ON) |
|
|
|
`uvm_field_int(rlast,UVM_ALL_ON) |
|
|
|
`uvm_field_int(rresp,UVM_ALL_ON) |
|
|
|
`uvm_field_int(rvalid,UVM_ALL_ON) |
|
|
|
`uvm_field_int(rready,UVM_ALL_ON) |
|
|
|
|
|
|
|
`uvm_object_utils_end |
|
|
|
|
|
|
|
//constraints for axi |
|
|
|
|
|
|
|
constraint aligned_addr{awadd%2**awsize==0;} |
|
|
|
|
|
|
|
constraint wrap_addr{solve awburst before awlen |
|
|
|
if(awburst==2'b 10) |
|
|
|
awlen inside{1,3,7,15};} |
|
|
|
|
|
|
|
constraint wid_sig{awid==wid;} |
|
|
|
|
|
|
|
constraint rid_sig{arid==rid;} |
|
|
|
|
|
|
|
constraint axi_4kb{awaddr%4096+(2**awsize*(awlen+1))<=4096;} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//:constrain |
|
|
|
endclass:axi_seq_item |
|
|
|
|
|
|
|
|
|
|
|
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 |