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