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

Vcs Quickstart

Uploaded by

Faizan Gokak
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views

Vcs Quickstart

Uploaded by

Faizan Gokak
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 94

VCS® Testbench

Quick Start Guide


version Y-2006.06-SP1
April 2007

The Native Testbench technology in VCS is currently available to customers as part of a Early Access
program. Using these features requires additional LCA license features. Please contact
[email protected] for more details.

Comments?
E-mail your comments about this manual to
[email protected].
Copyright Notice and Proprietary Information
Copyright © 2006 Synopsys, Inc. All rights reserved. This software and documentation contain confidential and proprietary
information that is the property of Synopsys, Inc. The software and documentation are furnished under a license agreement and
may be used or copied only in accordance with the terms of the license agreement. No part of the software and documentation may
be reproduced, transmitted, or translated, in any form or by any means, electronic, mechanical, manual, optical, or otherwise,
without prior written permission of Synopsys, Inc., or as expressly provided by the license agreement.
Destination Control Statement
All technical data contained in this publication is subject to the export control laws of the United States of America.
Disclosure to nationals of other countries contrary to United States law is prohibited. It is the reader’s responsibility to
determine the applicable regulations and to comply with them.
Disclaimer
SYNOPSYS, INC., AND ITS LICENSORS MAKE NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH
REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
Registered Trademarks (®)
Synopsys, AMPS, Arcadia, C Level Design, C2HDL, C2V, C2VHDL, Cadabra, Calaveras Algorithm, CATS, CSim,
Design Compiler, DesignPower, DesignWare, EPIC, Formality, HSPICE, Hypermodel, iN-Phase, in-Sync, Leda, MAST,
Meta, Meta-Software, ModelAccess, ModelTools, NanoSim, OpenVera, PathMill, Photolynx, Physical Compiler,
PowerMill, PrimeTime, RailMill, Raphael, RapidScript, Saber, SiVL, SNUG, SolvNet, Stream Driven Simulator,
Superlog, System Compiler, Testify, TetraMAX, TimeMill, TMA, VCS, Vera, and Virtual Stepper are registered
trademarks of Synopsys, Inc.
Trademarks (™)
abraCAD, abraMAP, Active Parasitics, AFGen, Apollo, Apollo II, Apollo-DPII, Apollo-GA, ApolloGAII, Astro, Astro-Rail,
Astro-Xtalk, Aurora, AvanTestchip, AvanWaves, BCView, Behavioral Compiler, BOA, BRT, Cedar, ChipPlanner, Circuit
Analysis, Columbia, Columbia-CE, Comet 3D, Cosmos, CosmosEnterprise, CosmosLE, CosmosScope, CosmosSE,
Cyclelink, Davinci, DC Expert, DC Expert Plus, DC Professional, DC Ultra, DC Ultra Plus, Design Advisor, Design
Analyzer, Design Vision, DesignerHDL, DesignTime, DFM-Workbench, DFT Compiler, Direct RTL, Direct Silicon
Access, Discovery, DW8051, DWPCI, Dynamic-Macromodeling, Dynamic Model Switcher, ECL Compiler, ECO
Compiler, EDAnavigator, Encore, Encore PQ, Evaccess, ExpressModel, Floorplan Manager, Formal Model Checker,
FoundryModel, FPGA Compiler II, FPGA Express, Frame Compiler, Galaxy, Gatran, HDL Advisor, HDL Compiler,
Hercules, Hercules-Explorer, Hercules-II, Hierarchical Optimization Technology, High Performance Option, HotPlace,
HSPICE-Link, iN-Tandem, Integrator, Interactive Waveform Viewer, i-Virtual Stepper, Jupiter, Jupiter-DP, JupiterXT,
JupiterXT-ASIC, JVXtreme, Liberty, Libra-Passport, Library Compiler, Libra-Visa, Magellan, Mars, Mars-Rail, Mars-
Xtalk, Medici, Metacapture, Metacircuit, Metamanager, Metamixsim, Milkyway, ModelSource, Module Compiler, MS-
3200, MS-3400, Nova Product Family, Nova-ExploreRTL, Nova-Trans, Nova-VeriLint, Nova-VHDLlint, Optimum
Silicon, Orion_ec, Parasitic View, Passport, Planet, Planet-PL, Planet-RTL, Polaris, Polaris-CBS, Polaris-MT, Power
Compiler, PowerCODE, PowerGate, ProFPGA, ProGen, Prospector, Protocol Compiler, PSMGen, Raphael-NES,
RoadRunner, RTL Analyzer, Saturn, ScanBand, Schematic Compiler, Scirocco, Scirocco-i, Shadow Debugger, Silicon
Blueprint, Silicon Early Access, SinglePass-SoC, Smart Extraction, SmartLicense, SmartModel Library, Softwire,
Source-Level Design, Star, Star-DC, Star-MS, Star-MTB, Star-Power, Star-Rail, Star-RC, Star-RCXT, Star-Sim, Star-
SimXT, Star-Time, Star-XP, SWIFT, Taurus, Taurus-Device, Taurus-Layout, Taurus-Lithography, Taurus-Process,
Taurus-Topography, Taurus-Visual, Taurus-Workbench, TimeSlice, TimeTracker, Timing Annotator, TopoPlace,
TopoRoute, Trace-On-Demand, True-Hspice, TSUPREM-4, TymeWare, VCS Express, VCSi, Venus, Verification
Portal, VFormal, VHDL Compiler, VHDL System Simulator, VirSim, and VMC are trademarks of Synopsys, Inc.
Service Marks (SM)
MAP-in, SVP Café, and TAP-in are service marks of Synopsys, Inc.

SystemC is a trademark of the Open SystemC Initiative and is used under license.
ARM and AMBA are registered trademarks of ARM Limited.
All other product or company names may be trademarks of their respective owners.
Contents

About This Guide. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii


Audience . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . viii
Supporting Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . viii

1. Introduction

2. Using Basic Features in VCS to Verify Your Design


The FIFO Design Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-3
Verification Architecture. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-3
Testbench Files for FIFO Example . . . . . . . . . . . . . . . . . . . . . . . . 2-5
Basic Features and Constructs forTestbench in VCS . . . . . . . . . . 2-6
Program Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-6
Constrained Random Stimulus . . . . . . . . . . . . . . . . . . . . . . . . 2-7
Verification Expected Checks . . . . . . . . . . . . . . . . . . . . . . . . . 2-9
Special Synchronization Constructs and Features . . . . . . . . . 2-10
Assertions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-13
Comprehensive Code Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . 2-16

iii
Functional Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-18
Running the Test Case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-19
FIFO Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-21
Debug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-28
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-30

3. Using Advanced Features in VCS to Verify Your Design


Verification Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2
Advanced Constructs for Testbench and Design in VCS . . . . . . . 3-4
Basic SystemVerilog Object Oriented Constructs for Testbench 3-4
Objects, Declaration and Instantiation . . . . . . . . . . . . . . . . . . . 3-4
Encapuslation and Data hiding: . . . . . . . . . . . . . . . . . . . . . . . . 3-5
Inheritance and Polymorphism: . . . . . . . . . . . . . . . . . . . . . . . . 3-6
Interface Construct and Signal Connectivity . . . . . . . . . . . . . . 3-9
modports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-10
Virtual Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-11
Eliminating Race-Conditions in Synchronous Designs . . . . . . 3-13
Assertions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-32
Comprehensive Code Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . 3-33
Functional Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-33
Running the Testcase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-33
FIFO Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-34
Debug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-38

iv
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-40

Appendix A. The FIFO Design Block

Appendix B. Testbench Files and Structure


Files for Using Basic Features in VCS to Verify Your Design . . . . B-2
Files for Using Advanced Features in VCS to Verify Your Design. B-3

Appendix C. Verification IP
Assertion IP Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C-2
The VCS Verification IP (VIP) Library . . . . . . . . . . . . . . . . . . . . . . C-3

v
vi
About This Guide

The latest release of VCS X-2006.06 incorporates a number of new capabilities


that enable you to find more design bugs faster and achieve up to five times
faster verification performance. The new capabilities include:

• Extension of the Native Testbench (NTB) technology to incorporate support


for the SystemVerilog testbench solution
• The new Discovery Visual Environment (DVE) that supports all of VCS
advanced bug-finding technologies
• The new VCS Assertion IP Library, which includes protocol checkers for
industry standards such as AMBA™ 2 AHB/APB protocols and PCI®
interfaces
• Native SystemC language simulation and support.

About This Guide


vii
VCS X-2006.06 beta Quick Start Guide

Audience
This quick start guide consists of several chapters, and will introduce the features
used in testbench and verification development from basic to more advanced in
steps. We will add to these chapters in the future installation of this guide.
• Chapter 2 is intended for engineers experienced with either Verilog or VHDL
and are ready to use new standard languages such as SystemVerilog to
raise the quality and efficiency of their design and verification processes
through advanced constrained-random and functional coverage and
assertion verification. This guide assumes basic knowledge of hardware
design and verification.
• Chapter 3 builds on chapter 2 content and assumes basic understanding of
SystemVerilog as well as design verification experience with either Verilog
or VHDL. This chapter introduces high-level data abstraction such as class
and object oriented programming concepts in the context of VCS supported
mechanisms. New constructs for structured and layered testbench
development are introduced such as interfaces and encapsulation of drivers
and monitors.

Supporting Documentation
The VCS Document Navigator provides an interface to the documentation set.
The navigator is invoked on the command line as follows:
vcs -doc

About This Guide


viii
1
Introduction 1
Simulation based verification dominates the majority of the design
validation process. The task for design and verification engineers
together is to create an environment that stimulates the input to the
design and watches for errors by checking the output from the
design.

Today’s RTL design and verification teams use Verilog or VHDL


(hardware description languages) to set up the verification
environment for their designs, relying on directed test cases. With
this approach the design and verification teams’ success depends
on their ability to anticipate scenarios for test cases.

To improve the efficiency and comprehensiveness of verification,


VCS supports built-in features for constrained random verification,
and functional coverage.

1-1
With these built-in features, you can code valid constraints on data
and types of activities to stimulate the Design Under Test (DUT).
Once a constraint-random environment is setup, you need to debug
and validate the simulation results. You can also perform functional
coverage analysis to find areas that have not been verified.

The built-in coverage features in VCS provides both functional


coverage (stimulus coverage), and code coverage. You can find out
where you need to steer the stimulus by modifying constraints in the
verification environment. You can then develop directed tests to deal
with the areas of interest, which have not been covered yet.

The code-coverage capabilities are supported for Verilog, VHDL,


and mixed-language designs. The VCS unified coverage metrics,
which encompasses functional coverage, assertion coverage, and
code coverage, enables the merging of results from different kinds of
coverage across all tests in a regression suite. This enables project
engineers to measure the status of the verification process and its
completeness.

The VCS verification solution also provides assertions to help you


check design correctness throughout the design hierarchy as well as
on the boundary of the design, thus enhancing visibility into the
design by revealing bugs very close to the source. Ideally, as
designers write the RTL, they document assumptions about the rules
for interfaces to adjoining blocks and how the design is expected to
behave. This documentation is also useful for reuse. The
SystemVerilog assertions (SVA), fully supported in VCS, significantly
enhance the development process. The SVA Checker library that is
incorporated into VCS is also very useful in this process since you
can easily plug in pre-written and pre-verified checks to help you with
bug-finding.

Chapter 1: Introduction
1-2
For larger designs under test, such as SOC, and systems which use
industry standard protocols such as PCIExpress, Ethernet, etc.,
users will have access to pre-built and pre-verified verification
components (VIP) that are ready to plug into the testbench
environment. VCS also incorporates pre-built and pre-verified
assertion-based IPs (AIP) which provide protocol coverage and
checks for dynamic simulations.

In addition to these features, VCS includes an integrated graphical


debug environment specially engineered to work with all of VCS’s
advanced bug-finding. DVE enables easy access to design and
verification data along with an intuitive menu-driven environment.
The debug capabilities include features such as: tracing drivers,
waveform compare, schematic views, path schematics and support
for VCD+ binary dump format. The debugging visualizations also
provides mixed-HDL (SystemVerilog, VHDL and Verilog) language
debug support, as well as assertion tracing, to help automate the
manual tracing of relevant signals and sequences.

In the chapters that follow, we will demonstrate how you can use the
features of VCS to verify the FIFO block described in Appendix A.
You do not have to re-architect your environment to take advantage
of the new verification features of VCS. We will also show you how
you can incrementally use these features with your existing
environment.

In this quick start book we will introduce the reader to the testbench
and verification features in steps. Each chapter will introduce the
next set of advanced constructs starting from chapter 2 with basic
constructs. Chapter 3 will introduce high-level abstraction by
introducing object-oriented programing concepts and interfaces. The
readers will be introduced to the concept of structured and layered

1-3
testbench development using the advanced constructs supported in
VCS. This will be extended in the next chapters in the future editions
of this quickstart book.

Chapter 1: Introduction
1-4
2
Using Basic Features in VCS to Verify Your
Design 2
The purpose of this chapter of the quick start guide is to provide a
conciseintroduction to the basic SystemVerilog assertions,
SystemVerilog testbench constructs, DV, functional and code
coverage. A simple FIFO module is used to demonstrate how to
develop a verification environment using SystemVerilog testbench
constructs for constraints and coverage.

In this chapter, you will be introduced to the methodology, testbench


constructs and assertion technology used in constructing a
constrainted random verification environment. One of the major
advantages of the new features in VCS is the ability to create a
verification environment in a way that completely separates the
testbench, and its code, from the design under test (DUT). Creating
this type of structure for the testbench reduces the number of errors,
and reduces the time taken to debug both the testbench and the
design code. In this methodology, the connection to the DUT from

2-1
the testbench is through port and boundary connections, thus
avoiding unintended non-structured access to the DUT. The
SystemVerilog program block facilitates this separation. This
program block is similar to a module in Verilog, but is specifically
intended to distinguish between the testbench and the design code.
In general, using a SystemVerilog program block in this way, avoids
race conditions that are usually inherent in simulation tests. In
addition, components and verification specific code blocks such as
constraint blocks, functional coverage, random data variables, etc.,
are referenced within program blocks.

Chapter 2: Using Basic Features in VCS to Verify Your Design


2-2
The FIFO Design Block
The FIFO block that we want to verify is a synchronous
(Single-Clock) FIFO with static flags. It is fully parameterized and has
single-cycle push and pop operations. It also has empty, half-full,
and full flags, as well as parameterized almost full and almost empty
flag thresholds with error flags. (see Appendix A, “The FIFO Design
Block” on page A-1).

The next few sections provide guidelines and examples of how you
can use the basic features of VCS to verify the FIFO block. The
testbench and verification code will provide you with the steps to
simulate designs with the latest VCS. You can use this structure and
the code with your current design environment to increase the
number of test cases as well as create more complete and complex
routines for testing the DUT.

Verification Architecture
In this section, you will be introduced to the methodology, testbench
constructs and assertion technology used in constructing a
constrainted random verification environment. One of the major
advantages of the new features in VCS is the ability to create a
verification environment in a way that completely separates the
testbench, and its code, from the design under test (DUT). Creating
this type of structure for the testbench reduces the number of errors,
and reduces the time taken to debug both the testbench and the
design code. In this methodology, the connection to the DUT from
the testbench is through port and boundary connections, thus
avoiding unintended non-structured access to the DUT. The
SystemVerilog program block facilitates this separation. This
program block is similar to a module in Verilog, but is specifically

The FIFO Design Block


2-3
intended to distinguish between the testbench and the design code.
In general, using a SystemVerilog program block in this way, avoids
race conditions that are usually inherent in simulation tests. In
addition, components and verification specific code blocks such as
constraint blocks, functional coverage, random data variables, etc.,
are referenced within program blocks.

A typical design hierarchy is as follows.

Figure 2-1 Verification Hierarchy

Top-Level
Clock generator

Testbench DUT
(Program (Verilog/
Block) VHDL)

Here the top-level shell contains the clock generator which is passed
to the testbench and the DUT. The DUT can be either Verilog,
SystemVerilog or VHDL. The testbench contains the program block,
which has additional verification features.

Chapter 2: Using Basic Features in VCS to Verify Your Design


2-4
Figure 2-2 Verification Architecture

fifo_mwrite fifo_mread

m
a
DUT
i
l
(Verilog/VHDL)
b
o
x

queue fifo_check

Figure 2-2 is a high level view of the verification architecture. The


architecture contains three main tasks: fifo_mwrite(), fifo_mread(),
and fifo_check(), along with two reset tasks. The fifo_mwrite() task
generates random data to the DUT, and place the data in a queue.
The fifo_mread() task reads data from the DUT and sends the data
to a mailbox. The fifo_check() task compares the expected output
with the actual output for correctness.

Testbench Files for FIFO Example


Links to the testbench and design files are listed in Files for Using
Basic Features in VCS to Verify Your Design on page B-2.

Testbench Files for FIFO Example


2-5
Basic Features and Constructs forTestbench in VCS
This section describes a few of the constructs added in VCS as part
of SystemVerilog for testbench development. There are many
additional constructs and SystemVerilog features in VCS. For details
of all the SystemVerilog capabilities in VCS, refer to the documents
listed in the VCS Document Navigator.

Program Block
The program block is a SystemVerilog module that is specialized for
verification purposes. Verification objects like constraint blocks,
functional coverage, random signals, etc., which comprise the test
stimulus will be referenced within program blocks. A program block
contains the testbench components for a design. Usually the design
is created in an HDL, such as SystemVerilog, Verilog, or VHDL. The
program block allows you to create a well-defined boundary between
the testbench code and the design code.

The abstraction and modeling constructs simplify the creation and


maintenance of testbenches. The ability to instantiate and
individually connect each instance of a program enables their use as
generalized models.

Chapter 2: Using Basic Features in VCS to Verify Your Design


2-6
For example, the program block for the FIFO module looks like this:

program fifo_test (
rst_n,clk,data_in,data_out,push_req_n,pop_req_n,diag_n,empty,full,
almost_empty,almost_full,half_full,error);

output logic rst_n;


input clk;
output logic [15:0] data_in;
input [15:0] data_out;
output logic push_req_n,pop_req_n,diag_n;
input empty,full,almost_empty,almost_full,half_full,error;
// declarations
// instantiations
// tasks...
// initial block
endprogram

One thing to remember here is that the program block drives data to
the DUT’s input and reads data from the DUT’s output, so the port
directions will be opposite to those of the DUT.

The testbench code such as tasks and variables are placed in the
program block as described in the following section.

Constrained Random Stimulus


Constrained random stimulus generation is a powerful technique
that helps you verify your designs. You use it by describing a
complex set of constraints for the design. The VCS constraint solver
then finds a valid solution, and generates many tests from your
constraints set. This method is better than using hand-coded tests
because it is much faster than creating tests manually. More
importantly, VCS is able to generate tests that check for unexpected
behavior, which may not occur to you.

Let’s assume the FIFO word length or the data field is 16-bits. The
depth of the FIFO can be parameterized at the top. The other field is
called data_rate and it is 16 bits wide. The data_rate specifies how

Basic Features and Constructs forTestbench in VCS


2-7
fast data is written, and read, to, and from, the FIFO. A data_rate of
8 means that the respective operation (read or write) occurs every 8
clock cycles.

To generate random data for these two fields, you need to use the
keyword rand. This marks these signals as randomizable data
fields.

You also need to wrap the randomizable variables in a special type


of construct called a class. The full usage of a class is beyond the
scope of this guide. It is sufficient to indicate that in this case it is
used as a vehicle to create random data.

The data rate can take values between 1 and 1023. We do not want
to test out all combinations. We want to check cases for low, medium
and high data rates. We want to generate data rates between 1 and
8, 128 and 135, and 512 and 519. We can use the dist construct to
specify this as shown below.

Using the constraint construct you can define the required


constraints. The following code defines two classes, one for the write
operation and one for the read operation.

//////////////////////////////////////////
// Definition: Random Write Data Class
//////////////////////////////////////////
class random_write_data;
rand logic [`WIDTH-1:0] data [`DEPTH];
rand logic [15:0] data_rate;

constraint reasonable {
data_rate > 0;
data_rate dist { [1:8] := 10 , [128:135] := 10, [512:519]
:=1 } ;
}

endclass

Chapter 2: Using Basic Features in VCS to Verify Your Design


2-8
//////////////////////////////////////////
// Definition: Random Read Data Class
//////////////////////////////////////////
class random_read_data;
rand logic [15:0] data_rate;

constraint reasonable {
data_rate > 0;
data_rate dist { [1:8] := 10 , [128:135] := 10, [512:519]
:=1 } ;}
endclass

In this code, constraint is a keyword. Within this block, you can add
any and all necessary constraints. Also, on the dist line the number
after the “:=” specifies the weight. The highest data rate will occur
less frequently than the lower data rates.

You can now use this data_rate variable to test different read/write
data-rates of the FIFO. For very slow data rates, delay will have a
very large value, and for fast data rates, delay will have a low value.

Verification Expected Checks


It is very useful to check for correct behavior of the DUT from within
the testbench. VCS provides two mechanisms for doing this: the
assert and the expect constructs. You can use the assert construct
to check for behavior at the current simulation time, and the expect
construct to check for sophisticated behavior or many clock cycles.

The syntax for these constructs is as follows:

[label:] assert (expression) [action block] [else statement]


[label:] expect (property spec) [action block] [else statement]

For example, in the FIFO testbench, the fifo_reset_check() task


checks to see that the outputs of the DUT are reset correctly to
known values within a specified amount of time.

Basic Features and Constructs forTestbench in VCS


2-9
task fifo_reset_check();
$write("FIFO_RESET_CHECK: Task reset_check started \n");
//all reset signals must be at proper value
E1: expect(@(posedge clk) ##[0:2] fifo_test_top.dut.empty ===
1'b1);
A1: assert(fifo_test_top.dut.almost_empty == 1'b1);
A2: assert(fifo_test_top.dut.half_full == 1'b0);
A3: assert(fifo_test_top.dut.almost_full == 1'b0);
A4: assert(fifo_test_top.dut.full == 1'b0);
A5: assert(fifo_test_top.dut.error == 1'b0);
endtask

This task first checks that empty becomes asserted within the first
two clock cycles. If empty does not become asserted within two
cycles, VCS will issue a verification error as follows:

Error: "fifo_test.v", 94:


fifo_test_top.test.fifo_reset_check.E1: at time 350

All verification checks should have labels for ease of debugging. The
expect statement blocks the task from executing the next line of code
until the check is completed successfully or an error message is
issued. The next five lines of code immediately check that the other
output signals are properly set by the DUT. If they are not set
properly, VCS issues a verification error.

Special Synchronization Constructs and Features


SystemVerilog provides advanced synchronization and concurrency
control mechanisms through several constructs. You can use these
features to develop test cases and checkers which mimic the true
function of the design. For example, semaphores are constructs
which are used in bus arbitration mechanisms. Another construct is
mailbox, which is used as communication means for passing data
and information between running processes. In the FIFO example
we will use the mailbox construct to pass data to the checker routine.

Chapter 2: Using Basic Features in VCS to Verify Your Design


2-10
Mailbox
Mailbox is a communication mechanism for message passing and
exchange of data between processes. Conceptually, it acts like a
FIFO, and ensures race-free communication between processes. It
also manages access to the data by various processes.

In the FIFO example, you can use a mailbox to send data from the
FIFO read task to the checker. First you need to instantiate and
initialize the mailbox as follows:

mailbox mbox =new;

Next, in the fifo_read() task, you need to wait until there is data in the
FIFO, then pop a word off of the FIFO, and put it in the mailbox as
follows:

while (empty) @(posedge clk);


pop_req_n <= 1'b0;
mbox.put(data_out);
@(posedge clk);
pop_req_n <= 1'b1;

The mailbox has some built-in methods; we are using the put()
method to place data into the mailbox.

Now, the fifo_check() task reads from the mailbox, and checks the
expected data against the actual data. The statement that reads data
from the mailbox is as follows:

mbox.get(tempOut);

Queues and Arrays in SystemVerilog


A queue a data type, storage for sequence of data variables. Its size
can vary, by adding and deleting elements from the queue. Access
to all stored elements are provided, as well insertion and removal at
the beginning or at the end of the queue in SystemVerilog. A queue
is similar to unpacked array. Like arrays, you can access the

Basic Features and Constructs forTestbench in VCS


2-11
elements of a queue using an index You can concatenate or slice the
elements as well compare elements through operators.ot The FIFO
example uses a queue to store all the data generated from the
fifo_write() task. The fifo_check() task reads from the queue and
checks the expected results against the actual results. The
declaration of the queue is as follows:

logic [‘WIDTH-1:0] cdata[$];

The fifo_write code that uses the queue is as follows:

push_req_n <= 1'b0;


cdata.push_back(WRITE_DATA.data[j]);
data_in <= WRITE_DATA.data[j];
@(posedge clk);
push_req_n <= 1'b1;

The first line of code asserts the push control line of the FIFO. The
second line puts the data generated into the queue. The generated
data (WRITE_DATA) is described in the following sections.

Figure 2-3 Process and Thread Control Through Fork/Join

jo
in jo
in_any jo
in_no
n e

In the FIFO testbench, there is a FIFO checker that should always


be active, and waiting for data. The following code shows the
fifo_check() task:

Chapter 2: Using Basic Features in VCS to Verify Your Design


2-12
task fifo_check();
logic [WIDTH-1:0] tempIn;
logic [WIDTH-1:0] tempOut;
while (1)
begin
mbox.get(tempOut);
tempIn = cdata.pop_front();
assert(tempIn == tempOut);
end
endtask

When fifo_check() is called, it will continuously wait for data from the
mailbox (which implies data was read from the FIFO), and then
check the data against the expected output.

This task is called using the fork/join_none construct in the initial


block of the program code, which will start the while loop, and then
continue with the next line of code.

program fifo_test(....);
// declarations
// tasks
//...
initial begin : main_prog
// instantiation of objects
// ...
fork
fifo_check();
join_none
..
//
end : main_prog
endprogram : fifo_test

Assertions
Assertions help designers and verification teams to catch bugs
faster. With VCS, you can easily add assertions into your design to
check for correct design behavior. Using VCS, you can write

Assertions
2-13
sophisticated assertions from scratch, or you can use the built-in
Checker Library. VCS has a rich set of checkers in its library that you
can easily instantiate in your design to identify bugs.

For a full description of the Checker Library, please see the


SystemVerilog Checker Library Reference Manual. The checks in
the library include: one hot/cold, mutual exclusion, even/odd parity,
handshake, overflow, underflow, window, arbiter and many others.
The advantage of using the Checker Library is that it is pre-written,
pre-verified, and ready to be instantiated. Another advantage of
using the Checker Library is that it has comprehensive assertion
coverage built into each checker. It includes corner case coverage
and range coverage. So the checkers not only find bugs, but also
report on coverage holes in your design.

For our FIFO design example, the FIFO word size is 16 bits with a
depth of 128. We can use a FIFO assertion checker from the library.
Within the checker, there is a useful category value for enabling and
disabling assertions wih the same category value.

You can instantiate the FIFO assertion directly into either the Verilog
or the VHDL design. The assertion can also be put into a separate
file using the bind construct. This works for both Verilog and VHDL
blocks. Here is how you place an FIFO assertion checker into the
sample FIFO block design, with category level of 10:

In Verilog:

assert_fifo #(.depth(128), .elem_sz(16), .coverage_level_1(31),


coverage_level_2(0),
.coverage_level_3(31) )
SVA_FIFO_inst (clk, rst_n, !push_req_n, data_in,
!pop_req_n, data_out);

Chapter 2: Using Basic Features in VCS to Verify Your Design


2-14
In VHDL

SVA_FIFO_inst : assert_fifo
generic map (depth => 128, elem_sz => 16,
coverage_level_1 => 31,
coverage_level_2 => 0,
coverage_level_3 => 31)
port map(clk => TOP_CLOCK, reset_n => rst_n, enq => push_req,
enq_data => data_in, deq => pop_req, deq_data => data_out);

The FIFO checker checks for the following failure modes:

• assertion assert_fifo_overflow reports a failure when enqueue is


issued while the FIFO is full.
• assertion assert_fifo_underflow reports a failure when the
dequeue is issued, and the FIFO is empty at that time (and no
simultaneous enqueue with pass_thru is enabled).
• assertion assert_fifo_value_chk reports (
sva_v_q[sva_v_head_ptr] == deq_data)) as the failing
expression when there is a dequeue, the FIFO is not empty, and
the data does not correspond to the expected value. It will report
(enq_data == deq_data) as the failing expression if there is a
dequeue, and pass_thru is enabled (=1), otherwise if there is a
dequeue on an empty FIFO it is a failure.
• assertion assert_fifo_hi_water_chk reports a failure if the FIFO is
filled above the high-water mark.
The assertion coverage that is reported is as follows:

• cov_level_1_0 indicates there was an enqueue operation.


• cov_level_1_1 indicates there was a dequeue operation
• cov_level_1_2 indicates there were simultaneous enqueue and
dequeue operations

Assertions
2-15
• cov_level_1_3 indicates there was an enqueue followed
eventually by a dequeue.
• cov_level_2_0 reports which FIFO fill levels were reached at
least once.
• cov_level_3_0 indicates the high water mark was reached on an
enqueue.
• cov_level_3_1 indicates there were simultaneous enqueue and
dequeue operations on an empty queue.
• cov_level_3_2 indicates there were simultaneous enqueue and
dequeue operations on a full queue.
• cov_level_3_3 indicates that empty condition was reached on
dequeue.
• cov_level_3_4 indicates that full condition was reached on
enqueue

Comprehensive Code Coverage


VCS has built-in comprehensive code coverage for both Verilog and
VHDL designs. For full documentation, see the VCS Coverage
Metrics User Guide located at $VCS_HOME/doc/UserGuide.

The types of coverage are as follows:

• Line coverage reports which lines, statements, and blocks for any
instance/module of design were exercised during simulation.
• Condition coverage monitors values taken on by Boolean and
bitwise expressions, such as conditional expressions in if
statements, or conditional concurrent signal assignments.

Chapter 2: Using Basic Features in VCS to Verify Your Design


2-16
• Toggle coverage reports whether signals and signal bits had 0->1
and 1->0 transitions. A signal is considered fully covered if, and
only if, it toggled in both directions: 0->1 and 1->0.
• Finite State Machine (FSM) Coverage recognizes some portion
of sequential logic as an FSM, and reports which FSM states and
which state transitions (among all possible) were executed. FSM
coverage can tell which parts of the design are implemented as
FSMs and gives specific information (which other kinds of
coverage do not provide) on all possible sequences of state
transitions.
In order to enable code coverage in the simulation, the following
compile and runtime arguments are used with the -cm option:

• -cm coverage_type specifies the type of coverage to collect.


The coverage_type options are:

Option Enables

line statement (line) coverage

tgl toggle coverage

cond condition coverage

fsm FSM coverage

Any combination of coverage types can be enabled simultaneously,


for example:

-cm cond+tgl+line+fsm

Comprehensive Code Coverage


2-17
Functional Coverage
Functional coverage provides a metric, for measuring the progress
of design verification, based on the functional test plan and design
specification. Functional coverage is used in conjunction with the
design code coverage. The main purpose of functional coverage is
to guide the verification process by identifying tested and untested
areas of design and ensuring corner cases are dealt with. The
built-in functional coverage mechanisms in VCS support:

• Variable and expression coverage, as well as cross coverage


• Automatic and/or user-defined coverage bins
• Filtering conditions (illegal values, values to ignore, etc.)
• Automatic coverage sample triggering by events and sequences
The FIFO example should test all different combinations of read and
write data rates. Because the data rate can take 1024 different
values, then combinations of data rates will be enormous. Instead of
exhaustively testing all combinations, lets define low, medium and
high data rates, and test for their combinations. In the following code
snippet a LOW data rate will be any data_rate between 1 and 127. A
MED data read will be any data_rate between 128 and 511. A high
data rate will be a data_rate between 512 and 1023. In order to test
for all combinations of LOW, MED and HIGH data rates we use the
"cross" construct to do this. Now there will be only nine different
combinations.

Chapter 2: Using Basic Features in VCS to Verify Your Design


2-18
covergroup Cvr;
RD: coverpoint READ_DATA.data_rate {
bins LOW = {[1:127]};
bins MED = {[128:511]};
bins HIGH = {[512:1023]};
}
WD: coverpoint WRITE_DATA.data_rate {
bins LOW = {[1:127]};
bins MED = {[128:511]};
bins HIGH = {[512:1023]};
}
RDxWD: cross RD,WD;
endgroup

Running the Test Case


In the quick start directory there is a makefile, to run the Verilog
version of the FIFO, here is the compile command:

vcs +vc -cm line -sverilog -debug fifo_test.v fifo.test_top.v \


DW_fifo_s1_sf.v DW_fifoctl_s1_sf.v DW_ram_r_w_s_dff.v
+define+ASSERT_ON+COVER_ON -y $(VCS_HOME)/packages/sva/ \
+libext+.sv \
+incdir+$(VCS_HOME)/packages/sva

Note:
(Location of the makefile is: $VCS_HOME/doc/examples/
nativetestbench/systemverilog/vcs_quickstart)

-cm line enables line coverage.The -sverilog option enables


SystemVerilog compilation. The -debug option enables interactive
debug.

To run the simulation for 50 tests use the "+NUM" options to simv:

simv -cm line +NUM+50

Running the Test Case


2-19
To generate assertion coverage report use the assertCovReport
utility:

assertCovReport

To generate testbench coverage, do the following step:

urg -dir simv.vdb -show text

To generate code coverage reports, do the following step:

cmView -b

To run the VHDL version of the FIFO, here is the compile command:

vlogan -q -sverilog fifo_test.v


vlogan -q +vc +define+ASSERT_ON+COVER_ON -sverilog \
$(VCS_HOME)/packages/sva/assert_fifo.v \
-y $(VCS_HOME)/packages/sva/ +libext+.v \
+incdir+$(VCS_HOME)/packages/sva
vhdlan -q DWpackages.vhd
vhdlan -q DW_fifo_s1_sf
vhdlan -q DW_fifo_s1_sf_sim.vhd
vhdlan -q fifo.test_top.vhd

Here is the elaboration step:

scs -cm line tb -debug -mhdl

To run the simulation for 50 tests use the "+NUM" options to scsim:

scsim -cm line -R -verilog "+NUM+50"

To generate assertion coverage report use the assertCovReport


utility:

assertCovReport -cm_assert_dir scsim.db.dir/simv.o.vdb/

To generate testbench coverage do the following step:

urg -dir simv.vdb -show text

Chapter 2: Using Basic Features in VCS to Verify Your Design


2-20
To generate code coverage reports, do the following step:

cmView -b

FIFO Results
Let's simulate the FIFO with five sets of data using the command line
below.

simv -cm line +NUM+5

The testbench reports the data_rate for each call of the task
fifo_mwrite() and fifo_mread().

The following is the output from the simulator:

Chronologic VCS simulator copyright 1991-2005 Contains Synopsys proprietary


information.
Compiler version X-2005.06; Runtime version X-2005.06; Jul 22 14:13 2005

VCS Coverage Metrics Release X-2005.06 Copyright (c) 2003 Synopsys, Inc
FIFO_RESET: Task reset_fifo started
FIFO_RESET_CHECK: Task reset_check started
FIFO_CHECK: Task check started
FIFO_MWRITE: Sending 128 words with data_rate of 1 to fifo at: 350
FIFO_MREAD: Reading 128 words with data_rate of 1 from fifo at: 350
FIFO_MWRITE: Sending 128 words with data_rate of 135 to fifo at: 26050
FIFO_MREAD: Reading 128 words with data_rate of 513 from fifo at: 26050
FIFO_MWRITE: Sending 128 words with data_rate of 134 to fifo at: 6605250
FIFO_MREAD: Reading 128 words with data_rate of 135 from fifo at: 6605250
FIFO_MWRITE: Sending 128 words with data_rate of 7 to fifo at: 8346050
FIFO_MREAD: Reading 128 words with data_rate of 3 from fifo at: 8346050
FIFO_MWRITE: Sending 128 words with data_rate of 1 to fifo at: 8448550
FIFO_MREAD: Reading 128 words with data_rate of 135 from fifo at: 8448550
FIFO_MWRITE: Sending 128 words with data_rate of 515 to fifo at: 10189350
FIFO_MREAD: Reading 128 words with data_rate of 130 from fifo at: 10189350

FIFO Results
2-21
At the end of the simulation, VCS reports on the assertion coverage
for the assert_fifo checker:

"/VCS_MX/Linux/packages/sva/assert_fifo.sv", 565:
fifo_test_top.SVA_FIFO_inst.cov_level_1_0.cover_number_of_enqs, 167943
attempts, 768 match, 0 vacuous match

"/VCS_MX/Linux/packages/sva/assert_fifo.sv", 572:
fifo_test_top.SVA_FIFO_inst.cov_level_1_1.cover_number_of_deqs, 167943
attempts, 768 match, 0 vacuous match

"/VCS_MX/Linux/packages/sva/assert_fifo.sv", 579:
fifo_test_top.SVA_FIFO_inst.cov_level_1_2.cover_simultaneous_enq_deq, 167943
attempts, 1 match, 0 vacuous match

"/VCS_MX/Linux/packages/sva/assert_fifo.sv", 587:
fifo_test_top.SVA_FIFO_inst.cov_level_1_3.cover_enq_followed_eventually_by_deq
, 167943 attempts, 547 match, 0 vacuous match

"VCS_MX/Linux/packages/sva/assert_fifo.sv", 715:

fifo_test_top.SVA_FIFO_inst.cov_level_3_1.cover_simultaneous_enq_deq_when_empt
y, 167943 attempts, 0 match, 0 vacuous match

"VCS_MX/Linux/packages/sva/assert_fifo.sv", 724:

fifo_test_top.SVA_FIFO_inst.cov_level_3_2.cover_simultaneous_enq_deq_when_full
, 167943 attempts, 0 match, 0 vacuous match

"VCS_MX/Linux/packages/sva/assert_fifo.sv", 733:
fifo_test_top.SVA_FIFO_inst.cov_level_3_3.cover_number_of_empty, 167943
attempts, 513 match, 0 vacuous match

"/VCS_MX/Linux/packages/sva/assert_fifo.sv", 744:
fifo_test_top.SVA_FIFO_inst.cov_level_3_4.cover_number_of_full, 167943
attempts, 0 match, 0 vacuous match

You can use the assertCovReport utility to generate an HTML report


of the assertion result, see figure on page 2-27.

The file: "simv.vdb/reports/report.index.html" includes the HTML


report.As you can see there are eight cover properties, five of which
are covered.

Chapter 2: Using Basic Features in VCS to Verify Your Design


2-22
Three are not covered by this test. The three cover properties not
covered are:

cover_simultaneous_enq_deq_when_empty
cover_simultaneous_enq_deq_when_full
cover_number_of_full

If you run the test longer, (250 tests),

simv -cm line +NUM+250

only two cover properties are not covered:

cover_simultaneous_enq_deq_when_empty
cover_simultaneous_enq_deq_when_full

The cover property cover_simultaneous_enq_deq_when_empty is


not allowed in this version of the FIFO and results in an error
condition.

The cover property cover_simultaneous_enq_deq_when_full is not


an error condition, but because 128 words are being written into the
fifo, this condition will not be hit. This can be rectified by writing 128
words, and then reading/writing at the same time:

fifo_mwrite(1);
fork
fifo_mwrite(1);
fifo_mread(1);
@(posedge clk) fifoCvr.sample();
join

The first line writes 128 words into the FIFO with a data_rate of 1.
The next five lines of code performs a simultaneous read and write,
ensuring the cover property
cover_simultaneous_enq_deq_when_full is hit.

FIFO Results
2-23
You can now look at the testbench coverage for 500 tests using this
command:

urg -dir simv.vdb -show text

The following is the generated report:

Functional Coverage Report

Coverage Summary
Number of coverage types: 1
Number of coverage Instances: 1
Cumulative coverage: 100.00
Instance coverage: 0.00

Coverage Groups Report

Coverage group # inst weight cum cov.


===============================================================
Cvr 1 1 100.00
===============================================================

===============================================================
= Cumulative report for Cvr
===============================================================

Summary:
Coverage: 100.00
Goal: 90

Coverpoint Coverage Goal Weight


===============================================================
RD 100.00 90 1

WD 100.00 90 1

===============================================================
Cross Coverage Goal Weight
===============================================================
RDxWD 100.00 90 1

===============================================================

Chapter 2: Using Basic Features in VCS to Verify Your Design


2-24
Cross Coverage report
CoverageGroup: Cvr
Cross: RDxWD
Summary
Coverage: 100.00
Goal: 90
Number of Coverpoints Crossed: 2
Coverpoints Crossed: RD WD
Number of Expected Cross Bins: 9
Number of User Defined Cross Bins: 0
Number of Automatically Generated Cross Bins: 9

Automatically Generated Cross Bins

RD WD # hits at least
=======================================================
HIGH HIGH 2 1
HIGH LOW 11 1
HIGH MED 7 1
LOW HIGH 7 1
LOW LOW 105 1
LOW MED 104 1
MED HIGH 10 1
MED LOW 124 1
MED MED 132 1
=======================================================

Coverpoint Coverage report


CoverageGroup: Cvr
Coverpoint: RD
Summary
Coverage: 100.00
Goal: 90
Number of User Defined Bins: 3
Number of Automatically Generated Bins: 0
Number of User Defined Transitions: 0

User Defined Bins

Bin # hits at least


============================================================
HIGH 20 1
LOW 216 1
MED 266 1
============================================================

FIFO Results
2-25
Coverpoint Coverage report
CoverageGroup: Cvr
Coverpoint: WD
Summary
Coverage: 100.00
Goal: 90
Number of User Defined Bins: 3
Number of Automatically Generated Bins: 0
Number of User Defined Transitions: 0

User Defined Bins

Bin # hits at least


============================================================
HIGH 19 1
LOW 240 1
MED 243 1
============================================================
Database Files Included in This Report:

fifo_test.db

Test Bench Runs Included in This Report:

Test Bench Simulation Time Random Seed Random48 Seed


===============================================================
fifo_test.db::fifo_test 866446150000 0 0
===============================================================

The code coverage reports are in the directory "simv.cm/reports" for


the Verilog test case and "scsim.cm/reports" or the VHDL test case.

Chapter 2: Using Basic Features in VCS to Verify Your Design


2-26
Figure 2-4 Functional Coverage Report

FIFO Results
2-27
Debug
VCS comes with a comprehensive built-in graphical user interface,
called Discovery Visual Environment (DVE). DVE supports graphical
debugging of mixed language designs including Verilog, VHDL, and
SystemVerilog. DVE is an intuitive environment that also supports
assertion debugging. Detailed documentation can be found in the
Discovery Visual Environment User Guide.

Figure 2-5 is a waveform trace showing an assertion failure at time


650 due to memory corruption in the FIFO. Assume there is a design
bug in the FIFO that affects the data read from the FIFO. During
simulation, there will be an assertion failure from the assert_fifo
checker library you have already instantiated. The error message will
look something like this:

"fifo_test.v", 162:
fifo_test_top.test.fifo_check.unnamed$$_1: started at
550000ps failed at 550000ps
Offending '(tempIn == tempOut)'
TEST: FIFO read data 'h5ec3 DID NOT match expected data 'ha13c

You can use the VCS GUI to help you debug the problem.

Chapter 2: Using Basic Features in VCS to Verify Your Design


2-28
Figure 2-5 Waveform Showing Assertion Failure Due to Memory
Corruption

DVE can be run interactively or in a post-processing manner. It is very easy


to invoke the debugger as shown below:

Debug
2-29
simv -gui

Once the debugger starts, you can set breakpoints in the design or
testbench code, trace drivers, and navigate through the hierarchy
very easily and efficiently.

Summary
As described in this Quick Start Guide, the built-in verification
features of VCS can be used to quickly ramp up new users who are
unfamiliar with the new standard languages, such as SystemVerilog
Hardware Design and Verification Language (HDVL). VCS is leading
the industry to incorporate testbench, assertion and coverage
capabilities needed for today’s design and verification engineering
tasks. With these technologies encapsulated, VCS creates the
framework and foundation for building verification environments at
all levels, from module to cluster-of-modules, chip and system level
verification. VCS’s native support for verification can yield up to a 5x
performance speedup and a 3x reduction in memory usage. VCS
enables the thorough verification of complex SoC designs, in much
less time than with other tools and methods. The result is a far higher
likelihood of first-silicon success, which is the goal of every design
and verification engineer.

In the following chapters we will introduce more advanced features


built-in VCS such as interfaces, object-oriented programming
concepts and structured testbench development.

Chapter 2: Using Basic Features in VCS to Verify Your Design


2-30
3
Using Advanced Features in VCS to Verify
Your Design 3
In Chapter 2 we used a FIFO design block example to discuss the
basic testbench constructs supported by VCS and created our
verification environment. We explained the basic feature set for
constrained random stimulus generation and functional coverage
along with assertions, code coverage and debug features. The
program block construct, process control mechanisms, queues and
arrays as well as mailbox elements were also reviewed in more detail
to provide support for testbench implementation for the FIFO.

In this chapter we will introduce object-oriented programming


concepts with high-level data abstractions, interfaces, and show the
reader how to use these advanced SystemVerilog constructs as well
as SystemC models to build a structured and layered testbench for
the FIFO design example. (Please refer to Appendix A, “The FIFO
Design Block” on page A-1).

3-1
Verification Environment
In previous chapter we introduced the program block as the basic
building block which contains the testbench in SystemVerilog. A
program block will allow creation of a well defined boundary between
the test code and design code that will reduce the time to debug the
design and test code. The abstraction and modeling constructs
simplify the creation and maintenance of test-benches. The ability to
instantiate and individually connect each instance of a program
enables their use as generalized models. A similar design heirarchy
is used in this chapter as well.

Figure 3-1 Verification Hierarchy

Top-Level
Clock generator

Testbench DUT
(Program (Verilog/
Block) VHDL)

Here the top-level shell contains the clock generator which is passed
to the testbench and the DUT. The DUT can be either Verilog,
SystemVerilog or VHDL. The program block will incorporate the
strucutred testbench environment and components.

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-2
Figure 3-2 below is a high level view of the verification architecture
we will be assuming here.

Figure 3-2

The architecture uses classes and hierarchy of classes to build a


structured testbench that enables reusability and scalabity. The top
level program will contain an environment object, which will contain
generator driver and checker objects. We have also included a
connection to a SystemC reference model to show the VCS features
supporting SystemC models.

Verification Environment
3-3
Advanced Constructs for Testbench and Design in VCS
This section describes a few more of the advanced constructs added
in VCS 2005.06 and VCS 2006.06(beta) as part of SystemVerilog for
Testbench development, in conjunction with their usage model in a
structured testbench verification environment. There are many
additional constructs and SystemVerilog features in VCS 2006.06.
For details of all the SystemVerilog capabilities in VCS, refer to the
documents listed in the VCS Document Navigator. In this chapter of
the guide we will use the basic structure developed for testbench in
previous chapter to show how easy it is to use the advanced object
oriented constructs in VCS to create scalable and reusable
verification environment.

Basic SystemVerilog Object Oriented Constructs for


Testbench
VCS provides data abstraction with class data types. Classes as
self-contained components form the foundation of Object-Oriented
programming structure. Object-oriented programming is different
from the procedural programming with which people are familiar.
There are three principles behind objects; Encapsulation,
Inheritance and Polymorphism.

Objects, Declaration and Instantiation


An object is an instance of a defined and declared class.

Sensor TempSense; //declare a variable of class Sensor


TempSense = new; // initialize variable, object of Sensor

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-4
Instantiation is done by calling the constructor new to the object.
Objects are dynamic data storage; hence memory is allocated at the
time of instantiation for that object and not at the time of definition
and declaration.

Encapuslation and Data hiding:


The class data type encapsulates all attributes of coherent data in a
system—the members that store data items and the member
functions and tasks that manipulate the data and communicate with
the rest of the system. Classes efficiently manage the complexity of
large programs through modularization. Once declared classes can
be instantiated and dynamically created as objects. Hence an object
is a container of variables and methods operating on them. We
operate on the object by calling its methods.

Classes can contain public part and private parts. Members—both


variable and methods—declared in the private part of class are
hidden from the rest of the system; using protected or local
attributes. The public segment is the section that connects the
objects to the rest of the environment. This lets designers and
verification engineers solve the details of their verification
environment piece by piece, in a modular format. As each section is
completed, it can be set aside with all its details of implementation
from the rest of the system, so that only the public section can affect
– or be affected by other segments. The following shows a simple
data class for a sensor.

Advanced Constructs for Testbench and Design in VCS


3-5
class Sensor;
string model;
integer address;
bit state; // 0 off, 1 on
integer value;
// constructor, initialization sub-routine
function new();
model = "Normal";
value = 0;
state = 0;
endfunction : new
// methods, accessing the variable members
task start_sensor();
state = 1;
endtask
function bit current_state();
current_state = state;
endtask
endclass: Sensor

In this example we have created a constructor function, new, and


one task that starts the sensor and a function which reports the state
of the sensor. You can add other methods that operate on the sensor
in this class.

Inheritance and Polymorphism:


In order to be able to build re-usable components, the
object-oriented technology provides a mechanism for creating
hierarchies of classes through derived classes. The process of
deriving classes is called inheritance. Inheritance is the mechanism
that allows a class B to inherit properties of a class A. We say ``B
extends A''. Objects of class B thus have access to attributes and
methods of class B without the need to redefine them.

If class B inherits from class A, then A is called a superclass of B. B


is called a subclass of A. Objects of a subclass can be used where
objects of the corresponding superclass are expected. This is due to
the fact that objects of the subclass share the same behavior as
objects of the superclass. Polymorphism, formed of Greek words,

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-6
meaning “having multiple forms” is the characteristic of being able to
assign different meaning or usage in different context to an entity. In
a subclass, explicit calls to the methods of a superclass are done by
using super. For example, super.new() in the subclass constructor
calls the superclass constructor and has to be the first call in the
subclass constructor definition. In the following example, Adult class
(subclass) extends from Person class (superclass).

class Person;
//data or class properties
string name;
integer age;
string gender;
//initialization
function new();
Name = "";
Age = 0;
endfunction;
virtual task speak();
$display("This is a person \n");
endtask
endclass

class Adult extends Person;


function new();
super.new();
endfunction;

virtual task speak();


$display(" my name is %s \n",name);
endtask
endclass: Adult
Note the usage of virtual attribute for the task speak(). Virtual
methods are a basic polymorphic construct. Virtual methods provide
prototypes for subroutines and override a method in all the base
classes, where as a normal method only overrides a method in that
class and its descendants. Subclasses override the virtual methods

Advanced Constructs for Testbench and Design in VCS


3-7
by following the prototype exactly; all versions of the virtual method
look identical in all subclasses as far as number of arguments, return
type, and encapsulation are concerned.

In our example if we were to define a generic Person class type,


knowing that the class will be extended to define the characteristics
of the functions such as speak(), the function has to be declared as
virtual and then its behavior defined in derived classes.

class Person;
//data or class properties
...
virtual task speak();
endtask
endclass: Person
Now we can define an adult person and a baby with extension of the
Person, note in this case we are overriding the function in the base
class.

class Adult extends Person;


...
virtual task speak();
$display(" my name is %s \n",name);
endtask
endclass: Adult
We can also extend class Person to provide function for another
entity, for example, Child:

class Child extends Person;


virtual task speak();
$display(“ bah-bah-bah %s \n”,name);
endtask
endclass: Child
In conjunction with its usage as a means of representing both the
common features and specialized aspects of different data
structures and components, class derivation is also a tool for

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-8
modularization. For example, a verification engineer can define a
derived class based on an existing class library that was produced
specifically for verification tasks.

The object-oriented (OO) class features in SystemVerilog supported


in VCS provide the inheritance mechanism to build re-usable and
modular verification environments to model complex systems. Using
the OO elements of VCS provides the foundation for a layered
architecture approach to implementing the verification environment.

In this chapter we will review a simple object based structure as an


introduction to these concepts. In future versions of this guide book
we will delve into the methodology supported in the Verification
Methodology Manual (VMM) for developing a layered architecture
testbench environment.

Classes and objects benefit users in various ways; above all they
encourage the reuse of software components that are developed for
specific task. Users will also reduce development time and risk
because systematic and modularized development using objects
provides more resilience and reduces code size.

Another new construct supported in VCS, interface, provides a


container for signals used in the design and verification environment.

Interface Construct and Signal Connectivity


VCS provides a new construct, interface as a container which acts
as bundle of wires, encapsulating signal definitions and
synchronization, and allows ease of connectivity between testbench
and design components. Interface can be instantiated like a module.
The interface construct provides flexibility through instantiation in a
module or a program. The best approach to declare signals for
connectivity is to declare interface signals as wire in SystemVerilog.

Advanced Constructs for Testbench and Design in VCS


3-9
interface fifo_intf(input clk);
parameter WIDTH = 16;
wire rst_n;
wire push_req_n;
...
wire [WIDTH-1: 0] data_out;
endinterface : fifo_intf
Once an interface container has been defined, variable of that
interface type can be declared and instantiated.

fifo_intf intfFifo(clk);
// declaration and instantiation of of type fifo_intf

modports
Directional information for module ports is provided by using the
modport construct in SystemVerilog. In a verification environment
there are various views and uses for interface signals: some are
driven, such as in driver transactors, some are simply monitored,
such as in monitor transactors. In order to compartmentalize these
different views, modports are declared and defined for each of the
transactor views.

interface fifo_intf(input clk);


parameter WIDTH = 16;
wire rst_n;
wire push_req_n;
...
wire [WIDTH-1: 0] data_out;
modport Fifo_Driver(output rst_n;
output push_req_n;
...
input data_out);

modport Fifo_Designer(input rst_n;


input push_req_n;
...
output data_out);
endinterface: fifo_intf

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-10
Now you can declare and instantiate the interface and pass the
modport to the testbench:

fifo_intf intfFifo(clk);
// declaration and instantiation of type fifo_intf
// pass modport to a program instantiation.
fifo_test test(intfFifo.Fifo_Driver);

Note that in order to avoid duplication of effort and create a modular


and flexible verification environment that allows extensibility, the
actual task and function code for transactors is not defined inside the
interface.

In the next sections we will describe the usage of clocking blocks to


allow synchronous sampling and driving of signals. This blocking
removes any potential race conditions between the design and
verification testbench. Using such constructs in SystemVerilog will
eliminate unpredictability in timing behavior of testbench and design
connection.

Virtual Interface
Virtual interfaces provide a mechanism for separating abstract
models and test programs from the actual signals that make up the
design further promoting code re-use. For example, a network switch
router has many identical ports that operate the same way, say a
10Gbit MII for Ethernet connection. A single virtual interface
declared inside a class that deals with these Ethernet signals can
represent different interface instances at various times throughout
the simulation. A virtual interface can be declared inside as a class
property that can be initialized procedurally or by an argument to the
class constructor.

Advanced Constructs for Testbench and Design in VCS


3-11
In the following code example the class fifo_driver instantiates a
virtual interface:

class fifo_driver
...
virtual fifo_intf v_intf; // full interface instance
...
endclass: fifo_driver
The instantiation of the interface can have several flavors in the
Testbench area:

In a program block:

v_intf = interface_passed_to_program;
Or through the class constructor:

function new(virtual fifo_intf vIntf, ...);


this.v_intf = vInft;
And with modport connections:

virtual fifo_intf.Fifo_Driver fifo_driver_if;


Similarly the assignment through program block and class
constructor is as follows:

a) Assignment to virtual interfaces:

fifo_wr_if = interface_passed_to_program;
b) Through class constructor:

function new(virtual fifo_intf.Fifo_Driver vIntfDR, ...);


this.v_intf = vInftDR;

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-12
Referencing signals within an interface can be accessed using a
relative hierarchical path name. For example:

...
initial
intfFifo.rst_n <= 0;
always @(posedge intfFifo.clk)
$display("Cycle is %0 \n",cyc++);
...

Eliminating Race-Conditions in Synchronous Designs


Clocking Blocks
One of the major contributions of SystemVerilog has been the
introduction of a clocking block as a synchronization construct for
signals between testbench and design. Usage of a clocking block
inside interfaces will help remove race conditions between the two
sides and handles signal delay differences between RTL and
gate-level models. Clocking blocks used an in interface definition in
conjunction with modports define proper directions for each modport
and signals in it. The clocking block arranges signals that are
synchronous to a particular clock and makes their timing explicit. The
clocking block is key in allowing engineers to focus on test
development rather than signals and transitions in time. Depending
on the nature of the design and verification environment there can be
more than one clocking block.

Advanced Constructs for Testbench and Design in VCS


3-13
An example of interface and clocking blocks follows:

interface fifo_intf(input clk,input clk2);


...
parameter setup_t = 2ns;
parameter hold_t = 3ns;
default input #setup_t output #hold_t;
clocking cb @(posedge clk);
output rst_n;
output push_req_n;
..
input data_out;
endclocking

clocking cbDR @(posedge clk2);


output rst_n;
output push_req_n;
....
endclocking
endinterface: fifo_intf
Signals within each clocking block are sampled and driven with
respect to the specified clock edge given appropriate setup and hold
time. An interface can contain one or more clocking blocks within it.

Figure 3-3 Timing reference for sample and drive of synchronous signals

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-14
Modport and Clocking Block
In the interface definition each modport will have a reference to a
clocking block. As discussed previously, the main transactors within
the Testbench program block connect to the signals through virtual
interface modports to allow extensibility.

interface fifo_intf;

modport fifo_Driver(clocking cbDR);


modport fifo_Checker(clocking cbCheck)

....
endinterface: fifo_intf

Signals are then referenced with respect to interface modport name,


and are synchronized with the appropriate clocking block timing.

v_intf.cb.push_req_n <= 1'b1; //direct clocking block


fifo_wr_if.cbDR.push_req_n <= 1'b1; //modport usage

Asynchronous Signals
The interface modport construct can be used to define and create
asynchronous ports and signal connections. The signal is defined as
an input or output in a modport declaration:

interface fifo_intf;
modport fifo_Driver(clocking cbDR, output rst_n);
modport fifo_Checker(clocking cbCheck)
....
endinterface: fifo_intf
In this case the signal rst_n is defined as asynchronous with respect
to the clock edges

Advanced Constructs for Testbench and Design in VCS


3-15
Testbench structure for the FIFO
In this section we will discuss the new testbench structure using
classes for encapsulation of signals, data and transactions. We will
use an object hierarchy in a simple layered structure to introduce the
use of more advanced object-oriented concepts. The testbench is
comprised of data types that encapsulate signal connections
(interface, fifo_intf), a fifo data class (data_tr), and an environment
class (fifo_env). Within the environment class we will incorporate
classes for test configuration, driver and checkers as well as
coverage groups. The main program instantiates the global data
object and environment object that run the test.

There are a few sample test files that help introduce various
advanced topics such as using class extension to create new tests
as well as incorporating a SystemC checker object to show the VCS
SystemVerilog to SystemC connection features.

Interface
We have defined an interface for the FIFO. The FIFO interface
encapsulates not only the signals that read and write from the FIFO,
but also the access mechanisms of the FIFO.

This interface is named “fifo_intf” and it contains a single input clk


that will be passed to the interface when it is instantiated in the top
level of our environment.

The interface also contains a clocking block that defines the signal
timing with respect to the positive edge of the clock. The clocking
block will be only used by the testbench, and not be referenced by
the FIFO itself. The clocking block ensures proper driving and
sampling from the testbench to the FIFO.

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-16
interface fifo_intf(input clk);
parameter WIDTH = 16;
wire rst_n;
wire push_req_n;
wire pop_req_n;
wire diag_n;
wire [WIDTH-1 : 0] data_in;
wire empty;
wire almost_empty;
wire half_full;
wire almost_full;
wire full;
wire error;
wire [WIDTH-1 : 0] data_out;

clocking cb @(posedge clk);


output push_req_n;
output pop_req_n;
output diag_n;
output data_in;
input empty;
input almost_empty;
input half_full;
input almost_full;
input full;
input error;
input data_out;
endclocking
modport tb (clocking cb, output rst_n);
modport dut( input clk, rst_n, push_req_n, pop_req_n,
diag_n,data_in,
output empty, almost_empty, half_full, almost_full,
full, error, data_out);
endinterface
We have also defined two modports “tb” and “dut.” These modports
establish access mechanisms from the design and testbench
perspective. From the design perspective, we can read the inputs
directly and drive the outputs directly.

Advanced Constructs for Testbench and Design in VCS


3-17
The “tb” modport establishes the access mechanism for the
testbench. The testbench can only read and write from the FIFO
through the clocking block, except for the rst_n signal. All reads and
writes are synchronous with respect to the positive edge of the clock
except for rst_n, which can be written to asynchronously.

The FIFO interface can be instantiated in the top level of my


environment as shown below:

fifo_intf intf(clk);

The interface can be now passed to both the testbench “fifo_test”


and to the design under test “DW_fifo_s1_sf_wrap”. We pass the
modport version of the FIFO to its respective instance as shown
below.

//program instantiation
fifo_test test(intf.tb);

// dut instantiation
DW_fifo_s1_sf_wrap #(WIDTH, DEPTH, ae_level, af_level,
err_mode, rst_mode)
dut (intf.dut);
Using modports ensures that the proper driving and sampling
semantics are used. If the engineer that is writing a test for the FIFO
attempts to drive signal “pop_req_n” asynchronously, then the
engineer will get an error. This prevents incorrect usage of the
interface.

Data Class
Following our example FIFO used in the first chapter let us assume
our FIFO word length is 16-bits. The depth of the FIFO is
parametrizable at the top. We have chosen the other fields for push
(write) or pop (read) data rates.

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-18
Figure 3-4 FIFO data format

The “data” field is 16-bits wide. The data_rates for write and read are
16-bit wide as well. In this example we want the “data” field to contain
values such that the highest-order 2 bits are set, and constrain the
operation to push and pop only for the purpose of this exercise. The
code for these constraints would look like this:

class data_tr;
rand logic [15:0] data;
rand logic [15:0] wr_data_rate;
rand logic [15:0] rd_data_rate;
constraint reasonable {
data [15:14] == 2'b11;
wr_data_rate > 0;
wr_data_rate dist { [1:8] := 10, [60:80] := 10 }
rd_data_rate > 0;
rd_data_rate dist { [1:8] := 10, [60:80] := 10 }
}
endclass

Any data type can be declared as random using the ‘rand’ keyword.
Here we have declared the fields of FIFO data as random. We need
to encapsulate our random variables within a class, and we have
called the class “data_tr.” We will also declare integer variables and
called “wr_data_rate” and “rd_data_rate,” and constrain them with a
distribution list. We will use these random variables to test out
different read/write data-rates of the FIFO. For very slow data rates,
delay will have a large value, and for fast data rates, delay will have
a low value. Finally, we create 10 different random values – here is
what the output would look like:

Advanced Constructs for Testbench and Design in VCS


3-19
wr_data_rate rd_data_rate data
20 12 c82b
28 24 c852
40 30 fb72
5 5 dd2a
35 35 c3e7
25 20 cb56
10 8 f208
15 12 f4b3
25 25 d1df
12 6 d715
Note that the distribution list allows interesting combinations of write
and read data rates for FIFO access.

FIFO Environment Classes and Transactors


In the previous chapter of the guide, the functionality that wrote, read
and reset the FIFO, was contained within four separate procedural
tasks: “fifo_mwrite,” “fifo_mread,” “fifo_reset,” and
“check_fifo_reset.” In our tutorial we assume that we have two
different FIFOs, which would require four additional tasks (one for
read, one for write, and two for reset), doubling the amount of code
that we would have to write and maintain.

Instead the read and write tasks of the FIFO can be considered as
part of a common function – one of these tasks would not be used in
isolation. So we will encapsulate all of the FIFO-related tasks into a
class. Now to instantiate more than one FIFO we only have to
declare a new instance of our class.

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-20
Here is a code snippet of the FIFO driver class.

class driver ;
...
task fifo_mwrite ();
..
endtask

task fifo_mread ();


..
endtask

endclass: driver
here fifo_mwrite() will drive data into our FIFO, and
fifo_mread() will read data from our FIFO.

A similar class is created for the FIFO checker. Self-checking will be


discussed further in the next section.

In addition to these transactors we create a new class, called


‘generator’ that now produces randomized FIFO data. The
generator class has functions and tasks declared as virtual so they
can be extended in inherited classes. In this way many constrained
random tests can be created by simply extending the generator class
in the main test program file.

class generator ;
rand data_tr rand_tr;
//holder randomized FIFO data(transaction)
virtual task main();
..
FIFO_DATA = get_transaction();
..
endtask: main

Advanced Constructs for Testbench and Design in VCS


3-21
/////////////////////////////////////////
// get_transaction method
/////////////////////////////////////////
virtual function data_tr get_transaction();
rand_tr.randomize();
get_transaction = rand_tr;
endfunction
..
endclass: generator
The function get_transaction will return a randomized transaction of
the FIFO data type (in this case data_tr) and is declared virtual so
that it can be modified by extending the generator class. We will
show an example of this extension and show how easy it is to create
new tests. When main is called in the generator the actual
randomized data transaction is returned to the global FIFO_DATA for
simplicity. In a future version of this guide we will show through the
VMM methodology how transactions are passed from layers through
channels that are setup and connect various layers from the top test
program to the DUT.

Through the generator class we have pushed the stimulus


generation up in the hierarchy, separating the generation from the
actual driving and checking segments of the testbench. We now can
easily change the data pattern (transaction) that is sent to the DUT
at the top layer and pass it to the lower layer drivers and checker
transactors.

We also create a configuration class that helps us “configure” our


test. In our case the config class contains a random number that
specifies how many times we write to the FIFO. Here is the code for
this class:

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-22
class test_cfg;
rand int NUM;
constraint num_runs {
NUM > 10; NUM < 50;
}
endclass: test_cfg
To make the design of these classes more systematic we incorporate
methods that are a part of all transactor classes and can call other
specific actions within the class. The main task that starts the
transactor is an example of this systematic approach. The top level
environment class contains our generator, driver, and checker
classes. Our environment class is the class that we instantiate in our
top-level program. Note that the reset related tasks are now part of
the environment class.

/// environment class for the FIFO testbench,


// instantiates the transactors and generator
class fifo_env ;
//declaration of other objects/transactors
generator fifo_gen;
checker fifo_checker;
driver fifo_driver;
test_cfg cfg;
int NUM;
// Coverage group definition
// Constructor

function new();
cfg = new();
cfg.randomize();
NUM = cfg.NUM;
$write(" Test configuration for FIFO \n");
Cvr = new();
fifo_gen = new();
endfunction: new

Advanced Constructs for Testbench and Design in VCS


3-23
virtual function void build();
begin
fifo_driver = new();
fifo_checker = new();
end
endfunction: build
/////////////////////////////////////////
task fifo_reset ();
..
endtask
task fifo_reset_check ();
..
endtask

task pre_test;
fork
fifo_reset();
fifo_reset_check();
join_none
start_checker();
endtask: pre_test

task post_test();
@(vintf.cb) Cvr.sample();
endtask: post_test
virtual task test();
repeat(NUM) begin
fifo_gen.main();
fork
fifo_driver.fifo_mwrite();
fifo_driver.fifo_mread();
join
post_test();
end
endtask: test

task run();
build();
pre_test();
test();

endtask: run

endclass: fifo_env

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-24
The “new” function of fifo_env() accomplishes a number of things: it
initializes test configuration (how many sets of data to push into the
FIFO), it creates the functional coverage object, and it creates the
data object that will be randomized.

The “build” function of fifo_env() creates or builds the driver and


checker objects.

The “pre_test” function resets the FIFO, and then starts the checker
running in the background.

The “test” task randomizes the data object, writes data to the FIFO,
and then reads back the data.

The “post_test” task is called after a single test to sample the data
rates for functional coverage.

The “run” function of fifo_env() calls the build function, pre_test and
then test task. This is the task that is called from the top level
program.

Checking for Functional Correctness Using a Self-Checking


Technique
It is important to check the functional correctness of the design under
test. Because we are generating random stimulus and sending this
stimulus to the FIFO, we need to be able to determine whether the
FIFO is operating correctly. In the next section we will illustrate two
different techniques.

Advanced Constructs for Testbench and Design in VCS


3-25
SystemVerilog Checker

The first way we will check for functional correctness is by comparing


the output of the FIFO to the data sent to the input of the FIFO.
Because this is a FIFO, we know that data sent to the FIFO will come
out the in same order.

So in task fifo_mwrite() that writes to the FIFO, we take the


input data and push it onto a SystemVerilog queue:

cdata.push_back(FIFO_DATA.data[j]);
In task fifo_mread() whenever data is popped off of the FIFO we
push it into a mailbox:

mbox.put(vintf.cb.data_out);

Now, in the checker class we will pop data off of the mailbox and off
of the queue and compare the two values (which should be the
same):

mbox.get(tempOut);
tempIn = cdata.pop_front();
assert( tempIn == tempOut )
else $write("TEST: FIFO read data 'h%0h DID NOT
match expected data 'h%0h\n",tempOut, tempIn);
Now, if our DUT was more complicated and transmitted out-of-order
data, then it would need searching through the queue to find the
correct value, using the built-in methods of the queue.

SystemC Reference Model Checker

VCS has incorporated transaction level interface support for


SystemVerilog and SystemC. This allows a SystemC reference
model to hook up to SystemVerilog design and testbench for
verification re-use. In this example we have included a call to a FIFO

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-26
reference model in SystemC that runs in parallel with the checker in
the SystemVerilog transaction level model described in previous
sections.

In order to export our FIFO SystemC model into HDL, we need to


define our access mechanism, which is derived from the
“sc_interface” SystemC class as follows:

////// systemC code reference model ///////


class fifo_if : public virtual sc_interface
{
public:
virtual void nb_push(int data) = 0;
virtual void pop(int *data) = 0;
virtual int status() = 0;
}; // end class fifo_if

We have defined the push method to be non-blocking, and the pop


method to be blocking – this is defined in the “idf” file, which is used
to automatically create the helper files.

interface fifo_if
direction sv_calls_sc
verilog_module fifo_helper
systemc_module fifo_sysc_helper
#include "fifo_if.h"
function nb_push
input int data

task pop
output int data

function int status


In this file format one can specify whether SystemVerilog calls
SystemC or vica-versa. Also, one needs to define either functions
(non-blocking) or tasks (blocking). See the VCS user guide for more
detailed information.

Advanced Constructs for Testbench and Design in VCS


3-27
The SystemC reference model includes three different function calls:

SC_MODULE(fifo) , public fifo_if


{
public:
sc_in<sc_logic> dummy;
sc_fifo<int> my_fifo;
int tmp;
SC_CTOR(fifo) : my_fifo(128) {
}
void pop(int *data) {
if (my_fifo.num_free() == 128)
printf("ERROR within SystemC.. pop when fifo is empty\n");
my_fifo.read(tmp);
*data = tmp;
}
void nb_push(int data) {
if (my_fifo.num_free() == 0)
printf("ERROR within SystemC.. push when fifo is
full\n");
my_fifo.nb_write(data);
}
int status() {
return (my_fifo.num_free() );
}

};
The method “push” is used whenever we want to push data into our
FIFO, and the method “pop” is used whenever we want to pop data
from our FIFO. We have also included a method “status” that returns
the number of free entries in the FIFO.

Now, in the testbench, in “fifo_mwrite” task, whenever we write data


into our DUT we will also call the “push” method of the reference
model:

fifo_test_top.fifo_reference_model.nb_push(FIFO_DATA.data[
j]);
Also, in the checker class, we can compare the output of the
SystemC reference model with the actual output of the DUT:

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-28
class checker;
virtual task main();
logic [`WIDTH-1:0] tempIn;
logic [`WIDTH-1:0] tempOut;
logic [`WIDTH-1:0] syscOut;
$write("FIFO_CHECK: Task check started \n");
forever begin
mbox.get(tempOut);
tempIn = cdata.pop_front();
////////// Checker #1 ////////////////////////
assert( tempIn == tempOut )
else $write("CHECKER: FIFO read data 'h%0h
DID NOT match expcted data 'h%0h\n
",tempOut, tempIn);

//////////// Checker #2 //////////////////


fifo_test_top.fifo_reference_model.pop(syscOut);
assert( syscOut == tempOut )
else $write("SYSC_CHECKER: FIFO read data
'h%0h DID NOT match expcted data 'h
%0h\n",tempOut, syscOut);

end
endtask: main
endclass: checker

How to Run Tests


As we discussed, the main test program instantiates the FIFO
environment and calls the main run routine. This is the default test
case set in fifo_test.v. We can extend the generator and transactions
to create new test cases.

Default Run fifo_test_00_default.v

The default test is contained in fifo_test.v and is as follows:

program fifo_test ( fifo_intf intf);


virtual fifo_intf.tb vintf;
`include "fifo_env.v"

Advanced Constructs for Testbench and Design in VCS


3-29
Here the program is declared with a single interface in the port list.
A virtual interface is declared as “vintf”. All of our base-classes are
included here also.

mailbox mbox;
data_tr FIFO_DATA;
fifo_env fifo_tb_env;
logic [`WIDTH-1:0] cdata[$];
Here all our global data is declared, our mailbox, our random data,
our environment class, and our queue.

initial begin : main_prog


vintf = intf;
mbox=new();
FIFO_DATA = new();
fifo_tb_env = new();
vintf.rst_n <= 1'b0;
@(vintf.cb);
fifo_tb_env.run();
end : main_prog
endprogram : fifo_test
Above is the main part of our test: first our virtual interface is
initialized from the actual interface, all our objects are created using
“new”, our reset signal is asserted; then the method “run” is called,
which runs our test and sends a random number of tests to the FIFO.

Extended Run fifo_test_01_extend.v

The benefit of this methodology is that it easily allows one to change


the definition of a testbench entity. If we want to change the
generator to write with a data rate equal to the read data rate of 128
we can easily implement this as follows:

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-30
class my_gen extends generator;
function data_tr get_transaction();
$write("this is from extended generator \n");
rand_tr.randomize() with {
wr_data_rate == 128;
rd_data_rate == wr_data_rate;};
get_transaction = rand_tr;
endfunction
endclass

We then “plug” this generator back into our environment as follows:

program fifo_test( fifo_intf intf);


...
class my_gen extends generator;
...
endclass

my_gen fifo_new_generator;
..
fifo_new_generator= new();
fifo_tb_env = new();

fifo_tb_env.fifo_gen = fifo_new_generator;
fifo_tb_env.run();

end: main_prog
endprogram: fifo_test
The key is that we do not need to modify any of our base classes.
This is all done in the test-specific file “fifo_test_01_extend.v”

If we want another test with different constraints we just copy the file
to “fifo_test_02_my_test.v” and edit that file.

Advanced Constructs for Testbench and Design in VCS


3-31
Assertions
As discussed in the previous chapter, Assertions help designers and
verification teams to catch bugs faster. With VCS, you can easily add
assertions into your design to check for correct design behavior.
Using VCS, you can write sophisticated assertions from scratch, or
you can use the built-in Checker Library. VCS has a rich set of
checkers in its library that you can easily instantiate in your design to
identify bugs.

For a full description of the Checker Library, please see the


SystemVerilog Checker Library Reference Manual. The checks in
the library include: one hot/ cold, mutual exclusion, even/odd parity,
handshake, overflow, underflow, window, arbiter and many others.
The advantage of using the Checker Library is that it is pre-written,
pre-verified, and ready to be instantiated. Another advantage of
using the Checker Library is that it has comprehensive assertion
coverage built into each checker. It includes corner case coverage
and range coverage. So the checkers not only find bugs, but also
report on coverage holes in your design.

You can instantiate the FIFO assertion directly into either the Verilog,
or the VHDL design. The assertion can also be put in a separate file
using the bind construct. This will work for both Verilog and VHDL
blocks.

For more detailed description please see Assertions on page


page 2-13.

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-32
Comprehensive Code Coverage
VCS has built-in comprehensive code coverage for both Verilog and
VHDL designs. You can refer to the VCS Coverage Metrics User
Guide for full documentation. For types of coverage supported see
Comprehensive Code Coverage on page 2-16.

Functional Coverage
Functional coverage provides a metric for measuring the progress of
design verification, based on the functional test plan and design
specification. Functional coverage is used in conjunction with the
design code coverage. The main purpose of functional coverage is
to guide the verification process by identifying tested and untested
areas of design and ensuring corner cases are tested. For more
details see the Functional Coverage section on page 2-18.

Running the Testcase


In the quickstart directory (whatever the name is-- need to provide
the path) there is a makefile. To run the Verilog version of the FIFO
with the default constraints, here is the compile command:

make verilog_00
For a VHDL version of the testcase, use the command:

make vhdl_00
To run with the extended generator, type:

make verilog_01
make vhdl_01

Comprehensive Code Coverage


3-33
To generate testbench coverage, do the following step:

urg -dir simv.vdb -show text

FIFO Results
Let's simulate the FIFO with the default configuration using the
command line below.

make verilog_00
The testbench reports the data_rate for each call in fifo_driver to the
methods fifo_mwrite and fifo_mread.

The following is the output from the simulator:

Chronologic VCS simulator copyright 1991-2005


Contains Synopsys proprietary information.
Compiler version X-2005.06-SP1-9; Runtime version X-2005.06-SP1-9; Jan 10 14:38
2006

Test configuration for FIFO


Sending 17 transactions to DUT
FIFO_RESET: Task reset_fifo started
FIFO_RESET_CHECK: Task reset_check started
FIFO_CHECK: Task check started
FIFO_MWRITE: Sending 128 words with data_rate of 130 to fifo at: 50
FIFO_MREAD: Reading 128 words with data_rate of 128 from fifo at: 50
FIFO_MWRITE: Sending 128 words with data_rate of 4 to fifo at: 1677150
FIFO_MREAD: Reading 128 words with data_rate of 7 from fifo at: 1677150
FIFO_MWRITE: Sending 128 words with data_rate of 2 to fifo at: 1779650
FIFO_MREAD: Reading 128 words with data_rate of 6 from fifo at: 1779650
FIFO_MWRITE: Sending 128 words with data_rate of 2 to fifo at: 1869350
FIFO_MREAD: Reading 128 words with data_rate of 129 from fifo at: 1869350
FIFO_MWRITE: Sending 128 words with data_rate of 514 to fifo at: 3533450
FIFO_MREAD: Reading 128 words with data_rate of 133 from fifo at: 3533450
FIFO_MWRITE: Sending 128 words with data_rate of 3 to fifo at: 10125750
FIFO_MREAD: Reading 128 words with data_rate of 514 from fifo at: 10125750
FIFO_MWRITE: Sending 128 words with data_rate of 4 to fifo at: 16717850
FIFO_MREAD: Reading 128 words with data_rate of 5 from fifo at: 16717850
FIFO_MWRITE: Sending 128 words with data_rate of 513 to fifo at: 16794850
FIFO_MREAD: Reading 128 words with data_rate of 512 from fifo at: 16794850
FIFO_MWRITE: Sending 128 words with data_rate of 132 to fifo at: 23374350
FIFO_MREAD: Reading 128 words with data_rate of 519 from fifo at: 23374350
FIFO_MWRITE: Sending 128 words with data_rate of 518 to fifo at: 30030450
FIFO_MREAD: Reading 128 words with data_rate of 516 from fifo at: 30030450
FIFO_MWRITE: Sending 128 words with data_rate of 517 to fifo at: 36673950
FIFO_MREAD: Reading 128 words with data_rate of 519 from fifo at: 36673950
FIFO_MWRITE: Sending 128 words with data_rate of 515 to fifo at: 43330050
FIFO_MREAD: Reading 128 words with data_rate of 3 from fifo at: 43330050
FIFO_MWRITE: Sending 128 words with data_rate of 128 to fifo at: 49935150

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-34
FIFO_MREAD: Reading 128 words with data_rate of 3 from fifo at: 49935150
FIFO_MWRITE: Sending 128 words with data_rate of 134 to fifo at: 51586650
FIFO_MREAD: Reading 128 words with data_rate of 132 from fifo at: 51586650
FIFO_MWRITE: Sending 128 words with data_rate of 7 to fifo at: 53314950
FIFO_MREAD: Reading 128 words with data_rate of 133 from fifo at: 53314950
FIFO_MWRITE: Sending 128 words with data_rate of 519 to fifo at: 55030250
FIFO_MREAD: Reading 128 words with data_rate of 131 from fifo at: 55030250
FIFO_MWRITE: Sending 128 words with data_rate of 4 to fifo at: 61686550
FIFO_MREAD: Reading 128 words with data_rate of 133 from fifo at: 61686550
$finish at simulation time 63401850000

You can now look at the testbench coverage for 500 tests using this
command:

urg -dir simv.vdb -show text

The following is the generated report:

Functional Coverage Report

Coverage Summary
Number of coverage types: 1
Number of coverage Instances: 1
Cumulative coverage: 100.00
Instance coverage: 0.00

Coverage Groups Report

Coverage group # inst weight cum cov.


==========================================================
fifo_env::Cvr 1 1 100.00
==========================================================

==========================================================
= Cumulative report for fifo_env::Cvr
==========================================================

Summary:
Coverage: 100.00
Goal: 100

Coverpoint Coverage Goal Weight


==========================================================
RD 100.00 100 1

FIFO Results
3-35
WD 100.00 100 1
==========================================================
Cross Coverage Goal Weight
==========================================================
RDxWD 100.00 100 1
==========================================================

Cross Coverage report


CoverageGroup: fifo_env::Cvr
Cross: RDxWD
Summary
Coverage: 100.00
Goal: 100
Number of Coverpoints Crossed: 2
Coverpoints Crossed: RD WD
Number of Expected Cross Bins: 9
Number of User Defined Cross Bins: 0
Number of Automatically Generated Cross Bins: 9

Automatically Generated Cross Bins

RD WD # hits at least
=======================================================
HIGH HIGH 3 1
HIGH LOW 1 1
HIGH MED 1 1
LOW HIGH 1 1
LOW LOW 3 1
LOW MED 1 1
MED HIGH 2 1
MED LOW 3 1
MED MED 2 1
=======================================================

Coverpoint Coverage report


CoverageGroup: fifo_env::Cvr
Coverpoint: RD
Summary
Coverage: 100.00
Goal: 100
Number of User Defined Bins: 3
Number of Automatically Generated Bins: 0
Number of User Defined Transitions: 0

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-36
User Defined Bins

Bin # hits at least

==========================================================
HIGH 5 1
LOW 5 1
MED 7 1

==========================================================

Coverpoint Coverage report


CoverageGroup: fifo_env::Cvr
Coverpoint: WD
Summary
Coverage: 100.00
Goal: 100
Number of User Defined Bins: 3
Number of Automatically Generated Bins: 0
Number of User Defined Transitions: 0
User Defined Bins

Bin # hits at least

==========================================================
HIGH 6 1
LOW 7 1
MED 4 1

==========================================================

Database Files Included in This Report:

fifo_test.db

Test Bench Runs Included in This Report:

Test Bench Simulation Time Random Seed


Random48 Seed
==========================================================
fifo_test.db::fifo_test 63401850000 0 0
==========================================================

FIFO Results
3-37
Debug
VCS and later versions come with a comprehensive built-in graphical
user interface, called Discovery Visual Environment (DVE). DVE
supports graphical debugging of mixed language designs including
Verilog, VHDL, and SystemVerilog. DVE is an intuitive environment
that also supports assertion debugging. Detailed documentation can
be found in the Discovery Visual Environment User Guide.

DVE can be run interactively or in a post-processing manner. It is


easy to invoke the debugger as shown below:

simv -gui
Once the debugger starts, you can set breakpoints in the design or
testbench code, trace drivers, and navigate through the hierarchy
easily and efficiently.

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-38
.

Debug
3-39
Summary
We have introduced the new constructs for testbench and
verification, interfaces, clocking blocks, as well as object-oriented
design constructs in VCS. As described in this Quick Start Guide,
the built-in verification features of VCS can be used to quickly ramp
up new users who are unfamiliar with the new standard languages,
such as SystemVerilog Hardware Design and Verification Language
(HDVL). VCS is leading the industry to incorporate testbench,
assertion and coverage capabilities needed for today’s design and

Chapter 3: Using Advanced Features in VCS to Verify Your Design


3-40
verification engineering tasks. With these technologies
encapsulated, VCS creates the framework and foundation for
building a structured layered verification environments at all levels,
from module to cluster-of-modules, chip and system level
verification. VCS’s native support for verification can yield up to a 5x
performance speedup and a 3x reduction in memory usage. VCS
enables the thorough verification of complex SoC designs, in much
less time than with other tools and methods. The result is a greater
likelihood of first-silicon success, which is the goal of every design
and verification engineer.

Summary
3-41
Chapter 3: Using Advanced Features in VCS to Verify Your Design
3-42
A
The FIFO Design Block A
The FIFO design is a synchronous (Single-Clock) FIFO with static
flags. It is fully parameterized and has single-cycle push and pop
operations. It also has empty, half-full, and full flags, as well as
parameterized almost full and almost empty flag thresholds with
error flags.

A block diagram for the FIFO design is as follows:

A-1
Figure A-1 FIFO Design

D W _ f if o _ s 1 _ s f

p u s h _ re q _ n

d a t a _ in

d a ta _ o u t

p o p _ re q _ n
f u ll

a lm o s t _ fu ll

h a lf _ f u ll

a lm o s t _ e m p t y
d ia g _ n

e m p ty

e rro r
c lk rs t_ n

The following sample timing diagram illustrates how the FIFO block
works.

Figure A-2 FIFO Timing Diagram

Chapter A: The FIFO Design Block


A-2
B
Testbench Files and Structure B
Links to the testbench and design files are provided below.

You can find the ASCII version of these files in the following location
in the installation:

$VCS_HOME/doc/examples/nativetestbench/systemverilog/
vcs_quickstart/ under
/basic and /advanced subdirectories

B-1
Files for Using Basic Features in VCS to Verify Your
Design
README

DW_fifo_s1_sf.v Verilog FIFO model

DW_fifoctl_s1_sf.v Verilog FIFO controller

DW_ram_r_w_s_dff.v Verilog memory

DW_fifo_s1_sf.vhd VHDL FIFO entity

DW_fifo_s1_sf_sim.vhd VHDL FIFO architecture

DWpackages.vhd VHDL packages

synopsys_sim.setup Setup file

fifo.test_top.v Verilog top level instantiating program and

fifo.test_top.vhd VHDL top level instantiating program and

fifo_test.v program testbench

Chapter B: Testbench Files and Structure


B-2
Files for Using Advanced Features in VCS to Verify
Your Design
README

DW_fifo_s1_sf.v Verilog FIFO model

DW_fifoctl_s1_sf.v Verilog FIFO controller

DW_ram_r_w_s_dff.v Verilog memory

DW_fifo_s1_sf.vhd VHDL FIFO entity

DW_fifo_s1_sf_sim.vhd VHDL FIFO architecture

DWpackages.vhd VHDL packages

synopsys_sim.setup Setup file

fifo.test_top.v Verilog top level instantiating program and

fifo.test_top.vhd VHDL top level instantiating program and

fifo_env.v environment, generator, transactor file

fifo_test_00_default.v program testbench

fifo_test_01_extend.v extend program testbench

fifo.h SystemC Models of FIFO

scu_dut.h SystemC wrapper file

fifo_sysc_helper.h SystemC helper files(automatically created)

Files for Using Advanced Features in VCS to Verify Your Design


B-3
fifo.idf SystemC interconnect definition file

Chapter B: Testbench Files and Structure


B-4
C
Verification IP C
Verification components help to automate the creation of a
verification environment. The VCS solution, besides fully supporting
DesignWare verification IP, has added an Assertion IP Library
components for standard protocols to help with verification tasks.

C-1
Assertion IP Library
Today’s designs have to conform to complex functional
specifications. Many of the design components use
industry-standard protocols in order to easily plug and play with other
system components. However these complex protocols such PCIX
standard usually require sophisticated verification environment to
validate the design. In order to fully test compliance to the standard
protocol, the Assertion IP Library components supported in VCS
provides a set of checkers that can be used to verify complex
protocols. The VCS Assertion IP Library contains a set of checkers
that can be used to verify complex protocols. The VCS Assertion IP
Library allows designers to perform functional checks during
simulation, identify and report protocol violations, and capture
assertion coverage data. You can easily augment your verification
environment, the constrained-random stimulus generation and
coverage routines with the assertion IP at the block-level to full
chip-level environment. As mentioned before, these components are
pre-built and pre-verified to comply with the standard protocols. You
can configure the assertion IP according to the functionality of your
design-under-test. Each IP contains set of assertions to monitor the
protocol behavior and coverage targets to aid in finding out more
about how far test cases exercise the respective protocol
functionality.

Included as a standard feature with the VCS 2005.06 and later


relapses, the VCS Assertion IP is provided for the following interface
and protocol standards:

PCI and PCI-X® 2.0 interface, AMBA 2 AHB and APB, 802.11a-g,
AGP, SMIA, DDR2, OCP 2.0 and LPC.

Chapter C: Verification IP
C-2
Please refer to $VCS_HOME/aip/ directory for complete component
list.

The VCS Verification IP (VIP) Library


The VCS Verification IP provide the framework for building
constrained-random stimulus for many of today’s complex standard
protocols. These components can be plugged in the verification
environment and create random scenarios based on the
configuration of the design-under-test. Also as part of the complete
functionality, these VIP components provide full monitors and
coverage to aid design teams in their verification tasks. The library
contains many popular standard protocols such as PCI, PCI-X, PCI
Express, USB 2.0, Ethernet, Serial ATA, AMBA, as well as memory
models.

For more information on verification and implementation IPs please


check the Verification IP site: http://www.synopsys.com/products/
designware/designware.html

The VCS Verification IP (VIP) Library


C-3
Chapter C: Verification IP
C-4

You might also like