image/svg+xml
  • Contents
      • Back
      • Digital Basics
      • Verilog
      • Verification
      • SystemVerilog
      • UVM
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

SystemVerilog
  Data Types
  Class
  Interface
  Constraints and more!
  Testbench Examples

UVM
  Sequences
  Testbench Components
  TLM Tutorial
  Register Model Tutorial
  Testbench Examples

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




SystemVerilog Tutorial

  1. What is SystemVerilog ?
  2. Why is Verilog not preferred ?
  3. What is verification ?
  4. What about Vera, e, and other similar HVL ?

What is SystemVerilog ?

Hardware Description Languages (HDL) like Verilog and VHDL are used to describe hardware behavior so that it can be converted to digital blocks made up of combinational gates and sequential elements. In order to verify that the hardware description in HDL is correct, there is a need for a language with more features in OOP that will support complicated testing procedures and is often called a Hardware Verification Language.

SystemVerilog is an extension of Verilog with many such verification features that allow engineers to verify the design using complex testbench structures and random stimuli in simulation.

Why is Verilog not preferred ?

Back in the 1990's, Verilog was the primary language to verify functionality of designs that were small, not very complex and had less features. As design complexity increases, so does the requirement of better tools to design and verify it. SystemVerilog is far superior to Verilog because of its ability to perform constrained random stimuli, use OOP features in testbench construction, functional coverage, assertions among many others.

What is verification ?

Verification is the process of ensuring that a given hardware design works as expected. Chip design is a very extensive and time consuming process and costs millions to fabricate. Functional defects in the design if caught at an earlier stage in the design process will help save costs. If a bug is found later on in the design flow, then all of the design steps have to be repeated again which will use up more resources, money and time. If the entire design flow has to be repeated, then its called a respin of the chip.

What about Vera, e, and other similar HVL ?

They have been in use for some time. SystemVerilog can be considered an extension of Verilog (the most popular HDL), and it makes sense to verify a Verilog design in SystemVerilog. Also SystemVerilog supports OOP which makes verification of designs at a higher level of abstraction possible.

Read more: SystemVerilog Tutorial

Verilog for Loop

A for loop is the most widely used loop in software, but it is primarily used to replicate hardware logic in Verilog. The idea behind a for loop is to iterate a set of statements given within the loop as long as the given condition is true. This is very similar to the while loop, but is used more in a context where an iterator is available and the condition depends on the value of this iterator.

Syntax


	for (<initial_condition>; <condition>; <step_assignment>) begin
		// Statements
	end

The keyword for is used to specify this type of loop and has three parts:

  1. Initial condition to specify initial values of signals
  2. A check to evaluate if the given condition is true
  3. Update control variable for the next iteration

The initial condition and updates to control variable are included in the for loop and is not required to be specified separately unlike a while loop. A while loop is more general purpose and is mostly used only when the given statements are required to be repeated as long as a given condition. However the for loop tyically has a definite beginning and end controlled by the step variable.

Here is a simple example that illustrates the usage of a for loop.


module my_design;
	integer i;
	
	initial begin
		// Note that ++ operator does not exist in Verilog !
		for (i = 0; i < 10; i = i + 1) begin
			$display ("Current loop#%0d ", i);
		end
	end
endmodule
 Simulation Log
ncsim> run
Current loop#0 
Current loop#1 
Current loop#2 
Current loop#3 
Current loop#4 
Current loop#5 
Current loop#6 
Current loop#7 
Current loop#8 
Current loop#9 
ncsim: *W,RNQUIE: Simulation is complete.

Design Example

Let us take a look at how an 8-bit left shift register can be implemented in Verilog without a for loop and then compare it with the code using a for loop just to appreciate the utility of a looping construct.


module lshift_reg (input 						clk,				// Clock input
                   input 						rstn,				// Active low reset input
                   input [7:0] 			load_val, 	// Load value 
                   input 						load_en, 		// Load enable
                   output reg [7:0] op); 				// Output register value

	 // At posedge of clock, if reset is low set output to 0
	 // If reset is high, load new value to op if load_en=1
	 // If reset is high, and load_en=0 shift register to left
	 always @ (posedge clk) begin
	    if (!rstn) begin
	      op <= 0;
	    end else begin
	    	if (load_en) begin
	      	op <= load_val;
	      end else begin
	        op[0] <= op[7];
	        op[1] <= op[0];
	        op[2] <= op[1];
	        op[3] <= op[2];
	        op[4] <= op[3];
	        op[5] <= op[4];
	        op[6] <= op[5];
	        op[7] <= op[6];
	      end
	    end
	  end
endmodule

The same behavior can be implemented using a for loop which will reduce the code and make it scalable for different register widths. If the width of the register is made a Verilog parameter, the design module will become scalable and the same parameter can be used inside the for loop.


module lshift_reg (input 						clk,				// Clock input
                   input    				rstn,				// Active low reset input
                   input [7:0] 			load_val, 	// Load value 
                   input 						load_en, 		// Load enable
                   output reg [7:0] op); 				// Output register value

	 integer i;
	 
	 // At posedge of clock, if reset is low set output to 0
	 // If reset is high, load new value to op if load_en=1
	 // If reset is high, and load_en=0 shift register to left
	 always @ (posedge clk) begin
	    if (!rstn) begin
	      op <= 0;
	    end else begin
	    
	    	// If load_en is 1, load the value to op
	    	// else keep shifting for every clock
	    	if (load_en) begin
	      	op <= load_val;
	      end else begin
            for (i = 0; i < 8; i = i + 1) begin
              op[i+1] <= op[i];
            end
            op[0] <= op[7];
	      end
	    end
	  end
endmodule

Testbench

The testbench code is shown below and instantiates the design.


module tb;
  reg clk;
  reg rstn;
  reg [7:0] load_val;
  reg load_en;
  wire [7:0] op;
  
  // Setup DUT clock
  always #10 clk = ~clk;
  
  // Instantiate the design
  lshift_reg u0 ( .clk(clk),
                 .rstn (rstn),
                 .load_val (load_val),
                 .load_en (load_en),
                 .op (op));
  
  initial begin
  	// 1. Initialize testbench variables
    clk <= 0;
    rstn <= 0;
    load_val <= 8'h01;
    load_en <= 0;
    
    // 2. Apply reset to the design
    repeat (2) @ (posedge clk);
    rstn <= 1;
    repeat (5) @ (posedge clk);
    
    // 3. Set load_en for 1 clk so that load_val is loaded
    load_en <= 1;
    repeat(1) @ (posedge clk);
    load_en <= 0;
    
    // 4. Let design run for 20 clocks and then finish
    repeat (20) @ (posedge clk);
    $finish;
  end
endmodule
hardware schematic for shift register

Verilog `ifdef Conditional Compilation

Verilog supports a few compiler directives that essentially direct the compiler to treat the code in a certain way. For example, a portion of the code may represent an implementation of a certain feature and there should be some way to not include the code in the design if the feature is not used.

This can be solved with conditional compilation where the designer can wrap the code within compiler directives which tell the compiler to either include or exclude the code for compilation when the given named flag is set.

Syntax

Conditional compilation can be achieved with Verilog `ifdef and `ifndef keywords. These keywords can appear anywhere in the design and can be nested one inside the other.

The keyword `ifdef simply tells the compiler to include the piece of code until the next `else or `endif if the given macro called FLAG is defined using a `define directive.


// Style #1: Only single `ifdef
`ifdef <FLAG>
	// Statements
`endif

// Style #2: `ifdef with `else part
`ifdef <FLAG>
	// Statements
`else
	// Statements
`endif

// Style #3: `ifdef with additional ifdefs
`ifdef <FLAG1>
	// Statements
`elsif <FLAG2>
	// Statements
`elsif <FLAG3>
	// Statements
`else
	// Statements
`endif

The keyword `ifndef simply tells the compiler to include the piece of code until the next `else or `endif if the given macro called FLAG is not defined using a `define directive.

Design Example with `ifdef


module my_design (input clk, d, 
`ifdef INCLUDE_RSTN
                  input rstn,
`endif                  
                  output reg q);
  
  always @ (posedge clk) begin
`ifdef INCLUDE_RSTN
    if (!rstn) begin
      q <= 0;
    end else 
`endif
    begin
      q <= d;
    end
  end
endmodule

Testbench


module tb;
  reg clk, d, rstn;
  wire q;
  reg [3:0] delay;
  
  my_design u0 ( .clk(clk), .d(d),
`ifdef INCLUDE_RSTN
                .rstn(rstn),
`endif
                .q(q));
  
  always #10 clk = ~clk;
  
  initial begin
    integer i;
    
    {d, rstn, clk} <= 0;
    
	#20 rstn <= 1;    
    for (i = 0 ; i < 20; i=i+1) begin
      delay = $random;
      #(delay) d <= $random;
    end
    
    #20 $finish;
  end
endmodule

Note that by default, rstn will not be included during compilation of the design and hence it will not appear in the portlist. However if a macro called INCLUDE_RSTN is either defined in any Verilog file that is part of the compilation list of files or passed through the command line to the compiler, rstn will be included in compilation and the design will have it.

Experiment by adding and removing +define+INCLUDE_RSTN from 'Compile & Run Options' on the left pane to know the difference.

Verilog `ifdef `elsif Example

The following example has two display statements inside separate `ifdef scopes which does not have a default `else part to it. So this means that by default nothing will be displayed. If the macro either MACRO is defined, the corresponding display message is included and will be displayed during simulation


module tb;
  initial begin

`ifdef MACRO1
    $display ("This is MACRO1");
    
`elsif MACRO2
    $display ("This is MACRO2");
    
`endif
  end
endmodule
 Simulation Log
# With no macros defined
ncsim> run
ncsim: *W,RNQUIE: Simulation is complete.

# With +define+MACRO1
ncsim> run
This is MACRO1
ncsim: *W,RNQUIE: Simulation is complete.

# With +define+MACRO2
ncsim> run
This is MACRO2
ncsim: *W,RNQUIE: Simulation is complete.

Verilog `ifndef `elsif Example

The same code can be written with `ifndef and results will be just the opposite.


module tb;
  initial begin

`ifndef MACRO1
    $display ("This is MACRO1");
    
`elsif MACRO2
    $display ("This is MACRO2");
    
`endif
  end
endmodule
 Simulation Log
# With no macros defined
ncsim> run
This is MACRO1
ncsim: *W,RNQUIE: Simulation is complete.

# With +define+MACRO1
ncsim> run
ncsim: *W,RNQUIE: Simulation is complete.

# With +define+MACRO2
ncsim> run
This is MACRO1
ncsim: *W,RNQUIE: Simulation is complete.

# With +define+MACRO1 +define+MACRO2
ncsim> run
This is MACRO2
ncsim: *W,RNQUIE: Simulation is complete.

Verilog Nested `ifdef Example

`ifdef and its flavors can be nested one inside the other to create complex ways of code inclusion and exclusion with defined macros.


module tb;
  initial begin
    `ifdef FLAG
    	$display ("FLAG is defined");
    	`ifdef NEST1_A
    		$display ("FLAG and NEST1_A are defined");
    		`ifdef NEST2
    			$display ("FLAG, NEST1_A and NEST2 are defined");
    		`endif
    	`elsif NEST1_B
    		$display ("FLAG and NEST1_B are defined");
    		`ifndef WHITE
    			$display ("FLAG and NEST1_B are defined, but WHITE is not");
    		`else
    			$display ("FLAG, NEST1_B and WHITE are defined");
    		`endif
    	`else
    		$display ("Only FLAG is defined");
    	`endif
    `else
    	$display ("FLAG is not defined");
    `endif
  end
endmodule
 Simulation Log
# Without defining any macro
ncsim> run
FLAG is not defined
ncsim: *W,RNQUIE: Simulation is complete.

# With +define+FLAG +define+NEST1_B
ncsim> run
FLAG is defined
FLAG and NEST1_B are defined
FLAG and NEST1_B are defined, but WHITE is not
ncsim: *W,RNQUIE: Simulation is complete.

# With +define+FLAG +define+NEST1_B +define+WHITE
ncsim> run
FLAG is defined
FLAG and NEST1_B are defined
FLAG, NEST1_B and WHITE are defined
ncsim: *W,RNQUIE: Simulation is complete.

# With +define+FLAG
ncsim> run
FLAG is defined
Only FLAG is defined
ncsim: *W,RNQUIE: Simulation is complete.

# With +define+WHITE
ncsim> run
FLAG is not defined
ncsim: *W,RNQUIE: Simulation is complete.

# With +define+NEST1_A
ncsim> run
FLAG is not defined
ncsim: *W,RNQUIE: Simulation is complete.

Note that as long as the parent macro is not defined, definition of any other nested macro within it does not get compiled. For example, NEST1_A or WHITE macro definitions without FLAG does not make the compiler pick up the nested code.

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
  1. SystemVerilog local
  2. SystemVerilog 'extern'
  3. Transaction Object
  4. Using get_next_item()
  5. Verilog Gate Level Examples

Page 58 of 63

  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
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
  • Verilog Testbench
  • Verilog Coding Style Effect
  • Verilog Conditional Statements
  • Verilog Interview Set 10
  • Synchronous FIFO
  • SystemVerilog Interview Set 10
  • SystemVerilog Interview Set 9
  • SystemVerilog Interview Set 8
  • SystemVerilog Interview Set 7
  • SystemVerilog Interview Set 6
  • UVM Singleton Object
  • UVM Component [uvm_component]
  • UVM Object [uvm_object]
  • UVM Root [uvm_root]
  • UVM Interview Set 4
© 2015 - 2023 ChipVerify
Terms and Conditions | DMCA.com Protection Status