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 (; ; ) begin // Statements end 
  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  

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  

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