0% found this document useful (0 votes)
27 views19 pages

Not Gate - UVM - TB - FLOWpdf

Uploaded by

angila rose
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
27 views19 pages

Not Gate - UVM - TB - FLOWpdf

Uploaded by

angila rose
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 19

VERIFICATION

WITH
NOT Gate Design
This NOT gate design is a simple combinational circuit that inverts the input
signal. There is no clock or reset involved, making the design straightforward
and purely combinational.

Specifications of the Design


Specification Details
Inputs in: 1-bit input signal
Outputs out: 1-bit output signal
Behavior Computes out = ~in
The output is the logical NOT (inversion) of the input signal

Testbench Architecture
Design.V

// Define the NOT gate module


module not_gate(
input in, // Input signal
output out // Output signal
);

// Assign the output as the logical negation of the input


// The '~' operator performs the bitwise NOT operation
assign out = ~in;

endmodule

Interface

// Define the interface not_if


interface not_if();
// Declare the signals in the interface
logic in; // Input signal for the DUT
logic out; // Output signal from the DUT
endinterface

not_if is an interface that bundles two signals, in and out, which are of type logic.
This interface would typically be used in a testbench or connected to a DUT where
in is an input and out is an output, perhaps for a simple NOT gate or similar logic.
Using an interface like this simplifies connections in complex designs and enhances
code readability by grouping related signals.
Sequence Item

// Define the seq_item class extending uvm_sequence_item


class seq_item extends uvm_sequence_item;

// Randomizable fields
rand bit in; // Input value to be randomized
bit out; // Output value to be used in the sequence item

// Constructor
function new(string name = "seq_item");
super.new(name); // Call the parent class constructor with the given name
endfunction

// UVM object utilities for sequence item


`uvm_object_utils_begin(seq_item)
// Register the fields for automatic reporting and recording
`uvm_field_int(in, UVM_ALL_ON) // Register the 'in' field with full
access for reporting
`uvm_field_int(out, UVM_ALL_ON) // Register the 'out' field with full
access for reporting
`uvm_object_utils_end

endclass

seq_item is a class that extends uvm_sequence_item, making it a part of the UVM


(Universal Verification Methodology) framework for verification.

• rand bit in; — A randomizable input field.


• bit out; — An output field, not randomizable.

The constructor new initializes the class by calling the parent class's constructor
with an optional name parameter.
uvm_object_utils_begin(seq_item) and uvm_object_utils_end — These macros
provide utilities for the seq_item class, such as factory registration and field
automation.
uvm_field_int(in, UVM_ALL_ON) and uvm_field_int(out, UVM_ALL_ON) — These
macros register the in and out fields for automatic reporting, recording, and
comparison, with full access.
This class represents a sequence item in UVM, typically used to generate stimuli for
verification purposes, with the ability to randomize input values and track outputs.
Sequence

// Define the base_seq class extending uvm_sequence with a parameterized type


seq_item
class base_seq extends uvm_sequence#(seq_item);
`uvm_object_utils(base_seq) // Macro to register the class with the UVM
factory

// Constructor
function new(string name ="base_seq");
super.new(name); // Call the parent class constructor
endfunction

// Task defining the sequence behavior


task body();
// Create an instance of the sequence item
req = seq_item::type_id::create("req");

// Start the sequence item and check for successful start


start_item(req);

// Randomize the sequence item and check for successful randomization


assert(req.randomize());

// Finish the sequence item, signaling completion


finish_item(req);
endtask

endclass

base_seq extends uvm_sequence with a parameterized type seq_item, making it a


UVM sequence designed to work with seq_item objects.
uvm_object_utils(base_seq) — Registers the base_seq class with the UVM factory for
object creation and management.
new(string name = "base_seq") — Initializes the class by calling the parent class
constructor with an optional name.
body() — Defines the behavior of the sequence:

o Creates an instance of seq_item.


o Starts the sequence item with start_item(req).
o Randomizes the item using req.randomize() and checks for success.
o Ends the sequence item with finish_item(req).

This class is used to define and execute a sequence of operations on seq_item objects,
including item creation, randomization, and management within the UVM sequence
framework.
Sequencer

// Define the sequencer class extending uvm_sequencer with a parameterized


type seq_item
class sequencer extends uvm_sequencer#(seq_item);
`uvm_component_utils(sequencer) // Macro to register the class with the UVM
factory

// Constructor
function new(string name="sequencer", uvm_component parent=null);
super.new(name, parent); // Call the parent class constructor with the
given name and parent
endfunction

// Build phase of the sequencer


function void build_phase(uvm_phase phase);
super.build_phase(phase); // Call the parent class build_phase method for
any necessary setup
endfunction

endclass

sequencer extends uvm_sequencer with a parameterized type seq_item, making it a


UVM sequencer designed to handle seq_item objects.

• uvm_component_utils(sequencer) — Registers the sequencer class with the UVM


factory for object creation and management.

• new(string name = "sequencer", uvm_component parent = null) — Initializes the


class with a name and an optional parent component.

• build_phase(uvm_phase phase) — Overrides the build_phase method to perform


any necessary setup during the build phase, and calls the parent class's
build_phase method.

This class sets up the sequencer component that manages the sequence of seq_item
transactions in a UVM testbench environment.
Driver

// Define the driver class extending uvm_driver with a parameterized type


seq_item
class driver extends uvm_driver#(seq_item);
`uvm_component_utils(driver) // Macro to register the class with the UVM
factory

// Virtual interface for communication with the DUT


virtual not_if vif;

// Constructor
function new(string name="driver", uvm_component parent=null);
super.new(name, parent); // Call the parent class constructor with the
given name and parent
endfunction

// Build phase of the driver


function void build_phase(uvm_phase phase);
super.build_phase(phase); // Call the parent class build_phase method

// Check if the virtual interface (vif) is correctly set in the UVM


configuration database
if (!uvm_config_db#(virtual not_if)::get(this, "", "vif", vif)) begin
// Report a fatal error if the virtual interface is not set
`uvm_fatal(get_type_name(), "Virtual interface not set on top level")
end
endfunction

// Run phase of the driver


task run_phase(uvm_phase phase);
seq_item req; // Sequence item to be driven
forever begin
// Get the next sequence item from the sequencer
seq_item_port.get_next_item(req);

/* Uncomment the following checks if needed:


// Check if the received item is null
if (req == null) begin
`uvm_fatal(get_type_name(), "Received null item from sequencer.")
end

// Check if the virtual interface is null


if (vif == null) begin
`uvm_fatal(get_type_name(), "Virtual interface (vif) is not set.")
end
*/

// Log the input value of the sequence item


`uvm_info(get_type_name(), $sformatf("IN = %0d", req.in), UVM_LOW);

// Drive the value onto the DUT via the virtual interface
vif.in <= req.in;
// Indicate that the item has been processed
seq_item_port.item_done();

// Small delay to avoid simulation lockups


#1ns;
end
endtask

endclass

driver extends uvm_driver with a parameterized type seq_item, designed to drive


transactions of type seq_item onto the Design Under Test (DUT).

• uvm_component_utils(driver) — Registers the driver class with the UVM factory


for object creation and management.

• virtual not_if vif — Defines a virtual interface to interact with the DUT.

• new(string name = "driver", uvm_component parent = null) — Initializes the driver


with a name and an optional parent component.

• build_phase(uvm_phase phase) — Checks if the virtual interface is properly set


in the UVM configuration database. Reports a fatal error if not.

• run_phase(uvm_phase phase) — Continuously fetches sequence items from the


sequencer, logs the input value, drives the value onto the DUT through the virtual
interface, and marks the item as done. Includes a small delay to prevent
simulation lockups.

This class drives sequence items onto the DUT and performs necessary checks and
logging to ensure correct operation.
Monitor

// Define the monitor class extending uvm_monitor


class monitor extends uvm_monitor;
`uvm_component_utils(monitor) // Macro to register the class with the UVM
factory

// Virtual interface to connect with the DUT


virtual not_if vif;

// Analysis port to send monitored items to the scoreboard


uvm_analysis_port#(seq_item) item_collect_port;

// Sequence item to hold monitored data


seq_item mon_item;

// Constructor
function new(string name="monitor", uvm_component parent=null);
super.new(name, parent); // Call the parent class constructor with the
given name and parent
item_collect_port = new("item_collect_port", this); // Create a new
analysis port for sending data
endfunction

// Build phase of the monitor


function void build_phase(uvm_phase phase);
super.build_phase(phase); // Call the parent class build_phase method

// Check if the virtual interface is correctly set


if (!uvm_config_db#(virtual not_if)::get(this, "", "vif", vif)) begin
`uvm_fatal(get_type_name(), "Virtual interface not set on top level")
// Report an error if vif is not set
end

// Initialize the sequence item for monitoring


mon_item = seq_item::type_id::create("mon_item");
endfunction

// Run phase of the monitor


task run_phase(uvm_phase phase);
forever begin
// Monitor and log input and output values from the DUT
mon_item.in <= vif.in; // Capture the input value from the DUT
`uvm_info(get_type_name(), $sformatf("IN = %0d", mon_item.in),
UVM_LOW); // Log the input value
mon_item.out <= vif.out; // Capture the output value from the DUT
`uvm_info(get_type_name(), $sformatf("OUT = %0d", mon_item.out),
UVM_LOW); // Log the output value

// Send the monitored item to the scoreboard


item_collect_port.write(mon_item);

// Small delay to avoid simulation lockups


#1ns;
end
endtask

endclass

monitor extends uvm_monitor and is used to observe and collect data from the DUT.

• uvm_component_utils(monitor) — Registers the monitor class with the UVM


factory.

• virtual not_if vif — Connects the monitor to the DUT for observing signals.

• uvm_analysis_port#(seq_item) item_collect_port — Sends monitored sequence


items to the scoreboard.

• seq_item mon_item — Holds the data being monitored.

• new(string name = "monitor", uvm_component parent = null) — Initializes the


monitor with a name and an optional parent component, and creates a new
analysis port.

• build_phase(uvm_phase phase) — Ensures the virtual interface is set correctly


and initializes the sequence item.

• run_phase(uvm_phase phase) — Continuously monitors input and output values


from the DUT, logs these values, sends the monitored data to the scoreboard,
and includes a small delay to prevent simulation lockups.

This class observes the DUT's signals, logs the values, and sends the data to the
scoreboard for further analysis and verification.
Agent

// Define the agent class extending uvm_agent


class agent extends uvm_agent;
`uvm_component_utils(agent) // Macro to register the class with the UVM
factory

// Declare member variables for the sequencer, driver, and monitor


sequencer seqr; // Sequencer component instance
driver drv; // Driver component instance
monitor mon; // Monitor component instance

// Constructor
function new(string name="agent", uvm_component parent=null);
super.new(name, parent); // Call the parent class constructor with the
given name and parent
endfunction

// Build phase of the agent


function void build_phase(uvm_phase phase);
super.build_phase(phase); // Call the parent class build_phase method

// Check if the agent is active before creating the sequencer and driver
if(get_is_active == UVM_ACTIVE) begin
// Create instances of the sequencer and driver components
seqr = sequencer::type_id::create("seqr", this);
drv = driver::type_id::create("drv", this);
end

// Create an instance of the monitor component (always created regardless


of active state)
mon = monitor::type_id::create("mon", this);
endfunction

// Connect phase of the agent


function void connect_phase(uvm_phase phase);
super.connect_phase(phase); // Call the parent class connect_phase method

// Connect the driver’s sequence item port to the sequencer’s sequence


item export
if(get_is_active == UVM_ACTIVE) begin
drv.seq_item_port.connect(seqr.seq_item_export);
end
endfunction

endclass
agent extends uvm_agent and acts as a container for the sequencer, driver, and
monitor components.

• uvm_component_utils(agent) — Registers the agent class with the UVM factory.

• sequencer seqr — Instance of the sequencer component.


• driver drv — Instance of the driver component.
• monitor mon — Instance of the monitor component.

• new(string name = "agent", uvm_component parent = null) — Initializes the agent


with a name and optional parent component.

• build_phase(uvm_phase phase) —
o Creates instances of the sequencer and driver only if the agent is active
(get_is_active == UVM_ACTIVE).
o Always creates an instance of the monitor.

• connect_phase(uvm_phase phase) —
o Connects the driver's sequence item port to the sequencer's sequence item
export if the agent is active.

The agent class sets up and manages the sequencer, driver, and monitor, ensuring
proper connections and creation based on the agent's active state.
Environment

// Define the env class extending uvm_env


class env extends uvm_env;
`uvm_component_utils(env) // Macro to register the class with the UVM
factory

// Declare member variables


agent agt; // Agent component instance
scoreboard sb; // Scoreboard component instance

// Constructor
function new(string name="env", uvm_component parent=null);
super.new(name, parent); // Call the parent class constructor
endfunction

// Build phase of the environment


function void build_phase(uvm_phase phase);
super.build_phase(phase); // Call the parent class build_phase method

// Create instances of the agent and scoreboard components


agt = agent::type_id::create("agt", this);
sb = scoreboard::type_id::create("sb", this);
endfunction

// Connect phase of the environment


function void connect_phase(uvm_phase phase);
super.connect_phase(phase); // Call the parent class connect_phase method

// Connect the monitor's item collection port to the scoreboard's item


collection export
agt.mon.item_collect_port.connect(sb.item_collect_export);
endfunction

endclass

env extends uvm_env and represents the test environment that includes components
like the agent and scoreboard.

• uvm_component_utils(env) — Registers the env class with the UVM factory.

• agent agt — Instance of the agent component.


• scoreboard sb — Instance of the scoreboard component.

• new(string name = "env", uvm_component parent = null) — Initializes the


environment with a name and optional parent component.

• build_phase(uvm_phase phase) — Creates instances of the agent and scoreboard


components.
• connect_phase(uvm_phase phase) — Connects the monitor's item collection port
(item_collect_port) from the agent to the scoreboard's item collection export
(item_collect_export).

The env class sets up the test environment by instantiating and connecting the agent
and scoreboard, facilitating the overall testbench structure.

Scoreboard

// Define the scoreboard class extending uvm_scoreboard


class scoreboard extends uvm_scoreboard;
`uvm_component_utils(scoreboard) // Macro to register the class with the
UVM factory

// Analysis import port to receive monitored sequence items


uvm_analysis_imp #(seq_item, scoreboard) item_collect_export;

// Constructor
function new(string name="scoreboard", uvm_component parent=null);
super.new(name, parent); // Call the parent class constructor with the
given name and parent
item_collect_export = new("item_collect_export", this); // Create a new
analysis import port for receiving data
endfunction

// Build phase of the scoreboard


function void build_phase(uvm_phase phase);
super.build_phase(phase); // Call the parent class build_phase method
endfunction

// Method to process and check received sequence items


function void write(seq_item req);
$display("-------------------------------------------");

// Compare the received output with the expected value


if (req.out == ~req.in) begin
// Log a match if output is the bitwise negation of input
`uvm_info(get_type_name(), $sformatf("MATCH IN=%0d, OUT=%0d", req.in,
req.out), UVM_LOW);
end else begin
// Log a mismatch if the comparison fails
`uvm_info(get_type_name(), $sformatf("NOT MATCH IN=%0d, OUT=%0d",
req.in, req.out), UVM_LOW);
end

$display("-------------------------------------------");
endfunction

endclass
scoreboard extends uvm_scoreboard and is responsible for comparing and verifying
the DUT's output against expected values.

• uvm_component_utils(scoreboard) — Registers the scoreboard class with the


UVM factory.

• uvm_analysis_imp #(seq_item, scoreboard) item_collect_export — Analysis import


port to receive monitored sequence items.

• new(string name = "scoreboard", uvm_component parent = null) — Initializes the


scoreboard with a name and optional parent component. Creates the
item_collect_export port for receiving data.

• build_phase(uvm_phase phase) — Calls the parent class's build_phase method


for any necessary setup.

• write(seq_item req) —
o Receives a sequence item (req), checks if the output (req.out) matches the
bitwise negation of the input (req.in).
o Logs a message indicating whether the output matches the expected result
or not.

The scoreboard class is used to validate the correctness of the DUT's outputs by
comparing them with expected values and reporting results.
Test

`include "package.sv" // Include the package file containing class and


function definitions

// Define the base_test class, extending the uvm_test class


class base_test extends uvm_test;
`uvm_component_utils(base_test) // Macro to register the class with the UVM
factory

// Declare member variables


env env_o; // Environment object instance
base_seq bseq; // Sequence object instance

// Constructor
function new(string name="base_test", uvm_component parent=null);
super.new(name, parent); // Call the parent class constructor
endfunction

// Build phase of the test


function void build_phase(uvm_phase phase);
super.build_phase(phase); // Call the parent class build_phase method

// Create an instance of the environment component


env_o = env::type_id::create("env", this);
endfunction

// Run phase of the test


task run_phase(uvm_phase phase);

// Raise an objection to prevent the test from ending


phase.raise_objection(this);

// Create an instance of the sequence


bseq = base_seq::type_id::create("bseq");

// Repeat the sequence execution 5 times with a 5-time unit delay between
each
repeat(5) begin
#5; // Wait for 5 time units
bseq.start(env_o.agt.seqr); // Start the sequence using the sequence
driver
end

// Drop the objection to allow the test to end


phase.drop_objection(this);

// Print an informational message to the simulation log


`uvm_info(get_type_name(), "END OF TESTCASE", UVM_LOW);

endtask

endclass
base_test extends uvm_test and is used to set up and execute a test.

• uvm_component_utils(base_test) — Registers the base_test class with the UVM


factory.

• env env_o — Instance of the env class representing the environment.


• base_seq bseq — Instance of the base_seq class representing the sequence.

• new(string name = "base_test", uvm_component parent = null) — Initializes the


test with a name and optional parent component.

• build_phase(uvm_phase phase) — Calls the parent class's build_phase method


and creates an instance of the env component.

• task run_phase(uvm_phase phase) —


o Raises an objection to keep the test running.
o Creates an instance of the base_seq sequence.
o Executes the sequence 5 times with a 5-time unit delay between
executions.
o Drops the objection to allow the test to end.
o Logs an informational message indicating the end of the test case.

The base_test class is responsible for running a test by creating the environment,
executing a sequence multiple times, and managing the test's lifecycle.
Testbench Top

`include "uvm_macros.svh" // Include UVM macros for UVM functionalities


import uvm_pkg::*; // Import UVM package for UVM classes and methods

`include "interface.sv" // Include the definition of the interface


`include "base_test.sv" // Include the base test class definition

module tb_top;

// Instantiate the interface


not_if vif(); // Declare an instance of the interface not_if

// Instantiate the Device Under Test (DUT)


not_gate dut (
.in(vif.in), // Connect the input of the DUT to the input of the
interface
.out(vif.out) // Connect the output of the DUT to the output of the
interface
);

initial begin
// Set the interface instance in the UVM configuration database
// This allows the test to access the interface instance via the
config_db
uvm_config_db#(virtual not_if)::set(uvm_root::get(), "*", "vif", vif);
end

initial begin
// Run the testbench with the base test class
run_test("base_test");
end

endmodule

• uvm_macros.svh — Imports UVM macros for UVM functionalities.


• uvm_pkg::* — Imports the UVM package for UVM classes and methods.
• interface.sv — Includes the definition of the not_if interface.
• base_test.sv — Includes the definition of the base_test class.

• tb_top — The top-level testbench module.

• not_if vif(); — Declares an instance of the not_if interface.

• not_gate dut — Instantiates the not_gate module (Device Under Test) and
connects its ports to the vif interface.
• Initial Blocks:

• First Block: Sets the vif interface instance in the UVM configuration database
using uvm_config_db, allowing it to be accessed by the UVM test.
• Second Block: Runs the test using the base_test class.

The tb_top module sets up the test environment, connects the DUT to the interface,
and runs the base_test class to execute the testbench.

Package

// Include the definition of the sequence item class


`include "seq_item.sv" // Contains the seq_item class which defines the
sequence item structure

// Include the base sequence class definition


`include "base_seq.sv" // Contains the base_seq class which defines the
base sequence for test scenarios

// Include the sequencer class definition


`include "sequencer.sv" // Contains the sequencer class which is responsible
for driving sequences of items

// Include the driver class definition


`include "driver.sv" // Contains the driver class which drives sequence
items onto the DUT

// Include the monitor class definition


`include "monitor.sv" // Contains the monitor class which observes signals
and collects data

// Include the scoreboard class definition


`include "scoreboard.sv" // Contains the scoreboard class which checks the
correctness of the DUT's responses

// Include the agent class definition


`include "agent.sv" // Contains the agent class which bundles the
sequencer, driver, and monitor

// Include the environment class definition


`include "env.sv" // Contains the environment class which sets up and
connects the agent and other components

You might also like