An Introduction to Loops in Verilog

In this post, we talk about the different types of loop which we can use in verilog – the for loop, while loop, forever loop and repeat loop.

As we saw in our previous post on sequential statements in verilog, there are a number of statements which we can only use within procedural blocks.

We use these statements to control the way that data is assigned in our verilog design.

The four different types of loop which we can use in verilog are also sequential statements which we use to assign data in our designs.

As a result of this, we can only write loops inside of procedural blocks such as an always block or initial block.

In the rest of this post, we talk about how each of these loops is used in verilog. We then consider a short example for each of these constructs to show how we use them in practise.

Loops in Verilog

We use loops in verilog to execute the same code a number of times.

The most commonly used loop in verilog is the for loop. We use this loop to execute a block of code a fixed number of times.

We can also use the repeat keyword in verilog which performs a similar function to the for loop. However, we generally prefer to use the for loop rather than the repeat keyword in verilog designs.

The other type of loop which we commonly use in verilog is the while loop. We use this loop to execute a part of our code for as long as a given condition is true.

Let’s take a closer look at each of these types of loop.

Verilog forever loop

We use the forever loop in verilog to create a block of code which will execute continuously, much like an infinite loop in other programming languages.

This is in contrast to the other types of loop in verilog, such as the for loop and while loop, which only run a fixed number of times.

As we see saw in our previous post on verilog testbenches, one of the most common use cases for the forever loop is generating a clock signal in a verilog test bench.

The forever loop can not be synthesized meaning that we can only use it in our test bench code.

The code snippet below shows the general syntax for the verilog forever loop.

forever begin
  // Code to be executed by the loop goes here
end

Forever loop example

To better demonstrate how we use the forever loop in practise let’s consider an example.

For this example we will generate a clock signal with a frequency of 10MHz which we could use inside of a test bench.

To do this, we firstly assign our signal to an initial value. We then use the forever block to invert the signal at regular intervals.

The code snippet below shows how we would implement this clock example in verilog.

 initial begin
    clk = 1'b0;
    forever begin
      #500 clk = ~clk;
    end
  end

There are two important things to say about this example.

Firstly, note that we use the verilog initial block which is another example of a procedural statement. Any code which we write in an initial block is executed once at the beginning of a simulation.

We almost always use initial blocks rather than always blocks in our testbench code. The reason for this is that they only execute once and we typically only need to run our test once.

The other important thing to note here is the use of the # symbol to model time delays in verilog.

In order for this example to work properly we would need to include the verilog timescale compiler directive in our code.

We use the timescale compiler directive to specify the time unit and resolution of our simulations.

In this instance, we need to set the time units to ns as is shown in the code snippet below.

`timescale 1ns / 1ps

Verilog repeat loop

We use the repeat loop to execute a given block of verilog code a fixed number of times.

We specify the number of times the code block will execute in the repeat loop declaration.

Although we most commonly use the repeat loop in verilog test benches, we can also use it in sythesizable code.

However, we have to take care when using this construct synthesizable code as we can only use it to describe repetitive structures.

The code snippet below shows the general syntax of the verilog repeat loop

repeat (<number>) begin
  // Code to be executed in the loop
end

We use the <number> field to determine how many times the repeat loop is executed.

The repeat loop is very similar to the for loop in verilog as they both execute code a fixed number of times.

The main difference between these two types of loop is that the for loop includes a local variable which we can reference inside the loop. The value of this variable is updated on every iteration of the loop.

In contrast, the repeat loop doesn’t include this local loop variable. As a result of this, the repeat loop is actually less verbose than the for loop in instances where we don’t need this variable.

Repeat Loop Example

The repeat loop is a relatively straight forward construct. However, let’s consider a basic example to better demonstrate how it works.

For this example, let’s suppose that we have a signal in our design that we want to toggle whenever there is a rising edge on another signal in our design.

The waveform below shows the functionality which we are trying to achieve in this example loop.

A waveform which shows a signal named sig_b being inverted every time there is a rising edge on a signal named sig_a.

However, we only want this toggle action to be effective a total of six times.

We can easily implement this in a repeat block, as shown in the code snippet below.

repeat (6) begin
  @(posedge sig_a)
  sig_b = ~sig_b;
end

We can see in this example that we have set the <number> field to 6. As a result of this, the repeat loop will run a total of six times before terminating.

We then use the posedge macro which we talk about in the post on the verilog always block. This macro tells us when a rising edge has occurred on the sig_a signal in our code.

In verilog we use the @ symbol to tell our code to wait for an event to occur.

This simply means that the code will pause at this line and wait for the condition in the brackets to evaluate as true. Once this happens, the code will carry on running.

In this example, we use this operator to block the execution of our repeat loop until a rising edge is detected on the sig_a signal.

Finally, we can use the not verilog bit wise operator (~) to invert the sig_b signal whenever a rising edge has been detected.

The waveform below shows the simulation result of this code, as taken from the icarus verilog simulator and output to the gtkwave wave viewer.

A simulation output which shows a signal named sig_b being inverted every time there is a rising edge on a signal named sig_a.

Verilog while Loop

We use the while loop to execute a part of our verilog code for as long as a given condition is true.

The specified condition is evaluated before each iteration of the loop.

As a result of this, all of the code in the block will execute in each valid iteration.

This happens even if the condition changes so that it no longer evaluates to true whilst the code in the block is running.

We can think of the while loop as an if statement that executes repeatedly.

As while loops are generally not synthesizable, we often use them in our testbenches to generate stimulus.

The code snippet below shows the general syntax for a while loop in verilog.

while <condition> begin
  // Code to execute
end

We use the <condition> field in the above construct to determine when the execution of the loop is stopped.

while loop Example

To better demonstrate how we use the while loop in verilog, let’s consider a basic example.

For this example, we will create an integer type variable which is increased from 0 to 3. We then print the value of this variable on each iteration of the loop.

Although this is a trivial example, it demonstrates the fundamental principles of the while loop.

The code snippet below shows how we would implement this example. This example can also be simulated on EDA playground.

while (iter < 4) begin
  $display("iter = %0d", iter);
  iter = iter + 1;
end

This example assumes that the iter variable has already been declared and assigned an intial value of 0.

In every iteration of the loop, the second line of the code within the loop body increments the iter variable.

The <condition> field in this example is set so that the loop only executes when the iter variable is less than 4. As a result of this, the iter variable is incremented from 0 to 3 in this loop.

We use the $display system task, which we discussed in a previous post, to print the value of the iter variable on each iteration of the loop. The %0d operator indicates that the variable should be printed as a decimal number.

Verilog For Loop

When writing verilog code, we use the for loop to execute a block of code a fixed number of times.

As with the while loop, the for loop will execute for as long as a given condition is true. The specified condition is evaluated before each iteration of the loop.

We specify this condition as part of the for loop declaration. This condition is used to control the number of times the loop is executed.

Although it is commonly used in testbenches, we can also use the for loop in synthesizable verilog code.

When we use the for loop in synthesizable code, we typically use it to replicate sections of our hardware. One of the most common examples of this is a shift register.

As we previously mentioned, the for loop is very similar to the repeat loop. The main difference is that the for loop uses a local variable which can be used in our loop code.

The code snippet below shows the syntax we use in a verilog for loop.

  for (<initial_condition>; <stop_condition>; <increment>) begin
    // Code to execute
  end

We use the <initial_condition> field to set the initial value of our loop variable. We must declare the variable that we use in our loop before we can use it in our code.

The <stop_condition> field is the conditional statement which determines how many times the loop runs. The for loop will continue to execute until this field evaluates as false.

We use the <increment> field to determine how the loop variable is updated in every iteration of the loop.

Verilog for loop example

To better demonstrate how we use the for loop in verilog, let’s consider a basic example.

For this example, we will write a simple four bit serial shift register using the verilog for loop. Implementing a shift register is actually one of the most common use cases of the for loop.

The shift register can be implemented using a simple verilog array.

We can then assign the input to the shift register to the first element of the array. We then use a for loop to shift the existing contents of the array to the left by one place.

The verilog code snippet below shows how we would implement this shift register using a for loop.

// The circuit input goes into the first register
shift[0] <= circuit_in;

// A for loop to shift the contents of the register
for (i = 1; i < 4; i = i + 1) begin
  shift[i] <= shift[i-1];
end

The first thing to notice in this code is that we use a loop variable (i) to reference an element of the array in our loop. We must declare this loop variable before we use it in our code.

As our shift array has four bits, we set the <stop_condition> field so that the loop executes only when the loop variable (i) is less than four.

Finally, we set the <increment> field so that the loop variable is incremented by one in every iteration. This allows us to iterate over every element in the array.

In this example, we make use of non-blocking assignment. The reason for this is that a shift register is an example of a sequential logic circuit.

Therefore, we would have to write this code inside of a clocked verilog always block to properly model a shift register.

Exercises

Which type of loop do we use to create code which runs continuously?

The forever loop executes continuously.

Which function do we normally use a forever loop to implement in a verilog testbench?

The forever loop is commonly used to implement a clock signal in a verilog testbench

What is the main difference between a for loop and a repeat loop?

The for loop includes a local loop variable which is incremented on every iteration of the loop.

Write a for loop which implements an 8 bit shift register.

// The circuit input goes into the first register
shift[0] <= circuit_in;

// A for loop to shift the contents of the register
for (i = 1; i < 8; i = i + 1) begin
  shift[i] <= shift[i-1];
end

Rewrite the previous exercise so that it is implemented using a while loop.

// The circuit input goes into the first register
shift[0] <= circuit_in;

// A while loop to shift the contents of the register
i = 1;
while (i < 8) begin
  shift[i] <= shift[i-1];
  i = i + 1;
end