UVM Driver example

UVM Driver

    • A driver is written by extending the uvm_driver
    • uvm_driver is inherited from uvm_component, Methods and TLM port (seq_item_port) are defined for communication between sequencer and driver
    • The uvm_driver is a parameterized class and it is parameterized with the type of the request sequence_item and the type of the response sequence_item

UVM_Driver Methods

get_next_item

This method blocks until a REQ sequence_item is available in the sequencer.

try_next_item

This is a non-blocking variant of the get_next_item() method. It will return a null pointer if there is no REQ sequence_item available in the sequencer.

item_done

The non-blocking item_done() method completes the driver-sequencer handshake and it should be called after a get_next_item() or a successful try_next_item() call.

put

The put() method is non-blocking and is used to place an RSP sequence_item in the sequencer.

 Writing Driver :

1. A driver is written by extending the UVM_DRIVER

class mem_driver extends uvm_driver #(mem_seq_item);

  `uvm_component_utils(mem_driver)

  // Constructor
  function new (string name, uvm_component parent);
    super.new(name, parent);
  endfunction : new

endclass : mem_driver

2. Declare the virtual interface,

  // Virtual Interface
  virtual mem_if vif;the interface handle using get config_db, 

3. Get the interface handle using get config_db,

  if(!uvm_config_db#(virtual mem_if)::get(this, "", "vif", vif))
       `uvm_fatal("NO_VIF",{"virtual interface must be set for: ",get_full_name(),".vif"});

4. Will place the get config_db in the build_phase,

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
     if(!uvm_config_db#(virtual mem_if)::get(this, "", "vif", vif))
       `uvm_fatal("NO_VIF",{"virtual interface must be set for: ",get_full_name(),".vif"});
  endfunction: build_phase

5. Add driving logic. get the seq_item and drive to DUT signals,

  // run phase
  virtual task run_phase(uvm_phase phase);
    forever begin
    seq_item_port.get_next_item(req);
     ......
     .. driving logic ..
     ......
    seq_item_port.item_done();
    end
  endtask : run_phase

The uvm driver example

below is the complete drive code.

`define DRIV_IF vif.DRIVER.driver_cb
class mem_driver extends uvm_driver #(mem_seq_item);

  // Virtual Interface
  virtual mem_if vif;

  `uvm_component_utils(mem_driver)
    
  //uvm_analysis_port #(mem_seq_item) Drvr2Sb_port;

  // Constructor
  function new (string name, uvm_component parent);
    super.new(name, parent);
  endfunction : new

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
     if(!uvm_config_db#(virtual mem_if)::get(this, "", "vif", vif))
       `uvm_fatal("NO_VIF",{"virtual interface must be set for: ",get_full_name(),".vif"});
  endfunction: build_phase

  // run phase
  virtual task run_phase(uvm_phase phase);
    forever begin
    seq_item_port.get_next_item(req);
    //respond_to_transfer(req);
    drive();
    seq_item_port.item_done();
    end
  endtask : run_phase

  // drive 
  virtual task drive();
    req.print();
      `DRIV_IF.wr_en <= 0;
      `DRIV_IF.rd_en <= 0;
      @(posedge vif.DRIVER.clk);
      `DRIV_IF.addr <= req.addr;
    if(req.wr_en) begin
        `DRIV_IF.wr_en <= req.wr_en;
        `DRIV_IF.wdata <= req.wdata;
      //$display("\tADDR = %0h \tWDATA = %0h",req.addr,trans.wdata);
        @(posedge vif.DRIVER.clk);
      end
    if(req.rd_en) begin
        `DRIV_IF.rd_en <= req.rd_en;
        @(posedge vif.DRIVER.clk);
        `DRIV_IF.rd_en <= 0;
        @(posedge vif.DRIVER.clk);
        req.rdata = `DRIV_IF.rdata;
       // $display("\tADDR = %0h \tRDATA = %0h",trans.addr,`DRIV_IF.rdata);
      end
      $display("-----------------------------------------");
  endtask : drive

endclass : mem_driver

❮ Previous Next ❯