UVM Testbench For Multiplexer

     Hello again, so in this blog we will verify 4x1 multiplexer using UVM , and also learn how to create .log file for dumping reporting messages like `uvm_info(). In the verification we will also use coverage to measure verification progress.

     Link : https://www.edaplayground

     Updated TB with Scoreboard (self checking TB) : https://www.edaplayground.com 

     So the architecture of testbench is shown below.


design.sv


module mux4x1(in,sel,out);
  
  input [3:0]in;
  input [1:0]sel;
  
  output out;
  
  assign out=in[sel];
  
endmodule

mux_sequence_item

class mux_sequence_item extends uvm_sequence_item;
  //------------ i/p || o/p field declaration-------------

  rand logic [3:0]in ;  //i/p
  rand logic [1:0]sel ;
  
  logic out;        //o/p
  
  //register mux_sequence_item class with factory ---------
  `uvm_object_utils_begin(mux_sequence_item) 
     `uvm_field_int(in   ,UVM_ALL_ON)
     `uvm_field_int(sel  ,UVM_ALL_ON)
  `uvm_object_utils_end
  //--------------------------------------------------------

  
  //-----------------  constructor --------------------
  function new(string name="mux_sequence_item");
    super.new(name);
  endfunction
  //---------------------------------------------------
    
endclass:mux_sequence_item

mux_sequence

class mux_sequence extends uvm_sequence#(mux_sequence_item);
  //----------------------------------------------------
  `uvm_object_utils(mux_sequence)            
  //----------------------------------------------------

  mux_sequence_item txn;                     
  
  //----------------------------------------------------
  function new(string name="mux_sequence");  
    super.new(name);
  endfunction
  //----------------------------------------------------

  //----------------------------------------------------
  virtual task body();
    
  endtask:body
  //----------------------------------------------------
endclass:mux_sequence

class random_data extends mux_sequence;
  //----------------------------------------------------   
  `uvm_object_utils(random_data)      
  //----------------------------------------------------
  
  mux_sequence_item txn;
  
  //----------------------------------------------------
  function new(string name="");
      super.new(name);
  endfunction
  //----------------------------------------------------
  
  //----------------------------------------------------
  task body();
    repeat(20)
      begin
        txn=mux_sequence_item::type_id::create("txn");
        start_item(txn);
        txn.randomize();
        #4;
        finish_item(txn);
      end
  endtask:body
  //----------------------------------------------------
  
endclass:random_data

class mux_sel_00 extends mux_sequence;
  //----------------------------------------------------   
  `uvm_object_utils(mux_sel_00)      
  //----------------------------------------------------
  
  mux_sequence_item txn;
  
  //----------------------------------------------------
  function new(string name="");
      super.new(name);
  endfunction
  //----------------------------------------------------
  
  //----------------------------------------------------
  task body();
    repeat(10)
      begin
        txn=mux_sequence_item::type_id::create("txn");
        start_item(txn);
        txn.randomize()with{txn.sel==0;};
        #4;
        finish_item(txn);
      end
  endtask:body
  //----------------------------------------------------
  
endclass:mux_sel_00


class mux_sel_01 extends mux_sequence;
  //----------------------------------------------------   
  `uvm_object_utils(mux_sel_01)      
  //----------------------------------------------------
  
  mux_sequence_item txn;
  
  //----------------------------------------------------
  function new(string name="");
      super.new(name);
  endfunction
  //----------------------------------------------------
  
  //----------------------------------------------------
  task body();
    repeat(10)
      begin
        txn=mux_sequence_item::type_id::create("txn");
        start_item(txn);
        txn.randomize()with{txn.sel==1;};
        #4;
        finish_item(txn);
      end
  endtask:body
  //----------------------------------------------------
  
endclass:mux_sel_01


class mux_sel_10 extends mux_sequence;
  //----------------------------------------------------   
  `uvm_object_utils(mux_sel_10)      
  //----------------------------------------------------
  
  mux_sequence_item txn;
  
  //----------------------------------------------------
  function new(string name="");
      super.new(name);
  endfunction
  //----------------------------------------------------
  
  //----------------------------------------------------
  task body();
    repeat(10)
      begin
        txn=mux_sequence_item::type_id::create("txn");
        start_item(txn);
        txn.randomize()with{txn.sel==2;};
        #4;
        finish_item(txn);
      end
  endtask:body
  //----------------------------------------------------
  
endclass:mux_sel_10


class mux_sel_11 extends mux_sequence;
  //----------------------------------------------------   
  `uvm_object_utils(mux_sel_11)      
  //----------------------------------------------------
  
  mux_sequence_item txn;
  
  //----------------------------------------------------
  function new(string name="");
      super.new(name);
  endfunction
  //----------------------------------------------------
  
  //----------------------------------------------------
  task body();
    repeat(10)
      begin
        txn=mux_sequence_item::type_id::create("txn");
        start_item(txn);
        txn.randomize()with{txn.sel==3;};
        #4;
        finish_item(txn);
      end
  endtask:body
  //----------------------------------------------------
  
endclass:mux_sel_11
 

mux_sequencer


class mux_sequencer extends uvm_sequencer#(mux_sequence_item);
  //----------------------------------------------------
  `uvm_component_utils(mux_sequencer)  
  //----------------------------------------------------

  //----------------------------------------------------
  function new(string name="",uvm_component parent);  
    super.new(name,parent);
  endfunction
  //----------------------------------------------------
  
endclass:mux_sequencer

mux_driver


class mux_driver extends uvm_driver #(mux_sequence_item);
  //-----------------------------------------------------------------
  `uvm_component_utils(mux_driver)
  //-----------------------------------------------------------------

  //-----------------------------------------------------------------
  function new(string name="",uvm_component parent);
    super.new(name,parent);
  endfunction
  //----------------------------------------------------------------- 

  //--------------------------  virtual interface handel ------------  
  virtual interface intf vif;
  //-----------------------------------------------------------------
  
  //-------------------------  get interface handel from top --------
  function void build_phase(uvm_phase phase);
    if(!(uvm_config_db#(virtual intf)::get(this,"","vif",vif))) begin
      `uvm_fatal("driver","unable to get interface",UVM_MEDIUM);
    end
  endfunction
  //-----------------------------------------------------------------
  
  //---------------------------- run task ---------------------------
  task run_phase(uvm_phase phase);
    mux_sequence_item txn;
    forever begin
      seq_item_port.get_next_item(txn);
      vif.sel =txn.sel;
      vif.in  =txn.in;
      `uvm_info(get_type_name(),$sformatf("sel=%2b in=%4b",txn.sel,txn.in)\
       ,UVM_MEDIUM)
      seq_item_port.item_done();    
    end
  endtask
  //------------------------------------------------------------------
  
endclass:mux_driver

interface


interface intf();
    // ------------------- port declaration--------------
    logic [3:0]in ;
    logic [1:0]sel;
    logic out;
    
    //---------------------------------------------------

    //------------- clocking & modport declaration ------
   /* clocking clocking_block_name @(posedge signal_name);
      default input #1step output #1step;
      output //input of DUT
      input  //output of DUT
    endclocking
   */
    //modport modport_name(clocking name_of_block);
    //---------------------------------------------------
        
endinterface

mux_monitor


class mux_monitor extends uvm_monitor;
  //-------------------------------------------------------------
  `uvm_component_utils(mux_monitor)
  //-------------------------------------------------------------


  //------------------- constructor -----------------------------
  function new(string name="",uvm_component parent);
    super.new(name,parent);
  endfunction
  //-------------------------------------------------------------

  
  //---------------- sequence_item class ------------------------
  mux_sequence_item  txn;
  //-------------------------------------------------------------

  
  //------------------------ virtual interface handle------------  
  virtual interface intf vif;
  //-------------------------------------------------------------


  //------------------------ analysis port ----------------------
  uvm_analysis_port#(mux_sequence_item) ap_mon;
  //-------------------------------------------------------------
  

  //------------------- build phase -----------------------------
  function void build_phase(uvm_phase phase);
    if(!(uvm_config_db#(virtual intf)::get(this,"","vif",vif)))
    begin
      `uvm_fatal("monitor","unable to get interface")
    end
    
    ap_mon=new("ap_mon",this);
    txn=mux_sequence_item::type_id::create("txn",this);
  endfunction
  //--------------------------------------------------------------

  //-------------------- run phase -------------------------------
  task run_phase(uvm_phase phase);
    forever
    begin
      // write monitor code here 
      @(vif.in or vif.sel or vif.out);
      txn.in  = vif.in;
      txn.sel = vif.sel;
      txn.out = vif.out;
      ap_mon.write(txn);
      #1;
      `uvm_info(get_type_name(),$sformatf("sel=%2b in=%4b out=%0b"\
       ,txn.sel,txn.in,txn.out),UVM_MEDIUM)
    end
  endtask
  //--------------------------------------------------------------
endclass:mux_monitor

mux_agent


class mux_agent extends uvm_agent;

  //-----------------------------------------------------------------------
  `uvm_component_utils(mux_agent)
  //-----------------------------------------------------------------------


  //-----------------------------------------------------------------------
  function new(string name="",uvm_component parent);
    super.new(name,parent);
  endfunction
  //-----------------------------------------------------------------------


  //----------------- class handles ---------------------------------------
  mux_sequencer sequencer_h;
  mux_driver    driver_h;
  mux_monitor   monitor_h;
  //-----------------------------------------------------------------------


  //---------------------- build phase ------------------------------------
  function void build_phase(uvm_phase phase);    
    driver_h    = mux_driver::type_id::create("driver_h",this);
    sequencer_h = mux_sequencer::type_id::create("sequencer_h",this);
    monitor_h   = mux_monitor::type_id::create("monitor_h",this);
  endfunction
  //------------------------------------------------------------------------


  //----------------------- connect phase ----------------------------------
  function void connect_phase(uvm_phase phase);
    driver_h.seq_item_port.connect(sequencer_h.seq_item_export);
  endfunction
  //------------------------------------------------------------------------

endclass:mux_agent

mux_coverage


class mux_coverage extends uvm_subscriber #(mux_sequence_item);

  //-----------------------------------------------------------------------
  `uvm_component_utils(mux_coverage)
  //-----------------------------------------------------------------------
  
  //-----------------------------------------------------------------------
  function new(string name="",uvm_component parent);
    super.new(name,parent);
    cg=new();
  endfunction
  //-----------------------------------------------------------------------
  
  function void build_phase(uvm_phase phase);
  endfunction

  //-----------------------------------------------------------------------
  mux_sequence_item txn;
  real cov;
  //------------------------------------------------------------------------
  
  //------------------------------------------------------------------------
  covergroup cg;
    IN:coverpoint txn.in {   
        bins in1_1={[0:3]};
        bins in2_1={[4:7]};
        bins in3_1={[8:11]};
        bins in4_1={[12:15]};
    }
    SEL:coverpoint txn.sel{  
        bins sel1_2={0};
        bins sel2_2={1};
        bins sel3_2={2};
       bins sel4_2={3};
    }
  endgroup:cg

  //------------------------------------------------------------------------

  //---------------------  write method -----------------------------------
  function void write(mux_sequence_item t);
    txn=t;
    //inside suscriber
    cg.sample();
  endfunction
  //-----------------------------------------------------------------------

  //-----------------------------------------------------------------------
  function void extract_phase(uvm_phase phase);
    cov=cg.get_coverage();
  endfunction
  //-----------------------------------------------------------------------

  //-----------------------------------------------------------------------
  function void report_phase(uvm_phase phase);
    `uvm_info(get_type_name(),$sformatf("Coverage is %f",cov),\
     UVM_MEDIUM)
  endfunction
  //-----------------------------------------------------------------------
  
endclass:mux_coverage

mux_env

class mux_env extends uvm_env;
   //----------------------------------------------------------------------
  `uvm_component_utils(mux_env)
   //----------------------------------------------------------------------

  //-----------------------------------------------------------------------
  function new(string name="",uvm_component parent);
    super.new(name,parent);
  endfunction
  //-----------------------------------------------------------------------

  //-------------------- class handles ------------------------------------
  mux_agent    agent_h;
  mux_coverage coverage_h;
  //-----------------------------------------------------------------------
  
  //---------------------- build phase ------------------------------------
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    agent_h    = mux_agent::type_id::create("agent_h",this);
    coverage_h = mux_coverage::type_id::create("coverage_h",this);
  endfunction
  //-----------------------------------------------------------------------

  //-------------------------- connect phase ------------------------------
  function void connect_phase(uvm_phase phase);
    agent_h.monitor_h.ap_mon.connect(coverage_h.analysis_export);
  endfunction
  //------------------------------------------------------------------------
endclass:mux_env

mux_test


class mux_any_test extends uvm_test;

    //-----------------------------------------------------------------------
    `uvm_component_utils(mux_any_test)
    //-----------------------------------------------------------------------

    //-----------------------------------------------------------------------
    function new(string name="",uvm_component parent);
      super.new(name,parent);
    endfunction
    //-----------------------------------------------------------------------

    int file_h; //use for file operation (file handel)
  
    mux_env env_h;
  random_data seq;
    mux_sel_00 seq00;
    mux_sel_01 seq01;
    mux_sel_10 seq10;
    mux_sel_11 seq11;
  
    //-----------------------------------------------------------------------
    function void build_phase(uvm_phase phase);
      env_h = mux_env::type_id::create("env_h",this);
      seq= random_data::type_id::create("seq");
      seq00= mux_sel_00::type_id::create("seq00");
      seq01= mux_sel_01::type_id::create("seq01");
      seq10= mux_sel_10::type_id::create("seq10");
      seq11= mux_sel_11::type_id::create("seq11");
    endfunction
    //-----------------------------------------------------------------------

  
    //-----------------------------------------------------------------------
    function void start_of_simulation_phase(uvm_phase phase);
      file_h=$fopen("mux_report.log","w");
      env_h.set_report_default_file_hier(file_h);
      env_h.set_report_severity_action_hier(UVM_INFO,UVM_DISPLAY\
      +UVM_LOG);
      env_h.set_report_verbosity_level_hier(UVM_MEDIUM);
    endfunction
    //-----------------------------------------------------------------------
  
    //-----------------------------------------------------------------------
    function void end_of_elobartion_phase(uvm_phase phase);
      //factory.print();
      $display("End of eleboration phase in agent");
    endfunction
    //-----------------------------------------------------------------------

    //-----------------------------------------------------------------------
    task run_phase(uvm_phase phase);
      phase.raise_objection(this);
          seq00.start(env_h.agent_h.sequencer_h);   
          seq01.start(env_h.agent_h.sequencer_h);   
          seq10.start(env_h.agent_h.sequencer_h);   
          seq11.start(env_h.agent_h.sequencer_h);   
          seq.start(env_h.agent_h.sequencer_h);
          #5;
      phase.drop_objection(this);
    endtask
    //-----------------------------------------------------------------------

endclass:mux_any_test

tb_pkg.sv


`ifndef TB_PKG
`define TB_PKG
`include "uvm_macros.svh"
package tb_pkg;
 import uvm_pkg::*;
 `include "mux_sequence_item.sv"        // transaction class
 `include "mux_sequence.sv"             // sequence class
 `include "mux_sequencer.sv"            // sequencer class
 `include "mux_driver.sv"               // driver class
 `include "mux_monitor.sv"
 `include "mux_agent.sv"                // agent class  
 `include "mux_coverage.sv"             // coverage class
 `include "mux_env.sv"                  // environment class

 `include "mux_test.sv"                 // test1

endpackage
`endif 

testbench_top.sv


`include "interface.sv"
`include "tb_pkg.sv"
module top;
  import uvm_pkg::*;
  import tb_pkg::*;
   
  intf i_intf();
  
  mux4x1 DUT(.sel(i_intf.sel),
             .in(i_intf.in),
             .out(i_intf.out)
            );
  
  initial begin
    $dumpfile("dump1.vcd");
    $dumpvars(0,top);
  end
  
  initial begin
    uvm_config_db#(virtual intf)::set(uvm_root::get(),"","vif",\
    i_intf);
  end

  initial begin
    run_test("mux_any_test");
  end
  
endmodule

 output messages


 log file



     As you run this code you will see that functional coveragge is 100% , so we verified our simple design in UVM. In next blog we will verify 64KB RAM.

    Thank you for reading have a nice day 😊😊👍.

    Shortcut for emojie in PC is " Windows + .(dot)"

Share:
Copyright © VLSI Verification Concepts . Designed by OddThemes