[go: up one dir, main page]

0% found this document useful (0 votes)
52 views13 pages

Lab2 Layered Verficiation

1. The objectives of using a layered testbench approach are to divide the verification code into smaller and more manageable pieces that can be developed separately, and to allow for reuse of verification IP components. This helps overcome the limitations of a flat testbench design. 2. SystemVerilog is an object-oriented hardware description and verification language that supports features like classes, objects, interfaces, assertions and functional coverage that improve on Verilog for verification purposes. 3. The document describes creating a basic class in SystemVerilog that defines some data properties and methods, and shows instantiating an object of that class in a testbench module to demonstrate its use.

Uploaded by

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

Lab2 Layered Verficiation

1. The objectives of using a layered testbench approach are to divide the verification code into smaller and more manageable pieces that can be developed separately, and to allow for reuse of verification IP components. This helps overcome the limitations of a flat testbench design. 2. SystemVerilog is an object-oriented hardware description and verification language that supports features like classes, objects, interfaces, assertions and functional coverage that improve on Verilog for verification purposes. 3. The document describes creating a basic class in SystemVerilog that defines some data properties and methods, and shows instantiating an object of that class in a testbench module to demonstrate its use.

Uploaded by

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

Department of Electrical & Electronic Engineering

Bangladesh University of Engineering & Technology

EEE458 VLSI II Laboratory


Laboratory Module 2:
ASIC Front End Design: Layered Verification of a digital sub-system

Objectives:
The overcome the limitations of flat testbench, a key concept that was developed is the layered
testbench. Initially it would seem, to make the testbench more complex, but actually it makes the
task easier by dividing the code into smaller pieces that can be developed separately. If we write a
single routine that can randomly generate all types of stimuli, both legal and illegal, plus inject
errors with a multi-layer protocol, the routine will quickly become complex and unmaintainable. In
addition, a layered approach allows reuse and encapsulation of Verification IP (VIP) which are
Object Oriented Programming (OOP) concepts. These requirements can not be fulfilled by a
hardware description language such as Verilog. This limitations leads to the development of the
hardware verification language SystemVerilog which is an OOP language.

Lab 2 1. Introduction to SystemVerilog

A digital hardware design language such as Verilog has to represent digital hardware at the
following levels:

1. Netlist: A netlist describes logic gates and switches (pass transistors) connected by wires,
organized into a hierarchical structure of modules, with a naming system. The leaf modules are
cells (in ASIC designs).

2. Register transfer: At register transfer level, a logic design consists of Boolean and integer
arithmetic expressions and concurrent assignments to clocked registers. The expressions that
represent combinational logic may be evaluated by asynchronous data flow and should not contain
loops (cycles). In the concurrent assignments, all the expressions on the right hand side must be
evaluated before the left hand sides are updated. To describe complex and regular Boolean
expressions, it is convenient to be able to use procedural code including user-defined functions, like
in a general-purpose programming language.
However, besides the above 2 levels, a digital hardware verification language such as
SystemVerilog has to represent digital hardware at the following additional levels:

3. General programming: To model the scenarios of the environment for simulation, and to
instrument the code for debugging, it is necessary to have I/O functions like in a general purpose
programming language, as well as concurrent processes with waiting for times or events. It is
useful to be able to link to other code, such as a third party tool.

4. Testbench: A very concise way of generating a variety of test cases is to use constrained
randomized data and sequences. For example a data packet can be constructed with various header

©ABM H. Rashid, Dept. of EEE, BUET Page 1 29/11/2022


fields and a payload. There are constraints on the fields and these must be provided to a constraint
solver. Such a packet must be created and then kept for a while in the simulation, so it requires
heap storage. Variations of the packet are needed for testing, so an object-oriented or aspect-
oriented language is convenient. The testbench also needs a flexible connection to the design under
test (DUT).

5. Temporal properties: Many of the bugs in hardware design are caused by incorrect sequences
of signals. Specifying and checking a hardware communication protocol requires the expression of
temporal properties. These are most conveniently written like the regular expressions of a finite
state grammar, with sequences of Boolean expressions and timing.

6. Functional coverage: It is important to check that verification has included all control states,
significant data values, and combinations of these. For this purpose it is necessary to specify when
they are sampled and what values or ranges are significant.

The following table shows the basic difference between Verilog and SystemVerilog in terms of
capability of hardware verification.

Table1 Difference between Verilog and SystemVerilog


Verilog SystemVerilog
Verilog is a HDL(Hardware Description SystemVerilog(SV) is both a HDL and HVL(Hardware
Language). Verification Language),so combined termed as HDVL.
Verilog has mainly 2 data types Reg SV is enriched with wide variety of data type like int,
and Wire which are 4 valued logic shortint, longint, logic, bit, real, realtime, reg, user defined
0,1,X,Z. data type etc. which are both combination of 4 and 2 valued
logic.
Verilog has a single always block for SV uses always_ff, always_comb, always_latch construct
implementation of combinational and for use of different logic.
sequential logic.
Verilog does not have interface SV uses interface construct which is used for bunching of all
construct. the signals along with clocking block which is used for
synchronization unlike Verilog in which instantiation with
the DUT becomes tedious because of large number of
signals.
Verilog uses module level testbench. SV uses Class based testbench which is dynamic in nature.
Verilog does not have Coverage and Features like Functional Coverage, SV assertions and
Assertion features. constraint random verification can only be possible with SV
which helps in debugging purpose and to discover uncover
bugs

Lab2 2. SystemVerilog Class and Creation of a Class.

SystemVerilog is an object oriented programming language. In Object Oriented Programming


Paradigm a program is broken into classes (data and methods) and objects (which are instances of
classes). Objects operate on their own data.

Object Oriented Programming (OOP) in SystemVerilog is supported through the “Class Data
type”. SystemVerilog OOP comprises of few key concepts, listed below:

 Class - a basic building block containing routines and variables. A class encapsulates the data
together with the routines that manipulate it. One of the most important features of classes (and

©ABM H. Rashid, Dept. of EEE, BUET Page 2 29/11/2022


OOPS in general) is inheritance. It allows for new classes to be created by inheriting properties
from previously defined classes. The new class is called the “derived class” while the old class is
referred to as the “base class”. Hence inheritance is the ability to extend or override those
containers with additional data and new behaviors. The followings are some properties of class.

 Object - an instance of a class. An “object” may contain data (data fields - strings, integers, etc.)
and methods (member functions) that operate on the data.

 Handle - a pointer to an object.

 Property - a variable that holds data.

 Method - the procedural code that manipulates variables, contained in tasks and functions.

 Prototype - the header of a routine that shows the name, type, and argument list. The body of the
routine contains the executable code.

Lab2 2-1 : Setup the Working Environment

In you working directory create a directory named ‘cds_digital’ ($mkdir cds_digital)


Move to cds_digital ($cd cds_digital)
Now copy the working directory as follows :

$cp –R /home/cad/VLSI2Lab/Digital/Demo_3_Class Demo_3_Class.

Similarly copy the Demo_4_CB, Demo_5_Rand_Event_Thread, Demo_6_Inheritance and the


ALU_layered directory.

Lab2 2-2 : Creating a Class

The following shows defining a class named as somecls. It has two data types and a void function
named as print();

(a) Define a class named as somecls.sv

class somecls;
//CLass Properties
int some_int;
bit [7:0] some_byte;

//Class Methods
function void print();
$display("*****************************************");
$display(" SumCls Data ");
$display("*****************************************");
$display(" some_int = %0d", some_int );
$display(" some_byte = %b" , some_byte );
$display("*****************************************");

©ABM H. Rashid, Dept. of EEE, BUET Page 3 29/11/2022


endfunction

extern function void some_int_inc();


endclass

function void somecls::some_int_inc();


some_int++;
endfunction

(b) Now define an example named ex1_tb.sv

`include "somecls.sv"

module toptb;
somecls somecls0, somecls1, somecls2;

initial begin
somecls0 = new();
somecls0.some_int = 5;
somecls0.some_byte = 8'b10100110;
$display("");
$display("Displaying data for somecls0");
$display("");
somecls0.print();
end
endmodule

(c) Execute the command


Move to Demo_3_Class. In this directory. From this directory go to the ‘run’ directory and
execute the following command:

$irun +access+r -disable_sem2009 -svseed random -incdir ../src/ -sysv ../src/ex1_tb.sv


Alternately you can source the run shell script as follows : $source run.sh

The irun utility provides a use-model to run simulations with Incisive Unified Simulator (IUS) in a
simple and consistent manner. The main benefit of irun is that it can simulate the multi-language
design & verification environments in a single step by simply specifying all input source files and
options on a single command line!!

After the run the following Design hierarchy summary will be displayed:
Instances Unique
Modules: 1 1
Registers: 7 9
Initial blocks: 1 1
Compilation units: 1 1

©ABM H. Rashid, Dept. of EEE, BUET Page 4 29/11/2022


SV Class declarations: 1 1
SV Class specializations: 1 1
Writing initial simulation snapshot: worklib.toptb:sv
Loading snapshot worklib.toptb:sv .................... Done
ncsim>source /home/eda/cadence/lnx/INCSIVE/icd/icdcm_t1b_016/flow/INCISIV/INCISIV151/
15.10.015/lnx86/tools/inca/files/ncsimrc
ncsim> run

The following data will be Displayed for somecls0

*****************************************
SumCls Data
*****************************************
some_int = 5
some_byte = 10100110
*****************************************
ncsim: *W,RNQUIE: Simulation is complete.
ncsim> exit

Lab2 2-3 : Creating new object and copying Class Properties

Examine the output with the source code and try to understand Class properties.

Next we will observe the copy function of class properties. To do this open the ex2_tb.sv file and
see how somecls1 is defined and copied the properties and data of somecls0.

Now modify the run.sh shell command to run the ex2_tb.sv file and observe the output.

data and properties.

Repeat this for ex3_tb and find some more properties of class.

Finally run toptb.sv and learn more interesting properties of class.

©ABM H. Rashid, Dept. of EEE, BUET Page 5 29/11/2022


Lab 2 3. SystemVerilog handle, Interface and Clocking Block:
Connecting Testbench and Design.
3-1 The handle construct

Both Verilog and OOP have the concept of instantiation, but there are some differences in the
details. SystemVerilog stimulus objects are constantly being created and used to drive the DUT and
check the results. Later, the objects may be freed so their memory can be used by new ones.
In example below ‘sc’ is a handle that points to an object of type simpleclass . For brevity, you can
just say ‘sc’ is a simpleclass handle.

//example of instantiation

initial
begin
simpleclass sc; //declare a handle
sc = new(); //Allocate a simpleclass object.
end

When you declare the handle sc, it is initialized to the special value null. A handle is an indirect
reference to a class object, like a pointer to an address in memory. Unlike pointers in other
languages such as C/C++, you are very limited in what you can do with a handle in SystemVerilog.
It allocates the space to hold handle sc of simpleclass, but not the objects itself.
On the next line, call the new() function to construct the simpleclass object. The new keyword is a
constructor, it creates the object.

3-2 The Interface construct

SystemVerilog interface can be considered as an intelligent bundle of wires. It contains the


direction, connectivity, synchronization and optionally the functionality of the communication
between two or more blocks. They connect between blocks and/or testbenches.

The signals of the alu developed in Lab 1 are put to-gather in an interface. The clock can be part of
the interface or a separate port. The interface is defined with a clocking block. Clocking blocks
have been introduced in SystemVerilog to address the problem of specifying the timing and
synchronisation requirements of a design in a testbench. A clocking block is a set of signals
synchronised on a particular clock. It basically separates the time related details from the structural,
functional and procedural elements of a testbench. It helps the designer develop testbenches in
terms of transactions and cycles. Clocking blocks can only be declared inside a module, interface or
program. The following figure shows alu interface and an example code is shown below:

©ABM H. Rashid, Dept. of EEE, BUET Page 6 29/11/2022


Driver Monitor
alu_if
Command
Signal modport Monitor
modport Driver DUT

Driver_cb Mon_cb

interface alu_if(input clk);


logic [7:0] a,b;
logic [3:0] s;
logic [15:0] out;
clocking driver_cb @(negedge clk);
default input #3 output #2;
output a,b,s;
endclocking

clocking mon_cb @(negedge clk);


default input #3 output #2;
input a,b,s;
input out;
endclocking

modport DRIVER (clocking driver_cb, input clk);


modport MONITOR (clocking mon_cb, input clk);

endinterface

3-3 Logic vs. Wire in an interface


Note that the logic data type is used that lets you use signals via assign statement and in a
procedural block. Remember that in Verilog you could drive a reg only in procedural block and
wire only in assign statement. Another reason is that signal connected to the DUT should support
the 4-states so that X/Z values can be caught. If these signals were bit then X/Z would have shown
up as 0, and you would missed that the DUT had a X/Z value.

3-4 Controlling Timing with a Clocking block


Next we introduced clocking block. Signals that are specified inside a clocking block will be
sampled or driven with respect to that clock. There can be multiple Colcking block in an interface
as there is a single clock expression in each block. Typical clock expressions are @(posedge clk)
for a single edge clock and @clk for a double data rate (ddr) clock. You want to control when the
testbench drives and samples signals from DUT. In the above example, we have specified that by
default, input should be sampled 3ns before negedge of clk, and output should be driven 2ns after
negedge of clk.

Once you have defined a clocking block, your testbench can wait for the clocking expression with
@alu_if.cb rather than having to spell out the exact clock and edge. Now if you change the clock or
edge in the clocking block, you do not have to change your testbench.

©ABM H. Rashid, Dept. of EEE, BUET Page 7 29/11/2022


3-5 Grouping Signals in an Interface Using Modports
The testbench in exmpale 3 uses a point-to-point connection scheme with no signal directions in the
interface. The original modules using ports had this information that the compiler uses to check for
wiring mistakes. The modport construct in an interface lets you group signals and specify
directions. The DRIVER and the MONITOR modport in the example above allows you to connect
a DRIVER and a MONITOR module to the interface. Different MODPORT directions can be
passed to different components that allow us to define different input-output directions for each
components.

There are two ways to use these modport names in your design. You can specify them in the
modules that connect to the interface signals. The alternative is to specify the modport when you
instantiate the module.

3-6 Example of Interface and clocking block : a counter example

There are Here we will use interface and clocking block to simulate a counter.

Below is the code of counter.sv

module counter(clk, rst, load, data, out);


input clk;
input rst;
input load;

input [7:0] data;


output reg [7:0] out;

always @(posedge clk) begin


if(rst) out <= 0;
else if (load) out <= data;
else #8 out <= out + 1;
end
endmodule

The following shows the interface

interface counter_interface(input bit clk, rst);


logic [7:0] data;
logic [7:0] out;
logic load;

clocking clocking_cb @(posedge clk);


default input #1 output #2;
input out;
output data;
output load;
endclocking

clocking clocking_cb_b @(posedge clk);


default input #3 output #1;
input out;
endclocking
endinterface

©ABM H. Rashid, Dept. of EEE, BUET Page 8 29/11/2022


Viewing the following shows the top level testbench

interface counter_interface(input bit clk, rst);


logic [7:0] data;
logic [7:0] out;
logic load;

clocking clocking_cb @(posedge clk);


default input #1 output #2;
input out;
output data;
output load;
endclocking

clocking clocking_cb_b @(posedge clk);


default input #3 output #1;
input out;
endclocking
endinterface

3-7 Executing and Viewing the waveform in simvision

Move to Demo_4_CB and execute the irun in the run directory. After the program is executed the
output waveform will be generated.
Cadence simvision EDA tool is used to view waveform generated by digital simulators such as
ncsim. To view the waveforms in simvision

Open Simvision in your RUN directory with the command $simvision &
In simvision
Click File  Open Database  Display File of Type  VCD File.

Select the signals and you will get the waveform as shown below :

©ABM H. Rashid, Dept. of EEE, BUET Page 9 29/11/2022


Lab 2 4. SystemVerilog Interprocess Communication : Events and
Threads

A testbench has many threads running in parallel. All of these threads need to synchronize and
exchange data. At the most basic level, one thread waits for another, such as the environment
object waiting for the generator to complete. Multiple threads might try to access a single resource
such as bus in the DUT, so the testbench needs to ensure that one and only one thread is granted
access. At the highest level, threads need to exchange data such as transaction objects that are
passed from the generator to the agent. All of this data exchange and control synchronization is
called interprocess communication (IPC), which is implemented in SystemVerilog with events,
semaphores, and mailboxes. These are described in the remainder of this chapter.

There are generally three parts to IPC: a producer that creates the information, a consumer that
accepts the information, and the channel that carries the information.

The producer and consumer are in separate threads

4-1 SystemVerilog Events


A Verilog event synchronizes threads. System Verilog enhances the Verilog event in several ways.
An event is now a handle to a synchronization object that can be passed around to routines. This
feature allows you to share events across objects without having to make the events global. The
most common way is to pass the event into the constructor for an object. In the following code e1
and e2 are defined as 2 events.

event e1, e2.

Events operations are of two staged processes in which one process will trigger the event, and the
other processes will wait for an event to be triggered.

Events are triggered using -> operator or ->> operator.

wait for an event to be triggered using @ operator or wait() construct

SystemVerilog events act as handles to synchronization queues. Thus, they can be passed as
arguments to tasks, and they can be assigned to one another or compared.

Event triggering

-> operator : Named events are triggered via the -> operator. Triggering an event unblocks all
processes currently waiting on that event.

->> operator : Non-blocking events are triggered using the ->> operator

©ABM H. Rashid, Dept. of EEE, BUET Page 10 29/11/2022


Waiting for event trigger

@ operator

wait for an event to be triggered via the event control operator, @.

@(event_name.triggered);

The @ operator blocks the calling process until the given event is triggered.

For a trigger to unblock a process waiting on an event, the waiting process must execute the @
statement before the triggering process executes the trigger operator, ->

4-2 Mailboxes
How can we pass information between two threads? A mailbox is a communication mechanism that
allows messages to be exchanged between processes. The process which wants to talk to another
process posts the message to a mailbox, which stores the messages temporarily in a system defined
memory object, to pass it to the desired process.
Based on the sizes mailboxes are categorized as,
bounded mailbox
unbounded mailbox
A bounded mailbox is with the size defined. Mailbox becomes full on storing a bounded number of
messages. A process that attempts to place a message into a full mailbox shall be suspended until
enough space becomes available in the mailbox queue.
Unbounded mailboxes are with unlimited size.

Mailbox types
There are two types of mailboxes,
Generic Mailbox
Parameterized mailbox

Generic Mailbox (type-less mailbox) :The default mailbox is type-less, that is, a single mailbox
can send and receive data of any type.
mailbox mailbox_name;
Parameterized mailbox (mailbox with particular type) : Parameterized mailbox is used to transfer
a data of particular type.
mailbox #(type) mailbox_name;
Mailbox Methods :SystemVerilog Mailbox is a built-in class that provides the following methods.
These are applicable for both Generic and Parameterized mailboxes
new(); - Create a mailbox
put(); - Place a message in a mailbox
try_put(); - Try to place a message in a mailbox without blocking
get(); or peek(); - Retrieve a message from a mailbox
num(); - Returns the number of messages in the mailbox
try_get(); or try_peek(); - Try to retrieve a message from a mailbox without blocking

©ABM H. Rashid, Dept. of EEE, BUET Page 11 29/11/2022


Creation of Mailbox :
A mailbox is an object and thus has to be instantiated by calling the new function. This takes an
optional size argument to limit the number of entries in the mailbox. If the size is 0 or not specified,
the mailbox is unbounded and can hold an unlimited number of entries.
You put data into a mailbox with the put() task, and remove it with the blocking get() task. A put()
blocks if the mailbox is full, and get() blocks if the mailbox is empty. Use try_put() if you want to
see if the mailbox is full. and try_get() to see if it is empty. The peek() task gets a copy of the data
in the mailbox but does not remove it.
The data is a single value, such as an integer, or logic of any size or a handle. A mailbox never
contains objects, only references to them. By default, a mailbox does not have a type, so you could
put any mix of data into it. Don’t do it! Enforce one data type per mailbox by sticking with
parameterized mailboxes as shown in Sample below to catch type mismatches at compile time
Mailbox #(packet) mbx_pr //Parameterized : recommended
Mailbox mbx_pr //Unspecified : avoid
Mailboxes are created with the new() method.
mailbox_name = new(); // Creates unbounded mailbox and returns mailbox handle
mailbox_name = new(m_size); //Creates bounded mailbox with size m_size and returns
mailbox handle ,where m_size is integer variable

4-3 Execution of Event and Inter Process Communication.


Move to Demo_5_Rand_Event_Thread. Study the producer.sv, consumer.sv, transaction.sv and
tp_top.sv. Now execute the testbench and observe the output.

Lab 2 5. SystemVerilog Inheritance

Inheritance is an OOP concept that allows one to extend a class to create another class with the
ability to access to all the properties and methods of the original parent class from the handle of a
new class object. This allows us to create modification without touching the base class at all.

5-1 Virtual Methods

SystemVerilog Methods declared with the keyword virtual are referred to as virtual methods.

Virtual Methods
Virtual Functions : A function declared with a virtual keyword before the function
keyword is referred to as virtual Function
Virtual Tasks : Task declared with a virtual keyword before the task keyword is referred
to as virtual task

In a virtual method, if the base_class handle is referring to the extended class, then the extended
class method handle will get assigned to the base class handle.
In the below explanation, extended_class is an extended class of base_class.

base_class pbr;
extended_class epr;

©ABM H. Rashid, Dept. of EEE, BUET Page 12 29/11/2022


Considering both the class's has the method display().

assigning epr to bpr,

bpr = epr;

On calling bpr.display()

if display() method in base_class is virtual, then extended class display method will get called
if display() method in base_class is non-virtual, then base class display method will get called

Lab 2 6. Layered testbench for efficient testing of the ALU.

Move to ALU_layered and move to the run directory. Study the run shell script and see which one
is the top level testbench. Study all the dependent files and see how layered testing of ALU is
planned and coded.

Now execute the irun and observe the output.

You will get the following output

ncsim> run
------------------Scoreboard Test Starts--------------------
Passed : a= 0 b=128 s=15 Expected out=65535 Resulted out=65535
Passed : a= 8 b=235 s=15 Expected out= 7 Resulted out= 7
Passed : a= 19 b=137 s=15 Expected out= 18 Resulted out= 18
Passed : a= 97 b= 77 s=14 Expected out= 98 Resulted out= 98
Passed : a= 34 b= 91 s=15 Expected out= 33 Resulted out= 33
------------------Scoreboard Test Ends--------------------
Simulation complete via $finish(1) at time 65 NS + 1
../testbench/environment.sv:39 $finish;

Report :
1. Intentionally introduce some bugs in the RTL code of the ALU and use layered testbench to
identify the bugs. Modify your testbench to increase coverage as much as possible and to
identify all the errors.
2. Report the performance of your testbench and suggest testing strategies that can enhance
coverage, reduce verification time and efforts.

©ABM H. Rashid, Dept. of EEE, BUET Page 13 29/11/2022

You might also like