Skip to content

UVM Driver

Summary

The UVM Driver is

Coding Guidelines

Coding Guidelines

  • Use conditional compilation guards to avoid compiling the same include file more than once.
  • Create user-defined transaction classes by extending the class uvm_sequence_item.
  • Do not use field macros. (This comes at a heavy cost in terms of performance)
  • Use the rand qualifier in front of any class member variables that might need to be randomized, now or in the future.
  • After any member variables, define a constructor that includes a single string name argument with a default value of the empty string, a call to super.new, and is otherwise empty.
  • After the constructor, always override the convert2string, do_copy, do_compare, do_print, and do_record methods.
  • Always instantiate transaction objects using the factory.
    var_name = transaction_type::type_id::create("var_name");
    

Code Example

driver.sv
`ifndef GPIO_UVC_DRIVER_SV
`define GPIO_UVC_DRIVER_SV

class gpio_uvc_driver extends uvm_driver #(gpio_uvc_sequence_item);

  `uvm_component_utils(gpio_uvc_driver)

  virtual gpio_uvc_if vif;
  gpio_uvc_config     m_config;

  extern function new(string name, uvm_component parent);

  extern function void build_phase(uvm_phase phase);
  extern task run_phase(uvm_phase phase);
  extern task drive_sync();
  extern task drive_async();
  extern task do_drive();

endclass : gpio_uvc_driver


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


function void gpio_uvc_driver::build_phase(uvm_phase phase);
  if (!uvm_config_db#(virtual gpio_uvc_if)::get(get_parent(), "", "vif", vif)) begin
    `uvm_fatal(get_name(), "Could not retrieve gpio_uvc_if from config db")
  end

  if (!uvm_config_db#(gpio_uvc_config)::get(get_parent(), "", "config", m_config)) begin
    `uvm_fatal(get_name(), "Could not retrieve gpio_uvc_config from config db")
  end
endfunction : build_phase


task gpio_uvc_driver::run_phase(uvm_phase phase);
  forever begin
    seq_item_port.get_next_item(req);
    do_drive();
    seq_item_port.item_done();
  end
endtask : run_phase


task gpio_uvc_driver::drive_sync();
  @(vif.cb_drv);
  vif.cb_drv.gpio_pin <= req.gpio_pin;
  `uvm_info(get_type_name(), {"Sending item: ", req.convert2string()}, UVM_MEDIUM)
endtask : drive_sync


task gpio_uvc_driver::drive_async();
  vif.gpio_pin = req.gpio_pin;
  `uvm_info(get_type_name(), {"Sending item: ", req.convert2string()}, UVM_MEDIUM)
  if (req.delay_enable == GPIO_UVC_ITEM_DELAY_ON) begin
    #(req.delay_duration_ps * 1ps);
  end else begin
    @(vif.cb_drv);
  end
endtask : drive_async


task gpio_uvc_driver::do_drive();
  if (req.trans_type == GPIO_UVC_ITEM_ASYNC) begin
    drive_async();
  end else begin
    drive_sync();
  end
endtask : do_drive

`endif // GPIO_UVC_DRIVER_SV

Reference Material

Accellera

Verification Methodology Cookbooks

Articles

Source code