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.
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.
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.
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.
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
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
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.
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.
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.
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.
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.
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.
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 <= 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.
Which type of loop do we use to create code which runs continuously?show answer
The forever loop executes continuously.hide answer
Which function do we normally use a forever loop to implement in a verilog testbench?show answer
The forever loop is commonly used to implement a clock signal in a verilog testbenchhide answer
What is the main difference between a for loop and a repeat loop?show answer
The for loop includes a local loop variable which is incremented on every iteration of the loop.hide answer
Write a for loop which implements an 8 bit shift register.show answer
// The circuit input goes into the first register shift <= 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