//driver class driver extends uvm_driver #(packet); `uvm_component_utils(driver) virtual axi_if vif; packet pkt; function new(string name="driver", uvm_component parent=null); super.new(name, parent); endfunction virtual function void build_phase(uvm_phase phase); super.build_phase(phase); pkt=packet::type_id::create("pkt"); if(!uvm_config_db#(virtual axi_if)::get(this,"","vif",vif)) `uvm_error("drv","Unable to access Interface"); endfunction task reset_dut(); repeat (3) begin //write address channel vif.awvalid <= 0; vif.awready <= 0; vif.awid <= 0; vif.awlen <= 0; vif.awsize <= 0; vif.awaddr <= 0; vif.awburst <= 0; //write data channel (w) vif.wvalid <= 0; vif.wready <= 0; vif.wid <= 0; vif.wdata <= 0; vif.wstrb <= 0; vif.wlast <= 0; //write response channel (b) vif.bready <= 0; vif.bvalid <= 0; vif.bid <= 0; vif.bresp <= 0; ///////////////read address channel (ar) vif.arvalid <= 0; vif.arready <= 0; vif.arid <= 0; vif.arlen <= 0; vif.arsize <= 0; vif.araddr <= 0; vif.arburst <= 0; /////////// read data channel (r) vif.rvalid <= 0; vif.rready <= 0; vif.rid <= 0; vif.rdata <= 0; vif.rstrb <= 0; vif.rlast <= 0; vif.rresp <= 0; //1 clk delay @(posedge vif.clk); `uvm_info(get_type_name(),"*** Reset Applied by driver ***",UVM_MEDIUM) end endtask virtual task run_phase(uvm_phase phase); reset_dut(); forever begin seq_item_port.get_next_item(pkt); `uvm_info(get_type_name(),"*** Driver Received the transaction by sequencer ***",UVM_MEDIUM) //--------------------------------------------------------- //---------------------------------------------------------- //////////////////////////////////////// WRITE ADDRESS CHANNEL task write_address_pkt_channel(); `uvm_info("MASTER_DRIVER",$sformatf("PRINTING FROM DRIVER \n %s",pkt.sprint()),UVM_HIGH) case (pkt.awburst) 2'b00 : write_address_fixed_burst; 2'b01 : write_address_incr_burst; 2'b10 : write_address_wrap_burst; endcase endtask //////////////////////////////////////// WRAP address BURST task write_address_wrap_burst(); begin int start_addr=(`INT pkt.awaddr/((pkt.awlen+1)*(2**pkt.awsize)))*((pkt.awlen+1)*(2**pkt.awsize)); int end_addr=(start_addr + ((pkt.awlen+1)*(2**pkt.awsize))); for (int i=0; i< (pkt.awlen+1);i++) begin vif.awaddr <= pkt.awaddr; if(vif.awaddr == end_addr) vif.awaddr <= start_addr; else vif.awaddr <= vif.awaddr+ (2**vif.awsize); vif.awid <= pkt.awid; vif.awvalid<= 1; wait(vif.awready); vif.awvalid<=0; end write_data_wrap_burst(); endtask /////////////////////////////////////// wrapBURST task write_data_wrap_burst(); if (vif.awvalid || vif.wvalid ||( vif.awvalid &&vif.wvalid)) foreach(pkt.wdata[i]) begin case (pkt.wstrobe[i]) 4'b0001 : vif.wdata [7:0] <= pkt.wdata[i]; 4'b0010 : vif.wdata [15:8] <= pkt.wdata[i]; 4'b0100 : vif.wdata [23:16] <= pkt.wdata[i]; 4'b1000 : vif.wdata [31:24] <= pkt.wdata[i]; 4'b0011 : vif.wdata [15:0] <= pkt.wdata[i]; 4'b1100 : vif.wdata [31:16] <= pkt.wdata[i]; 4'b1110 : vif.wdata [31:8] <= pkt.wdata[i]; 4'b1111 : vif.wdata [31:0] <= pkt.wdata[i]; endcase vif.wstrobe <= pkt.wstrobe[i]; vif.wid <= pkt.wid; if (i == pkt.awlen ) vif.wlast <= 1; else vif.wlast <= 0; vif.wvalid <= 1; wait (vif.wready); vif.wlast <= 0; vif.wvalid <= 0; end write_response_channel (); endtask //////////////////////////////////////// INCR address INCREMENT BURST task write_address_incr_burst(); vif.awlen <=pkt.awlen; for(int i=0; i<(awlen +1);i++) begin vif.awaddr<=pkt.awaddr; vif.awid <= pkt.awid; vif.awvalid<= 1; pkt.awaddr<= pkt.awaddr +(2**vif.awsize); wait(vif.awready); vif.awvalid<=0; end write_data_incr_burst(); endtask /////////////////////////////////////// write data INCREMENT BURST task write_data_incr_burst(); if (vif.awvalid || vif.wvalid ||( vif.awvalid &&vif.wvalid)) foreach(pkt.wdata[i]) begin case (pkt.wstrobe[i]) 4'b0001 : vif.wdata [7:0] <= pkt.wdata[i]; 4'b0010 : vif.wdata [15:8] <= pkt.wdata[i]; 4'b0100 : vif.wdata [23:16] <= pkt.wdata[i]; 4'b1000 : vif.wdata [31:24] <= pkt.wdata[i]; 4'b0011 : vif.wdata [15:0] <= pkt.wdata[i]; 4'b1100 : vif.wdata [31:16] <= pkt.wdata[i]; 4'b1110 : vif.wdata [31:8] <= pkt.wdata[i]; 4'b1111 : vif.wdata [31:0] <= pkt.wdata[i]; endcase vif.wstrobe <= pkt.wstrobe[i]; vif.wid <= pkt.wid; if (i == pkt.awlen ) vif.wlast <= 1; else vif.wlast <= 0; vif.wvalid <= 1; wait (vif.wready); vif.wlast <= 0; vif.wvalid <= 0; end write_response_channel (); endtask ///////////////write address fixed burst task write_address_fixed_burst (); vif.awlen <= 4'b0000; vif.awid <= pkt.awid; vif.awaddr <= pkt.awaddr; vif.awvalid<= 1; wait(vif.awready); vif.awvalid<=0; write_data_fixed_burst(); endtask ////////////////////////////////////// write data first burst task write_data_fixed_burst (); if (vif.awvalid || vif.wvalid ||( vif.awvalid &&vif.wvalid)) foreach(pkt.wdata[i]) begin case (pkt.awsize) 3'b000 : vif.wdata[7:0] <= pkt.wdata[i]; 3'b001 : vif.wdata[15:0] <= pkt.wdata[i]; 3'b010 : vif.wdata[31:0] <= pkt.wdata[i]; 3'b011 : vif.wdata[63:0] <= pkt.wdata[i]; 3'b100 : vif.wdata[127:0] <= pkt.wdata[i]; 3'b101 : vif.wdata[255:0] <= pkt.wdata[i]; 3'b110 : vif.wdata[511:0] <= pkt.wdata[i]; 3'b110 : vif.wdata[1023:0] <= pkt.wdata[i]; endcase vif.wid <= pkt.wid; if (i == pkt.awlen) vif.wlast <= 1; else vif.wlast <= 0; vif.wvalid <= 1; wait (vif.wready); vif.wlast <= 0; vif.wvalid <= 0; end write_response_channel (); endtask /////////////////////////////////////// WRITE RESPONSE CHANNEL task write_response_channel (); if (vif.awvalid && vif.awready && vif.awlast) wait(vif.bvalid) begin vif.bid = pkt.bid; vif.bresp = pkt.bresp; end vif.bready <= 1; foreach (vif.wdata[i]) begin if (vif.awid == vif.bid) begin case (vif.bresp) 2'b00 : s = "Transaction OKAY"; 2'b01 : s = "Transaction FAILED"; 2'b10 : s = "SLAVE ERROR"; 2'b11 : s = "DEEOCDE ERROR"; endcase `uvm_info("MASTER_DRIVER",$sformatf("\n\n \t\t\t\t\t\t %s RESPONSE FOR THE DATA \n",s),UVM_MEDIUM) end end vif.bready <= 0; endtask /////////////////////////////////////// READ ADDRESS CHANNEL task read_address_pkt_channel(); `uvm_info("MASTER_DRIVER",$sformatf("PRINTING FROM DRIVER \n %s",pkt.sprint()),UVM_HIGH) vif.arid <= pkt.arid; vif.araddr <= pkt.araddr; vif.arlen <= pkt.arlen; vif.arsize <= pkt.arsize; vif.arburst <= pkt.arburst; vif.arvalid <= 1; @(vif); wait (vif.arready); vif.arvalid <= 0; read_data_response_sema.put(1); pkt_sema.put(1); repeat(2) @(vif); endtask //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// WRITE ADDRESS CHANNEL task read_address_pkt_channel(); `uvm_info("MASTER_DRIVER",$sformatf("PRINTING FROM DRIVER \n %s",pkt.sprint()),UVM_HIGH) case (pkt.awburst) 2'b00 : read_address_fixed_burst; 2'b01 : read_address_incr_burst; 2'b10 : read_address_wrap_burst; endcase endtask //////////////////////////////////////// WRAP address BURST task read_address_wrap_burst(); begin int start_read_addr=(`INT pkt.araddr/((pkt.arlen+1)*(2**pkt.arsize)))*((pkt.arlen+1)*(2**pkt.arsize)); int end_read_addr=(start_read_addr + ((pkt.arlen+1)*(2**pkt.arsize))); for (int i=0; i< (pkt.arlen+1);i++) begin vif.araddr <= pkt.araddr; if(vif.araddr == end_read_addr) vif.araddr <= start_read_addr; else vif.araddr <= vif.araddr+ (2**vif.arsize); vif.arid <= pkt.arid; vif.arvalid<= 1; wait(vif.arready); vif.arvalid<=0; end read_data_wrap_burst(); endtask /////////////////////////////////////// wrapBURST task read_data_wrap_burst(); if (vif.arvalid || vif.rvalid ||( vif.arvalid &&vif.rvalid)) vif.arid <= pkt.rid; if (i == pkt.arlen ) vif.rlast <= 1; else vif.rlast <= 0; vif.rvalid <= 1; wait (vif.rready); vif.rlast <= 0; vif.rvalid <= 0; end if (vif.arvalid && vif.arready && vif.arlast) wait(vif.rvalid) begin vif.rid = pkt.rid; vif.rresp = pkt.rresp; end vif.rready <= 1; foreach (vif.rdata[i]) begin if (vif.arid == vif.rid) begin case (vif.rresp) 2'b00 : s = "Transaction OKAY"; 2'b01 : s = "Transaction FAILED"; 2'b10 : s = "SLAVE ERROR"; 2'b11 : s = "DEEOCDE ERROR"; endcase `uvm_info("MASTER_DRIVER",$sformatf("\n\n \t\t\t\t\t\t %s RESPONSE FOR THE DATA \n",s),UVM_MEDIUM) end end vif.rready <= 0; endtask //////////////////////////////////////// INCR address INCREMENT BURST task read_address_incr_burst(); vif.arlen <=pkt.arlen; for(int i=0; i<(arlen +1);i++) begin vif.araddr<=pkt.araddr; vif.arid <= pkt.arid; vif.arvalid<= 1; pkt.araddr<= pkt.araddr +(2**vif.arsize); wait(vif.arready); vif.arvalid<=0; end read_data_incr_burst(); endtask /////////////////////////////////////// read data INCREMENT BURST task read_data_incr_burst(); if (vif.arvalid || vif.rvalid ||( vif.arvalid &&vif.rvalid)) vif.rid <= pkt.rid; for(int i=0; i<(arlen +1);i++) begin vif.rdata <= pkt.rdata; if (i == pkt.arlen ) vif.rlast <= 1; else vif.rlast <= 0; vif.rvalid <= 1; wait (vif.rready); vif.rlast <= 0; vif.rvalid <= 0; end if (vif.arvalid && vif.arready && vif.arlast) wait(vif.rvalid) begin vif.rid = pkt.rid; vif.rresp = pkt.rresp; end vif.rready <= 1; foreach (vif.rdata[i]) begin if (vif.arid == vif.rid) begin case (vif.rresp) 2'b00 : s = "Transaction OKAY"; 2'b01 : s = "Transaction FAILED"; 2'b10 : s = "SLAVE ERROR"; 2'b11 : s = "DEEOCDE ERROR"; endcase `uvm_info("MASTER_DRIVER",$sformatf("\n\n \t\t\t\t\t\t %s RESPONSE FOR THE DATA \n",s),UVM_MEDIUM) end end vif.rready <= 0; endtask ///////////////read address fixed burst task read_address_fixed_burst (); begin vif.arlen <= 4'b0000; vif.arid <= pkt.arid; vif.araddr <= pkt.araddr; vif.arvalid<= 1; wait(vif.arready); vif.arvalid<=0; end read_data_fixed_burst(); endtask ////////////////////////////////////// read data first burst task read_data_fixed_burst (); if (vif.arvalid || vif.rvalid ||( vif.arvalid &&vif.rvalid)) foreach(pkt.rdata[i]) begin case (pkt.arsize) 3'b000 : vif.rdata[7:0] <= pkt.rdata[i]; 3'b001 : vif.rdata[15:0] <= pkt.rdata[i]; 3'b010 : vif.rdata[31:0] <= pkt.rdata[i]; 3'b011 : vif.rdata[63:0] <= pkt.rdata[i]; 3'b100 : vif.rdata[127:0] <= pkt.rdata[i]; 3'b101 : vif.rdata[255:0] <= pkt.rdata[i]; 3'b110 : vif.rdata[511:0] <= pkt.rdata[i]; 3'b110 : vif.rdata[1023:0] <= pkt.rdata[i]; endcase vif.rid <= pkt.rid; if (i == pkt.arlen) vif.rlast <= 1; else vif.rlast <= 0; vif.rvalid <= 1; wait (vif.rready); vif.rlast <= 0; vif.rvalid <= 0; end if (vif.arvalid && vif.arready && vif.arlast) wait(vif.rvalid) begin vif.rid = pkt.rid; vif.rresp = pkt.rresp; end vif.rready <= 1; foreach (vif.rdata[i]) begin if (vif.arid == vif.rid) begin case (vif.rresp) 2'b00 : s = "Transaction OKAY"; 2'b01 : s = "Transaction FAILED"; 2'b10 : s = "SLAVE ERROR"; 2'b11 : s = "DEEOCDE ERROR"; endcase `uvm_info("MASTER_DRIVER",$sformatf("\n\n \t\t\t\t\t\t %s RESPONSE FOR THE DATA \n",s),UVM_MEDIUM) end end vif.rready <= 0; endtask //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- if(pkt.op==RESET) begin reset_dut(); end //Write operation support else if(pkt.op == WRITE) begin `uvm_info(get_type_name(),"*** WRITE packet is received in driver ***",UVM_MEDIUM) begin write_address_pkt_channel(); end //read operation support else if( pkt.op == READ) begin read_address_pkt_channel(); //put read drive logic here end seq_item_port.item_done(); end endtask endclass