4 minutes reading time (861 words)

SystemVerilog Loops - when and where to use

Loooooops. A very powerful tool. SystemVerilog has many different types of loops that can be used in a variety of ways. Using the correct loop type in the correct context helps in readability, maintenance, and shorter code. Here are a few tips to know when to use what type of loop in SystemVerilog.

Tip #1: Use 'repeat' to count

repeat is a SystemVerilog loop that simply repeats all statements within the following begin and end. However many still use for and while loops to achieve the same thing.

Take this example where we need to wait for 10 clocks and how a for loop is used.

 
module tb;
  bit clk;
 
  always #10 clk = ~clk;
 
  initial begin
    for (int i = 0; i < 10; i++) begin
      @(posedge clk);
      $display ("[%0t] Posedge of clock", $time);
    end
  end
endmodule
 

In the code shown below, a repeat looping construct is used for the same purpose. This is useful mainly when the iterator i in the for loop above, is not required to be referenced within the loop.

 
module tb;
  bit clk;
  int cnt = 15;
 
  always #10 clk = ~clk;
 
  initial begin
    repeat (10) begin
      @(posedge clk);
      $display ("[%0t] Posedge of clock", $time);
    end
 
    // If the display statement is not required, it can be even shorter
    repeat (10) @(posedge clk);
 
    // You can replace the hard coded value of 10 with a variable as well
    repeat (cnt) @ (posedge clk);
  end
endmodule  
 

Use a repeat loop if the iterator is not required to be accessed within the loop

Tip #2: Use 'foreach' for array iteration

foreach was introduced in SystemVerilog to make array iteration easier. Many still use a for loop to do the same. Here is an example of how that is done.

 
module tb;
  int m_que[$] = '{1, 2, 3, 4, 5};
 
  initial begin
    // Note that size() is not available for dynamic arrays/static arrays
    for (int i = 0; i < m_que.size(); i++) begin
      $display ("m_que[%0d] = %0d", i, m_que[i]);
    end
  end
endmodule
 

And, here is how the same thing can be done with a foreach loop.

 
module tb;
  int m_que[$] = '{1, 2, 3, 4, 5};
 
  initial begin
    foreach (m_que[i]) begin
      $display ("m_que[%0d] = %0d", i, m_que[i]);
    end
  end
endmodule
 

Use a foreach loop to iterate through all arrays

Tip #3: Use 'for' loop for conditional iterations with access to iterator

A for loop is best useful if the given set of statements is required to be executed based on a condition that depends on the value of an iterator that typically changes within the loop. Many of us still use while loops instead to achieve the same purpose although it results in slightly lengthier code.

Here is an example of a simple while loop that iterates until the count reaches 10. This requires the iterator to be initialized and incremented within the while loop.

 
module tb;
  initial begin
    int i = 0;
    while (i < 10) begin
      $display ("Iterator i=%0d", i );
      i++;
    end
  end
endmodule
 

The same code can be rewritten with a for loop and looks like what is shown below. Iterator initialization and incrementation is included within the for loop construct and reduces a couple of lines and is more condensed.

 
module tb;
  initial begin
    for (int i = 0; i < 10; i++) begin
      $display ("Iterator i=%0d", i );
    end
  end
endmodule
 

Use a for loop if all three fields in a for loop can be used

Tip #4: Use 'while' loop for conditonal expressions

The idea behind a while loop is that it should run as long as the given condition is maintained. Until the availability of for loop in SystemVerilog, this was used as the main looping construct.

 
  module tb;
    bit clk;
    bit poll_stop;
 
    always #10 clk = ~clk;
 
    // Assume we are polling a register field called
    // "poll_stop" and this field is updated by the
    // HW design. For our purpose lets simply make 
    // the testbench bit one when required.
    initial begin
      clk <= 0;
      repeat(50) @ (posedge clk);
      poll_stop = 1;
    end
 
    // This thread keeps reading the register field
    // value until it is set
    initial begin
      while (!poll_stop) begin
        $display ("Keep polling ...");
        @(posedge clk);
      end
    end
  endmodule
 

Use a while loop for conditional expressions

Tip #5: Use 'forever' for infinite loops

This loop keeps running forever as it does not have any condition to exit. It is the same as using a while(1) loop, but a forever loop might have a better simulator performance because it can skip checking the condition to see if it is true.

In the code shown below, there are two initial blocks where one starts an infinite while loop and another a forever loop.

 
module tb;
  bit clk;
  always #10 clk = ~clk;
 
  initial begin
    while (1) begin
      @(posedge clk) $display ("Runs infinitely");
    end
  end
 
  initial begin
    forever begin
      @(posedge clk) $display ("Runs literally forever");
    end
  end
endmodule
 

Use a forever loop instead of while(1)

Have fun with loops !

Power of SystemVerilog Constraints

Related Posts

 

Comments

No comments made yet. Be the first to submit a comment
Already Registered? Login Here
Guest
Monday, 24 June 2019

You consent to our cookies if you continue to use our website. To know more about cookies, see our privacy policy. I accept cookies from this site.

Agree