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

Driver Sequencer Handshake

How does a sequencer communicate with the driver ?

The driver class contains a TLM port called uvm_seq_item_pull_port which is connected to a uvm_seq_item_pull_export in the sequencer in the connect phase of a UVM agent. The driver can use TLM functions to get the next item from the sequencer when required.

uvm-driver-sequencer-connection

Why do we need the driver sequencer API methods ?

These API methods help the driver to get a series of sequence_items from the sequencer's FIFO that contains data for the driver to drive to the DUT. Also, there is a way for the driver to communicate back with the sequence that it has finished driving the given sequence item and can request for the next item.

What is the port in driver called ?

Declaration for the TLM ports can be found in the class definitions of uvm_driver and uvm_sequencer as follows.


// Definition of uvm_driver
class uvm_driver #(type REQ=uvm_sequence_item,
                   type RSP=REQ) extends uvm_component;
  // Port: seq_item_port
  // Derived driver classes should use this port to request items from the
  // sequencer. They may also use it to send responses back.

  uvm_seq_item_pull_port #(REQ, RSP) seq_item_port;

  // Port: rsp_port
  // This port provides an alternate way of sending responses back to the
  // originating sequencer. Which port to use depends on which export the
  // sequencer provides for connection.

  uvm_analysis_port #(RSP) rsp_port;
  REQ req;
  RSP rsp;
  
  // Rest of the code follows ...

endclass

What is the TLM port in sequencer called ?

A uvm_sequencer has an inbuilt TLM pull implementation port called seq_item_export which is used to connect with the driver's pull port.


// Definition of uvm_sequencer
class uvm_sequencer #(type REQ=uvm_sequence_item, RSP=REQ)
                                   extends uvm_sequencer_param_base #(REQ, RSP);
  // Variable: seq_item_export
  // This export provides access to this sequencer's implementation of the
  // sequencer interface.

  uvm_seq_item_pull_imp #(REQ, RSP, this_type) seq_item_export;
  
  // Rest of the class contents follow ...
  
endclass

How is a driver connected to a sequencer ?

The port in uvm_driver is connected to the export in uvm_sequencer in the connect phase of the UVM component in which both the driver and sequencer are instantiated. Typically, a driver and sequencer are instantiated in a uvm_agent.


class my_agent extends uvm_agent;
	`uvm_component_utils (my_agent)
	
	my_driver  		#(my_sequence_item) 	m_drv;
	uvm_sequencer 	#(my_sequence_item)  	m_seqr;
	
	virtual function void connect_phase (uvm_phase phase);
		// Always the port is connected to an export
		m_drv.seq_item_port.connect(m_seqr.seq_item_export);
	endfunction
	
endclass

The connect between a driver and sequencer is a one-to-one connection. Multiple drivers are not connected to a sequencer nor are multiple sequencers connected to a single driver. Once the connection is made, the driver can utilize API calls in the TLM port definitions to receive sequence items from the sequencer.

Verilog Ring Counter

Straight Ring Counter

Design


module ring_ctr  #(parameter WIDTH=4) 
  (  
	input clk,                
	input rstn,
  	output reg [WIDTH-1:0] out
  );    
 
  always @ (posedge clk) begin
      if (!rstn)
         out <= 1;
      else begin
        out[WIDTH-1] <= out[0];
        for (int i = 0; i < WIDTH-1; i=i+1) begin
          out[i] <= out[i+1];
        end
      end
  end
endmodule

Testbench


module tb;
  parameter WIDTH = 4;
  
  reg clk;
  reg rstn;
  wire [WIDTH-1:0] out;
  
  ring_ctr 	u0 (.clk (clk),
                .rstn (rstn),
                .out (out));
  
  always #10 clk = ~clk;
  
  initial begin
    {clk, rstn} <= 0;

    $monitor ("T=%0t out=%b", $time, out);
    repeat (2) @(posedge clk);
    rstn <= 1;
    repeat (15) @(posedge clk);
    $finish;
  end
endmodule
 Simulation Log
ncsim> run
T=0 out=xxxx
T=10 out=0001
T=50 out=1
000
T=70 out=01
00
T=90 out=001
0
T=110 out=0001
T=130 out=1
000
T=150 out=01
00
T=170 out=001
0
T=190 out=0001
T=210 out=1000
T=230 out=0100
T=250 out=0010
T=270 out=0001
T=290 out=1000
T=310 out=0100
Simulation complete via $finish(1) at time 330 NS + 0

SystemVerilog local

A member declared as local is available only to the methods of the same class, and are not accessible by child classes. However, nonlocal methods that access local members can be inherited and overridden by child class.

Example

In the following example, we will declare two variables - one public and another local. We expect to see an error when a local member of the class is accessed from somewhere outside the class. This is because the keyword local is used to keep members local and visible only within the same class.

When accessed from outside the class


class ABC;
  // By default, all variables are public and for this example,
  // let's create two variables - one public and the other "local"
  byte  	  public_var;   
  local byte local_var; 	
  
  // This function simply prints these variable contents
  function void display();
    $display ("public_var=0x%0h, local_var=0x%0h", public_var, local_var); 
  endfunction
endclass

module tb;
  initial begin
    
    // Create a new class object, and call display method
    ABC abc = new();
    abc.display();
    
    // Public variables can be accessed via the class handle
    $display ("public_var = 0x%0h", abc.public_var);
    
    // However, local variables cannot be accessed from outside
    $display ("local_var = 0x%0h", abc.local_var);
  end
endmodule

As expected, the compiler gives out a compilation error pointing to the line where a local member is accessed from outside the class.

 Simulation Log
    $display ("local_var = 0x%0h", abc.local_var);
                                               |
ncvlog: *E,CLSNLO (testbench.sv,24|47): Access to local member 'local_var' in class 'ABC' is not allowed here.
irun: *E,VLGERR: An error occurred during parsing.  Review the log file for errors with the code *E and fix those identified problems to proceed.  Exiting with code (status 1).

In the above example, we can remove the line that causes a compilation error and see that we get a good output. The only other function that accesses the local member is the display() function.


module tb;
  initial begin
    
    ABC abc = new();
    
    // This should be able to print local members of class ABC
    // because display() is a member of ABC also
    abc.display();
    
    // Public variables can always be accessed via the class handle
    $display ("public_var = 0x%0h", abc.public_var);
  end
endmodule
 Simulation Log
ncsim> run
public_var=0x0, local_var=0x0
public_var = 0x0
ncsim: *W,RNQUIE: Simulation is complete.

When accessed by child classes

In this example, let us try to access the local member from within a child class. We expect to see an error here also because local is not visible to child classes either.


// Define a base class and let the variable be "local" to this class
class ABC;
  local byte local_var; 	
endclass

// Define another class that extends ABC and have a function that tries
// to access the local variable in ABC
class DEF extends ABC;  
  function show();
    $display ("local_var = 0x%0h", local_var);
  endfunction
endclass

module tb;
  initial begin
    
    // Create a new object of the child class, and call the show method
    // This will give a compile time error because child classes cannot access
    // base class "local" variables and methods
    DEF def = new();
    def.show();

  end
endmodule

As expected, child classes cannot access the local members of their parent class.

 Simulation Log
    $display ("local_var = 0x%0h", local_var);
                                           |
ncvlog: *E,CLSNLO (testbench.sv,10|43): Access to local member 'local_var' in class 'ABC' is not allowed here.
irun: *E,VLGERR: An error occurred during parsing.  Review the log file for errors with the code *E and fix those identified problems to proceed.  Exiting with code (status 1).

SystemVerilog 'extern'

Class definitions can become very long with a lot of lines between class and endclass. This makes it difficult to understand what all functions and variables exist within the class because each function and task occupy quite a lot of lines.

Using extern qualifier in method declaration indicates that the implementation is done outside the body of this class.

Example


class ABC;
  
  // Let this function be declared here and defined later
  // by "extern" qualifier
  extern function void display();
    
endclass
    
// Outside the class body, we have the implementation of the
// function declared as "extern"
function void ABC::display();
  
   $display ("Hello world");
  
endfunction

module tb;
  
  // Lets simply create a class object and call the display method
  initial begin
    ABC abc = new();
    abc.display();
  end
endmodule
 Simulation Log
ncsim> run
Hello world
ncsim: *W,RNQUIE: Simulation is complete.

Transaction Object

A UVM transaction class typically defines all the input and output control signals that can be randomized and driven to the DUT.

Steps to create a UVM transaction object

1. Create custom class inherited from uvm_sequence_item, register with factory and call new

// my_object is user-given name for this class that has been derived from "uvm_sequence_item"
class my_object extends uvm_sequence_item;
	
	// This is standard code for all components
	function new (string name = "my_object", uvm_component parent = null);
		super.new (name, parent);
	endfunction
	
	// Code for rest of the steps come here
endclass

2. Declare variables related to this transaction class

	// Declare variables and make the ones that has to be randomized as "rand"
	rand bit [15:0] addr;
	rand bit [31:0] data;
	rand bit [2:0]  burst;

3. Register the class with factory and apply UVM field macros if required

	`uvm_object_utils_begin (my_object)
		// Apply the given object macros to the corresponding variables
		`uvm_field_int (addr,  UVM_ALL_ON | UVM_NO_COMPARE)
		`uvm_field_int (data,  UVM_ALL_ON)
		`uvm_field_int (burst, UVM_ALL_ON)
	`uvm_object_utils_end

4. Add constraints as required

	constraint c_addr { addr <= 16'hBFFF; }
	constraint c_burst { burst inside {[0:4]}; }
Define convert2string function

	function string convert2string();
		return $sformatf("addr=0x%0h data=0x%0h burst=0x%0h", addr, data, burst);
	endfunction
  1. Using get_next_item()
  2. Verilog Gate Level Examples
  3. SystemVerilog Packed Arrays
  4. Verilog generate block
  5. Combinational Logic with always

Page 64 of 68

  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
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