UVM Test

In UVM, the test is the highest-level component that orchestrates the verification process. It’s responsible for configuring the environment, running sequences, and ultimately determining the success or failure of the verification effort. Understanding UVM tests is essential for creating and executing effective verification plans.

UVM Test Diagram

+----------------------+
|      UVM Test        |
+----------------------+
          |
          v
+----------------------+       +---------------------+
|    Environment       |       |     Sequence        |
+----------------------+       +---------------------+
          |                             |
          v                             v
+----------------------+       +---------------------+
|       Agent          |       | Transaction (Tx)   |
+----------------------+       +---------------------+
          |                             |
          v                             v
+----------------------+       +---------------------+
|      Driver          |       | Sequence Item (Tx) |
+----------------------+       +---------------------+
          |
          v
+----------------------+
|     Monitor          |
+----------------------+
          |
          v
+----------------------+
|   Scoreboard         |
+----------------------+
          |
          v
+----------------------+
|       DUT            |
+----------------------+

 

Key Responsibilities of a UVM Test:

  • Environment Instantiation: The test instantiates the environment, which contains all the agents, monitors, and other components needed for verification.
  • Test Configuration: The test configures the environment and its components based on the specific verification scenario. This might involve setting register values, configuring interfaces, or selecting specific sequences.
  • Sequence Execution: The test starts sequences that generate stimulus for the design under verification (DUV).
  • Test Control: The test controls the overall flow of the test, including setting timeouts, handling errors, and determining the test result.

Key Components of UVM Test

  1. Test Class: Inherits from uvm_test and configures the environment and test-specific sequences.
  2. Environment: A composite component containing agents, drivers, monitors, and scoreboards.
  3. Sequence: Defines a sequence of transactions for the test scenario.
  4. DUT (Design Under Test): The hardware design being verified.

 

Structure of a UVM Test:

A UVM test is a class that extends uvm_test. It typically contains the following key elements:

  1. \uvm_component_utils` Macro: This macro is essential for registering the test with the UVM factory and enabling other UVM features.  
  2. new() Constructor: The constructor is used to create an instance of the test.
  3. build_phase(): This phase is used to create and configure the environment and other components.  
  4. run_phase(): This phase is used to execute the test scenario, typically by starting sequences.

Diagram 1: Test and Environment Relationship

+---------+     +-------------+
| Test    |---->| Environment |
| (my_test)|     | (my_env)    |
+---------+     +-------------+
| build() |     |             |
| run()   |     |             |
+---------+     +-------------+

Example Code:

`include "uvm_macros.svh"

class my_test extends uvm_test;
  `uvm_component_utils(my_test)

  my_env env;

  function new(string name = "my_test", uvm_component parent = null);
    super.new(name, parent);
  endfunction

  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    env = my_env::type_id::create("env", this); // Create the environment
  endfunction

  virtual task run_phase(uvm_phase phase);
    uvm_sequence_base seq = new(); // Create a sequence
    phase.raise_objection(this);
    seq.start(env.agent.sequencer); // Start sequence on the agent's sequencer
    #100ns; //Example delay
    phase.drop_objection(this);
  endtask
endclass

Diagram 2: Test Class Structure

+-----------------+
| my_test         |
+-----------------+
| `uvm_component_|
|  utils(my_test) |
| env env;        |
| new()           |
| build_phase()   |
| run_phase()     |
+-----------------+

Test Selection and Execution:

Tests are selected and executed using the $uvm_root.run_test() function in the testbench top module. You can specify the test name as a string argument to run_test().

Example Testbench Top:

`include "uvm_macros.svh"

module testbench_top;
  import uvm_pkg::*;
  import my_test_pkg::*;

  initial begin
    run_test("my_test"); // Run the my_test test
  end
endmodule

Diagram 3: Test Selection in Testbench Top

+---------------------+
| Testbench Top       |
+---------------------+
| run_test("my_test")|----> Selects and runs my_test
+---------------------+

Command-Line Test Selection:

You can also select the test to run from the command line using the +UVM_TESTNAME option.

Example:

vcs +UVM_TESTNAME=another_test testbench_top.sv

Test Hierarchy:

Tests can be organized into a hierarchy, with base tests and derived tests. This allows you to create reusable test components and easily extend existing tests.  

class base_test extends uvm_test;
  // ... common test functionality ...
endclass

class extended_test extends base_test;
  // ... additional test functionality ...
endclass

Defining a UVM Test

1. Test Class

The test class is derived from uvm_test. It configures the environment and controls the execution flow of the test.

class my_test extends uvm_test;
  `uvm_component_utils(my_test)

  my_env env;

  function new(string name = "my_test", uvm_component parent = null);
    super.new(name, parent);
  endfunction

  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    env = my_env::type_id::create("env", this);
  endfunction

  task run_phase(uvm_phase phase);
    phase.raise_objection(this);
    // Start sequences here
    env.m_sequencer.start(my_sequence::type_id::create("my_seq"));
    phase.drop_objection(this);
  endtask
endclass

2. Environment

The environment contains the agents, drivers, monitors, and scoreboards, and sets up the testbench infrastructure.

class my_env extends uvm_env;
  `uvm_component_utils(my_env)

  my_agent agt;
  my_scoreboard scb;

  function new(string name = "my_env", uvm_component parent = null);
    super.new(name, parent);
  endfunction

  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    agt = my_agent::type_id::create("agt", this);
    scb = my_scoreboard::type_id::create("scb", this);
  endfunction
endclass

Benefits of UVM Test

  • Modularity: Organizes the testbench into manageable components.
  • Reusability: Promotes the reuse of test components across different projects.
  • Configurability: Allows for easy configuration and customization of the test environment.
  • Scalability: Facilitates the creation of complex verification environments.