The SystemVerilog repeat loop runs a set of statements a fixed number of times, N. There is no loop variable and no condition to manage. You state how many passes you want and the loop takes care of the rest. In testbenches it is the shortest way to send N transactions or wait N clock cycles.
5 min read | Intermediate Level
What You'll Learn
- The syntax of
repeatand when it is a better fit thanfor - How
repeatcombined with an event control waits a number of clock cycles - How the repeat count is evaluated, including 0 and unknown values
- Where
repeatfits in design and verification code
Syntax
repeat (<number>)
// Single Statement
repeat (<number>) begin
// Multiple Statements
end
- number: an expression giving the number of passes. It can be a constant, a parameter or a variable.
- The expression is evaluated once, when the loop starts. Changing the variable inside the loop does not change the number of passes.
- If the count is 0, or contains X or Z bits, the body does not run at all.
Example #1: Repeat a Statement
module tb;
initial begin
repeat (5) begin
$display ("Repeat this statement");
end
end
endmodule
ncsim> run Repeat this statement Repeat this statement Repeat this statement Repeat this statement Repeat this statement ncsim: *W,RNQUIE: Simulation is complete.
A repeat loop can also be written as a for loop, but that is more verbose:
for (int i = 0; i < number; i++) begin
// Code
end
If you don't need to read the loop variable i inside the body, repeat is the better fit. When you do need the iteration number, for example to compute an address, use for.
Example #2: Wait for N Clock Cycles
repeat combined with an event control is the standard way to wait a number of clock cycles. Here the loop body is just @(posedge clk), so each pass waits for one rising edge.
module tb;
bit clk;
always #10 clk = ~clk;
initial begin
bit [2:0] num = $random;
$display ("[%0t] Repeat loop is going to start with num = %0d", $time, num);
repeat (num) @(posedge clk);
$display ("[%0t] Repeat loop has finished", $time);
$finish;
end
endmodule
ncsim> run [0] Repeat loop is going to start with num = 4 [70] Repeat loop has finished Simulation complete via $finish(1) at time 70 NS + 0
The clock period is 20 ns, and the first rising edge happens at 10 ns. The next three rising edges happen at 30, 50 and 70 ns, after which the loop ends. So this repeat loop waits until four rising clock edges have passed.
$random returns a 32-bit value, and only the lower 3 bits are kept in num, so it can be anything from 0 to 7. With a different seed, num could be 0. In that case the loop is skipped entirely and the second message prints at time 0.
Quick Check
Q: The code below starts with n = 3. How many lines does it print?
int n = 3;
initial begin
repeat (n) begin
$display ("n = %0d", n);
n++;
end
end
Show Answer
Three lines: n = 3, n = 4 and n = 5. The count is read once when the loop starts, so incrementing n inside the body does not add extra passes.
Using repeat in Verification
The two most common testbench patterns are sending a fixed number of stimulus items and inserting idle cycles. Both appear in the example below.
module tb;
bit clk;
logic [7:0] data;
always #5 clk = ~clk;
initial begin
repeat (4) begin // drive 4 random data values
@(posedge clk);
data <= $urandom_range(0, 255); // new value on each rising edge
end
repeat (2) @(posedge clk); // then 2 idle cycles
$finish;
end
endmodule
Where is repeat used in verification?
Reset sequences commonly hold reset for a fixed number of cycles with repeat (10) @(posedge clk);. Test sequences often send repeat (num_items) randomized transactions, where num_items is a knob the test can change.
Using repeat in Digital Design
In RTL, a loop is only synthesizable when the tool can work out its iteration count at elaboration time. Several synthesis tools accept repeat with a constant count, but support varies between tools. A for loop with constant bounds is the portable choice, and it also gives you an index if you need one. Treat repeat mainly as a verification construct.
Common Beginner Mistakes
Mistake #1: Expecting a changing count to change the number of passes
The repeat expression is read once on entry. Why? Unlike while, repeat never re-checks anything. If the number of passes must depend on something that changes during the loop, use a while loop.
Mistake #2: Misplacing the semicolon after the event control
Wrong: repeat (3) @(posedge clk); data <= data + 1;
Right: repeat (3) begin @(posedge clk); data <= data + 1; end
Why? In the first line, the loop body is only @(posedge clk). The loop waits three clocks and then increments data once. If you want something done on every pass, wrap it in begin ... end.
Mistake #3: An uninitialized 4-state count
If the count is a logic or integer variable that was never assigned, it is X, and the loop silently runs zero times. Why? The standard treats an X or Z count as 0. Initialize the count, or use a 2-state type such as int.
Practice Exercise
Challenge: A reusable wait task
Write a testbench task wait_cycles that takes an integer n and returns after n rising edges of clk. Use it to hold rstn low for 5 cycles.
Hint
The whole task body can be one line built from repeat and @(posedge clk). Declare the task automatic so that two processes can call it at the same time.
Solution
module tb;
bit clk, rstn;
always #5 clk = ~clk;
task automatic wait_cycles (input int n);
repeat (n) @(posedge clk); // one pass per rising edge
endtask
initial begin
rstn = 0; // assert active-low reset
wait_cycles (5); // hold for 5 clock cycles
rstn = 1; // release reset at the 5th rising edge (45 ns)
wait_cycles (3);
$finish;
end
endmodule
Summary
In this tutorial, you learned:
repeat (N)runs its body N times with no loop variable to manage- The count is evaluated once at entry; a count of 0, X or Z runs the body zero times
repeat (N) @(posedge clk);is the standard way to wait N clock cycles- Use
begin ... endwhen the body must do more than wait - Use
forinstead when you need the iteration index, or when writing portable synthesizable RTL