| @@ -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 | |||||