|HOME |ABOUT |ARTICLES |ACK |FEEDBACK |TOC |LINKS |BLOG |JOBS |


Tutorials



PHASE 8 SCOREBOARD


In this phase we will see the scoreboard implementation.

Scoreboard

Scoreboard is implemented by extending ovm_scorboard. For our requirement, we can use ovm_in_order_comparator, but we will see develop our own scoreboard by extending ovm_scorboard. Scoreboard has 2 analysis imports. One is used to for getting the packets from the driver and other from the receiver.  Then the packets are compared and if they don't match, then error is asserted. For comparison, compare () method of the Packet class is used.

Implement the scoreboard in file Scoreboard.sv.

Steps to create a scoreboard:
1) Useing macro `ovm_analysis_imp_decl(<_portname>), to declare ovm_analysis_imp_<_portname>  class.
2) The above macro, creates write_<_portname>(). This method has to be define as per our requirements.


1) Declare a scoreboard by extending ovm_scoreboard class.

class Scoreboard extends ovm_scoreboard;

endclass : Scoreboard

2) We need 2 import, one for expected packet which is sent by driver and received packet which is coming from receiver.
   Declare 2 imports using `ovm_analysis_imp_decl macros.

    `ovm_analysis_imp_decl(_rcvd_pkt)
    `ovm_analysis_imp_decl(_sent_pkt)

3)  Declare the utility macro.

   `ovm_component_utils(Scoreboard)

4) Declare a queue which stores the expected packets.

   Packet exp_que[$];

5) Declare imports for getting expected packets and received packets.

   ovm_analysis_imp_rcvd_pkt #(Packet,Scoreboard) Rcvr2Sb_port;
   ovm_analysis_imp_sent_pkt #(Packet,Scoreboard) Drvr2Sb_port;

6) In the constructor, create objects for the above two declared imports.

    function new(string name, ovm_component parent);
       super.new(name, parent);
       Rcvr2Sb_port = new("Rcvr2Sb", this);
       Drvr2Sb_port = new("Drvr2Sb", this);
    endfunction : new

7) Define write_sent_pkt() method which was created by macro `ovm_analysis_imp_decl(_sent_pkt).
   In this method, store the received packet in the expected queue.

   virtual function void write_sent_pkt(input Packet pkt);
       exp_que.push_back(pkt);
   endfunction : write_sent_pkt

8) Define write_rcvd_pkt() method which was created by macro `ovm_analysis_imp_decl(_rcvd_pkt)
  In this method, get the transaction from the expected queue and compare.

   virtual function void write_rcvd_pkt(input Packet pkt);
       Packet exp_pkt;
       pkt.print();
       if(exp_que.size())
       begin
           exp_pkt = exp_que.pop_front();
           exp_pkt.print();
           if( pkt.compare(exp_pkt))
               ovm_report_info(get_type_name(),
               $psprintf("Sent packet and reeived packet mathed"), OVM_LOW);
           else
               ovm_report_error(get_type_name(),
               $psprintf("Sent packet and reeived packet mismatched"), OVM_LOW);
       end
       else
           ovm_report_error(get_type_name(),
           $psprintf("No more packets in the expected queue to compare"), OVM_LOW);
   endfunction : write_rcvd_pkt

9) Define the report() method to print the Scoreboard information.

  virtual function void report();
      ovm_report_info(get_type_name(),
      $psprintf("Scoreboard Report %s", this.sprint()), OVM_LOW);
  endfunction : report

Complete Scoreboard Code
`ifndef GUARD_SCOREBOARD
`define GUARD_SCOREBOARD

`ovm_analysis_imp_decl(_rcvd_pkt)
`ovm_analysis_imp_decl(_sent_pkt)

class Scoreboard extends ovm_scoreboard;
    `ovm_component_utils(Scoreboard)
  
    Packet exp_que[$];
  
    ovm_analysis_imp_rcvd_pkt #(Packet,Scoreboard) Rcvr2Sb_port;
    ovm_analysis_imp_sent_pkt #(Packet,Scoreboard) Drvr2Sb_port;
  
    function new(string name, ovm_component parent);
        super.new(name, parent);
        Rcvr2Sb_port = new("Rcvr2Sb", this);
        Drvr2Sb_port = new("Drvr2Sb", this);
    endfunction : new
  
    virtual function void write_rcvd_pkt(input Packet pkt);
        Packet exp_pkt;
        pkt.print();

        if(exp_que.size())
        begin
           exp_pkt = exp_que.pop_front();
           exp_pkt.print();
           if( pkt.compare(exp_pkt))
             ovm_report_info(get_type_name(),
             $psprintf("Sent packet and reeived packet mathed"), OVM_LOW);
           else
             ovm_report_error(get_type_name(),  
             $psprintf("Sent packet and reeived packet mismatched"), OVM_LOW);
        end
        else
             ovm_report_error(get_type_name(),
             $psprintf("No more packets to in the expected queue to compare"), OVM_LOW);
   endfunction : write_rcvd_pkt
  
   virtual function void write_sent_pkt(input Packet pkt);
        exp_que.push_back(pkt);
   endfunction : write_sent_pkt
  
  
   virtual function void report();
        ovm_report_info(get_type_name(),
        $psprintf("Scoreboard Report %s", this.sprint()), OVM_LOW);
   endfunction : report
  
endclass : Scoreboard
`endif

Environment Class Updates

We will take the instance of scoreboard in the environment and connect its ports to driver and receiver ports.



1) Declare scoreboard object.

     Scoreboard Sbd;

2) Construct the scoreboard object using create() method in build() method.

        Sbd   = Scoreboard::type_id::create("Sbd",this);

3) In connect() method, connect the driver and receiver ports to scoreboard.

        Drvr.Drvr2Sb_port.connect(Sbd.Drvr2Sb_port);

        Rcvr[0].Rcvr2Sb_port.connect(Sbd.Rcvr2Sb_port);
        Rcvr[1].Rcvr2Sb_port.connect(Sbd.Rcvr2Sb_port);
        Rcvr[2].Rcvr2Sb_port.connect(Sbd.Rcvr2Sb_port);
        Rcvr[3].Rcvr2Sb_port.connect(Sbd.Rcvr2Sb_port);

Environemnt class code

`ifndef GUARD_ENV
`define GUARD_ENV

class Environment extends ovm_env;

    `ovm_component_utils(Environment)

     Sequencer Seqncr;
     Driver Drvr;
     Receiver Rcvr[4];

     Scoreboard Sbd;

    function new(string name , ovm_component parent = null);
        super.new(name, parent);
    endfunction: new

    function void build();
        super.build();
        ovm_report_info(get_full_name(),"START of build ",OVM_LOW);

        Drvr   = Driver::type_id::create("Drvr",this);
        Seqncr = Sequencer::type_id::create("Seqncr",this);
        
        foreach(Rcvr[i]) begin
            Rcvr[i]   = Receiver::type_id::create($psprintf("Rcvr%0d",i),this);
            Rcvr[i].id = i;
        end

        Sbd   = Scoreboard::type_id::create("Sbd",this);

        ovm_report_info(get_full_name(),"END of build ",OVM_LOW);
    endfunction
    
    function void connect();
        super.connect();
        ovm_report_info(get_full_name(),"START of connect ",OVM_LOW);

        Drvr.seq_item_port.connect(Seqncr.seq_item_export);

        Drvr.Drvr2Sb_port.connect(Sbd.Drvr2Sb_port);

        Rcvr[0].Rcvr2Sb_port.connect(Sbd.Rcvr2Sb_port);
        Rcvr[1].Rcvr2Sb_port.connect(Sbd.Rcvr2Sb_port);
        Rcvr[2].Rcvr2Sb_port.connect(Sbd.Rcvr2Sb_port);
        Rcvr[3].Rcvr2Sb_port.connect(Sbd.Rcvr2Sb_port);

        ovm_report_info(get_full_name(),"END of connect ",OVM_LOW);
    endfunction

endclass : Environment
`endif


Download the Source Code

ovm_switch_8.tar
Browse the code in ovm_switch_8.tar

Command to run the simulation

 vcs -sverilog +incdir+$OVM_HOME/src $OVM_HOME/src/ovm_pkg.sv +incdir+. rtl.sv interface.sv top.sv -R +OVM_TESTNAME=test1
 qverilog +incdir+$OVM_HOME/src $OVM_HOME/src/ovm_pkg.sv +incdir+. rtl.sv interface.sv top.sv -R +OVM_TESTNAME=test1


Log report after simulation

OVM_INFO @ 0 [RNTST] Running test test1...
OVM_INFO @ 0: ovm_test_top.t_env [ovm_test_top.t_env] START of build
OVM_INFO @ 0: ovm_test_top.t_env [ovm_test_top.t_env] END of build
OVM_INFO @ 0: ovm_test_top.t_env [ovm_test_top.t_env] START of connect
OVM_INFO @ 0: ovm_test_top.t_env [ovm_test_top.t_env] END of connect
----------------------------------------------------------------------
Name                     Type                Size                Value
----------------------------------------------------------------------
Seqncr                   Sequencer           -               Seqncr@14
  rsp_export             ovm_analysis_export -           rsp_export@16
  seq_item_export        ovm_seq_item_pull_+ -      seq_item_export@40
  default_sequence       string              19    ovm_random_sequence
  count                  integral            32                     -1
  max_random_count       integral            32                   'd10
  sequences              array               5                       -
    [0]                  string              19    ovm_random_sequence
    [1]                  string              23   ovm_exhaustive_sequ+
    [2]                  string              19    ovm_simple_sequence
    [3]                  string              23   Seq_device0_and_dev+
    [4]                  string              19    Seq_constant_length
  max_random_depth       integral            32                    'd4
  num_last_reqs          integral            32                    'd1
  num_last_rsps          integral            32                    'd1
----------------------------------------------------------------------
OVM_INFO @ 30: ovm_test_top.t_env.Drvr [ovm_test_top.t_env.Drvr]
            Start of reset_dut() method
OVM_INFO @ 70: ovm_test_top.t_env.Drvr [ovm_test_top.t_env.Drvr]
            End of reset_dut() method
OVM_INFO @ 70: ovm_test_top.t_env.Drvr [ovm_test_top.t_env.Drvr]
            Start of cfg_dut() method
OVM_INFO @ 110: ovm_test_top.t_env.Drvr [ovm_test_top.t_env.Drvr]  
            Port 0 Address 00
OVM_INFO @ 130: ovm_test_top.t_env.Drvr [ovm_test_top.t_env.Drvr]
            Port 1 Address 01
OVM_INFO @ 150: ovm_test_top.t_env.Drvr [ovm_test_top.t_env.Drvr]
            Port 2 Address 02
OVM_INFO @ 170: ovm_test_top.t_env.Drvr [ovm_test_top.t_env.Drvr]
            Port 3 Address 03
OVM_INFO @ 190: ovm_test_top.t_env.Drvr [ovm_test_top.t_env.Drvr]
            End of cfg_dut() method
OVM_INFO @ 210: ovm_test_top.t_env.Drvr [ovm_test_top.t_env.Drvr]
            Driving packet ...
OVM_INFO @ 590: ovm_test_top.t_env.Drvr [ovm_test_top.t_env.Drvr]
            Driving packet ...
OVM_INFO @ 610: ovm_test_top.t_env.Rcvr0 [ovm_test_top.t_env.Rcvr0]
            Received packet ...
OVM_INFO @ 610: ovm_test_top.t_env.Sbd [Scoreboard]
            Sent packet and reeived packet mathed
OVM_INFO @ 970: ovm_test_top.t_env.Drvr [ovm_test_top.t_env.Drvr]
           Driving packet ...
OVM_INFO @ 990: ovm_test_top.t_env.Rcvr0 [ovm_test_top.t_env.Rcvr0]
           Received packet ...
OVM_INFO @ 990: ovm_test_top.t_env.Sbd [Scoreboard]
            Sent packet and reeived packet mathed
OVM_INFO @ 1000: ovm_test_top.t_env.Sbd [Scoreboard]
           Scoreboard Report
----------------------------------------------------------------------
Name                     Type                Size                Value
----------------------------------------------------------------------
Sbd                      Scoreboard          -                  Sbd@52
  Drvr2Sb                ovm_analysis_imp_s+ -              Drvr2Sb@56
  Rcvr2Sb                ovm_analysis_imp_r+ -              Rcvr2Sb@54
----------------------------------------------------------------------


--- OVM Report Summary ---

** Report counts by severity
OVM_INFO :   21
OVM_WARNING :    0
OVM_ERROR :    0
OVM_FATAL :    0







Index
Introduction
Specification
Verification Plan
Phase 1 Top
Phase 2 Configuration
Phase 3 Environment N Testcase
Phase 4 Packet
Phase 5 Sequencer N Sequence
Phase 6 Driver
Phase 7 Receiver
Phase 8 Scoreboard

Report a Bug or Comment on This section - Your input is what keeps Testbench.in improving with time!





<< PREVIOUS PAGE

TOP

NEXT PAGE >>

copyright © 2007-2017 :: all rights reserved www.testbench.in::Disclaimer