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




D Flip-Flop Async Reset

A D flip-flop is a sequential element that follows the input pin d at the given edge of a clock.

Design #1: With async active-low reset


module dff 	( input d,
              input rstn,
              input clk,
              output reg q);
	
	always @ (posedge clk or negedge rstn) 
       if (!rstn)
          q <= 0;
       else
          q <= d;
endmodule

Hardware Schematic

Testbench


module tb_dff;
	reg clk;
	reg d;
	reg rstn;
	reg [2:0] delay;
	
    dff  dff0 ( .d(d),
                .rsnt (rstn),
                .clk (clk),
                .q (q));
    
    // Generate clock
    always #10 clk = ~clk;
                   
    // Testcase
    initial begin
    	clk <= 0;
    	d <= 0;
    	rstn <= 0;
    	
    	#15 d <= 1;
    	#10 rstn <= 1;
    	for (int i = 0; i < 5; i=i+1) begin
    		delay = $random;
    		#(delay) d <= i;
    	end
    end
endmodule

Design #1: With sync active-low reset


module dff 	( input d,
              input rstn,
              input clk,
              output reg q);
	
	always @ (posedge clk) 
       if (!rstn)
          q <= 0;
       else
          q <= d;
endmodule

Hardware Schematic

Testbench


module tb_dff;
	reg clk;
	reg d;
	reg rstn;
	reg [2:0] delay;
	
    dff  dff0 ( .d(d),
                .rsnt (rstn),
                .clk (clk),
                .q (q));
    
    // Generate clock
    always #10 clk = ~clk;
                   
    // Testcase
    initial begin
    	clk <= 0;
    	d <= 0;
    	rstn <= 0;
    	
    	#15 d <= 1;
    	#10 rstn <= 1;
    	for (int i = 0; i < 5; i=i+1) begin
    		delay = $random;
    		#(delay) d <= i;
    	end
    end
endmodule

D Latch

A latch has two inputs : data(D), clock(clk) and one output: data(Q). When the clock is high, D flows through to Q and is transparent, but when the clock is low the latch holds its output Q even if D changes.

A flip-flop on the other hand captures data at its input at the positive or negative edge of a clock and output does not reflect changes in the input until the next clock edge.

Design

In this example, we'll build a latch that has three inputs and one output. The input d stands for data which can be either 0 or 1, rstn stands for active-low reset and en stands for enable which is used to make the input data latch to the output. Reset being active-low simply means that the design element will be reset when this input goes to 0 or in other words, reset is active when its value is low. The value of output q is dictated by the inputs d, en and rstn.


module d_latch (  input d,           // 1-bit input pin for data
                  input en,          // 1-bit input pin for enabling the latch
                  input rstn,        // 1-bit input pin for active-low reset
                  output reg q);     // 1-bit output pin for data output
 
   // This always block is "always" triggered whenever en/rstn/d changes
   // If reset is asserted then output will be zero
   // Else as long as enable is high, output q follows input d
   always @ (en or rstn or d)
      if (!rstn)
         q <= 0;
      else
         if (en)
            q <= d;
endmodule

Read more: D Latch

Verilog n-bit Bidirectional Shift Register

In digital electronics, a shift register is a cascade of flip-flops where the output pin q of one flop is connected to the data input pin (d) of the next. Because all flops work on the same clock, the bit array stored in the shift register will shift by one position. For example, if a 5-bit right shift register has an initial value of 10110 and the input to the shift register is tied to 0, then the next pattern will be 01011 and the next 00101.

5-bit shift register

Design

This shift register design has five inputs and one n-bit output and the design is parameterized using parameter MSB to signify width of the shift register. If n is 4, then it becomes a 4-bit shift register. If n is 8, then it becomes an 8-bit shift register.

This shift register has a few key features:

  • Can be enabled or disbled by driving en pin of the design
  • Can shift to the left as well as right when dir is driven
  • If rstn is pulled low, it will reset the shift register and output will become 0
  • Input data value of the shift register can be controlled by d pin


module shift_reg  #(parameter MSB=8) (  input d,                      // Declare input for data to the first flop in the shift register
                                        input clk,                    // Declare input for clock to all flops in the shift register
                                        input en,                     // Declare input for enable to switch the shift register on/off
                                        input dir,                    // Declare input to shift in either left or right direction
                                        input rstn,                   // Declare input to reset the register to a default value
                                        output reg [MSB-1:0] out);    // Declare output to read out the current value of all flops in this register


   // This always block will "always" be triggered on the rising edge of clock
   // Once it enters the block, it will first check to see if reset is 0 and if yes then reset register
   // If no, then check to see if the shift register is enabled
   // If no => maintain previous output. If yes, then shift based on the requested direction
   always @ (posedge clk)
      if (!rstn)
         out <= 0;
      else begin
         if (en)
            case (dir)
               0 :  out <= {out[MSB-2:0], d};
               1 :  out <= {d, out[MSB-1:1]};
            endcase
         else
            out <= out;
      end
endmodule

Hardware Schematic

Testbench

The testbench is used to verify the functionality of this shift register. The design is instantiated into the top module and the inputs are driven with different values. The design behavior for each of the inputs can be observed at the output pin out.

n-bit shift register TB

module tb_sr;
   parameter MSB = 16;        // [Optional] Declare a parameter to represent number of bits in shift register

   reg data;                  // Declare a variable to drive d-input of design
   reg clk;                   // Declare a variable to drive clock to the design
   reg en;                    // Declare a variable to drive enable to the design
   reg dir;                   // Declare a variable to drive direction of shift registe
   reg rstn;                  // Declare a variable to drive reset to the design
   wire [MSB-1:0] out;        // Declare a wire to capture output from the design

   // Instantiate design (16-bit shift register) by passing MSB and connect with TB signals
   shift_reg  #(MSB) sr0  (  .d (data),
                             .clk (clk),
                             .en (en),
                             .dir (dir),
                             .rstn (rstn),
                             .out (out));

   // Generate clock time period = 20ns, freq => 50MHz
   always #10 clk = ~clk;

   // Initialize variables to default values at time 0
   initial begin
      clk <= 0;
      en <= 0;
      dir <= 0;
      rstn <= 0;
      data <= 'h1;
   end

   // Drive main stimulus to the design to verify if this works
   initial begin
   
      // 1. Apply reset and deassert reset after some time
      rstn <= 0;
      #20 rstn <= 1;
          en <= 1;
          
	  // 2. For 7 clocks, drive alternate values to data pin
      repeat (7) @ (posedge clk)
         data <= ~data;
   
     // 4. Shift direction and drive alternate value to data pin for another 7 clocks
      #10 dir <= 1;
      repeat (7) @ (posedge clk)
         data <= ~data;

      // 5. Drive nothing for next 7 clocks, allow shift register to simply shift based on dir
      repeat (7) @ (posedge clk);
      
      // 6. Finish the simulation
      $finish;
   end

   // Monitor values of these variables and print them into the logfile for debug
   initial
      $monitor ("rstn=%0b data=%b, en=%0b, dir=%0b, out=%b", rstn, data, en, dir, out);
endmodule

The time when shift register is enabled is highlighted in green in the log given below. The time when it shifts its direction is highlighted in yellow. The time when data input pin remains constant is highlighted in blue.

 Simulation Log
ncsim> run
rstn=0 data=1, en=0, dir=0, out=xxxxxxxxxxxxxxxx
rstn=0 data=1, en=0, dir=0, out=0000000000000000
rstn=1 data=1, en=1, dir=0, out=0000000000000000
rstn=1 data=0, en=1, dir=0, out=0000000000000001
rstn=1 data=1, en=1, dir=0, out=0000000000000010
rstn=1 data=0, en=1, dir=0, out=0000000000000101
rstn=1 data=1, en=1, dir=0, out=0000000000001010
rstn=1 data=0, en=1, dir=0, out=0000000000010101
rstn=1 data=1, en=1, dir=0, out=0000000000101010
rstn=1 data=0, en=1, dir=0, out=0000000001010101
rstn=1 data=0, en=1, dir=1, out=0000000001010101
rstn=1 data=1, en=1, dir=1, out=0000000000101010
rstn=1 data=0, en=1, dir=1, out=1000000000010101
rstn=1 data=1, en=1, dir=1, out=0100000000001010
rstn=1 data=0, en=1, dir=1, out=1010000000000101
rstn=1 data=1, en=1, dir=1, out=0101000000000010
rstn=1 data=0, en=1, dir=1, out=1010100000000001
rstn=1 data=1, en=1, dir=1, out=0101010000000000
rstn=1 data=1, en=1, dir=1, out=1010101000000000
rstn=1 data=1, en=1, dir=1, out=1101010100000000
rstn=1 data=1, en=1, dir=1, out=1110101010000000
rstn=1 data=1, en=1, dir=1, out=1111010101000000
rstn=1 data=1, en=1, dir=1, out=1111101010100000
rstn=1 data=1, en=1, dir=1, out=1111110101010000
Simulation complete via $finish(1) at time 430 NS + 0
n-bit shift register waveform

UVM TLM Nonblocking Put Port

A previous article showed examples of using a uvm_blocking_put_port TLM port that was blocking in nature where the sender gets stalled until the receiver finishes with the put task.

Similarly, UVM TLM also has a non-blocking method of type uvm_nonblocking_put_port where the sender has to use try_put to see if the put was successful or can_put method to see if the receiver is ready to accept a transfer. Like before, the UVM TLM non-blocking put port should ultimately be connected to a non-blocking put implementation port.

UVM TLM Nonblocking Put Example

A class called Packet is defined below to act as the data item that will be transferred from one component to another. This class object will have two random variables that can be randomized before sending.


// Create a class data object that can be sent from one 
// component to another
class Packet extends uvm_object;
  rand bit[7:0] addr;
  rand bit[7:0] data;
  
  `uvm_object_utils_begin(Packet)
  	`uvm_field_int(addr, UVM_ALL_ON)
  	`uvm_field_int(data, UVM_ALL_ON)
  `uvm_object_utils_end
  
  function new(string name = "Packet");
    super.new(name);
  endfunction
endclass
1. Create sender class with a port of type uvm_nonblocking_put_port

A class called componentA is created which has a uvm_nonblocking_put_port parameterized to accept a data object of type Packet. The port has to be instantiated with the new() method preferably in the build_phase of the same component.

In this example, a class object of type Packet is created, randomized and sent via the put_port handle by calling the try_put method. Many such packets can be sent using a simple loop controlled by a configurable variable. The try_put function should ideally return 1 if the transfer is successful and 0 if it failed and should be provided by the receiver which implements the function.


class componentA extends uvm_component;
   `uvm_component_utils (componentA)
 
  // Create a nonblocking TLM put port which can send an object
  // of type 'Packet'
  uvm_nonblocking_put_port #(Packet) m_put_port;
  int m_num_tx;
 
   function new (string name = "componentA", uvm_component parent= null);
      super.new (name, parent);
   endfunction

   // Remember that TLM put_port is a class object and it will have to be 
   // created with new ()
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
     m_put_port = new ("m_put_port", this);
   endfunction
 
  // Create a packet, randomize it and send it through the port
  // Note that put() is a method defined by the receiving component
  // Repeat these steps N times to send N packets
   virtual task run_phase (uvm_phase phase);
     phase.raise_objection(this);
     repeat (m_num_tx) begin
        bit success;
         Packet pkt = Packet::type_id::create ("pkt");
         assert(pkt.randomize ()); 
       
        // Print the packet to be displayed in log
         `uvm_info ("COMPA", "Packet sent to CompB", UVM_LOW)
         pkt.print (uvm_default_line_printer);
 
		// Try to put the packet through the put port
	    success = m_put_port.try_put(pkt);
	    if (success) 
           `uvm_info("COMPA", $sformatf("COMPB was ready to accept and transfer is successful"), UVM_MEDIUM)
         else
           `uvm_info("COMPA", $sformatf("COMPB was NOT ready to accept and transfer failed"), UVM_MEDIUM)
      end
     phase.drop_objection(this);
   endtask
endclass
3. Create receiver class that implements the put method

The receiver class needs to define an implementation port using uvm_nonblocking_put_imp. Since the port is nonblocking in nature, the try_put implementation is a function which has to be defined by this component.


class componentB extends uvm_component;
   `uvm_component_utils (componentB)
 
   // Mention type of transaction, and type of class that implements the put ()
  uvm_nonblocking_put_imp #(Packet, componentB) m_put_imp;

   function new (string name = "componentB", uvm_component parent = null);
      super.new (name, parent);
   endfunction
 
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      m_put_imp = new ("m_put_imp", this);
   endfunction
 
  // 'try_put' method definition accepts the packet and prints it.
  // Note that it should return 1 if successful so that componentA
  // knows how to handle the transfer return code
  virtual function bit try_put (Packet pkt);
    `uvm_info ("COMPB", "Packet received", UVM_LOW)
      pkt.print(uvm_default_line_printer);
      return 1;
  endfunction
  
  virtual function bit can_put();
  endfunction

endclass
tlm-testbench-structure 4. Connect port and its implementation at a higher level

The connection between a port and its implementation has to be done at a higher hierarchical level. Since both components are instantiated directly within the test class in this example, the connection between them can be done during the connect_phase of the test. If these two components were instantiated in another component or environment, they have to be connected during the connect_phase of that component or environment.


class my_test extends uvm_test;
  `uvm_component_utils (my_test)
 
   componentA compA;
   componentB compB;
 
  function new (string name = "my_test", uvm_component parent = null);
      super.new (name, parent);
   endfunction
 
     // Create objects of both components, set number of transfers
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      compA = componentA::type_id::create ("compA", this);
      compB = componentB::type_id::create ("compB", this);
      compA.m_num_tx = 2;
   endfunction
 
   // Connection between componentA and componentB is done here
   // Note that the "put_port" is connected to its implementation "put_imp"
   virtual function void connect_phase (uvm_phase phase);
     compA.m_put_port.connect (compB.m_put_imp);  
   endfunction
  
  virtual function void end_of_elaboration_phase(uvm_phase phase);
    super.end_of_elaboration_phase(phase);
    uvm_top.print_topology();
  endfunction
endclass
 Simulation Log
UVM_INFO @ 0: reporter [RNTST] Running test my_test...
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_root.svh(579) @ 0: reporter [UVMTOP] UVM testbench topology:
-----------------------------------------------------
Name            Type                      Size  Value
-----------------------------------------------------
uvm_test_top    my_test                   -     @1836
  compA         componentA                -     @1905
    m_put_port  uvm_nonblocking_put_port  -     @1971
  compB         componentB                -     @1936
    m_put_imp   uvm_nonblocking_put_imp   -     @2010
-----------------------------------------------------

UVM_INFO testbench.sv(60) @ 0: uvm_test_top.compA [COMPA] Packet sent to CompB
pkt: (Packet@2048) { addr: 'ha1  data: 'h64  } 
UVM_INFO testbench.sv(96) @ 0: uvm_test_top.compB [COMPB] Packet received
pkt: (Packet@2048) { addr: 'ha1  data: 'h64  } 
UVM_INFO testbench.sv(66) @ 0: uvm_test_top.compA [COMPA] COMPB was ready to accept and transfer is successful
UVM_INFO testbench.sv(60) @ 0: uvm_test_top.compA [COMPA] Packet sent to CompB
pkt: (Packet@2091) { addr: 'hc1  data: 'hb9  } 
UVM_INFO testbench.sv(96) @ 0: uvm_test_top.compB [COMPB] Packet received
pkt: (Packet@2091) { addr: 'hc1  data: 'hb9  } 
UVM_INFO testbench.sv(66) @ 0: uvm_test_top.compA [COMPA] COMPB was ready to accept and transfer is successful
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_objection.svh(1271) @ 0: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 0: reporter [UVM/REPORT/SERVER] 
--- UVM Report Summary ---

Nonblocking Behavior

The code snippet in the example shown above can be modified to model try_put in a blocking manner. componentA now uses a do while loop for multiple attempts until try_put is successful.


class componentA extends uvm_component;
   `uvm_component_utils (componentA)

   // Rest of the code remains same 

   virtual task run_phase (uvm_phase phase);
     phase.raise_objection(this);
     repeat (m_num_tx) begin
        bit success;
         Packet pkt = Packet::type_id::create ("pkt");
         assert(pkt.randomize ()); 
       
        // Print the packet to be displayed in log
         `uvm_info ("COMPA", "Packet sent to CompB", UVM_LOW)
         pkt.print (uvm_default_line_printer);
 
       // do-while loop uses a "try_put" to keep the sender blocked until the receiver is ready. Return
       // type of the try_put indicates if the transfer was successful. So, lets just try putting 
       // the same packet until the receiver returns a 1 indicating successful transfer. 
       // Note that this is the same as using "put" but we are doing it with "try_put" and a loop
       do begin
         success = m_put_port.try_put(pkt);
         if (success) 
           `uvm_info("COMPA", $sformatf("COMPB was ready to accept and transfer is successful"), UVM_MEDIUM)
         else
           `uvm_info("COMPA", $sformatf("COMPB was NOT ready to accept and transfer failed, try after 1ns"), UVM_MEDIUM)
         #1;
       end while (!success);
      end
     phase.drop_objection(this);
   endtask
endclass

Implementation of the try_put function by componentB is changed to return a random value to model the readiness of the receiver. try_put will return 0 if the receiver is not ready to accept.


class componentB extends uvm_component;
   `uvm_component_utils (componentB)
 
  // Rest of the code remains same
 
  // 'try_put' method definition accepts the packet and prints it.
  // Note that it should return 1 if successful so that componentA
  // knows how to handle the transfer return code
  // For purpose of example, lets randomize a variable 
  // just to say that this component is ready or not
  virtual function bit try_put (Packet pkt);
    bit ready;
    std::randomize(ready);
    
    if (ready) begin
      `uvm_info ("COMPB", "Packet received", UVM_LOW)
      pkt.print(uvm_default_line_printer);
      return 1;
      
    end else begin
    	return 0;
    end
  endfunction
  
  virtual function bit can_put();
  endfunction
endclass
 Simulation Log
UVM_INFO @ 0: reporter [RNTST] Running test my_test...
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_root.svh(579) @ 0: reporter [UVMTOP] UVM testbench topology:
-----------------------------------------------------
Name            Type                      Size  Value
-----------------------------------------------------
uvm_test_top    my_test                   -     @1836
  compA         componentA                -     @1905
    m_put_port  uvm_nonblocking_put_port  -     @1971
  compB         componentB                -     @1936
    m_put_imp   uvm_nonblocking_put_imp   -     @2010
-----------------------------------------------------

UVM_INFO testbench.sv(60) @ 0: uvm_test_top.compA [COMPA] Packet sent to CompB
pkt: (Packet@2048) { addr: 'ha1  data: 'h64  } 
UVM_INFO testbench.sv(74) @ 0: uvm_test_top.compA [COMPA] COMPB was NOT ready to accept and transfer failed, try after 1ns
UVM_INFO testbench.sv(125) @ 1: uvm_test_top.compB [COMPB] Packet received
pkt: (Packet@2048) { addr: 'ha1  data: 'h64  } 
UVM_INFO testbench.sv(72) @ 1: uvm_test_top.compA [COMPA] COMPB was ready to accept and transfer is successful
UVM_INFO testbench.sv(60) @ 2: uvm_test_top.compA [COMPA] Packet sent to CompB
pkt: (Packet@2104) { addr: 'h68  data: 'h7d  } 
UVM_INFO testbench.sv(125) @ 2: uvm_test_top.compB [COMPB] Packet received
pkt: (Packet@2104) { addr: 'h68  data: 'h7d  } 
UVM_INFO testbench.sv(72) @ 2: uvm_test_top.compA [COMPA] COMPB was ready to accept and transfer is successful
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_objection.svh(1271) @ 3: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 3: reporter [UVM/REPORT/SERVER] 
--- UVM Report Summary ---

UVM TLM can_put Example

Instead of directly trying to put a packet, the sender can first query to see if the receiver is ready or not with can_put function and then send the packet.


class componentA extends uvm_component;
   `uvm_component_utils (componentA)
 
   // Rest of the code remains same
	
   virtual task run_phase (uvm_phase phase);
     phase.raise_objection(this);
     repeat (m_num_tx) begin
        bit success;
         Packet pkt = Packet::type_id::create ("pkt");
         assert(pkt.randomize ()); 
       
        // Print the packet to be displayed in log
         `uvm_info ("COMPA", "Packet sent to CompB", UVM_LOW)
         pkt.print (uvm_default_line_printer);
 
       	// Another way to do the same is to loop until can_put returns a 1. In this case, its is 
       	// not even attempted to send a transaction using put, until the sender knows for sure
       	// that the receiver is ready to accept it
       	`uvm_info("COMPA", $sformatf("Waiting for receiver to be ready ..."), UVM_MEDIUM)
       	do begin
         	success = m_put_port.can_put();
       	end while (!success);
       	`uvm_info("COMPA", $sformatf("Receiver is now ready to accept transfers"), UVM_MEDIUM)
       	m_put_port.try_put(pkt);
      end
     phase.drop_objection(this);
   endtask
endclass

The can_put function in componentB is set to return a random value in this example to model readiness of the receiver.


class componentB extends uvm_component;
   `uvm_component_utils (componentB)
 
  // Rest of the code remains same
 
  virtual function bit try_put (Packet pkt);
    `uvm_info ("COMPB", "Packet received", UVM_LOW)
    pkt.print(uvm_default_line_printer);
    return 1;
  endfunction
  
  // Return a random value to model readiness
  virtual function bit can_put();
    return $urandom_range(0,1);    
  endfunction
endclass
 Simulation Log
UVM_INFO @ 0: reporter [RNTST] Running test my_test...
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_root.svh(579) @ 0: reporter [UVMTOP] UVM testbench topology:
-----------------------------------------------------
Name            Type                      Size  Value
-----------------------------------------------------
uvm_test_top    my_test                   -     @1837
  compA         componentA                -     @1906
    m_put_port  uvm_nonblocking_put_port  -     @1972
  compB         componentB                -     @1937
    m_put_imp   uvm_nonblocking_put_imp   -     @2011
-----------------------------------------------------

UVM_INFO testbench.sv(60) @ 0: uvm_test_top.compA [COMPA] Packet sent to CompB
pkt: (Packet@2049) { addr: 'ha1  data: 'h64  } 
UVM_INFO testbench.sv(81) @ 0: uvm_test_top.compA [COMPA] Waiting for receiver to be ready ...
UVM_INFO testbench.sv(85) @ 0: uvm_test_top.compA [COMPA] Receiver is now ready to accept transfers
UVM_INFO testbench.sv(125) @ 0: uvm_test_top.compB [COMPB] Packet received
pkt: (Packet@2049) { addr: 'ha1  data: 'h64  } 
UVM_INFO testbench.sv(60) @ 0: uvm_test_top.compA [COMPA] Packet sent to CompB
pkt: (Packet@2059) { addr: 'h24  data: 'hba  } 
UVM_INFO testbench.sv(81) @ 0: uvm_test_top.compA [COMPA] Waiting for receiver to be ready ...
UVM_INFO testbench.sv(85) @ 0: uvm_test_top.compA [COMPA] Receiver is now ready to accept transfers
UVM_INFO testbench.sv(125) @ 0: uvm_test_top.compB [COMPB] Packet received
pkt: (Packet@2059) { addr: 'h24  data: 'hba  } 
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_objection.svh(1271) @ 0: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 0: reporter [UVM/REPORT/SERVER] 
--- UVM Report Summary ---

4-bit counter

The 4-bit counter starts incrementing from 4'b0000 to 4'h1111 and then rolls over back to 4'b0000. It will keep counting as long as it is provided with a running clock and reset is held high.

The rollover happens when the most significant bit of the final addition gets discarded. When counter is at a maximum value of 4'b1111 and gets one more count request, the counter tries to reach 5'b10000 but since it can support only 4-bits, the MSB will be discarded resulting in 0.

	0000
	0001
	0010
	...
	1110
	1111
	       rolls over
	0000
	0001
	...

The design contains two inputs one for the clock and another for an active-low reset. An active-low reset is one where the design is reset when the value of the reset pin is 0. There is a 4-bit output called out which essentially provides the counter values.

Electronic Counter Design


module counter (  input clk,               // Declare input port for clock to allow counter to count up
                  input rstn,              // Declare input port for reset to allow the counter to be reset to 0 when required
                  output reg[3:0] out);    // Declare 4-bit output port to get the counter values

  // This always block will be triggered at the rising edge of clk (0->1)
  // Once inside this block, it checks if the reset is 0, if yes then change out to zero
  // If reset is 1, then design should be allowed to count up, so increment counter
  always @ (posedge clk) begin
    if (! rstn)
      out <= 0;
    else 
      out <= out + 1;
  end
endmodule

Read more: 4-bit counter

  1. Verilog Hello World
  2. Verilog Positive Edge Detector
  3. SystemVerilog 'unique' and 'priority' if-else
  4. SystemVerilog Polymorphism
  5. Verilog Operators

Page 37 of 63

  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
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