From 2166be21092546376c1ed8c441a5dbc765022892 Mon Sep 17 00:00:00 2001 From: shivakanta_kondapalli Date: Tue, 21 May 2024 10:41:21 +0000 Subject: [PATCH] Upload files to '' --- axi_read_seq.sv | 60 ++++++++ axi_s_driver.sv | 350 +++++++++++++++++++++++++++++++++++++++++++++ axi_s_monitor.sv | 109 ++++++++++++++ axi_scoreboard.sv | 86 +++++++++++ axi_slave_agent.sv | 44 ++++++ 5 files changed, 649 insertions(+) create mode 100644 axi_read_seq.sv create mode 100644 axi_s_driver.sv create mode 100644 axi_s_monitor.sv create mode 100644 axi_scoreboard.sv create mode 100644 axi_slave_agent.sv diff --git a/axi_read_seq.sv b/axi_read_seq.sv new file mode 100644 index 0000000..da4cad0 --- /dev/null +++ b/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 diff --git a/axi_s_driver.sv b/axi_s_driver.sv new file mode 100644 index 0000000..74a6489 --- /dev/null +++ b/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=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=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 diff --git a/axi_s_monitor.sv b/axi_s_monitor.sv new file mode 100644 index 0000000..db36b72 --- /dev/null +++ b/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