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

SV Lab Manual

Here are the key steps to implement deep copy in SystemVerilog: 1. Declare a copy() method in each class that performs a member-wise copy of the class. 2. The copy() method should return a handle to a new instance of the class. 3. When copying derived classes, the copy() method must also perform a deep copy of any base classes. 4. To test it: - Create two handles to the same class instance - Perform a shallow copy by assigning one handle to the other - Modify the copy and check if the original is also modified - Perform a deep copy using the copy() method - Modify the copy and check if the original is not modified

Uploaded by

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

SV Lab Manual

Here are the key steps to implement deep copy in SystemVerilog: 1. Declare a copy() method in each class that performs a member-wise copy of the class. 2. The copy() method should return a handle to a new instance of the class. 3. When copying derived classes, the copy() method must also perform a deep copy of any base classes. 4. To test it: - Create two handles to the same class instance - Perform a shallow copy by assigning one handle to the other - Modify the copy and check if the original is also modified - Perform a deep copy using the copy() method - Modify the copy and check if the original is not modified

Uploaded by

Shakeel Scet
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 20

SystemVerilog

Lab Manual
CONTENTS
LAB1: DATATYPES

Objective: Understand the usage of SystemVerilog Datatypes such as associative arrays

LAB2: INTERFACE

Objective: Understand the usage of SystemVerilog interface construct

LAB3: OOP Basics

Objective: Understand the usage of Class, Basics of OOP such as handle assignment

LAB4: ADVANCED OOP

Objective: Understand deep copy, inheritance and the usage of virtual functions
(polymorphism)

LAB5: RANDOMIZATION

Objective: Understand the usage of Random variables and Constraints

LAB6: THREADS, MAILBOX and SEMAPHORE

Objective: Understand the usage of threads, mailbox and semaphore

LAB7: TRANSACTION

Objective: Understand transaction and how to create transaction

LAB8: TRANSACTORS

Objective: Understand the usage of transactors like generator, driver, monitor and
reference model

LAB9: SCOREBOARD

Objective: Understand the usage of scoreboard

LAB10: ENVIRONMENT

Objective: Understand the usage of environment


LAB1: DATATYPES

Objective: Understand the usage of SystemVerilog Datatypes such as


associative arrays

 Working directory : ../labs/lab01

 In mem_model.sv add the following


o Declare an associative array of bit type(32 bits) and is indexed using bit
type(32 bits)
o Declare another associative array for storing the random address of bit
type(32 bits) and index type(32 bits)

o In the task write


 Declare input arguments
 addr - 32 bits(Type bit), data – 32 bit(Type bit)
 Update the associative array with the data content
based on the addr
o In the task read
 Declare input arguments
 addr – 32 bits(Type bit)
 Display the associative array contents based on the addr

o Within initial block


 Perform 10 random writes by calling the write task
 Generate random address and data for writes
 Note – Store the random address in another associative
array declared for storing the address
 Perform 10 reads from the already written locations by calling
the read task
 Use the same address generated for writes
 Display the associative array contents as following
 Display the entire array
 The first index of the array
 The first element of the array
 The last index of the array
 The last element of the array

o Optional : Explore other manipulative array methods such as reduction


methods, ordering methods, etc.

o Execute the file using : qverilog mem_model.sv


Expectation: Use all the available array methods and manipulate the array elements

LAB2 : INTERFACES

Objective: Understand the usage of SystemVerilog interface construct

 Working directory : ../labs/lab02/env

 In ram_if.sv add the following

o Declare the interface signals


 data_in, data_out(logic type , size 64)
 read, write(logic type, size 1)
 rd_address, wr_address (logic type , size 12)

o Add driver clocking block dr_cb that is triggered at posedge of clock


 Give the following direction to the signals
 output : data_in, wr_address, write, rd_address, read
 input : data_out

o Add monitor clocking block mon_cb that is triggered at the posedge of


clock
 Give the following direction to the signals
 input : data_in, wr_address, write, rd_address,
read, data_out

o Add driver modport DRV_MP with driver clocking block(dr_cb) as the


input argument

o Add monitor modport MON_MP with monitor clocking block(mon_cb) as


the input argument

 In driver.sv add the following

o Define the module and pass the driver interface instance argument
o Include the read and write tasks provided within the driver module

 In monitor.sv add the following

o Define the module and pass the monitor interface instance argument
o Declare an associative array(mem) of bit type(64 bits) indexed by int

o In always block
 if write operation
 Update the associative array based on interface write
address and data
 For eg :
mem[mon_if.mon_cb.wr_address]=mon_if.mon_cb.data_in
 If read operation call the check task provided and pass the read
address and data_out from the interface
 Understand and include the check task that compares the actual
data from the DUT and expected data(saved in associative array)

 Working directory : ../labs/lab02/test

 In testcase.sv add the following

o Within initial
 Perform 10 write operations by calling the driver write task to the
first 10 address locations (incremental)
o Perform 10 read operations by calling the driver read task

 Working directory : ../labs/lab02/env

 In top.sv add the following

o Instanstiate interface ram_if


o Instantiate driver and pass interface instance name
o Instantiate monitor and pass interface instance name
o Instantiate testcase
o Generate clock

 Working directory : ../labs/lab02/sim

 Execute : Make run_test


 Make run_gui (GUI Version)

Expectation : Run the Simulation in the GUI mode. Observe 10 write transactions
followed by 10 read transactions w.r.t RAM DUT signals on the
waveform.

LAB 3 - OOP Basics

Objective: Understand the usage of Class, Basics of OOP such as handle


assignment
 Working directory : ../labs/lab03

 In Handle_Object.sv

o Declare class account_c

 Declare variable balance as int type


 Write a function summary
 returns balance
 Write a task deposit with pay(int type) as the input argument
 add pay with the balance

o Declare an handle for class account_c

o Within initial block


 Create an instance of the class
 Call method deposit and pass pay value as the input argument
 Call method summary to display balance

o Execute the file using : qverilog Handle_Object.sv

Observation : Basic class syntax, construction of object and accessing object


variables.

 Working directory : ../labs/lab03

 In pkt_class.sv add the following

o Declare class packet


 Declare the following class properties
 data (bit type, size 4)
 addr (bit type, size 16)
 mem (bit type, size 16)

o Declare two handles for the packet class pkth1, pkth2

o Within initial block


 Construct pkth1 object
 Assign random values to the addr, data and mem of pkth1 object
 Assign pkth1 to pkth2
 Make changes to addr and data using handle pkth2
 Display the addr and data using handle pkth1
 Observe that pkth1 and pkth2 will display the same
contents because both the handles point to the same
object

 Execute the file using qverilog : pkt_class.sv

Expectation : Assigning Class handles. Assigning one class handle to another does
not perform copy, instead both the handles point to the same object.

LAB 4 - Advanced OOP

Objective: Understand deep copy, inheritance and the usage of virtual


functions (polymorphism)

 Working directory : ../labs/lab04

 In deep_copy.sv add the following

o In class parity_calc_c
 Declare parity (bit type, size 8)
 Write copy method that returns parity_calc_c class type
 Create copy instance
 Copy all the current properties into copy object

o In class packet_c
 Declare header (bit type , size 8), initialize it with some default
value
 Declare data (bit type , size 8), initialize it with some default value
 Create parity_calc_c instance
 Write copy method that returns packet_c class type
 Create copy instance
 Copy all the current properties into copy object

o Declare 2 handles pkt_h1, pkt_h2 of packet_c

o Within initial
 Create pkt_h1 object
 Use shallow copy method to copy pkt_h1 to pkt_h2
 Display the parent class and subclass properties of pkt_h1 and
pkt_h2
 Use %p to display class contents
 Assign random value to the header of pkt_h2
 Display the parent class and subclass properties of pkt_h1 and
pkt_h2
 Observe pkt_h1.header does not change (Shallow Copy)

 Change parity of pkt_h2 using the subclass handle from the class
packet_c
 Ex : pkt_h2.sub_par_h.parity=19;

 Display the parent class and subclass properties of pkt_h1 and


pkt_h2
 Observe that parity also changes in pkt_h1 as the both the
subclass handles are pointing to the same subclass object

 Perform deep copy by calling the parent class Copy method


 Ex : pkt_h2=pkt_h1.copy;
 Change parity of pkth2
 pkt_h2.par_h.parity=210;

 Display parent class and subclass properties of pkt_h1 and


pkt_h2
 Observe that parity does not change for pkt_h1 as they
are two different subclass objects

 Execute the file using qverilog : deep_copy.sv

Expectation :Difference between Shallow Copy and Deep Copy.

 Working directory : ../labs/lab04

 In Inheritance.sv add the following

o In class account_c
 Declare balance as int type and initialize it with value 20
 In the function summary_deposit ,return balance
 In the task deposit,
 Pass an input argument pay(int type)
 Add pay with previous balance
 Extend class account_c1 from account_c
 Override balance as int type and initialize it with value 30
 In function summary,
o The new balance returned should be a summation
of the base class balance and derived class
balance
o Hint : Use super to access balance from base class
 Within initial
 Construct extended class object
 Pass the amount for the method deposit and call method
summary_deposit to display balance
 Call method summary to display balance
o Observe that the super.balance returns the base
class balance

 Execute the file using : qverilog Inheritance.sv

Expectation : Inheritance and accessing the base class members from the extended
class, when the members are overridden.

 Working directory : ../labs/lab04

 In Without_Virtual_Functions.sv add the following

o In class packet_c
 In task send
 Display message “Sending base class packet”

o Extend class badpacket_c from packet_c


 Override task send
 Display message “Sending derived class packet”

o Within initial
 Create instances for badpacket_c and packet_c
 Call send tasks using base and extended handles
 Assign extended class handle to base class handle
 Call send task using base class handle
 Observe that the base class send task is called instead of
the extended class send task even though the base class
handle is pointing to the extended class handle

 Execute the file using : qverilog Without_Virtual_Functions.sv

Expectation : Behaviour of base class methods when they are overridden in the
extended class. Assigning an extended class method to the base class
method does not invoke the extended class overrriden method using
the base class handle.
 Working directory : ../labs/lab04

o Copy Without_Virtual_Functions.sv as With_Virtual_Functions.sv


 Replace task send in the base class with Virtual task send
 Run the simulation
 Observe that the extended class send task is called instead of
the base class send task because the base class handle is
pointing to the extended class handle and the method send() is
Virtual

Expectation : By making the base class methods virtual, the overridden methods in
the extended class can be accessed using the base class handle.

LAB 5 - RANDOMIZATION

Objective: Understand the usage of Random variables and Constraints

 Working directory : ../labs/lab05

 In Constraints.sv add the following :

o Declare class alu_trans_c


 Declare a typedef variable OPERATION of type enum with
LOGIC, ARITH and SHIFT as the values
 Add the following rand fields
 alu_sel_in ( logic type, size 4)
 rand_oper ( OPERATION type)
 Apply following constraints
 If rand_oper = LOGIC then alu_sel_in should be inside
[0:5]
 If rand_oper = ARITH, then alu_sel_in should be inside
[6:9]
 If rand_oper = SHIFT, then alu_sel_in should be inside
[10:15]
 Give weightage of 2 to ARITH operation

o In post_randomized method , display all the values

o Within initial
 Create an instance of alu_trans_c
 Generate 10 set of random values for the instance alu_trans_c
 Randomize using 'assert' or 'if' construct
 Execute the file using : qverilog Constraints.sv

Expectation : Observe that 10 different random values have been generated which is
based on the written constraints.

LAB 6 – THREADS, MAILBOX and SEMAPHORE

Objective: Understand the usage of threads, mailbox and semaphore

 Working directory : ../labs/lab06

 In fork_join.sv add the following

o Execute code using fork join and observe the output


o Execute code using fork join_any and observe the output
o Execute code using fork join_none and observe the output
 Observe the difference in output by commenting and
uncommenting the disable thread

 Execute the file using : qverilog fork_join.sv

Expectation : Observed the difference between fork-join, join_any and join_none

 Working directory : ../labs/lab06

 In mailbox_example.sv add the following

 Declare class packet


o Add the following rand fields
 addr (bit type , size 4)
 data (bit type , size 4)
o In display function pass a string as an input argument
 Display the input string message
 Display Data and Address
o In post_randomize methods call display method
 Pass the string argument as “RANDOMIZED DATA”

 In class generator
o Declare an handle of packet class
o Declare the mailbox parameterized by type class packet
o In constructor
 Pass the mailbox parameterized by packet as an argument
 Assign the mailbox handle to the argument
o In task start
 Generate 10 random packets
 Randomize using assert
 Put the generated random packets into the mailbox

 In class driver
o Declare an handle of packet class
o Declare a mailbox parameterized by type class packet
o In constructor
 Pass the mailbox parameterized by packet as an argument
 Assign the mailbox handle to the argument
o In task start
 Get the 10 generated random packets from the mailbox
 Use display method in the packet class to display the
received data

 In class env
o Create the mailbox instance parameterized by packet
o Declare handles of generator and driver
o In build function
 Create instance of generator and driver by passing mailbox as an
input argument
o In task start
 Call start task of generator and driver within fork join

 Within initial block


o Create an instance of env
o Call build and start task of env

 Execute the file using : qverilog mailbox_example.sv


Expectation : Connection between Generator and the Driver through the mailbox.
Generator generates 10 random data which is put into the mailbox.
Driver gets the 10 random data from the mailbox. This data is used by
the Driver to drive on the DUT interface according to the protocol.

 Working directory : ../labs/lab06

 In semaphore_example.sv add the following

 In class driver
o Write task send with an input argument of string type
 Get the key using semaphore handle
 Display the string which indicates the respective driver
information
 Put the key using sem handle
 Display the string which indicates the respective driver
information

 Declare an array of two drivers

 Declare an handle for semaphore

 Within initial block


o Create instances of drivers
o Create the instance of semaphore handle and initialize it with one key
 Call the send task of both the drivers 10 times within fork and join
 Pass meaningful string messages to indicate the driver
information

 Execute the file using : qverilog semaphore_example.sv

Expectation : Usage of Semaphore where two drivers want to drive the same
interface. Semaphores are used to synchronise between different
components trying to access the same channel for communication.

LAB 7 – TRANSACTION

Objective: Understand transaction and how to create transaction


 Working directory : ../labs/lab07

 In ram_trans.sv
 Declare class ram_trans and add the following
o Declare the following rand fields
 data (bit/logic type , size 64)
 rd_address, wr_address (bit/logic type , size 12)
 read, write (bit/logic type , size 1)
o Declare a variable data_out (logic type , size 64)
o Static variable trans_id (int type), to keep the count of transactions
generated
o Declare static variables no_of_read_trans, no_of_write_trans and
no_of_RW_trans, to keep the count of transactions generated
o Add the following constraints
 wr_address!=rd_address;
 read,write != 2'b00;
 data between 1 and 4294967295
o In display method
 Display the string
 Display all the properties of the transaction class
o In post_randomize method
 If it is only read transaction, increment no_of_read_trans
 If it is only write transaction, increment no_of_write_trans
 If it is read-write transaction, increment no_of_RW_trans
 call the display method and pass a string

 Working directory : ../labs/lab07

 In test.sv, within module ram_test add the following


o Include ram_trans.sv
o Declare an handle of type class ram_trans
o Declare an associative array of type ram_trans indexed by int type
o Within initial,
 Generate 10 random transaction items
 Create an instance of ram_trans handle
 Increment trans_id using handle
 Randomize it
 Copy the handle into the array
o For eg : arr[pkth.trans_id]=pkth;
 Repeat the above 10 times
 Display the array

 Execute the file using qverilog test.sv

Expectation : Generate 10 set of random transactions and store it in an associative


array which can be later used and manipulated using array methods.
LAB 8 - TRANSACTORS

Objective: Understand the usage of transactors like generator, driver, monitor

Note : Copy the ram_trans from lab07/env/ram_trans.sv to labs/lab08/env

 Working directory : ../labs/lab08/env

 In ram_gen.sv add the following


o Declare a class ram_gen
 Declare gen_trans handle of class type ram_trans which has to
be randomized
 Declare data2send handle of class type ram_trans which has to
be put into the mailboxes
 Declare 2 mailboxes parameterized by ram_trans
 In the constructor function new()
 Add mailbox argument parameterized by transaction
class and make the assignment to the mailbox
 And create the object for the handle to be randomized
o In virtual task start
 Inside fork join_none
 Generate random transactions equal to
number_of_transactions(defined in package)
 Increment static variable trans_id present in ram_trans
 Randomize using transaction handle using 'if' or 'assert‘
o If randomization fails, display message "DATA NOT
RANDOMIZED" and stop the simulation
 Copy of gen_trans to data2send.
 Put the shallow copy handle into both the mailboxes

 Working directory : ../labs/lab08/env


 In ram_read_bfm.sv add the following
o In class ram_read_bfm
 Instantiate virtual interface instance rd_if of type ram_if with
RD_BFM modport
 Declare an handle for ram_trans “data2duv”
 Declare a mailbox ‘gen2rd' parameterized by ram_trans
 Understand and include the drive task
 In constructor
 Pass the following as the input arguments
o virtual interface
o mailbox handle parameterized 'gen2rd' ram_trans
o make the connections
 For example : this.gen2rd=gen2rd
o In virtual task start
 Within fork join_none
 Within forever , inside begin end
o get the data from mailbox gen2rd
o call drive task
 In ram_write_bfm.sv add the following
o In class ram_read_bfm
 Instantiate virtual interface instance wr_if of type ram_if with
WR_BFM modport
 Declare an handle for ram_trans “data2duv”
 Declare a mailbox 'gen2wr' parameterized by ram_trans
 Understand and include the drive task
 In constructor
 Pass the following as the input arguments
o virtual interface
o mailbox handle parameterized 'gen2wr' ram_trans
o make the connections
 For example : this.gen2wr=gen2wr
o In virtual task start
 Within fork join_none
 Within forever , inside begin end
o get the data from mailbox gen2wr
o call drive task

 Working directory : ../labs/lab08/env


 In ram_read_mon.sv add the following
o In class ram_read_mon
o Instantiate virtual interface instance rdmon_if of type ram_if with
RD_MON modport
o Declare two handles data2rm,data2sb of class type ram_trans
o Declare two mailboxes mon2rm and mon2sb parameterized by type
ram_trans
o In constructor
 Pass the following properties as the input arguments
 Virtual interface and the two mailboxes as arguments
o make the connections
o In start task
 within fork-join_none
 In forever loop
o Call the monitor task
 Understand the provided monitor task.
Monitor task samples the interface signals
according to the protocol and convert to
transaction items
 Shallow copy data2rm to data2sb.
o Put the transaction item into two mailboxes mon2rm
and mon2sb
 call the display of the ram_trans to display the monitor
data

 In ram_write_mon.sv add the following


o In class ram_write_mon
o Instantiate virtual interface instance wrmon_if of type ram_if with
WR_MON modport
o Declare an handle data2rm of class type ram_trans
o Declare a mailbox mon2rm parameterized by type ram_trans
o In constructor
 Pass the following properties as the input arguments
 pass the virtual interface and the two mailboxes as
arguments
o make the connections
o In start task
 within fork-join_none
 In forever loop
o Call the monitor task
 Understand the provided monitor task.
Monitor task samples the interface signals
according to the protocol and convert to
transaction items
o Put the transaction item into the mailboxes mon2rm
 call the display of the ram_trans to display the monitor
data

 Execute these file using make run_test

Expectation : Implementation of Generator, Write & Read BFMs, Write and Read
Monitors. Write BFM gets the transaction data from the Generator and drives the
interface according to the Write protocol. Read BFM gets the transaction data from
the Generator and drives the interface according to the Read protocol.
Write Monitor samples the interface signals according to the write protocol and
convert interface signals into transactions required by the reference model.
Read Monitor samples the interface signals according to the read protocol and
convert interface signals into transactions required by the scoreboard to generate the
actual data and the reference model to generate the expected data.

LAB 9 - SCOREBOARD

Objective: Understand the usage of scoreboard and reference model


Note : Copy ram_gen.sv, ram_read_bfm.sv, ram_write_bfm,
ram_read_mon.sv and ram_write_mon from lab08/env to lab09/env

 In ram_env.sv add the following


o In class ram_env
o Add 3 more mailboxes "mon2rm", "rm2sb" and "mon2sb" parameterized
by ram_trans
o Create handles for ram_model and scoreboard
o In build task, construct ram_model and scoreboard

 In ram_model.sv add the following


o In class ram_model
 Declare 2 handles "mon_data1" and "mon_data2" of type
ram_trans ( to store the data from the read and write monitor)
 Declare an associative array of 64 bits(logic type) and indexed int
type
 Declare 3 mailboxes "wr2rm","rd2rm" and "rm2sb" parameterized
by ram_trans
 In constructor
 Pass mailboxes as the arguments
 Connect the mailboxes
 Understand and include the task dual_mem_fun_write and
dual_mem_fun_read
 This task performs the following
o During write, the associative array is updated based
on the write address and data
o During read, the expected data is generated by the
associative array based on the read address –
expected data
 In start task
 Within fork join_none
o Within fork join
 Within forever
 Get the data from wr2rm mailbox to
mon_data1
 Call dual_mem_fun_write task and
pass the data "mon_data1" as an
argument
 Within forever
 Get the data from rd2rm mailbox to
mon_data2
 Call dual_mem_fun_read task and
pass the data "mon_data2" as an
argument
 Put "mon_data2" into rm2sb mailbox
 In ram_sb.sv add the following
o In class ram_sb
 Declare an event 'DONE'
 Declare three int datatypes for counting number of read data
from the reference model(rm_data_count), read data received
from the monitor(mon_data_count)),read data verified by the
scoreboard(data_verified)
 Declare ram_trans handles as 'rm_data', 'rcvd_data' and
cov_data
 Instantiate 2 mailboxes as 'rm_in_ch','mon_in_ch' parameterized
by ram_trans
 Write the functional coverage model
 Define a covergroup as 'mem_coverage'
o Define coverpoint and bins for 'write' and 'read'
 Bins only when write =1 and read = 1
o Define cross for write, wr_address, data – valid
writes
o Define cross for read, rd_address, data – valid
reads
o Define cross for write,read,wr_address,rd_address
and data
 In constructor ,
 Connect mailboxes
 Create an instance of mem_coverage
o In start task
 Within fork join_none begin end
 Get the data from mailbox rm_in_ch
 Increment rm_data_count
 Get the data from mailbox mon_in_ch
 Increment mon_data_count
 Call check task and pass 'rcvd_data' handle as the input
argument
 Call the sample function on the covergroup
 Increment data_verified
 Trigger the event when the data_verified is equal to the
number of read transactions
o In function void report
 Display gen_data_count, rcvd_data_count, data_verified
 Execute these files using make run_test

 Expectation : Write functional coverage model and integrate it with


scoreboard, ram reference model and the other components such as write and
read bfms, generator and monitors. Create an env class which has all these
components integrated and connected.

LAB 10 – ENVIRONMENT
Objective: Understand the usage of environment

Note : Copy all the files from ../labs/lab09/ except ram_env.sv

 Working directory : ../labs/lab10/env

 In ram_env.sv add the following

 In class ram_env
o Declare virtual interfaces with Write BFM modport, Read BFM modport,
Write monitor modport, Read monitor modport
o Declare 6 mailboxes parameterized by ram_trans and construct it
o Create handle for ram_gen, ram_read_bfm, ram_write_bfm,
ram_read_mon, ram_write_mon , ram_model and ram_sb
o Declare an event
o In constructor
 pass the BFM and monitor interface instances as the argument
 connect the properties of ram_env
o In build task
 Create instances for generator, Read BFM, Write BFM, Write
monitor, Read monitor, Reference model, Scoreboard
o In virtual task start
 call the task start of generator, Read BFM, Write BFM, Read
monitor, Write Monitor, reference model, scoreboard
o In run task
 Call the provided reset_dut task , start and stop tasks
 Using scoreboard handle call report task

 Execute these files using make run_test

 Three testcases are provided in ../lab10/test, make TC1 and make TC2 for
executing test1.sv and test2.sv

 Use make regress for regression testing

Expectation : Integration of the testbench components with the DUT and Interface. Re-using
the same testbench environment and creating different testcases TC1, TC2, TC3
etc..to drive different type of stimulus. TC1 drives base transactions, TC2 drives
short transactions, and so on..using the same testbench components and
controlling by polymorphism within the testcases.

You might also like