SystemVerilog gives you two statements for changing a loop's flow from inside the loop. break exits the loop immediately. continue skips the rest of the current pass and moves on to the next one. Both are borrowed from C and were added in SystemVerilog. Plain Verilog-2001 had neither, and designers had to use disable on a named block to get the same effect.

6 min read | Intermediate Level

What You'll Learn

  • How break and continue change the flow of any loop
  • How they behave in nested loops and in while loops
  • How to use break to build a synthesizable "find first" circuit
  • Where these statements are not allowed, and what to use instead

Syntax


break;       // exit the innermost enclosing loop now
continue;    // skip to the next pass of the innermost enclosing loop

Both work in every SystemVerilog loop: for, foreach, while, do while, repeat and forever. Both act only on the innermost loop that contains them.

Flow of a for loop showing break jumping out of the loop and continue jumping to the step expression

break

The loop below would normally print iterations 0 to 9. When i becomes 7, break ends the loop at once, and execution continues with the first statement after the loop.


module tb;
  	initial begin

      // This for loop increments i from 0 to 9 and exit
      for (int i = 0 ; i < 10; i++) begin
        $display ("Iteration [%0d]", i);

        // Let's create a condition such that the
        // for loop exits when i becomes 7
        if (i == 7)
          break;
      end
    end
endmodule
Output
ncsim> run
Iteration [0]
Iteration [1]
Iteration [2]
Iteration [3]
Iteration [4]
Iteration [5]
Iteration [6]
Iteration [7]
ncsim: *W,RNQUIE: Simulation is complete.

Iteration 7 is still printed, because the $display comes before the if. The step expression i++ does not run after a break.

continue

Here, when i is 7, continue skips the $display for that pass only. The loop then carries on with 8 and 9.


module tb;
  	initial begin

      // This for loop increments i from 0 to 9 and exit
      for (int i = 0 ; i < 10; i++) begin

        // Let's create a condition such that the
        // for loop
        if (i == 7)
          continue;

        $display ("Iteration [%0d]", i);
      end
    end
endmodule
Output
ncsim> run
Iteration [0]
Iteration [1]
Iteration [2]
Iteration [3]
Iteration [4]
Iteration [5]
Iteration [6]
Iteration [8]
Iteration [9]
ncsim: *W,RNQUIE: Simulation is complete.

In a for loop, continue jumps to the step expression (i++) and then to the condition check. In a while or do while loop it jumps straight to the condition check, because those loops have no separate step.

Quick Check

Q: In the continue example, what would print if continue were replaced with break?

Show Answer

Iterations 0 to 6. When i reaches 7, break exits the loop before the $display runs, so 7, 8 and 9 never print.

break in Nested Loops

break leaves only the loop it is directly inside. The outer loop keeps running.


module tb;
  initial begin
    for (int row = 0; row < 3; row++) begin
      for (int col = 0; col < 3; col++) begin
        if (col == 1)
          break;                          // leaves the inner (col) loop only
        $display ("row %0d col %0d", row, col);
      end
    end
  end
endmodule
// Prints: row 0 col 0, row 1 col 0, row 2 col 0

To leave both loops at once, set a flag before the inner break and test it in the outer loop. Alternatively, put the loops in a named block and use disable on it.

Using break in Digital Design

Most current synthesis tools accept break and continue inside loops with constant bounds. The loop is still unrolled. break simply turns the remaining iterations into logic that is gated off once the exit condition is met.

A "find first" circuit is a natural fit. The module below returns the index of the lowest set bit of req:


module find_first_one (
  input  logic [7:0] req,
  output logic [2:0] idx,
  output logic       found
);
  always_comb begin
    idx   = '0;                 // defaults when no bit is set
    found = 1'b0;
    for (int i = 0; i < 8; i++) begin
      if (req[i]) begin
        idx   = i;              // lowest set bit wins
        found = 1'b1;
        break;                  // stop scanning after the first match
      end
    end
  end
endmodule

For req = 8'b0010_0110, idx is 1. Without the break, later matches would overwrite idx and the result would be the highest set bit, 5. The synthesized hardware is a priority chain from bit 0 upwards.

Where are break and continue used?

In RTL, break keeps leading-one detectors, free-slot finders in buffer allocators and first-match lookups compact and readable. In testbenches, continue skips transactions a scoreboard should ignore, such as idle cycles, and break ends a forever polling loop once a completion flag or timeout is seen.

Where break and continue Are Not Allowed

  • Outside a loop. Using break to leave an if or a begin ... end block is a compile error. To leave a task or function early, use return.
  • Across a fork boundary. A break inside a fork ... join cannot exit a loop that surrounds the fork, because each forked branch is a separate process.

Common Beginner Mistakes

Mistake #1: continue before the increment in a while loop

Wrong:


int i = 0;
while (i < 10) begin
  if (i == 7) continue;   // jumps back to the check with i still 7
  $display ("i = %0d", i);
  i++;
end

Right: increment before the continue, or use a for loop, where continue still runs the step.

Why? A while loop has no step expression. Skipping the rest of the body also skips i++, so i stays at 7 forever.

Mistake #2: Expecting break to exit every nested loop

break exits only the innermost loop. Why? It is defined relative to the nearest enclosing loop. Use a flag or disable on a named block to exit several levels at once.

Mistake #3: Using break where return belongs

Wrong: if (error) break; at the top level of a task, outside any loop
Right: if (error) return;

Why? break is only legal inside a loop. return exits the task or function from anywhere in its body.

Practice Exercise

Challenge: Sum the even values, stop at a marker

Given int data[6] = '{4, 7, 10, 3, -1, 8};, add up only the even values, and stop as soon as you reach -1, which marks the end of valid data. The expected sum is 14.

Hint

Use foreach. Check for the -1 marker first with break, then skip odd values with continue.

Solution

module tb;
  int data[6] = '{4, 7, 10, 3, -1, 8};
  int sum;

  initial begin
    foreach (data[i]) begin
      if (data[i] == -1) break;       // end-of-data marker: stop scanning
      if (data[i] % 2 != 0) continue; // skip odd values
      sum += data[i];
    end
    $display ("sum = %0d", sum);      // sum = 14 (4 + 10); 8 is never reached
  end
endmodule

The order of the two checks matters. The marker test comes first so that -1 is never treated as data.

Summary

In this tutorial, you learned:

  • break exits the innermost loop immediately; continue skips to its next pass
  • Both work in all six SystemVerilog loops and act only on the innermost one
  • In a for loop, continue still runs the step; in a while loop, it jumps straight to the condition
  • break inside a constant-bound loop is synthesizable and gives first-match priority logic
  • Outside a loop, use return to leave a task or function, or disable to leave a named block
Did you find what you were looking for?

Quiz

Test Your Knowledge

1 of 5 Score: 0 / 5