From 5b11fe273037840bc2b5b48236495a41b8b0d8b4 Mon Sep 17 00:00:00 2001 From: Ambuj Dhar Dwivedi Date: Tue, 12 Mar 2024 15:10:40 +0530 Subject: [PATCH] Ambuj --- axi_slave_if.sv | 204 +++++++++++++++++++++++++++++++++++++++++++++ axi_slave_p_mon.sv | 72 ++++++++++++++++ axi_txn1.sv | 170 +++++++++++++++++++++++++++++++++++++ slave_p_agent.sv | 0 4 files changed, 446 insertions(+) create mode 100755 axi_slave_if.sv create mode 100755 axi_slave_p_mon.sv create mode 100755 axi_txn1.sv create mode 100755 slave_p_agent.sv diff --git a/axi_slave_if.sv b/axi_slave_if.sv new file mode 100755 index 0000000..9ebed63 --- /dev/null +++ b/axi_slave_if.sv @@ -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 diff --git a/axi_slave_p_mon.sv b/axi_slave_p_mon.sv new file mode 100755 index 0000000..eb85294 --- /dev/null +++ b/axi_slave_p_mon.sv @@ -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 + + diff --git a/axi_txn1.sv b/axi_txn1.sv new file mode 100755 index 0000000..278320f --- /dev/null +++ b/axi_txn1.sv @@ -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 diff --git a/slave_p_agent.sv b/slave_p_agent.sv new file mode 100755 index 0000000..e69de29