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