UVM Scoreboard

The Universal Verification Methodology (UVM) scoreboard is a crucial component in functional verification, enabling the verification of the design under test (DUT) by comparing expected and actual outputs. The expected outputs can come from a reference model or they can be golden reference values. A well-designed scoreboard ensures that the DUT behaves as intended under various test scenarios.

A user-defined scoreboard class is extended from uvm_scoreboard. uvm_scoreboard is inherited by uvm_component.

class <scoreboard_name> extends uvm_scoreboard;

Components of a UVM Scoreboard

  1. Analysis Port: Receives transactions from monitors or other components.
  2. Reference Model: Simulates the expected behavior of the DUT.
  3. Comparison Logic: Compares expected and actual outputs.
  4. Result Handling: Reports mismatches, errors, or pass conditions.

The communication between monitor and scoreboard will happen through TLM ports and exports.

Steps to Create a UVM Scoreboard

  1. Define the Scoreboard Class: Extend the uvm_scoreboard base class.
  2. Declare Analysis Ports: Use analysis ports to connect the scoreboard to monitors.
  3. Implement Data Comparison Logic: Write logic to compare received transactions.
  4. Override Functions: Customize behavior by overriding methods like build_phase and run_phase.
  5. Integrate into Environment: Connect the scoreboard to the UVM environment for end-to-end verification. The analysis Export of scoreboard is connected to monitor analysis port in UVM environment.
p_agnt.monitor.p_collect_port.connect(scb.p_collect_export);

Example: Writing a UVM Scoreboard

Design Under Test (DUT) Overview

Let’s consider a simple DUT: an Adder that takes two inputs (a and b) and produces their sum (sum).

Scoreboard Code

Below is an example of a UVM scoreboard for verifying the Adder DUT.

// Define a transaction class
class adder_transaction extends uvm_sequence_item;
  rand int a;
  rand int b;
  int sum; // Output from DUT
  
  `uvm_object_utils_begin(adder_transaction)
  `uvm_field_int(a,UVM_ALL_ON)
  `uvm_field_int(b,UVM_ALL_ON)
  `uvm_field_int(sum,UVM_ALL_ON)
  `uvm_object_utils_end
  
  // Constructor
  function new(string name = "adder_transaction");
    super.new(name);
  endfunction

endclass

// Scoreboard class
class adder_scoreboard extends uvm_scoreboard;
  // Analysis port for receiving transactions
  uvm_analysis_imp #(adder_transaction, adder_scoreboard) analysis_port;

  // Constructor
  function new(string name = "adder_scoreboard", uvm_component parent = null);
    super.new(name, parent);
    analysis_port = new("analysis_port", this);
  endfunction
  
  int expected_sum;   //Declaring expected sum for comparison

  // Reference model for adder
  function int ref_model(int a, int b);
    return a + b; // Simple adder functionality
  endfunction

  // Data comparison logic
  virtual function void write(adder_transaction trans);
    $display("SCB::Packet received - a=%0d, b=%0d, sum=%0d", trans.a, trans.b, trans.sum);

    // Calculate expected value using the reference model
    expected_sum = ref_model(trans.a, trans.b);

    // Compare DUT output with expected output
    if (trans.sum != expected_sum) begin
      `uvm_error("SCOREBOARD", $sformatf("Mismatch detected! a=%0d, b=%0d, DUT sum=%0d, Expected sum=%0d", trans.a, trans.b, trans.sum, expected_sum))
    end else begin
      `uvm_info("SCOREBOARD", $sformatf("Match: a=%0d, b=%0d, sum=%0d", trans.a, trans.b, trans.sum), UVM_MEDIUM)
    end
  endfunction

endclass