diff --git a/axi_driver.sv b/axi_driver.sv new file mode 100755 index 0000000..920dc34 --- /dev/null +++ b/axi_driver.sv @@ -0,0 +1,393 @@ +class driver extends uvm_driver #(packet); + + `uvm_component_utils(driver) + + virtual axi_if vif; + + + int data_bus_byte; + + packet write_address_queue [$]; + packet write_address; + packet write_data_queue [$]; + packet write_data; + packet write_response_queue [$]; + packet read_address_queue [$]; + packet read_address; + packet read_data_response_queue [$]; + packet read_data; + + semaphore write_address_sema = new (1); + semaphore write_data_sema = new (1); + semaphore write_data_sema_1 = new (1); + semaphore write_response_sema = new (1); + semaphore write_response_sema_1 = new (1); + semaphore read_address_sema = new (1); + semaphore read_data_response_sema = new (1); + semaphore read_data_response_sema_1 = new (1); + + extern function new (string name = "driver", uvm_component parent); + extern function void build_phase (uvm_phase phase); + extern function void connect_phase (uvm_phase phase); + extern task run_phase (uvm_phase phase); + + extern task send_to_dut (); + + extern task write_address_channel (); + extern task write_data_channel (); + extern task fixed_burst (); + extern task incr_burst(); + + extern task write_response_channel (); + + extern task read_address_channel (); + + extern task read_data_response_channel (); + + extern task rd_incr_burst(); + +endclass + +//////////////////////////////////////// NEW FUNCTION + +function driver::new (string name = "driver", uvm_component parent); + + super.new (name,parent); + +endfunction + +/////////////////////////////////////// BUILD PHASE + 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 + +///////////////////////////////////////////////////// RUN PHASE + +task driver::run_phase (uvm_phase phase); + + forever + begin + seq_item_port.get_next_item(req); + send_to_dut(); + seq_item_port.item_done(); + end + +endtask + +/////////////////////////////////////// SEND TO DUT + +task driver::send_to_dut (); + + write_address_queue.push_back (req); + write_data_queue.push_back (req); + write_response_queue.push_back (req); + read_address_queue.push_back (req); + read_data_response_queue.push_back(req); + + fork + write_address_channel(); + write_data_channel(); + write_response_channel(); + read_address_channel (); + read_data_response_channel (); + + join_any + + +endtask + +/////////////////////////////////////// WRITE ADDRESS CHANNEL + +task driver::write_address_channel(); + + write_address_sema.get(1); + + write_address = write_address_queue.pop_front(); + + @(vif.mas_dr); + + req.control = 1; + `uvm_info("MASTER_DRIVER",$sformatf("PRINTING FROM DRIVER \n %s",write_address.sprint()),UVM_HIGH) + + vif.mas_dr.awid <= write_address.awid; + vif.mas_dr.awaddr <= write_address.awaddr; + vif.mas_dr.awlen <= write_address.awlen; + vif.mas_dr.awsize <= write_address.awsize; + vif.mas_dr.awburst <= write_address.awburst; + vif.mas_dr.awvalid <= 1; + + @(vif.mas_dr); + + wait (vif.mas_dr.awready); + + vif.mas_dr.awvalid <= 0; + + write_data_sema.put(1); + write_address_sema.put(1); + + repeat(2) + @(vif.mas_dr); +endtask + +//////////////////////////////////////// WRITE DATA CHANNEL + +task driver::write_data_channel(); + + write_data_sema.get(2); + write_data_sema_1.get(1); + + write_data = write_data_queue.pop_front(); + + @(vif.mas_dr); + + write_data.control = 2; + `uvm_info("MASTER_DRIVER",$sformatf("PRINTING FROM DRIVER \n %s",write_data.sprint()),UVM_HIGH) + + case (write_data.awburst) + + 2'b00 : fixed_burst; + 2'b01 : incr_burst; + 2'b10 : incr_burst; + + endcase + + write_data_sema.put(1); + write_data_sema_1.put(1); + write_response_sema.put(1); + read_address_sema.put(1); + +endtask + +/////////////////////////////////////// INCREMENT BURST + +task driver::incr_burst(); + + foreach(write_data.wdata[i]) + begin + + case (write_data.wstrobe[i]) + + 4'b0001 : vif.mas_dr.wdata [7:0] <= write_data.wdata[i]; + 4'b0010 : vif.mas_dr.wdata [15:8] <= write_data.wdata[i]; + 4'b0100 : vif.mas_dr.wdata [23:16] <= write_data.wdata[i]; + 4'b1000 : vif.mas_dr.wdata [31:24] <= write_data.wdata[i]; + 4'b0011 : vif.mas_dr.wdata [15:0] <= write_data.wdata[i]; + 4'b1100 : vif.mas_dr.wdata [31:16] <= write_data.wdata[i]; + 4'b1110 : vif.mas_dr.wdata [31:8] <= write_data.wdata[i]; + 4'b1111 : vif.mas_dr.wdata <= write_data.wdata[i]; + + endcase + + vif.mas_dr.wstrobe <= write_data.wstrobe[i]; + vif.mas_dr.wid <= write_data.wid; + + if (i == write_data.burst_len - 1) + vif.mas_dr.wlast <= 1; + else + vif.mas_dr.wlast <= 0; + + vif.mas_dr.wvalid <= 1; + + @(vif.mas_dr); + + wait (vif.mas_dr.wready); + + vif.mas_dr.wlast <= 0; + vif.mas_dr.wvalid <= 0; + + @(vif.mas_dr); + + end +endtask + +/////////////////////////////////////// FIXED BURST + +task driver::fixed_burst (); + + foreach(write_data.wdata[i]) + begin + + case (write_data.awsize) + + 2'b00 : vif.mas_dr.wdata[7:0] <= write_data.wdata[i]; + 2'b01 : vif.mas_dr.wdata[15:0] <= write_data.wdata[i]; + 2'b10 : vif.mas_dr.wdata[31:0] <= write_data.wdata[i]; + + endcase + + vif.mas_dr.wid <= write_data.wid; + + if (i == write_data.burst_len - 1) + vif.mas_dr.wlast <= 1; + else + vif.mas_dr.wlast <= 0; + + vif.mas_dr.wvalid <= 1; + + @(vif.mas_dr); + + wait (vif.mas_dr.wready); + + vif.mas_dr.wlast <= 0; + vif.mas_dr.wvalid <= 0; + + @(vif.mas_dr); + + end +endtask + + +/////////////////////////////////////// WRITE RESPONSE CHANNEL + +task driver::write_response_channel (); + + string s; + packet write_response = packet::type_id::create("Response"); + + write_response_sema.get(2); + write_response_sema_1.get(1); + + + @(vif.mas_dr); + + wait(vif.mas_dr.bvalid) + + write_response.bid = vif.mas_dr.bid; + write_response.bresp = vif.mas_dr.bresp; + + vif.mas_dr.bready <= 1; + @(vif.mas_dr); + + foreach (write_response_queue[i]) + begin + if (write_response_queue[i].awid == write_response.bid) + begin + case (write_response.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) + + write_response_queue[i].control = 1; + `uvm_info("MASTER_DRIVER",$sformatf("\n %s \n",write_response_queue[i].sprint),UVM_MEDIUM); + write_response_queue[i].control = 2; + `uvm_info("MASTER_DRIVER",$sformatf("\n %s \n",write_response_queue[i].sprint),UVM_MEDIUM); + + write_response_queue.delete(i); + break; + end + end + + vif.mas_dr.bready <= 0; + @(vif.mas_dr); + + write_response_sema.put(1); + write_response_sema_1.put(1); + +endtask + +/////////////////////////////////////// READ ADDRESS CHANNEL + +task driver::read_address_channel(); + + read_address_sema.get(1); + + read_address = read_address_queue.pop_front(); + + @(vif.mas_dr); + + read_address.control = 4; + `uvm_info("MASTER_DRIVER",$sformatf("PRINTING FROM DRIVER \n %s",read_address.sprint()),UVM_HIGH) + + vif.mas_dr.arid <= read_address.arid; + vif.mas_dr.araddr <= read_address.araddr; + vif.mas_dr.arlen <= read_address.arlen; + vif.mas_dr.arsize <= read_address.arsize; + vif.mas_dr.arburst <= read_address.arburst; + vif.mas_dr.arvalid <= 1; + + @(vif.mas_dr); + + wait (vif.mas_dr.arready); + + vif.mas_dr.arvalid <= 0; + + read_data_response_sema.put(1); + read_address_sema.put(1); + + repeat(2) + @(vif.mas_dr); +endtask + +////////////////////////////////////////// READ DATA AND RESPONSE CHANNEL + +task driver::read_data_response_channel(); + + read_data_response_sema.get(2); + read_data_response_sema_1.get(1); + + read_data = read_data_response_queue.pop_front(); + + case (read_data.awburst) + + 2'b00 : rd_incr_burst; + 2'b01 : rd_incr_burst; + 2'b10 : rd_incr_burst; + + endcase + + read_data_response_sema_1.put(1); + read_data_response_sema.put(1); + +endtask + +////////////////////////////////////////// READ INCREMENT BURST + +task driver::rd_incr_burst(); + + for (int i = 0;i < read_data.arlen+1; i++) + begin + + wait(vif.mas_dr.rvalid); + + case (read_data.arsize) + + 2'b00 : read_data.rdata.push_back(vif.mas_dr.rdata[7:0]); + 2'b01 : read_data.rdata.push_back(vif.mas_dr.rdata[15:0]); + 2'b10 : read_data.rdata.push_back(vif.mas_dr.rdata[31:0]); + + endcase + + case(vif.mas_dr.rresp) + + 2'b00 : read_data.rresp[i] = "TRANSACTION OKAY \n"; + 2'b01 : read_data.rresp[i] = "TRANSACTION FAILED \n"; + 2'b10 : read_data.rresp[i] = "SLAVE ERROR \n"; + 2'b11 : read_data.rresp[i] = "DECODE ERROR \n"; + + endcase + + repeat(read_data.rready_d) + @(vif.mas_dr); + + vif.mas_dr.rready <= 1; + + @(vif.mas_dr); + + vif.mas_dr.rready <= 0; + + @(vif.mas_dr); + end + + read_data.control = 5; + `uvm_info("MASTER_DRIVER",$sformatf("PRINTING FROM DRIVER \n %s",read_data.sprint()),UVM_MEDIUM) + +endtask