UVM TestBench For S R Latch

          Hello after long time , so in this post we will do verification of S R Latch using UVM.

UVM TestBench Architecture : 


 Design

module sr(s,r,q,qbar);
    input s;
    input r;
    output reg q;
    output reg qbar;

    always@(*) begin 
        if(s==0 && r==0) begin 
            q    <=  q;
            qbar <= ~q;
        end
        else if(s==0 && r==1) begin 
            q    <=  0;
            qbar <= ~q;
        end
        else if(s==1 && r==0) begin 
            q    <=  1;
            qbar <= ~q;
        end
        else begin 
            q    <= 1'bx;
            qbar <= ~q;
        end
    end
endmodule : sr

sr_sequence_item

class sr_sequence_item extends uvm_sequence_item;

  //------------ i/p || o/p field declaration-----------------

  rand logic  s;  //i/p
  rand logic  r;

  logic q;        //o/p
  logic qbar;
  
  //---------------- register sr_sequence_item class with factory --------
  `uvm_object_utils_begin(sr_sequence_item) 
     `uvm_field_int( r    ,UVM_ALL_ON)
     `uvm_field_int( s    ,UVM_ALL_ON)
     `uvm_field_int( q    ,UVM_ALL_ON)
     `uvm_field_int( qbar ,UVM_ALL_ON)
  `uvm_object_utils_end
  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------
  function new(string name="sr_sequence_item");
    super.new(name);
  endfunction
  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------
  // write DUT inputs here for printing
  function string input2string();
    return($sformatf(" s=%0b  r=%0b",s,r));
  endfunction
  
  // write DUT outputs here for printing
  function string output2string();
    return($sformatf(" q=%0b qbar=%0b", q,qbar));
  endfunction
    
  function string convert2string();
    return($sformatf({input2string(), " || ", output2string()}));
  endfunction
  //----------------------------------------------------------------------------

endclass:sr_sequence_item

sr_sequence


/***************************************************
** class name  : sr_sequence
** description : generate random input for DUT
***************************************************/
class sr_sequence extends uvm_sequence#(sr_sequence_item);
  //----------------------------------------------------------------------------
  `uvm_object_utils(sr_sequence)            
  //----------------------------------------------------------------------------

  sr_sequence_item txn;
  int unsigned LOOP=50;

  //----------------------------------------------------------------------------
  function new(string name="sr_sequence");  
    super.new(name);
  endfunction
  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------
  virtual task body();
  repeat(LOOP) begin 
    txn=sr_sequence_item::type_id::create("txn");
    start_item(txn);
    txn.randomize();
    #5;
    finish_item(txn);
  end
  endtask:body
  //----------------------------------------------------------------------------
endclass:sr_sequence

/***************************************************
** class name  : sequence_1
** description : first set and then memory state
***************************************************/
class sequence_1 extends sr_sequence;
  //----------------------------------------------------------------------------   
  `uvm_object_utils(sequence_1)      
  //----------------------------------------------------------------------------
  
  sr_sequence_item txn;
  int unsigned LOOP = 20;
  bit set=1;
  //----------------------------------------------------------------------------
  function new(string name="sequence_1");
      super.new(name);
  endfunction
  //----------------------------------------------------------------------------
  
  //----------------------------------------------------------------------------
  task body();
    for(int i=0;i<LOOP;i++) begin 
    txn=sr_sequence_item::type_id::create("txn");
    start_item(txn);
    txn.randomize()with{txn.s==set;txn.r==0;};
    #5;
    finish_item(txn);
    set=set+1;
  end
  endtask:body
  //----------------------------------------------------------------------------
  
endclass

/***************************************************
** class name  : sequence_2
** description : first reset and then memory state
***************************************************/
class sequence_2 extends sr_sequence;
  //----------------------------------------------------------------------------   
  `uvm_object_utils(sequence_2)      
  //----------------------------------------------------------------------------
  
  sr_sequence_item txn;
  int unsigned LOOP=20;
  bit rst=1;
  
  //----------------------------------------------------------------------------
  function new(string name="sequence_2");
      super.new(name);
  endfunction
  //----------------------------------------------------------------------------
  
  //----------------------------------------------------------------------------
  task body();
    for(int i=0;i<LOOP;i++) begin 
    txn=sr_sequence_item::type_id::create("txn");
    start_item(txn);
      txn.randomize()with{txn.s==0; txn.r==rst;};
    #5;
    finish_item(txn);
    rst=rst+1;
  end
  endtask:body
  //----------------------------------------------------------------------------
  
endclass


/***************************************************
** class name  : sequence_3
** description : first unknown and then memory state
***************************************************/
class sequence_3 extends sr_sequence;
  //----------------------------------------------------------------------------   
  `uvm_object_utils(sequence_3)      
  //----------------------------------------------------------------------------
  
  sr_sequence_item txn;
  int unsigned LOOP=20;
  bit ukn=1;
  //----------------------------------------------------------------------------
  function new(string name="sequence_3");
      super.new(name);
  endfunction
  //----------------------------------------------------------------------------
  
  //----------------------------------------------------------------------------
  task body();
    for(int i=0;i<LOOP;i++) begin 
    txn=sr_sequence_item::type_id::create("txn");
    start_item(txn);
    txn.randomize()with{txn.s==ukn; txn.r==ukn;};
    #5;
    finish_item(txn);
    ukn = ukn + 1;
  end
  endtask:body
  //----------------------------------------------------------------------------
  
endclass

sr_sequencer

class sr_sequencer extends uvm_sequencer#(sr_sequence_item);
  //----------------------------------------------------------------------------
  `uvm_component_utils(sr_sequencer)  
  //----------------------------------------------------------------------------

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

sr_driver


class sr_driver extends uvm_driver #(sr_sequence_item);
  //----------------------------------------------------------------------------
  `uvm_component_utils(sr_driver)
  //----------------------------------------------------------------------------

  uvm_analysis_port #(sr_sequence_item) drv2sb;

  //----------------------------------------------------------------------------
  function new(string name="sr_driver",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);
    super.build_phase(phase);
    if(!(uvm_config_db#(virtual intf)::get(this,"","vif",vif))) begin
      `uvm_fatal("driver","unable to get interface");
    end
    drv2sb=new("drv2sb",this);
  endfunction
  //----------------------------------------------------------------------------
  
  //---------------------------- run task --------------------------------------
  task run_phase(uvm_phase phase);
    sr_sequence_item txn=sr_sequence_item::type_id::create("txn");
    initilize(); // initilize dut at time 0
    forever begin
      seq_item_port.get_next_item(txn);
      drive_item(txn);
      drv2sb.write(txn);
      seq_item_port.item_done();    
    end
  endtask
  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------
  task initilize();
   // make changes here for input to dut 
   // vif.data = 0;
   // vif.addr = 0;
   // vif.read = 0;
   vif.s = 0;
   vif.r = 0;
  endtask
  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------
  task drive_item(sr_sequence_item txn);
    vif.s = txn.s;
    vif.r = txn.r;
  endtask
  //----------------------------------------------------------------------------
endclass:sr_driver

interface  



interface intf();
    // ------------------- port declaration-------------------------------------
    logic s;
    logic r;
    logic q;
    logic qbar;
    //--------------------------------------------------------------------------
    //--------------------------------------------------------------------------
        
endinterface

sr_monitor


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

  //------------------- constructor --------------------------------------------
  function new(string name="sr_monitor",uvm_component parent);
    super.new(name,parent);
  endfunction
  //----------------------------------------------------------------------------
  
  //---------------- sequence_item class ---------------------------------------
  sr_sequence_item  txn;
  //----------------------------------------------------------------------------
  
  //------------------------ virtual interface handle---------------------------  
  virtual interface intf vif;
  //----------------------------------------------------------------------------

  //------------------------ analysis port -------------------------------------
  uvm_analysis_port#(sr_sequence_item) ap_mon;
  //----------------------------------------------------------------------------
  
  //------------------- build phase --------------------------------------------
  function void build_phase(uvm_phase phase);
    super.build_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);
  endfunction
  //----------------------------------------------------------------------------

  //-------------------- run phase ---------------------------------------------
  task run_phase(uvm_phase phase);
    sr_sequence_item txn=sr_sequence_item::type_id::create("txn");
    forever
    begin
      sample_dut(txn);
      ap_mon.write(txn);
    end
  endtask
  //----------------------------------------------------------------------------

  task sample_dut(output sr_sequence_item txn);
    sr_sequence_item t = sr_sequence_item::type_id::create("t");
    #5.1;
    t.s    = vif.s;
    t.r    = vif.r;
    t.q    = vif.q;
    t.qbar = vif.qbar;
    txn    = t;
  endtask : sample_dut

endclass:sr_monitor

sr_agent


class sr_agent extends uvm_agent;

  //----------------------------------------------------------------------------
  `uvm_component_utils(sr_agent)
  //----------------------------------------------------------------------------

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

  //----------------- class handles --------------------------------------------
  sr_sequencer sequencer_h;
  sr_driver    driver_h;
  sr_monitor   monitor_h;
  //----------------------------------------------------------------------------

  //---------------------- build phase -----------------------------------------
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    driver_h    = sr_driver::type_id::create("driver_h",this);
    sequencer_h = sr_sequencer::type_id::create("sequencer_h",this);
    monitor_h   = sr_monitor::type_id::create("monitor_h",this);
  endfunction
  //----------------------------------------------------------------------------

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

endclass:sr_agent

sr_coverage


class sr_coverage extends uvm_subscriber #(sr_sequence_item);

  //----------------------------------------------------------------------------
  `uvm_component_utils(sr_coverage)
  //----------------------------------------------------------------------------

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

  //----------------------------------------------------------------------------
  sr_sequence_item txn;
  real cov;
  //----------------------------------------------------------------------------
  
  //----------------------------------------------------------------------------
  covergroup dut_cov;
    option.per_instance= 1;
    option.comment     = "dut_cov";
    option.name        = "dut_cov";
    option.auto_bin_max= 4;
    
    S:coverpoint txn.s { 
        bins s_high={1};
        bins s_low ={0};
    }

    R:coverpoint txn.r { 
        bins r_high={1};
        bins r_low ={0};
    }

    SXR:cross S,R;
  endgroup:dut_cov;

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

  //---------------------  write method ----------------------------------------
  function void write(sr_sequence_item t);
    txn=t;
    dut_cov.sample();
  endfunction
  //----------------------------------------------------------------------------

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


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

sr_scoreboard


/***************************************************
  analysis_port from driver
  analysis_port from monitor
***************************************************/

`uvm_analysis_imp_decl( _drv )
`uvm_analysis_imp_decl( _mon )

class sr_scoreboard extends uvm_scoreboard;
  //----------------------------------------------------------------------------
  `uvm_component_utils(sr_scoreboard)
  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------
  uvm_analysis_imp_drv #(sr_sequence_item, sr_scoreboard) aport_drv;
  uvm_analysis_imp_mon #(sr_sequence_item, sr_scoreboard) aport_mon;
  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------
  uvm_tlm_fifo #(sr_sequence_item) expfifo;
  uvm_tlm_fifo #(sr_sequence_item) outfifo;
  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------
  int VECT_CNT, PASS_CNT, ERROR_CNT;
  logic t_s;
  logic t_r;
  logic t_q,temp_q;
  logic t_qbar,temp_qbar;

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


  //----------------------------------------------------------------------------  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    aport_drv = new("aport_drv"this);
    aport_mon = new("aport_mon"this);
    expfifo= new("expfifo",this);
    outfifo= new("outfifo",this);
  endfunction
  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------
  function void write_drv(sr_sequence_item tr);
    `uvm_info("write_drv STIM"tr.input2string(), UVM_MEDIUM)
    t_r = tr.r;
    t_s = tr.s;
    t_q = temp_q;
    t_qbar = temp_qbar;

    if(t_s==0 && t_r==0) begin 
      temp_q    =  temp_q;
      temp_qbar = ~temp_q;
    end
    else if(t_s==0 && t_r==1) begin 
      temp_q    =  0;
      temp_qbar = ~temp_q;
    end
    else if(t_s==1 && t_r==0) begin 
      temp_q    =  1;
      temp_qbar = ~temp_q;
    end
    else begin 
      temp_q    = 1'bx;
      temp_qbar = ~temp_q;
    end

    tr.q    = t_q;
    tr.qbar = t_qbar;

    void'(expfifo.try_put(tr));
  endfunction
  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------
  function void write_mon(sr_sequence_item tr);
    `uvm_info("write_mon OUT "tr.convert2string(), UVM_MEDIUM)
    void'(outfifo.try_put(tr));
  endfunction
  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------
  task run_phase(uvm_phase phase);
  sr_sequence_item exp_tr, out_tr;
  static int unsigned count=0;
  forever begin
      `uvm_info("scoreboard run task","WAITING for expected output"UVM_DEBUG)
      expfifo.get(exp_tr);
      `uvm_info("scoreboard run task","WAITING for actual output"UVM_DEBUG)
      outfifo.get(out_tr);
        
        if (out_tr.q===exp_tr.q && out_tr.qbar===exp_tr.qbar && count>0) begin
            PASS();
          `uvm_info ("\n [ PASS ",out_tr.convert2string() , UVM_MEDIUM)
        end
      
        else if (out_tr.q!==exp_tr.q && out_tr.qbar!==exp_tr.qbar && count>0) begin
           ERROR();
          `uvm_info ("ERROR [ACTUAL_OP]",out_tr.convert2string() , UVM_MEDIUM)
          `uvm_info ("ERROR [EXPECTED_OP]",exp_tr.convert2string() , UVM_MEDIUM)
          `uvm_warning("ERROR",exp_tr.convert2string())
        end
        count++;
    end
  endtask
  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------
  function void report_phase(uvm_phase phase);
        super.report_phase(phase);
        if (VECT_CNT && !ERROR_CNT)
            `uvm_info("PASSED",$sformatf("*** TEST PASSED - %0d vectors ran, %0d vectors passed ***",
            VECT_CNT, PASS_CNT), UVM_LOW)

        else
            `uvm_info("FAILED",$sformatf("*** TEST FAILED - %0d vectors ran, %0d vectors passed, %0d vectors failed ***",
            VECT_CNT, PASS_CNT, ERROR_CNT), UVM_LOW)
  endfunction
  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------
  function void PASS();
    VECT_CNT++;
    PASS_CNT++;
  endfunction

  function void ERROR();
    VECT_CNT++;
    ERROR_CNT++;
  endfunction
  //----------------------------------------------------------------------------

endclass
 

sr_env


class sr_env extends uvm_env;

   //---------------------------------------------------------------------------
   `uvm_component_utils(sr_env)
   //---------------------------------------------------------------------------

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

  //-------------------- class handles -----------------------------------------
  sr_agent    agent_h;
  sr_coverage coverage_h;
  sr_scoreboard scoreboard_h;
  //----------------------------------------------------------------------------

  //---------------------- build phase -----------------------------------------
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    agent_h    = sr_agent::type_id::create("agent_h",this);
    coverage_h = sr_coverage::type_id::create("coverage_h",this);
    scoreboard_h = sr_scoreboard::type_id::create("scoreboard_h",this);
  endfunction
  //----------------------------------------------------------------------------

  //-------------------------- connect phase -----------------------------------
  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    agent_h.monitor_h.ap_mon.connect(coverage_h.analysis_export);
    // monitor to scoreboard connection
    agent_h.monitor_h.ap_mon.connect(scoreboard_h.aport_mon);
    // driver to scoreboard connection 
    agent_h.driver_h.drv2sb.connect(scoreboard_h.aport_drv);
  endfunction
  //----------------------------------------------------------------------------
endclass:sr_env

sr_test


class sr_test extends uvm_test;

    //--------------------------------------------------------------------------
    `uvm_component_utils(sr_test)
    //--------------------------------------------------------------------------

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

    sr_env env_h;
    int file_h;

    //--------------------------------------------------------------------------
    function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      env_h = sr_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
    //--------------------------------------------------------------------------

    //--------------------------------------------------------------------------
    function void start_of_simulation_phase(uvm_phase phase);
      $display("start_of_simulation_phase");
      file_h=$fopen("LOG_FILE.log","w");
      set_report_default_file_hier(file_h);
      set_report_severity_action_hier(UVM_INFO,UVM_DISPLAY+UVM_LOG);
      set_report_verbosity_level_hier(UVM_MEDIUM);
    endfunction
    //--------------------------------------------------------------------------

    //--------------------------------------------------------------------------
    task run_phase(uvm_phase phase);
        sr_sequence seq;
        sequence_1 seq1;
        sequence_2 seq2;
        sequence_3 seq3;
        phase.raise_objection(this);
            
            seq = sr_sequence::type_id::create("seq");
            seq1= sequence_1::type_id::create("seq1");
            seq2= sequence_2::type_id::create("se2");
            seq3= sequence_3::type_id::create("se3");

            seq.start(env_h.agent_h.sequencer_h);
            seq1.start(env_h.agent_h.sequencer_h);
            seq2.start(env_h.agent_h.sequencer_h);
            seq3.start(env_h.agent_h.sequencer_h);

            #10;
        phase.drop_objection(this);
    endtask
    //--------------------------------------------------------------------------

endclass:sr_test

tb_pkg


`ifndef TB_PKG
`define TB_PKG
`include "uvm_macros.svh"
package tb_pkg;
 import uvm_pkg::*;
 `include "sr_sequence_item.sv"        // transaction class
 `include "sr_sequence.sv"             // sequence class
 `include "sr_sequencer.sv"            // sequencer class
 `include "sr_driver.sv"               // driver class
 `include "sr_monitor.sv"              // monitor class
 `include "sr_agent.sv"                // agent class  
 `include "sr_coverage.sv"             // coverage class
 `include "sr_scoreboard.sv"           // scorebaord class
 `include "sr_env.sv"                  // environment class

 `include "sr_test.sv"                   // test1
 //`include "test2.sv"
 //`include "test3.sv"

endpackage
`endif 

top


`include "interface.sv"
`include "tb_pkg.sv"
module top;
  import uvm_pkg::*;
  import tb_pkg::*;
  

  //----------------------------------------------------------------------------
  intf i_intf();
  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------
  sr DUT(.s(i_intf.s),
         .r(i_intf.r),
         .q(i_intf.q),
         .qbar(i_intf.qbar)
        );
  //----------------------------------------------------------------------------               
  
  //----------------------------------------------------------------------------
  initial begin
    $dumpfile("dumpfile.vcd");
    $dumpvars;
  end
  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------
  initial begin
    uvm_config_db#(virtual intf)::set(uvm_root::get(),"","vif",i_intf);
  end
  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------
  initial begin
    run_test("sr_test");
  end
  //----------------------------------------------------------------------------
endmodule

Output : 


 Github              :  https://github.com

EdaplayGroung :  https://www.edaplayground.com

 

                   Thank you for reading have a nice day 😀😇.

Share:
Copyright © VLSI Verification Concepts . Designed by OddThemes