diff --git a/axi_drv.sv b/axi_drv.sv new file mode 100644 index 0000000..7e9b1c2 --- /dev/null +++ b/axi_drv.sv @@ -0,0 +1,126 @@ +class axi_drv extends uvm_driver#(axi_tx); +virtual axi_intf vif; +`uvm_component_utils(axi_drv) +`NEW_COMP + +function void build_phase(uvm_phase phase); + super.build_phase(phase); + if(!uvm_config_db#(virtual axi_intf)::get(this, "", "vif", vif)) begin + `uvm_error("CONFG_DB", "Not able to get axi intf handle") + end +endfunction + +task run_phase(uvm_phase phase); + @(negedge vif.arst);//waiting for release the reset + forever begin + seq_item_port.get_next_item(req); + req.print(); + drive_tx(req); + seq_item_port.item_done(); + end +endtask + +task drive_tx(axi_tx tx); + if (tx.wr_rd == 1) begin + write_addr(tx); + write_data(tx); + write_resp(tx); + end + if (tx.wr_rd == 0) begin + read_addr(tx); + read_data(tx); + end +endtask + +task write_addr(axi_tx tx); + `uvm_info("AXI_TX", "write_addr", UVM_MEDIUM); + //Master drives all write address channel signals (aw), it will drive at the posedge of clock + @(vif.mst_cb); + vif.mst_cb.awaddr <= tx.addr; + vif.mst_cb.awlen <= tx.burst_len; + vif.mst_cb.awsize <= tx.burst_size; + vif.mst_cb.awburst <= tx.burst_type; + vif.mst_cb.awid <= tx.txid; + vif.mst_cb.awvalid <= 1'b1; + wait (vif.mst_cb.awready == 1'b1); + @(vif.mst_cb); + vif.mst_cb.awaddr <= 0; + vif.mst_cb.awlen <= 0; + vif.mst_cb.awsize <= 0; + vif.mst_cb.awburst <= 0; + vif.mst_cb.awid <= 0; + vif.mst_cb.awvalid <= 0; +endtask + +task write_data(axi_tx tx); + `uvm_info("AXI_TX", "write_data", UVM_MEDIUM); + for (int i = 0; i <= tx.burst_len; i++) begin + @(vif.mst_cb) + vif.mst_cb.wdata <= tx.dataQ.pop_front(); + vif.mst_cb.wstrb <= 4'b1111; //need to be updated as per the burst size + vif.mst_cb.wvalid <= 1'b1; + vif.mst_cb.wid <= tx.txid; + //wlast=1 will be in last beat + if(i == tx.burst_len) vif.mst_cb.wlast <= 1'b1; + else vif.mst_cb.wlast <= 0; + wait(vif.mst_cb.wready == 1'b1); + end + //once data beats are done, then reset all signals to 0 + @(vif.mst_cb); + vif.mst_cb.wvalid <= 0; + vif.mst_cb.wlast <= 0; + vif.mst_cb.wdata <= 0; + vif.mst_cb.wstrb <= 0; + vif.mst_cb.wid <= 0; +endtask + +task write_resp(axi_tx tx); +bit bvalid_f = 0; + //`uvm_info("AXI_TX", "write_resp", UVM_MEDIUM); + //write response is initiated by slave + while (bvalid_f == 0) begin + @(vif.mst_cb); + bvalid_f = vif.mst_cb.bvalid; + end + vif.mst_cb.bready <= 1'b1; + @(vif.mst_cb); + vif.mst_cb.bready <= 1'b0; +endtask + +task read_addr(axi_tx tx); + `uvm_info("AXI_TX", "read_addr", UVM_MEDIUM); + @(vif.mst_cb); + vif.mst_cb.araddr <= tx.addr; + vif.mst_cb.arlen <= tx.burst_len; + vif.mst_cb.arsize <= tx.burst_size; + vif.mst_cb.arburst <= tx.burst_type; + vif.mst_cb.arid <= tx.txid; + vif.mst_cb.arvalid <= 1'b1; + wait (vif.mst_cb.arready == 1'b1); + @(vif.mst_cb); + vif.mst_cb.araddr <= 0; + vif.mst_cb.arlen <= 0; + vif.mst_cb.arsize <= 0; + vif.mst_cb.arburst <= 0; + vif.mst_cb.arid <= 0; + vif.mst_cb.arvalid <= 0; +endtask + +task read_data(axi_tx tx); +bit rvalid_f = 0; + `uvm_info("AXI_TX", "read_data", UVM_MEDIUM); + //since read data is happening multiple times, then handshaking should do multiple times + for (int i = 0; i <= tx.burst_len; i++) begin + rvalid_f = 0; + while (rvalid_f == 0) begin + @(vif.mst_cb); + rvalid_f = vif.mst_cb.rvalid; + vif.mst_cb.rready <= 1'b1; + end + end + @(vif.mst_cb); + vif.mst_cb.rready <= 1'b0; +endtask + +endclass +