0% found this document useful (0 votes)
90 views

Functional UVM

This document discusses the Universal Verification Methodology (UVM) and provides guidelines for using UVM concepts for functional verification. It describes the canonical structure of UVM components and transactions, constructing the UVM component hierarchy, interfacing with the design-under-test, using UVM sequences, and using factories and configurations. The goal is to enable users familiar with Verilog or VHDL to become productive in UVM by learning a minimal set of coding idioms.

Uploaded by

bibo
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)
90 views

Functional UVM

This document discusses the Universal Verification Methodology (UVM) and provides guidelines for using UVM concepts for functional verification. It describes the canonical structure of UVM components and transactions, constructing the UVM component hierarchy, interfacing with the design-under-test, using UVM sequences, and using factories and configurations. The goal is to enable users familiar with Verilog or VHDL to become productive in UVM by learning a minimal set of coding idioms.

Uploaded by

bibo
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/ 7

International Journal of Electrical, Electronics and Data Communication, ISSN: 2320-2084 Volume-2, Issue-3, March-2014

REVIEW ON UNIVERSAL VERIFICATION METHODOLOGY (UVM)


CONCEPTS FOR FUNCTIONAL VERIFICATION
1
SIDDHARTH RAGHUVANSHI, 2VISWAJEET SINGH
1
Department of Electronics Engineering, BVCOE, Pune-43, Maharastra, India
E-mail: [email protected], [email protected]

Abstract- The main goal of functional verification in hardware design is to find out the bugs in design description given by
design engineers and to check the functionality of design whether the output matches with desired value or not and then
customize the design to get the desired functionality of DUT. Various verification techniques have been developed from past
few years to make the verification process much easier and user friendly. This paper presents a recent approach to using
UVM, the Universal Verification Methodology, for functional verification by mainstream users. The goal is to identify a
minimal set of concepts sufficient for constrained random coverage-driven verification in order to ease the learning
experience for engineers coming from a hardware design background who do not have extensive object-oriented
programming skills. We describe coding guidelines to address the canonical structure of UVM component and transaction,
the construction of the UVM component hierarchy, the interface with the design-under-test, the use of sequences, and the use
of the factory and configuration mechanisms. We also provide some key factors which allowed the user to migrate from
OVM to UVM for verification purpose.

Keywords- SystemVerilog, OVM, UVM, Functional verification.

I. INTRODUCTION construction of the UVM component hierarchy, the


interface with the design-under-test, the use of UVM
Todays traditional design flow involves design at sequences, and the use of the factory. Starting from
multiple levels of abstraction. As the design these simple guidelines, user can create constrained
implementation is refined and the verification vehicle random verification environments in an object-
changes, the test bench needs to adjust to abstractions oriented coding style that are fully compliant with the
from transaction-level simulation, and RTL UVM standard, and hence are interoperable with
simulation to hardware acceleration. But the UVM verification IP from other sources.
challenge is that separate verification components,
test benches, tests, and plans are developed by II. SYSTEMVERILOG AND UVM
separate teams at different abstraction levels. This
requires more expertise to learn and understand, more Over the past few years, constrained random
code to develop and maintain, and larger teams to coverage-driven verification has been increasingly
fund and manage. adopted as the methodology-of-choice for simulation-
based functional verification to the point where it is
This paper provides an overview to use Universal widely used on the largest ASIC projects.
Verification Methodology (UVM) for functional SystemVerilog, as the only industry standard
verification by mainstream users as opposed to highly hardware verification language supported every one
skilled verification specialists. It arises from of the three largest EDA vendors, has displaced its
SystemVerilog and UVM provide mechanisms to rival single-vendor solutions in many companies.
create verification components for checking,
coverage collection, and stimulus generation, and to But SystemVerilog is not without its problems.
modify the behaviour of those components for Although current SystemVerilog implementations are
specific tests. But SystemVerilog and UVM provide in many ways both mature and robust, SystemVerilog
more than this, so much more in fact that the learning remains under-specified as a language.
curve can be daunting for non-specialists.
SystemVerilog was an extremely ambitious
The goal of this paper is to enable the user with standardization project that was undertaken prior to
experience in Verilog or VHDL to become the development of any complete proof-of-concept
productive in UVM by learning a small number of implementation, and as a result the IEEE 1800
new coding idioms, selected to minimize the SystemVerilog Language Reference Manual still has
conceptual clutter they have to deal with. As users many areas of ambiguity, and more than one of the
become fluent with this set of basic idioms, they can major implementations has significant gaps. The
then branch out to embrace the full feature set of simulation tool vendors themselves are in the
UVM as and when they need. We describe coding unenviable position of having to invest significant
guidelines to address the canonical structure of a engineering resources in trying to pin down and
UVM component and a UVM transaction, the implement a very complex language against an

Review on Universal Verification Methodology (UVM) Concepts for Functional Verification


101
International Journal of Electrical, Electronics and Data Communication, ISSN: 2320-2084 Volume-2, Issue-3, March-2014

ambiguous definition, and so take the very reasonable constrained random verification methodology
position of prioritizing their implementation choices because they enable reuse, yet these techniques are
according to customer demand. amongst the hardest to learn. OO techniques allow
verification components to be specialized to the needs
Nevertheless, certain areas of the SystemVerilog of a specific test bench or test without modifying
language do stand out as being well-defined and their source code and enables well-structured
consistently implemented across all the major communication between those components using
simulators. These include: function calls. We wanted to provide some of the
The concise RTL features such as ANSI- expressive power of the OO paradigm without getting
style port and parameter declarations, drawn into the full set of issues involved in OO
always_comb, always_ff, unique, priority, programming. In UVM, the class is used as a
and the abbreviated port connection syntax container to represent components, transactions,
C-like control constructs such as for, sequences, tests, and configurations. Let's take the
foreach, do-while, break, continue, return component. Unlike the VHDL design entity or the
SystemVerilog module, a component represents an
C-like data type features such as typedef,
abstraction across a whole family of possible
enum, struct, and the 2-valued integer types
structural building blocks. A component picks out
VHDL-like package and import features what is common across several such building blocks,
Classes and the features for constraints and but a component is not concrete, meaning that it is
functional coverage based thereon not the final once-and-for-all definition of the thing.
The class-based data types, namely strings, A VHDL design entity or a SystemVerilog module
queues, dynamic arrays and associative can describe a family of related components, but only
arrays if the variants are anticipated in advance and are
Interfaces and virtual interfaces sufficient explicitly captured in the source code by means of
for communication between classes and language features such as generic parameters and
modules generate statements. Because it is a class, a UVM
component can be extended after-the-fact in arbitrary
One reason that the features from the above list have ways. An extension can add new features or can
been implemented so thoroughly and consistently is modify existing features. In particular, we require this
that, with the exception of the concise RTL features, extension capability so that a test can extend a
they have been widely used to create the libraries of transaction or a sequence in order to add constraints,
base classes that underpin the functional verification and then use the factory mechanism to override the
methodologies AVM, URM, VMM, OVM, and now generation of those transactions or sequences.
UVM. Customer demand has pushed the EDA
vendors to support each others' methodology class IV. UVM CONCEPTS
libraries, which in turn has driven the
implementations to converge on a common The goal of this paper is to identify a minimal set of
understanding of the features and semantics of class- concepts sufficient for constrained random coverage-
based SystemVerilog. driven verification in order to ease the learning
experience for engineers coming from a hardware
SystemVerilog and UVM now form a virtuous circle. design background who do not have extensive object-
The class-based SystemVerilog features that support oriented programming skills. At the same time, we
constrained random verification are sufficiently well- did not want to strip down the conceptual framework
defined and well-implemented to allow the to the point where it lost all the expressive power of
development of robust and portable verification class the object-oriented paradigm. Some other attempts to
libraries, and the widespread use of those libraries present verification class libraries to hardware
ensures the ongoing support of the necessary designers have ended up doing little more than re-
language features by the tool vendors. In addition to present the semantics of VHDL or Verilog using
the Verilog-like and C-like features of classes, which was a pitfall we wished to avoid. In
SystemVerilog, we make use of classes, constraints, our experience, hardware designers moving to a new
covergroups, packages, interfaces and virtual language for verification, SystemVerilog in this case,
interfaces. UVM makes heavy use of type do indeed want to benefit from the increased
parameterization to classes, and fortunately all of the expressive power and flexibility afforded by a new
major simulator implementations now agree on the paradigm.
semantics in this area.
Our conceptual vocabulary is listed below. These
terms are elaborated later in the paper, and expanded
III. OBJECT ORIENTED CONCEPT definitions can be found in the documentation
accompanying the UVM distribution.
Object-oriented (OO) or aspect-oriented
programming concepts are key to contemporary Component a structural building block,
conceptually equivalent to a Verilog module
Review on Universal Verification Methodology (UVM) Concepts for Functional Verification
102
International Journal of Electrical, Electronics and Data Communication, ISSN: 2320-2084 Volume-2, Issue-3, March-2014

Transaction a bundle of data items, which verification environment, so has a standard structure
may be distributed over time and space in and conventions for how it can be customized.
the system, and which form a Components are created quasi-statically at the start of
communication abstraction such as a simulation.
handshake, bus cycle, or data packet
Sequence an ordered collection of Here is a skeleton component. The
transactions or of other sequences uvm_component_utils macro and the function new
should be treated as boilerplate code and written
Phase execution is subdivided into various
exactly as shown.
predefined phases that permit components to
agree on when to build components, connect
Class my_comp extends uvm_component;
ports, run simulation, and so forth
`uvm_component_utils(my_comp)
Factory a function call that returns a function new(string name, uvm_component parent);
component, transaction, or sequence, the super.new(name, parent);
type of which may be overridden from a test endfunction
Port and export connection points for ...
transaction-level communication between Endclass
components
Generation the creation of components, B. Transactions
transactions, or sequences, where the Transactions are the basic data objects that are passed
properties of each may be set between components. In contrast to VHDL signals
deterministically or at random under the and Verilog wires, transactions represent
control of constraints communication at an abstract level. In order to drive
Test a top-level component, which drives stimulus into the DUT, a so-called driver component
generation converts transactions into pin wiggles, while a so-
Configuration an object associated with a called monitor component performs the reverse
component which may be set or randomized operation, converting pin wiggles into transactions.
by a test and which it is used to configure Here is a skeleton transaction. Again, the
that component as the component hierarchy uvm_object_utils macro and function new should be
is built treated as boilerplates.
Sequencer a component that runs class my_tx extends uvm_sequence_item;
sequences and that sends transactions `uvm_object_utils(my_tx)
generated by those sequences downstream to function new (string name = "");
another sequencer or to a driver super.new(name);
endfunction
Driver a component that receives
...
transactions from a sequencer and that drives
Endclass
the signal-level interface of the Design
Under Test (DUT)
C. Phase
Monitor a component that senses the Every component implements the same set of phases,
signal-level interface of the DUT and that which are run in a predefined order during simulation
sends transactions to the verification in order to synchronize the behaviour of the
environment components. When compared with VHDL or Verilog,
Coverage functional coverage information UVM provides rather more temporal structure within
can be collected using SystemVerilog cover a simulation run. The standard phases are as follows:
groups within a component
Checking functional correctness of the 1. build create child component instances
DUT can be checked using either procedural 2. connect connect ports to exports on the
code within a component or SystemVerilog child components
assertions within an interface 3. End of elaboration housekeeping
4. Start of simulation housekeeping
A. Components 5. run runs simulation
Components are used to build a component hierarchy, 6. extract post-processing
conceptually very similar to the design hierarchy in 7. check post-processing
VHDL or the module hierarchy in Verilog. In this 8. report post-processing
case the component hierarchy is part of the
verification environment rather than the design, and Each phase is represented by a function within the
components represent stimulus generators, drivers, component, except for run, which is a task because it
monitors, coverage collectors, and checkers. The alone consumes simulation time. If a function is
component represents the reusable unit of the absent, that component will be inactive in the given
phase.
Review on Universal Verification Methodology (UVM) Concepts for Functional Verification
103
International Journal of Electrical, Electronics and Data Communication, ISSN: 2320-2084 Volume-2, Issue-3, March-2014

As you can infer from the above list, the primary function void build; // Build phase
distinction amongst the phases is between the phases super.build();
for building the component hierarchy, connecting the // Factory calls to create child components
ports, and running simulation, with additional b = B::type_id::create("b", this);
housekeeping phases pre-pended and appended to the c = C::type_id::create("c", this);
simulation phase. endfunction
...
D. Sequences Endclass
Sequences are assembled from transactions and are
used to build realistic sets of stimuli. A sequence F. Port and export
could generate a specific pre-determined set of Ports and exports are analogous to ports in VHDL or
transactions, a set of randomized transactions, or Verilog, but are used for transaction-level
anything in between. Sequences can run other communication rather than signal-level
sequences, possibly selecting which sequence to run communication. A component can send out a
at random. Sequences can be layered such that transaction out through a port, or receive an incoming
higher-level sequences send transactions to lower- transaction through an export. Transactions are
level sequences in a protocol stack. passed as arguments to function calls, which may be
non-blocking (return immediately) or blocking
Here is a skeleton sequence. It is similar to a (suspend and wait for some event before returning),
transaction in outline, but the base class uvm which is sufficient for basic synchronization within
sequence is parameterized with the type of the the verification environment. All detailed timing
transaction of which the sequence is composed. Also information should be pushed down into the driver
every sequence contains a body task, which when it and monitor components that connect to the DUT so
executes generates those transactions or runs other that the timing can be determined by the DUT
sequences. interface, which is typically locked to low-level
class my_seq extends uvm_sequence #(my_tx); clocks and other synchronization signals. Within the
`uvm_object_utils(my_seq) verification environment, control flow radiates
function new (string name = ""); outward from the DUT, with drivers calling get to
super.new(name); request transactions from sequencers when they are
endfunction ready for further stimulus, and monitors calling write
task body; to distribute transactions around the verification
... environment for analysis.
endtask
... A call to get from a driver may block if the stimulus
endclass generator is coordinating its activities with some
Transactions and sequences together represent the other part of the verification environment. A call to
domain of dynamic data within the verification write from a monitor is not permitted to block,
environment. because the DUT cannot be stalled waiting for
analysis activity.
E. Factory
The UVM factory mechanism is an implementation The example below shows a component A containing
of the so-called factory pattern described in the OO two child components B and C. The connect function
literature. The UVM factory can make components, connects p_port of component B to q_export of
transactions, and sequences. Use of the factory component C.
enables the choice of object type to be overridden class A extends uvm_component;
from the test, although a given component, `uvm_component_utils(A)
transaction or sequence can only be overridden with B b; // Child component having p_port
one that extends the class of the original. This is one C c; // Child component having q_export
of the main mechanisms by which a reusable function new(string name, uvm_component parent);
verification component can be customized to the super.new(name, parent);
current environment. endfunction
function void build; // Build phase
Here is an example of a component creating child super.build();
components during the build phase: b = B::type_id::create("b", this);
class A extends uvm_component; c = C::type_id::create("c", this);
`uvm_component_utils(A) endfunction
B b; // Child component function void connect; // Connect phase
C c; // Child component b.p_port.connect( c.q_export );
function new(string name, uvm_component parent); endfunction
super.new(name, parent); endclass
endfunction
Review on Universal Verification Methodology (UVM) Concepts for Functional Verification
104
International Journal of Electrical, Electronics and Data Communication, ISSN: 2320-2084 Volume-2, Issue-3, March-2014

G. Generation endclass
Generation exploits SystemVerilog randomization // A SEQUENCE is generated dynamically
and constraints. Component generation occurs quasi- class my_seq extends uvm_sequence #(my_tx);
statically during the so-called build phase of UVM, `uvm_object_utils(my_seq)
when a component is able to access its configuration function new (string name = "");
object (if there is one) in order to control the super.new(name);
generation of lower-level components. This is endfunction
analogous to the elaboration phase in VHDL or task body;
Verilog. Sequence generation occurs dynamically. my_tx tx;
Control over the precise sequence of transaction that tx = my_tx::type_id::create("tx");
finally arrives at the DUT can be distributed across start_item(tx);
pre-defined sequence generation components and the assert( tx.randomize() );
test, which is able to extend and constrain existing finish_item(tx);
sequences. endtask
endclass
Here is an example showing transaction generation class my_test extends uvm_test;
within the body task of a sequence: `uvm_component_utils(my_test)
class my_seq extends uvm_sequence #(my_tx); ...
... my_env env;
task body; ...
my_tx tx; task run;
tx = my_tx::type_id::create("tx"); my_seq seq;
start_item(tx); // Create the sequence
assert( tx.randomize() with { cmd == 0; } ); seq = my_seq::type_id::create("seq");
finish_item(tx); // randomize it
... assert( seq.randomize() );
endtask // and start it on the sequencer
endclass seq.start( env.agent.sqr );
In the example above, the transaction is being endtask
constrained as it is randomized in order to set the endclass
value of the command field to a specific value before
sending the transaction downstream. The start_item A sequencer can also receive transactions from other
and finish_item functions synchronize with the sequencers. Here is an example of one that does just
component that is pulling transactions from the that:
sequencer, which could be a driver or another class ano_sqr extends uvm_sequencer #(ano_tx);
sequencer. start_item waits for the downstream `uvm_component_utils(ano_sqr)
component to request the transaction, finish_item uvm_seq_item_pull_port #(my_tx) seq_item_port;
waits for the downstream component to indicate that ...
it has finished with the transaction. For its part, the function void build;
downstream component calls get to fetch the seq_item_port = new("seq_item_port", this);
transaction and may call put if it needs to send back a endfunction
response endclass

H. Sequencer Conceptually, all that is happening here is that a


A sequencer is a variety of component that runs sequence, running on a sequencer, is pulling in
sequences and sends them downstream to drivers or transactions through a port on that sequencer. In order
to other sequencers. At its simplest a sequencer looks to do so, it needs direct access to the sequencer object
like any other component, except that it has an that it is running on, which is provided by the
implicit transaction-level export for connection to a predefined variable p_sequencer. Through
driver. p_sequencer, a sequence can refer to variables
declared within the sequencer class, including ports
We can now get a little more ambitious and show an and references to other external components.
example including sequence, sequencer, and It turns out that this coding trick is all that is needed
launching the sequence from the test: in order to have a sequence start child sequences on
another sequencer, that is, on a sequencer other than
// A SEQUENCER is a component
the one it is itself running on. Such a sequence is
class my_sqr extends uvm_sequencer #(my_tx);
called a virtual sequence because it does not itself
`uvm_component_utils(my_sqr)
generate transactions but instead controls the
function new(string name, uvm_component parent);
execution of other sequences, running on other
super.new(name, parent);
sequencers.
endfunction

Review on Universal Verification Methodology (UVM) Concepts for Functional Verification


105
International Journal of Electrical, Electronics and Data Communication, ISSN: 2320-2084 Volume-2, Issue-3, March-2014

I. Monitor my_tx tx;


A monitor is a variety of component that is confined seq_item_port.get(tx);
to having passive access to the signal-level interface // Wiggle pins of DUT
of the DUT. The monitor monitors traffic going to dut_vi.cmd = tx.cmd;
and from the DUT from which it assembles dut_vi.addr = tx.addr;
transactions which are distributed to the rest of the dut_vi.data = tx.data;
verification environment through one or more end
analysis ports. endtask
endclass
All of the necessary concepts have already been
discussed above. Here is an example: In the example above, the driver communicates with
class my_monitor extends uvm_monitor; the sequencer by means of the call get(tx) through the
`uvm_component_utils(my_monitor) implicit seq_item_port. Having got a transaction, it
uvm_analysis_port #(my_tx) aport; then drives the signal-level interface to the DUT by
virtual dut_if dut_vi; making assignments to the members of a
... SystemVerilog interface, which is done through the
task run; virtual interface dut_vi. The virtual interface is the
forever SystemVerilog language mechanism that is used to
begin pass data between structural Verilog modules and the
my_tx tx; class-based verification environment.
// Sense the DUT pins on a clock edge
@(posedge dut_vi.clock); The example above all shows how a configuration
tx = my_tx::type_id::create("tx"); object can be used to pass the virtual interface down
tx.cmd = dut_vi.cmd; to the driver during the build phase.
tx.addr = dut_vi.addr;
tx.data = dut_vi.data; K. Transaction operations
aport.write(tx); It is common to need to perform operations on
end transactions, operations such as printing out the
endtask contents of a transaction, making a copy of a
endclass transaction, or comparing two transactions for
equivalence. For example, the subscriber described
J. Driver above may wish to log the data from a transaction or
A driver is a variety of component that always sits compare a transaction from the DUT with another
downstream of a sequencer. The driver pulls transaction representing the expected behaviour.
transactions from its sequencer and controls the UVM provides a standard set of functions for
signal-level interface to the DUT. The transaction- purposes such as these, as illustrated below:
level interface between the sequencer and the driver Function void write(my_tx t);
is a fixed feature of UVM, and is unusual in the sense ...
that both the port and the export required for TL- my_tx tx;
communication are implicit. tx.copy(t)
history.push_back(tx);
class my_driver extends uvm_driver #(my_tx); if ( !t.compare(expected))
`uvm_component_utils(my_driver) uvm_report_error("mismatch",
virtual dut_if dut_vi; $sformatf("Bad transaction = %s",
function new(string name, uvm_component parent); t.convert2string()));
super.new(name, parent); endfunction
endfunction
function void build; Firstly, the copy function takes a complete copy of
super.build(); the transaction passed as an argument, in this case
begin storing the copy in a queue of past transactions.
uvm_object obj; Secondly, the compare function compares two
my_config config; different transactions for equivalence. Finally, the
get_config_object("config", obj, 0); convert2string function returns a string representing
assert( $cast(config, obj) ); the contents of the transaction in printable format.
dut_vi = config.dut_vi; The uvm_report_error function is one of several
end standard utility for message reporting.
endfunction
task run; There is more to a transaction than meets the eye. As
forever well as containing data fields representing properties
begin of the protocol being modeled, a transaction object

Review on Universal Verification Methodology (UVM) Concepts for Functional Verification


106
International Journal of Electrical, Electronics and Data Communication, ISSN: 2320-2084 Volume-2, Issue-3, March-2014

may contain housekeeping information such as return(status);


timestamps, logs, and diagnostics. This secondary endfunction
information typically needs to be treated differently endclass
when performing copy, compare, or convert2string
operations, and such differences need to be accounted Note that the behavior of copy and compare are
for by the user when declaring transaction classes. overridden by providing functions named do_copy
For example: and do_compare, respectively, as part of the
transaction class. Each function should exclude any
class my_tx extends uvm_sequence_item; housekeeping or diagnostic fields.
`uvm_object_utils(my_tx)
rand bit cmd; CONCLUSION
rand int addr;
rand int data; UVM is a rich and capable class library that has
... evolved over several years from much experience
function string convert2string; with real verification projects large and small, and
return $sformatf(...); SystemVerilog itself is a large and complex language.
endfunction As a result, although UVM offers a lot of powerful
function void do_copy(uvm_object rhs); features for verification experts, it can present a
my_tx rhs_; daunting challenge to Verilog and VHDL designers
super.do_copy(rhs); who want to start benefitting from test bench reuse.
$cast(rhs_, rhs); The guidelines presented in this paper aim to ease the
cmd = rhs_.cmd; transition from HDL to UVM.
addr = rhs_.addr;
data = rhs_.data; REFERENCES
endfunction
function bit do_compare(uvm_object rhs, [1] IEEE Std 1800-2009 IEEE Standard for System Verilog-
Unified Hardware Design, Specification, and Verification
uvm_comparer comparer);
Language,
my_tx rhs_; http://dx.doi.org/10.1109/IEEESTD.2009.5354441
bit status = 1;
[2] UVM 1.0 EA Class Reference,
status &= super.do_compare(rhs, comparer); http://www.accellera.org/activities/vip
$cast(rhs_, rhs);
status &= comparer.compare_field("cmd", cmd, [3] Universal Verification Methodology (UVM) draft 1.0
Users Guide [Beta/D6], January 15, 2011
rhs_.cmd, $bits(cmd));
status &= comparer.compare_field("addr", addr, [4] On-line resources from http://www.uvmworld.org/
rhs_.addr, $bits(addr)); [5] On-line resources from
status &= comparer.compare_field("data", data, http://www.doulos.com/knowhow/sysverilog/uvm/
rhs_.data, $bits(data));

Review on Universal Verification Methodology (UVM) Concepts for Functional Verification


107

You might also like