UVM Testbench for Up Counter

     Hello , in this blog post we will verify up counter using UVM. Testbench architecture is shown below. link for code is given at the end of post.

Note : For readablity open this post on your PC.

UVM TB Architecture


DUT : 

module up_counter(out,
                 clk,
                 rst_h,
                 );
input clk,rst_h;
output reg[7:0]out;

always@(posedge clk or posedge rst_h)
    begin
        if(rst_h==1)
            out<=8'b0;
        else 
            out<=out+1;
    end

endmodule:up_counter

 

 up_counter_sequence_item

class up_counter_sequence_item extends uvm_sequence_item;

    //------------ i/p || o/p field declaration-----------------
  
    logic rst_h  ;  //i/p
    logic [7:0]out;  
    //register up_counter_sequence_item class with factory -----
    `uvm_object_utils_begin(up_counter_sequence_item) 
       `uvm_field_int(rst_h  ,UVM_ALL_ON)
    `uvm_object_utils_end
    //--------------------------------------------------------
    
    //-----------------  constructor --------------------
    function new(string name="up_counter_sequence_item");
      super.new();
    endfunction
    //---------------------------------------------------
      
  endclass:up_counter_sequence_item

 up_counter_sequence

  class up_counter_sequence extends uvm_sequence#(up_counter_sequence_item);
 
    `uvm_object_utils(up_counter_sequence)            
     // Register up_counter_sequence with factory
   
    up_counter_sequence_item txn;                      
    //object of up_counter_sequence_item class
    
   //constructor -> create first base class and then derive class
    function new(string name="up_counter_sequence");  
      super.new(name);
    endfunction
    
   virtual task body();
      
   endtask:body
    
  endclass:up_counter_sequence
  
  class call_rst_h extends up_counter_sequence;
  
    `uvm_object_utils(call_rst_h)            
     // Register call_rst_h with factory
  
    function new(string name="call_rst_h"); 
      super.new(name);
    endfunction
  
    task body();
      up_counter_sequence_item txn;
      txn=up_counter_sequence_item::type_id::create("txn");
      start_item(txn);
      txn.rst_h=1;
      finish_item(txn);
    endtask
  
  endclass:call_rst_h
  
  
  class call_rst_h_low extends up_counter_sequence;
  
    `uvm_object_utils(call_rst_h_low)             
    // Register call_rst_h_low with factory
  
    function new(string name="call_rst_h_low");  
      super.new(name);
    endfunction
  
    task body();
      up_counter_sequence_item txn;
      txn=up_counter_sequence_item::type_id::create("txn");
      start_item(txn);
      txn.rst_h=0;
      finish_item(txn);
    endtask
  
  endclass:call_rst_h_low
  

 up_counter_sequencer

  class up_counter_sequencer extends uvm_sequencer#(up_counter_sequence_item);
  
    `uvm_component_utils(up_counter_sequencer)  
    
    function new(string name="",uvm_component parent);  
      super.new(name,parent);
    endfunction
    
  endclass:up_counter_sequencer

 up_counter_driver

class up_counter_driver extends uvm_driver #(up_counter_sequence_item);
    `uvm_component_utils(up_counter_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");
      end
    endfunction
    //-----------------------------------------------------------------
    
    //---------------------------- run task ---------------------------
    task run_phase(uvm_phase phase);
      up_counter_sequence_item txn;
      forever begin
        seq_item_port.get_next_item(txn);
        @(posedge this.vif.clk);
        $display($time," [Driver] ----------------------------------------");
        this.vif.driver_block.cb_driver.rst_h<=txn.rst_h;
        //this.vif.rst_h=txn.rst_h;
        seq_item_port.item_done();    
      end
    endtask
    
  endclass:up_counter_driver
  

 interface

interface intf(input logic clk);
    // ------------------- port declaration--------------
    logic rst_h;
    logic [7:0]out;
    //---------------------------------------------------
  
    //------------------- clocking & modport declaration ------

    
    // Clocking outputs are DUT inputs and vice versa
    clocking cb_driver @(posedge clk);
      default input #1step output #1step;
      output rst_h;
      input out;
    endclocking
    //---------------------------------------------------------
        
    modport driver_block(clocking cb_driver);
    
    //---------------------- ASSERTION -------------------------
    property check_counter;
      disable iff (rst_h)
      @(posedge clk) out|->(out==$past(out,1)+1);
    endproperty
      
    //----------------------------------------------------------
    
 ASSERT:assert property(check_counter) \
 $display($time," [Interface]--------- ASSERTION PASS --------");
 else \
 $display($time," [Interface]----------- ASSERTION FAILS -----"); 
    
endinterface

 up_counter_monitor

class up_counter_monitor extends uvm_monitor;
    //-------------------------------------------------------------
    `uvm_component_utils(up_counter_monitor)
    //-------------------------------------------------------------
  
  
    //------------------- constructor -----------------------------
    function new(string name="",uvm_component parent);
      super.new(name,parent);
    endfunction
    //-------------------------------------------------------------
  
    
    //---------------- sequence_item class ------------------------
    up_counter_sequence_item  txn;
    //-------------------------------------------------------------
  
    
    //------------------------ virtual interface handle------------  
    virtual interface intf vif;
    //-------------------------------------------------------------
  
  
    //------------------- 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
      
      txn=up_counter_sequence_item::type_id::create("txn");
    endfunction
    //--------------------------------------------------------------
  
    //-------------------- run phase -------------------------------
    task run_phase(uvm_phase phase);
      forever
      begin
        // write monitor code here 
        @(posedge vif.clk);
        #1;
        txn.out=vif.out;
        $display($time," [Monitor] ----------- inside monitor -------");
      end
    endtask
    //--------------------------------------------------------------
 
  endclass:up_counter_monitor

up_counter_agent

  class up_counter_agent extends uvm_agent;

    //-----------------------------------------------------------------------
    `uvm_component_utils(up_counter_agent)
    //-----------------------------------------------------------------------
  
  
    //-----------------------------------------------------------------------
    function new(string name="",uvm_component parent);
      super.new(name,parent);
    endfunction
    //-----------------------------------------------------------------------
  
  
    //----------------- class handles ---------------------------------------
    up_counter_sequencer sequencer_h;
    up_counter_driver    driver_h;
    up_counter_monitor   monitor_h;
    //-----------------------------------------------------------------------
  
  
    //---------------------- build phase ------------------------------------
    function void build_phase(uvm_phase phase);    
      driver_h    = up_counter_driver::type_id::create("driver_h",this);
      sequencer_h = up_counter_sequencer::type_id::create("sequencer_h",this);
      monitor_h   = up_counter_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:up_counter_agent

up_counter_env

  class up_counter_env extends uvm_env;

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

   //-------------------- class handles ------------------------------------
   up_counter_agent    agent_h;
   //-----------------------------------------------------------------------
   
   //---------------------- build phase ------------------------------------
   function void build_phase(uvm_phase phase);
     super.build_phase(phase);
     agent_h    = up_counter_agent::type_id::create("agent_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:up_counter_env

up_counter_any_test

 class up_counter_any_test extends uvm_test;

    //-----------------------------------------------------------
    `uvm_component_utils(up_counter_any_test)
    //-----------------------------------------------------------

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

    up_counter_env env_h;

    //-----------------------------------------------------------
    function void build_phase(uvm_phase phase);
      env_h = up_counter_env::type_id::create("env_h",this);
    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);
        call_rst_h seq1;
        call_rst_h seq2;
        call_rst_h_low seq3;
        call_rst_h_low seq4;
        phase.raise_objection(this);
            $display("\t-------------- raise objection ---------");
            seq1= call_rst_h::type_id::create("seq1");
            seq3= call_rst_h_low::type_id::create("seq3");
            seq1.start(env_h.agent_h.sequencer_h);
            seq3.start(env_h.agent_h.sequencer_h);
            #500;
            seq2= call_rst_h::type_id::create("seq2");
            seq4= call_rst_h_low::type_id::create("seq4");
            seq2.start(env_h.agent_h.sequencer_h);
            seq4.start(env_h.agent_h.sequencer_h);
            #500;
            $display("\t-------------- drop objection ---------");
        phase.drop_objection(this);
    endtask
    //------------------------------------------------------------

endclass:up_counter_any_test

package

`ifndef TB_PKG
`define TB_PKG
`include "uvm_macros.svh"
package tb_pkg;
 import uvm_pkg::*;
 `include "up_counter_sequence_item.sv"     // transaction class
 `include "up_counter_sequence.sv"          // sequence class
 `include "up_counter_sequencer.sv"         // sequencer class
 `include "up_counter_driver.sv"            // driver class
 `include "up_counter_monitor.sv" // monitor class
 `include "up_counter_agent.sv"             // agent class  
 `include "up_counter_env.sv"               // environment class

 `include "up_counter_any_test.sv"          // test1

endpackage
`endif 

testbench_top

`include "interface.sv"
`include "tb_pkg.sv"
module top;
  import uvm_pkg::*;
  import tb_pkg::*;
  
  logic clk ;
  
  intf i_intf(clk);
  
  up_counter DUT(.out (i_intf.out),
                 .rst_h(i_intf.rst_h),
                 .clk (i_intf.clk)
                  );
  

  initial begin
    forever #5 clk=~clk;  
  end

  initial clk=0;
  
  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("up_counter_any_test");
  end
  
endmodule

waveform


Edaplayground Link  : https://www.edaplayground

 Thank you for reading have a nice day 😊😊.

Share:
Copyright © VLSI Verification Concepts . Designed by OddThemes