Funvizeo logo
  • Contents
      • Back
      • Verilog
      • SystemVerilog
      • UVM
      • Digital Basics
      • Verification
Most Popular
Verification
  Testbench Evolution
  Constraint Random Verification
  Verification Techniques
  Verification Plan
  Code Coverage

Verilog
  Data Types
  Basic Constructs
  Behavioral Modeling
  Gate Modeling
  Simulation Basics
  Design Examples
  Interview Questions

SystemVerilog
  Data Types
  Class
  Interface
  Constraints and more!
  Testbench Examples
  Interview Questions

UVM
  Sequences
  Testbench Components
  TLM Tutorial
  Register Model Tutorial
  Testbench Examples
  Interview Questions

Digital Fundamentals
  Binary Arithmetic
  Boolean Logic
  Karnaugh Maps
  Combinational Logic
  Sequential Logic

SystemVerilog Class Handle

What is a class handle ?

A class variable such as pkt below is only a name by which that object is known. It can hold the handle to an object of class Packet, but until assigned with something it is always null. At this point, the class object does not exist yet.

Class Handle Example


// Create a new class with a single member called
// count that stores integer values
class Packet;
	int count;
endclass

module tb;
  	// Create a "handle" for the class Packet that can point to an
  	// object of the class type Packet
  	// Note: This "handle" now points to NULL
	Packet pkt;
  
  	initial begin
      if (pkt == null)
        $display ("Packet handle 'pkt' is null");
      
      // Display the class member using the "handle"
      // Expect a run-time error because pkt is not an object
      // yet, and is still pointing to NULL. So pkt is not
      // aware that it should hold a member
      $display ("count = %0d", pkt.count);
  	end
endmodule
 Simulation Log
ncsim> run
Packet handle 'pkt' is null
count = ncsim: *E,TRNULLID: NULL pointer dereference.
          File: ./testbench.sv, line = 18, pos = 33
         Scope: tb
          Time: 0 FS + 0

./testbench.sv:18       $display ("count = %0d", pkt.count);
ncsim> exit

What is a class object ?

An instance of that class is created only when it's new() function is invoked. To reference that particular object again, we need to assign it's handle to a variable of type Packet.

Class Object Example


// Create a new class with a single member called
// count that stores integer values
class Packet;
	int count;
endclass

module tb;
  	// Create a "handle" for the class Packet that can point to an
  	// object of the class type Packet
  	// Note: This "handle" now points to NULL
	Packet pkt;
  
  	initial begin
      if (pkt == null)
        $display ("Packet handle 'pkt' is null");
      
      // Call the new() function of this class
      pkt = new();
      
      if (pkt == null)
        $display ("What's wrong, pkt is still null ?");
      else
        $display ("Packet handle 'pkt' is now pointing to an object, and not NULL");
      
      // Display the class member using the "handle"
      $display ("count = %0d", pkt.count);
  	end
endmodule
 Simulation Log
ncsim> run
Packet handle 'pkt' is null
Packet handle 'pkt' is now pointing to an object, and not NULL
count = 0
ncsim: *W,RNQUIE: Simulation is complete.

What happens when both handles point to same object ?

If we assign pkt to a new variable called pkt2, the new variable will also point to the contents in pkt.


// Create a new class with a single member called
// count that stores integer values
class Packet;
	int count;
endclass

module tb;
  	// Create two "handles" for the class Packet
  	// Note: These "handles" now point to NULL
	Packet pkt, pkt2;
  
  	initial begin

      
      // Call the new() function of this class and 
      // assign the member some value
      pkt = new();
      pkt.count = 16'habcd;
         
      // Display the class member using the "pkt" handle
      $display ("[pkt] count = 0x%0h", pkt.count);
      
      // Make pkt2 handle to point to pkt and print member variable
      pkt2 = pkt;
      $display ("[pkt2] count = 0x%0h", pkt2.count);
  	end
endmodule
 Simulation Log
ncsim> run
[pkt] count = 0xabcd
[pkt2] count = 0xabcd
ncsim: *W,RNQUIE: Simulation is complete.

Now we have two handles, pkt and pkt2 pointing to the same instance of the class type Packet. This is because we did not create a new instance for pkt2 and instead only assigned a handle to the instance pointed to by pkt.

SystemVerilog wait fork

wait fork allows the main process to wait until all forked processes are over. This is useful in cases where the main process has to spawn multiple threads, and perform some function before waiting for all threads to finish.

Example

We'll use the same example seen in the previous article where 3 threads are kicked off in parallel and the main process waits for one of them to finish. After the main thread resumes, let's wait until all forked processes are done.

Read more: SystemVerilog wait fork

SystemVerilog disable fork join

In the previous article, different ways to launch parallel threads was discussed. Now we'll see how to disable forked off threads.

All active threads that have been kicked off from a fork join block can be killed by calling disable fork.

Why disable a fork ?

The following things happen at the start of simulation for the given example:

  1. Main thread executes initial block and finds a fork join_any block
  2. It will launch three threads in parallel, and wait for any one of them to finish
  3. Thread1 finishes first because of least delay
  4. Execution of main thread is resumed

Read more: SystemVerilog disable fork join

SystemVerilog Soft Constraints

The normal constraints are called hard constraints because it is mandatory for the solver to always satisfy them. If the solver fails to find a solution, then the randomization will fail.

However, a constraint declared as soft gives the solver some flexibility that the constraint need to be satisfied if there are other contradicting constraints - either hard or a soft constraint with higher priority.

Soft constraints are used to specify default valus and distributions for random variables.

Example

Shown in the example below is a soft constraint that tells the solver to produce values within 4 and 12 for the variable called data.


class ABC;
  rand bit [3:0] data;
  
  // This constraint is defined as "soft" 
  constraint c_data { soft data >= 4;
                     data <= 12; }
endclass

module tb;
  ABC abc;
  
  initial begin
    abc = new;
    for (int i = 0; i < 5; i++) begin
      abc.randomize();
      $display ("abc = 0x%0h", abc.data);
    end
  end
endmodule

As expected, values of the randomized variable lies within 4 and 12.

 Simulation Log
ncsim> run
abc = 0x4
abc = 0x8
abc = 0x4
abc = 0x7
abc = 0x7
ncsim: *W,RNQUIE: Simulation is complete.

Let's see how a contradicting inline constraint is handled in this case.


module tb;
  ABC abc;
  
  initial begin
    abc = new;
    for (int i = 0; i < 5; i++) begin
      abc.randomize() with { data =%3d.html 2; };
      $display ("abc = 0x%0h", abc.data);
    end
  end
endmodule

See that the contradicting inline constraint allowed the solver to constrain value of the variable to 2.

Remember that it is contradicting because the original constraint c_data is supposed to constrain it within 4 and 12, but the inline constraint asks the variable to be set to 2, which is outside the original range.

 Simulation Log
ncsim> run
abc = 0x2
abc = 0x2
abc = 0x2
abc = 0x2
abc = 0x2
ncsim: *W,RNQUIE: Simulation is complete.

How is it different from hard constraints ?

Let us take the class ABC and turn it into a hard constraint by removing the soft keyword and apply a contradicting inline constraint.


class ABC;
  rand bit [3:0] data;

  constraint c_data { data >= 4;
                     data <= 12; }
endclass

module tb;
  ABC abc;
  
  initial begin
    abc = new;
    for (int i = 0; i < 1; i++) begin
      abc.randomize() with { data =%3d.html 2; };
      $display ("abc = 0x%0h", abc.data);
    end
  end
endmodule

The solver fails in this case because of the contradicting constraint and hence assigns the variable data to 0.

 Simulation Log
ncsim> run
      abc.randomize() with { data == 2; };
                  |
ncsim: *W,SVRNDF (./testbench.sv,14|18): The randomize method call failed. The unique id of the failed randomize call is 4.
Observed simulation time : 0 FS + 0
ncsim: *W,RNDOCS: These constraints contribute to the set of conflicting constraints:

  constraint c_data { data >= 4; (./testbench.sv,4)
      abc.randomize() with { data == 2; }; (./testbench.sv,14)
ncsim: *W,RNDOCS: These variables contribute to the set of conflicting constraints:

rand variables:
       data [./testbench.sv, 2]

abc = 0x0
ncsim: *W,RNQUIE: Simulation is complete.

HDL access routines

UVM has the facility of doing backdoor reads from HDL paths via DPI/PLI interface.

Consider a simple design hierarchy shown below for illustration purposes. We also need a testbench to instantiate the design and start the test.


module B;
	reg [3:0] cfg;
endmodule

module A;
	B b;
endmodule

// Testbench module
module tb;
	A a();
	initial 
		run_test("base_test");
endmodule

uvm_hdl_check_path

import "DPI-C" context function int uvm_hdl_check_path (string path);

This method returns 1 if the given HDL path exists, else it returns a 0.


class base_test extends uvm_test;
	...
	virtual function void build_phase (uvm_phase phase);
		if (uvm_hdl_check_path ("tb.a.b.cfg"))
			`uvm_info ("TEST", "Path tb.a.b.cfg exists", UVM_MEDIUM)
			
		if (!uvm_hdl_check_path ("tb.a.def"))
			`uvm_info ("TEST", "Path tb.a.def does not exist", UVM_MEDIUM)
	endfunction
endclass

Read more: HDL access routines

  1. SystemVerilog Immediate Assertions
  2. UVM Pool
  3. SystemVerilog Clocking Blocks Part II
  4. SystemVerilog fork join_any
  5. SystemVerilog foreach loop

Page 29 of 68

  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
Interview Questions
  Verilog Interview Set 1
  Verilog Interview Set 2
  Verilog Interview Set 3
  Verilog Interview Set 4
  Verilog Interview Set 5

  SystemVerilog Interview Set 1
  SystemVerilog Interview Set 2
  SystemVerilog Interview Set 3
  SystemVerilog Interview Set 4
  SystemVerilog Interview Set 5

  UVM Interview Set 1
  UVM Interview Set 2
  UVM Interview Set 3
  UVM Interview Set 4
Related Topics
  Digital Fundamentals
  Verilog Tutorial

  Verification
  SystemVerilog Tutorial
  UVM Tutorial
Latest in Verilog
  • Verilog $random
  • Verilog VCD Dump
  • Verilog VCD
  • Verilog Namespace
  • Verilog $stop $finish
Latest in SystemVerilog
  • SystemVerilog `define Macro
  • SystemVerilog Callback
  • SystemVerilog Interview Questions Set 10
  • SystemVerilog Interview Questions Set 9
  • SystemVerilog Interview Questions Set 8
Latest in UVM
  • UVM Callback
  • UVM Singleton Object
  • UVM Component [uvm_component]
  • UVM Object [uvm_object]
  • UVM Root [uvm_root]
© 2025 Funvizeo
Terms and Conditions