Gayathri Report - Content
Gayathri Report - Content
Gayathri Report - Content
The prior objective of the study is to thoroughly analyze, comprehend, and validate
the operational capabilities of a five-stage pipelined MIPS processor. The design
being tested consists of a total of 16 instructions, which further have 49 variants,
along with 5 pipeline stages and a hazard unit. The verification of the design is
performed using Constrained Random Verification techniques to test the
functionality of each instruction. The System Verilog Unified Verification
Methodology (UVM) is utilized to implement these verification techniques.
The layered testbench is built using components and objects from the UVM
environment, utilizing object-oriented programming (OOP) for class constructs.
Constrained randomization is employed to control the values generated during
randomization, ensuring compliance with declared conditions. Interconnectedness
among components is established through virtual interfaces. The verification process
incorporates the concept of pipelining and automation, enabling parallel organization
of activities for increased efficiency.
The primary objective of this study is to analyze, comprehend, and verify the
functionality of a MIPS processor with a five-stage pipelined architecture. The design
includes 16 instructions with 49 variants, 5 pipeline stages, and a hazard unit, which
are all subjected to verification in this project. The Constrained Random Verification
technique is employed to test the functionality of each instruction. The implementation
of these verification techniques is carried out using the System Verilog Unified
Verification Methodology (UVM).
The role of the UVM driver is to accept discrete sequence item transactions from the
UVM sequence and propel them onto the DUV interface by means of a virtual
interface connection. It extends the UVM_driver base class and initiates new
transaction requests, driving signals to lower-level components to perform signal
activities at the pin level.
As a general practice, the instruction execution process can be categorized into five
stages, namely fetch, decode, execute, memory access, and write back, denoted by Fi,
Di, Ei, Mi, and Wi. These stages encompass various operations such as instruction
fetch from memory (IF), instruction decode and register read (ID), execution of
operation or calculation of address (EX), access to memory operand (MEM), and
writing the result back to the register (WB).
CHAPTER 2
LITERATURE REVIEW
2.1 Introduction
The study presents a hierarchical verification platform using the Universal Verification
Methodology (UVM) for a RISC-V System-on-Chip (SoC) at both module and system levels.
At the module level, constrained random stimuli are generated to support module function
testing. The article discusses the functional verification of the RISC-V SoC and provides a
UVM verification platform for system and module-level verification [2]. By vertically reusing
the module-level verification environment, the platform implements a bottom-up hierarchical
verification approach at the system level. This UVM-based verification platform addresses the
drawbacks of FPGA verification, such as longer cycle times, lower efficiency, limited
reusability, and difficulty in measuring coverage. It enhances the effectiveness of verification
and achieves the functional coverage objective.
The driver module is extended from the base class of uvm_driver. The driver receives
the signals from the sequencer by the commands get_next_item() and item_done() to
fetch data and complete fetching. The driver [6] collects the signals as input and gives
them to DUT as transactions and to the scoreboard for comparison. For the
transportation of the data from the static components to the dynamic module and vice
versa, the model of interfacing [7] is used. The debugging of the design would be
simpler by implementing constrained random verification [8]. The digital inputs from
the DUT are randomly chosen and are constrained to check if the specifications are
met.
Functional coverage and assertions [16] are two major concepts that are to be
considered while constructing a system Verilog and UVM environment. Functional
coverage depicts whether the functionality of the design is tested, and assertions check
how the design behaves. Rerunning the test cases is necessary each time the design is
modified. Regression [17] is the process of determining whether the test cases have
reappeared after rerunning. It is very crucial to execute the regression when the design
code is modified. To avoid the problem of interlocking, we will be stalling the pipeline
stages. To stall the pipeline stages and to avoid data hazards, the ALU forwarding unit
[18] is employed which forwards the ALU result to the upcoming instructions instead
of writing back to register. In the processor, there will be an array of registers called
register files which holds instructions needed by the processor to execute in the current
simulation cycle. Data hazards [19,20] occur when an instruction depends on a prior
instruction's outcome, but that result hasn't yet been computed, and data hazards occur.
if storage is used by two separate instructions. The location shall appear to be executed
systematically.
2.2 Limitations & Research Gap(s)
Identifying and extracting relevant information from the project perspective has been
challenging due to limited recent papers/articles in the specific project area.
Analyzing and interpreting the appropriate approach to address this issue has been
time-consuming, and additional research work has been considered to align with
current industry standards for the verification process.
CHAPTER 3
RESEARCH METHODOLOGY
3.1 Introduction
UVM provides users with an automated and flexible verification environment that can
be configured and reused. Verification components can be easily reused across
different environments and hierarchies, and the code can be modified without
disrupting the UVM base class. The UVM class library includes base classes, macros,
and utilities, which can be extended to enhance the System Verilog environment. UVM
has three major types of classes: UVM_object, UVM_component, and
UVM_transaction. UVM phases are essential to ensure synchronization and ordered
flow of testbench execution, including build_phase(), connect_phase(),
end_of_elaboration_phase(), start_of_simulation_phase(), run_phase(), extract_phase(),
check_phase(), report_phase(), and final_phase(), which are executed sequentially
throughout the simulation.
The field macros in UVM contribute to the automation mechanism for implementing
compare, copy, and print operations on objects. These macros operate on class
properties and allow users to register a component or an object with the factory,
enabling the requested object type to be returned when needed without implementing
custom functions for each class. The UVM factory allows the creation of objects
without specifying a particular class, thus allowing for the override of default objects
and data items in the testbench.
The UVM testbench architecture comprises various modules, including the Top
Module, Test, Environment, Scoreboard, Agent, Sequencer, Sequence, Monitor, and
Driver. The environment module is responsible for combining higher-level blocks,
such as the agent and scoreboard, while the UVM agent groups UVM blocks that are
related to a specific interface. The sequence item defines the signals that are generated
and driven to the DUT (Design Under Test) through the driver. The UVM Driver is
utilized to drive the signals from the sequence item into the DUT. The UVM Sequence
determines the order in which the stimulus should be generated and sent to the driver.
The UVM Sequencer is employed to transfer the signals generated in the sequence to
the driver. The environment module is also used to bundle the agent and scoreboard,
which are higher-level blocks in the UVM testbench. The UVM agent groups UVM
blocks that are specific to an interface. The sequence item defines the signals that are
generated and driven to the DUT through the driver. The UVM Driver is used to drive
the signals from the sequence items into the DUT. The UVM Sequence specifies the
order in which the stimulus should be generated and sent to the driver. The UVM
Sequencer is utilized to transfer the signals generated in the sequence to the driver.
Fig.1 UVM Testbench Architecture
In a pipelined system, the second instruction's fetch can occur simultaneously with the
first instruction's decode. This allows for multiple activities to take place in parallel,
with up to five instructions being processed at any given time. To achieve this, five
separate hardware units are required, each capable of performing its task concurrently
without interference. Information is passed from one unit to the next through storage
buffers, ensuring that all the necessary information is available to downstream stages as
the instruction progresses through the pipeline. It's important to note that if the stages
of the pipeline are not balanced, the speed-up may be less effective, as increased
throughput does not necessarily result in decreased latency (time for each instruction).
Interface registers, also known as latches or buffers, are used to hold intermediate
outputs between two stages of the pipeline.
Fig.2 MIPS Architecture
3.3.2 Interfacing
The interface construct is used to establish connections between a design and testbench.
It defines a named bundle of wires that encapsulates communication, and specifies
directional information such as module ports and timing information like clocking
blocks. An interface can contain parameters, constants, variables, functions, and tasks.
It can be instantiated hierarchically similar to a module, with or without ports.
One of the key advantages of using interfaces over traditional connections is the ability
to group multiple signals together and represent them as a single port. This allows for
passing a single port handle instead of dealing with multiple individual signals or ports.
Additionally, interface declaration is done once, and the handle can be passed across
modules or components, making addition or deletion of signals easier to manage.
Random variables are designed to receive random values during randomization. However,
in some cases, it may be necessary to exert control over the values assigned during
randomization. This can be achieved by using constraints. Constraints are written for
random variables in the form of constraint blocks, which are class members similar to tasks,
functions, and variables. Constraint blocks have unique names within a class and are
enclosed in curly braces {}. Constraints are expressions or conditions that constrain or
regulate the values of a random variable. They can be specified either within the class or
externally, similar to extern methods. An externally defined constraint block is referred to as
an extern constraint block.
3.3.4 MIPS Instruction set
It is crucial to manage most of the verification tasks, such as stimulus generation and
coverage data collection, at the transaction level, which aligns with the natural way of
thinking for verification engineers when validating a system. At the transaction level,
UVM offers a comprehensive array of communication channels and interfaces that
assist in interconnecting components. TLM models operate at a higher level of
abstraction, closely matching the level of abstraction at which verification engineers and
design engineers conceptualize the intended functionality. This simplifies model
development and enhances understanding for other engineers. In Transaction Level
Modeling (TLM), interaction between diverse modules or components is realized via
transaction objects. A TLM port characterizes a collection of methods (API) for a
specific connection, whereas the concrete realization of these methods is identified as
TLM exports.
GOAL 1: No Poverty
The UVM processor driver sends a request for a sequence item to the sequencer
through get_next_item(), once the sequencer authorizes the sequence, it transmits the
sequence item to the driver logic, which subsequently propels the sequence item into
the DUV. In UVM connect phase, we connect the sequencer to the driver. In the event
that a response is expected by the Sequence/Sequencer, the item_done (rsp) function is
invoked, leading to a refresh of the "rsp (response)" object handle in the FIFO
sequencer response. Response from the DUV is put into the driver and through the
sequencer get_response(rsp) is obtained in the UVM_sequence. The communication
from the sequencer to the driver is done by TLM ports where communication should
not be called through the component handle. It is necessary to have an intermediate
object to handle the communication as data packets between UVM components.
Fig.5 Driver Module Code Implementation
CHAPTER 6
RESULTS & DISCUSSION
Subsequently, when the design part of the processor code is implemented with the
testbench, the driver part is successfully verified by obtaining the UVM report
summary with severity counts of UVM_info (858), UVM_warning (1), UVM_error
(8), UVM_fatal (0). All the constrained random verification test cases are executed,
and all the cases were passed on to obtain the report counts by ID. It is observed that
the actual instruction, calculation, memory address, and register address passed are
matched with the respective expected results. The overall coverage report after the
simulation performed has given a cumulative summary of the coverage group with
design-based coverage and the weighted average as 100 percent (%).