@@ -0,0 +1,204 @@ | |||||
interface axi_slave_if (input bit clk, resetn); | |||||
///////////////////write address channel | |||||
input logic awvalid; /// master is sending new address | |||||
output logic awready; /// slave is ready to accept request | |||||
input logic [3:0] awid; ////// unique ID for each transaction | |||||
input logic [3:0] awlen; ////// burst length AXI3 : 1 to 16, AXI4 : 1 to 256 | |||||
input logic [2:0] awsize; ////unique transaction size : 1,2,4,8,16 ...128 bytes | |||||
input logic [31:0] awaddr; ////write adress of transaction | |||||
input logic [1:0] awburst; ////burst type : fixed , INCR , WRAP | |||||
/////////////////////write data channel | |||||
input logic wvalid; //// master is sending new data | |||||
output logic wready; //// slave is ready to accept new data | |||||
input logic [3:0] wid; /// unique id for transaction | |||||
input logic [31:0] wdata; //// data | |||||
input logic [3:0] wstrb; //// lane having valid data | |||||
input logic wlast, //// last transfer in write burst | |||||
///////////////write response channel | |||||
input logic bready; ///master is ready to accept response | |||||
output logic bvalid; //// slave has valid response | |||||
output logic [3:0] bid; ////unique id for transaction | |||||
output logic [1:0] bresp; /// status of write transaction | |||||
////////////// read address channel | |||||
output logic reg arready; //read address ready signal from slave | |||||
input logic [3:0] arid; //read address id | |||||
input logic [31:0] araddr; //read address signal | |||||
input logic [3:0] arlen; //length of the burst | |||||
input logic [2:0] arsize; //number of bytes in a transfer | |||||
input logic [1:0] arburst;//burst type - fixed, incremental, wrapping | |||||
input logic arvalid; //address read valid signal | |||||
///////////////////read data channel | |||||
output logic [3:0] rid; //read data id | |||||
output logic [31:0]rdata; //read data from slave | |||||
output logic [1:0] rresp; //read response signal | |||||
output logic rlast; //read data last signal | |||||
output logic rvalid; //read data valid signal | |||||
input logic rready | |||||
//========================== ASSERTIONS======================== | |||||
// WRITE ADDRESS CHANNEL************************************************************************************************************ | |||||
//1st.(When awvalid is asserted then it remains asserted until awready is HIGH) | |||||
property AXI_AWVALID_AWREADY; | |||||
@(posedge clk) awvalid |-> (awvalid throughout (awready[->1])); | |||||
endproperty | |||||
A1:assert property (AXI_AWVALID_AWREADY); | |||||
else `uvm_error("ASSERTION","Failure AXI_AWVALID_AWREADY"); | |||||
//2nd.(BURST can not cross a 4KB Boundary) | |||||
property w_burst_boundary; | |||||
@(posedge clk) (awvalid && awready) |-> (((2**awsize)*(awlen+1)) < 4096) ; | |||||
endproperty | |||||
A2:assert property (w_burst_boundary) | |||||
else `uvm_error("ASSERTION","Failure w_burst_boundary"); | |||||
//3rd.(all write address channel remains stable after AWVALID is asserted) | |||||
property AXI_AWVALID_STABLE; | |||||
@(posedge clk) $rose(awvalid)|->($stable(awid)&& $stable(awaddr) | |||||
&&$stable(awlen)&& $stable(awsize) | |||||
&&$stable(awburst))throughout awready[->1]; | |||||
endproperty | |||||
A3:assert property (AXI_AWVALID_STABLE) | |||||
else `uvm_error("ASSERTION","Failure AXI_AWVALID_STABLE"); | |||||
//4th.(AWLEN value is 1,3,7,15 for Wrapping type Burst) | |||||
property AWLEN_WRAP_BURST; | |||||
@(posedge clk) disable iff(!resetn) (awburst==2'b10) |->(awlen==1|awlen==3||awlen==7||awlen==15); | |||||
endproperty | |||||
A4:assert property (AWLEN_WRAP_BURST) | |||||
else `uvm_error("ASSERTION","Failure AWLEN_WRAP_BURST"); | |||||
//5th.(AWBURST val cant be 2'b11) | |||||
property AWBURST_CANT_2b11; | |||||
@(posedge clk) (awvalid && awready) |-> (awburst != 2'b11); | |||||
endproperty | |||||
A5:assert property (AWBURST_CANT_2b11) | |||||
else `uvm_error("ASSERTION","Failure AWBURST_CANT_2b11"); | |||||
//WRITE DATA CHANNEL************************************************************************************************************** | |||||
//1st. | |||||
property AXI_WVALID_WREADY; | |||||
@(posedge clk) wvalid |-> (wvalid throughout (wready[->1])) ; | |||||
endproperty | |||||
A6: assert property (AXI_WVALID_WREADY) | |||||
else `uvm_error("ASSERTION","Failure AXI_WVALID_WREADY"); | |||||
//2nd. Property to check whether all write address channel remains stable after WVALID is asserted | |||||
property AXI_WVALID_WREADY; | |||||
@(posedge clk) $rose(wvalid) |-> ( $stable(wid) | |||||
&& $stable(wdata) | |||||
&& $stable(wstrb) | |||||
&& $stable(wlast)) throughout wready[->1]; | |||||
endproperty | |||||
A7:assert property (AXI_WVALID_STABLE) | |||||
else `uvm_error("ASSERTION","Failure AXI_WVALID_STABLE"); | |||||
//WRITE RESPONSE CHANNEL**************************************************************************************************************** | |||||
//1st. | |||||
property AXI_BVALID_BREADY; | |||||
@(posedge clk) bvalid|-> (bvalid throughout (bready[->1])) ; | |||||
endproperty | |||||
A8:assert property (AXI_BVALID_BREADY) | |||||
else `uvm_error("ASSERTION","Failure AXI_BVALID_BREADY"); | |||||
//2nd.to check whether all write address channel remains stable after BVALID is asserted | |||||
property AXI_BVALID_STABLE; | |||||
@(posedge clk) $rose(bvalid)|->($stable(bid)&& $stable(bresp))throughout bready[->1]; | |||||
endproperty | |||||
A9:assert property (AXI_BVALID_STABLE) | |||||
else `uvm_error("ASSERTION","Failure AXI_BVALID_STABLE"); | |||||
//READ ADDRESS CHANNEL*********************************************************************************************** | |||||
//1st. | |||||
property AXI_ARVALID_ARREADY; | |||||
@(posedge clk) arvalid |-> (arvalid throughout (arready[->1])) ; | |||||
endproperty | |||||
B1:assert property AXI_ARVALID_ARREADY; | |||||
else`uvm_error("ASSERTION","Failure AXI_ARVALID_ARREADY"); | |||||
//2nd.(BURST can not cross a 4KB Boundary) | |||||
property r_burst_boubadary; | |||||
@(posedge clk) (arvalid && arready) |-> (((2**arsize)*(arlen+1)) < 4096); | |||||
endproperty | |||||
B2:assert property (r_burst_boubadary) | |||||
else `uvm_error("ASSERTION","Failure r_burst_boubadary"); | |||||
//3rd.(ARLEN value is 1,3,7,15 for Wrapping type Burst) | |||||
property ARLEN_WRAP_BURST; | |||||
@(posedge clk) disable iff (!resetn) (arburst==2'b10) |-> (arlen==1 || arlen==3 || arlen==7 || arlen==15); | |||||
endproperty | |||||
B3:assert property (ARLEN_WRAP_BURST) | |||||
else `uvm_error("ASSERTION","Failure ARLEN_WRAP_BURST"); | |||||
//4th.(arburst val cant be 2'b11) | |||||
property ARBURST_CANT_2b11; // | |||||
@(posedge clk) (arvalid && arready) |-> (arburst != 2'b11); | |||||
endproperty | |||||
B4:assert property (ARBURST_CANT_2b11) | |||||
else `uvm_error("ASSERTION","Failure ARBURST_CANT_2b11"); | |||||
//5th. Property to check whether all write address channel remains stable after ARVALID is asserted | |||||
property AXI_ARVALID_STABLE; | |||||
@(posedge clk) $rose(arvalid) |-> ( $stable(arid) | |||||
&&$stable(araddr) | |||||
&&$stable(arlen) | |||||
&&$stable(arsize) | |||||
&&$stable(arburst)) throughout arready[->1]; | |||||
endproperty | |||||
B5:assert property (AXI_ARVALID_STABLE) | |||||
else `uvm_error("ASSERTION","Failure AXI_ARVALID_STABLE"); | |||||
//READ DATA CHANNEL*********************************************************************************************************** | |||||
/1st. | |||||
property AXI_RVALID_RREADY; | |||||
@(posedge clk) rvalid |-> (rvalid throughout (rready[->1])); | |||||
endproperty | |||||
B6:assert property (AXI_RVALID_RREADY) | |||||
else `uvm_error("ASSERTION","Failure AXI_RVALID_RREADY"); | |||||
//2nd.to check whether all write address channel remains stable after RVALID is asserted | |||||
property AXI_RVALID_STABLE; | |||||
@(posedge clk) $rose(rvalid) |-> ( $stable(rid) | |||||
&& $stable(rdata) | |||||
&& $stable(rresp) | |||||
&& $stable(rlast)) throughout rready[->1]; | |||||
endproperty | |||||
B7:assert property (AXI_RVALID_STABLE) | |||||
else`uvm_error("ASSERTION","Failure AXI_RVALID_STABLE"); | |||||
endinterface |
@@ -0,0 +1,72 @@ | |||||
class axi_slave_p_mon extends uvm_monitor; | |||||
`uvm_component_utils(axi_slave_p_mon) | |||||
uvm_analysis_port #(axi_txn) ap; | |||||
virtual axi_slave_if vif; | |||||
axi_txn mon_txn; | |||||
function new( string name = "axi_slave_p_mon", uvm_component parent = null); | |||||
super.new(name, parent); | |||||
ap = new("ap",this); | |||||
mon_txn= new ("mon_txn"); | |||||
endfunction | |||||
virtual function void build_phase(uvm_phase phase); | |||||
super.build_phase(phase); | |||||
if (!uvm_config_db#(virtual axi_slave_if)::get(this,"","vif",vif)) | |||||
begin | |||||
`uvm_error( get_type_name(),"Not able to get AXI INTF HANDLE") | |||||
end | |||||
endfunction | |||||
virtual task run_phase(uvm_phase phase); | |||||
forever begin | |||||
@(vif); | |||||
//WA | |||||
if (vif.awvalid == 1 && vif.awready == 1)begin | |||||
mon_txn = axi_tx::type_id::create("mon_txn"); | |||||
mon_txn.awre = vif.awaddr; | |||||
mon_txn.awlen = vif.awlen; | |||||
mon_txn.awsize = vif.awsize; | |||||
mon_txn.awburst = burst_type_t'(vif.mon_cb.awburst); | |||||
tx.tx_id = vif.mon_cb.awid; | |||||
num_writes = 0; | |||||
end | |||||
//WD | |||||
if (vif.mon_cb.wvalid == 1 && vif.mon_cb.wready == 1)begin | |||||
num_writes++; | |||||
if (num_writes > 1)begin | |||||
tx.dataQ.push_back(vif.mon_cb.wdata); | |||||
end | |||||
end | |||||
//WR(B) | |||||
if (vif.mon_cb.bvalid == 1 && vif.mon_cb.bready == 1)begin | |||||
tx.resp = vif.mon_cb.bresp; | |||||
ap_port.write(tx); | |||||
end | |||||
//RA | |||||
if (vif.mon_cb.arvalid == 1 && vif.mon_cb.arready == 1)begin | |||||
tx = axi_tx::type_id::create("tx"); | |||||
tx.wr_rd = 1'b0; | |||||
tx.addr = vif.mon_cb.araddr; | |||||
tx.burst_len = vif.mon_cb.arlen; | |||||
tx.burst_size = vif.mon_cb.arsize; | |||||
tx.burst_type = burst_type_t'(vif.mon_cb.arburst); | |||||
tx.tx_id = vif.mon_cb.arid; | |||||
num_reads = 0; | |||||
end | |||||
//RD | |||||
if (vif.mon_cb.rvalid == 1 && vif.mon_cb.rready == 1)begin | |||||
num_reads++; | |||||
if(num_reads > 1)begin | |||||
tx.dataQ.push_back(vif.mon_cb.rdata); | |||||
end | |||||
if (vif.mon_cb.rlast == 1)begin | |||||
ap_port.write(tx); | |||||
end | |||||
end | |||||
end | |||||
endtask | |||||
endclass | |||||
@@ -0,0 +1,170 @@ | |||||
`include "uvm_macros.svh" | |||||
import uvm_pkg::*; | |||||
class axi_txn extends uvm_sequence_item ; | |||||
function new(string name = "axi_txn"); | |||||
super.new(name); | |||||
endfunction | |||||
///////////////////write address channel | |||||
logic awvalid;// master is sending new address | |||||
logic awready; /// slave is ready to accept request | |||||
randc bit [3:0] awid; ////// unique ID for each transaction | |||||
randc logic [3:0] awlen; ////// burst length AXI3 : 1 to 16, AXI4 : 1 to 256 | |||||
rand logic [2:0] awsize; ////unique transaction size : 1,2,4,8,16 ...128 bytes | |||||
rand logic [31:0] awaddr; ////write adress of transaction | |||||
randc logic [1:0] awburst; ////burst type : fixed , INCR , WRAP | |||||
/////////////////////write data channel | |||||
logic wvalid; //// master is sending new data | |||||
logic wready; //// slave is ready to accept new data | |||||
randc bit [3:0] wid;/// unique id for transaction | |||||
rand logic [31:0] wdata; //// data | |||||
rand logic [3:0] wstrb; //// lane having valid data | |||||
logic wlast; //// last transfer in write burst | |||||
///////////////write response channel | |||||
logic bready; ///master is ready to accept response | |||||
logic bvalid; //slave has valid response | |||||
bit [3:0] bid; ////unique id for transaction | |||||
logic [1:0] bresp; /// status of write transaction | |||||
////////////// read address channel | |||||
logic arready; //read address ready signal from slave | |||||
logic arvalid; //address read valid signal | |||||
randc bit [3:0] arid; //read address id | |||||
rand logic [31:0] araddr; //read address signal | |||||
randc logic [3:0] arlen; //length of the burst | |||||
randc logic [2:0] arsize; //number of bytes in a transfer | |||||
logic [1:0] arburst;//burst type - fixed, incremental, wrapping | |||||
///////////////////read data channelogic [3:0] rid; //read data id | |||||
logic [31:0]rdata; //read data from slave | |||||
logic [1:0] rresp; //read response signal | |||||
logic rlast; //read data last signal | |||||
logic rvalid; //read data valid signal | |||||
logic rready; | |||||
bit rid; | |||||
`uvm_object_param_utils_begin(axi_txn) | |||||
`uvm_field_int(awready,UVM_ALL_ON) | |||||
`uvm_field_int(awvalid,UVM_ALL_ON) | |||||
`uvm_field_int(awburst,UVM_ALL_ON) | |||||
`uvm_field_int(awsize,UVM_ALL_ON) | |||||
`uvm_field_int(awlen,UVM_ALL_ON) | |||||
`uvm_field_int(awaddr,UVM_ALL_ON) | |||||
`uvm_field_int(awid,UVM_ALL_ON) | |||||
`uvm_field_int(wready,UVM_ALL_ON) | |||||
`uvm_field_int(wvalid,UVM_ALL_ON) | |||||
`uvm_field_int(wlast,UVM_ALL_ON) | |||||
`uvm_field_int(wstrb,UVM_ALL_ON) | |||||
`uvm_field_int(wdata,UVM_ALL_ON) | |||||
`uvm_field_int(wid,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(arready,UVM_ALL_ON) | |||||
`uvm_field_int(arvalid,UVM_ALL_ON) | |||||
`uvm_field_int(arburst,UVM_ALL_ON) | |||||
`uvm_field_int(arsize,UVM_ALL_ON) | |||||
`uvm_field_int(arlen,UVM_ALL_ON) | |||||
`uvm_field_int(araddr,UVM_ALL_ON) | |||||
`uvm_field_int(arid,UVM_ALL_ON) | |||||
`uvm_field_int(rready,UVM_ALL_ON) | |||||
`uvm_field_int(rvalid,UVM_ALL_ON) | |||||
`uvm_field_int(rlast,UVM_ALL_ON) | |||||
`uvm_field_int(rresp,UVM_ALL_ON) | |||||
`uvm_field_int(rdata,UVM_ALL_ON) | |||||
`uvm_field_int(rid,UVM_ALL_ON) | |||||
`uvm_object_utils_end | |||||
//-------------------- | |||||
// Same ID constraint for write transactions | |||||
constraint same_wr_id { awid==wid;} | |||||
// Same ID constraint for read transactions | |||||
constraint same_rd_id { arid==rid;} | |||||
//----------------------------------------------------------------------------- | |||||
//-------------- | |||||
//4KB address boundary for write address channel | |||||
constraint awdder_4kb {awadder %4096 + (awlen+1 << awsize) <= 4096;} | |||||
//4KB address boundary for read address channel | |||||
constraint ardder_4kb {aradder % 4096 + (arlen+1 << arsize) <= 4096;} | |||||
//--------------------------------------------------------------------------------- | |||||
//-------------------- | |||||
//support 1 to 16 awlen. so max write data size is 16*(2**awsize) | |||||
//awburst!=2'b10(means-> if it's not wrap type) | |||||
constraint wr_data_size {if (awburst !=2'b10) | |||||
wdata inside {[1:(16*(2**awsize))]}; } | |||||
//support 1 to 16 arlen. so max write data size is 16*(2**arsize) | |||||
//arburst!=2'b10(means-> if it's not wrap type) | |||||
constraint rd_data_size {if (arburst !=2'b10) | |||||
rdata inside {[1:(16*(2**arsize))]}; } | |||||
//---------------------------------------------------------------------------- | |||||
//------------------- | |||||
// bcs for Wrapping burst the length of the burst must be 2, 4, 8, or 16. | |||||
//so therefore write data should be multiple of BL(2,4,8, or 16) and (2**awsize) | |||||
constraint awburst_val {if (awburst ==2'b10) | |||||
{wdata inside {((2**awsize)*2),((2**awsize)*4),((2**awsize)*8),((2**awsize)*16)}; }} | |||||
// bcs for Wrapping burst the length of the burst must be 2, 4, 8, or 16. | |||||
//so therefore write data should be multiple of BL(2,4,8, or 16) and (2**arsize) | |||||
constraint arburst_val {if (arburst ==2'b10) | |||||
{rdata inside {((2**arsize)*2),((2**arsize)*4),((2**arsize)*8),((2**arsize)*16)}; }} | |||||
//------------------------------------------------------------------------------ | |||||
//-------------------- | |||||
//for Wrapping burst the length of the burst must be 2, 4, 8, or 16 (bcs BL= axlen+1) | |||||
constraint awburst_val {if (awburst==2'b10) {awlen inside {1,3,7,15};}} | |||||
//for Wrapping burst the length of the burst must be 2, 4, 8, or 16 (bcs BL= axlen+1) | |||||
constraint arburst_val {if (arburst==2'b10) {arlen inside {1,3,7,15};}} | |||||
//--------------------------------------------------------------------------------- | |||||
endclass: axi_txn | |||||
module top; | |||||
axi_txn txt; | |||||
initial begin | |||||
repeat(10) begin | |||||
txt=new(); | |||||
txt.randomize(); | |||||
$display("pass"); | |||||
end end | |||||
endmodule |