A forever loop runs forever, or for infinite simulation time. It has no condition and never ends on its own. That makes it the natural choice for testbench processes that must stay alive for the whole test, such as clock generators, drivers and monitors. It also means every forever loop needs two things: a timing control inside the body, and a way to stop.
6 min read | Intermediate Level
What You'll Learn
- The syntax of
foreverand how it differs from analwaysblock - Why a
foreverloop without a timing control hangs the simulator - How to build clocks and monitors with
forever - How to stop a
foreverloop cleanly
Syntax
forever
// Single statement
forever begin
// Multiple statements
end
forever takes no arguments. It is the same as while (1) or for (;;), but it states the intent more clearly.
forever vs always
A forever loop behaves much like the Verilog always block below. Both run for infinite simulation time, and both must contain a delay or event control.
always
// Single statement
always begin
// Multiple statements
end
An always or forever block without a delay element will hang the simulation. The simulator only moves time forward when every process is waiting. A loop that never waits keeps running at the same timestamp, and no other process gets a turn.
The difference is where each one may appear:
always | forever | |
|---|---|---|
| What it is | A procedural block, declared directly in a module, interface or program | A loop statement, used inside a procedural block or task |
| Allowed in classes or tasks? | No | Yes |
| Can be exited? | No, it runs until the simulation ends | Yes, with break, disable or by killing its process |
| Synthesizable? | Yes, as always_ff, always_comb and so on | No |
Because an always block cannot be placed inside a class or another procedural block, class-based testbenches use a forever loop inside a task to get the same effect.
Example: Clock Generation
A free-running clock is the classic use of forever. The loop toggles the clock after every half-period delay.
module tb;
bit clk; // 2-state, starts at 0
initial begin
forever #5 clk = ~clk; // toggle every 5 ns: 10 ns period (100 MHz)
end
initial begin
#50 $finish; // the clock loop never ends, so stop here
end
endmodule
The clock rises at 5, 15, 25, 35 and 45 ns. The second initial block is essential: without $finish, the clock would keep the simulation running forever.
Example: A Testbench Monitor
The pseudo code below sketches a testbench monitor. Once started, it keeps running for as long as there is activity on the bus it watches.
class Monitor;
virtual task run();
forever begin
@(posedge vif.clk);
if (vif.write & vif.sel)
// Capture write data
if (!vif.write & vif.sel)
// Capture read data
end
endtask
endclass
module tb;
Monitor mon = new();
// Start the monitor task and allow it to continue as
// long as there is activity on the bus
initial begin
fork
mon.run();
join_none
end
endmodule
@(posedge vif.clk)is the timing control. Each pass samples the bus once per clock and then waits for the next edge.fork ... join_nonestartsrun()as a separate process. Theinitialblock can then carry on instead of being stuck inside a task that never returns.
This is pseudo code. Comments are not statements, so as written the second if becomes the body of the first, and the second if has no body at all, which is a compile error. In real code, give each if its own statement or begin ... end block. vif would also need to be declared in the class as a virtual interface handle.
Where is forever used in verification?
Almost every reusable testbench component runs on a forever loop. A driver repeatedly fetches the next transaction and drives it onto the pins. A monitor repeatedly samples the interface and sends observed transactions to a scoreboard. In UVM, the run_phase of drivers and monitors is typically a single forever loop.
Quick Check
Q: What would happen if the testbench called mon.run(); directly inside the initial block, without fork ... join_none?
Show Answer
The monitor would still run, but run() never returns. Any statements after the call in that initial block, such as starting a test sequence, would never execute.
Stopping a forever Loop
A forever loop has no exit condition, so something must end it explicitly:
$finishends the whole simulation, as in the clock example.breakinside the loop exits just that loop, and execution continues after it.disableon a named block, ordisable fork, stops the loop from another process. See disable fork.
module tb;
bit clk, done;
int cycles;
always #5 clk = ~clk; // clock rises at 5, 15, 25 ... ns
initial #73 done = 1; // some other process signals completion
initial begin
forever begin
@(posedge clk);
cycles++;
if (done) break; // leave the loop on the first edge after done
end
// Runs only after break: prints "Loop exited after 8 cycles at 75"
$display ("Loop exited after %0d cycles at %0t", cycles, $time);
$finish;
end
endmodule
done goes high at 73 ns. The loop sees it on the next rising edge at 75 ns, which is the eighth edge, and break hands control to the $display after the loop.
forever in Digital Design
forever is a verification-only construct, and mainstream synthesis tools do not accept it in RTL. Hardware that "runs forever" is described with always_ff for clocked logic and always_comb for combinational logic (see always_comb and always_ff). Design engineers still use forever in their own block-level testbenches to generate clocks and apply stimulus.
Common Beginner Mistakes
Mistake #1: Waiting on a level that is already true
Wrong: forever begin wait (ready); send_item(); end
Right: forever begin @(posedge clk); if (ready) send_item(); end
Why? wait (ready) does not block if ready is already 1. If send_item() also takes no time, the loop spins at the same timestamp and hangs, even though it appears to contain a timing control. Make sure every pass is guaranteed to advance time, for example by waiting on a clock edge.
Mistake #2: Code after a forever loop that never runs
In initial begin forever #5 clk = ~clk; reset_dut(); end, reset_dut() is never called. Why? Statements after a forever loop run only if the loop is exited with break. Put the clock in its own initial block, or start the loop with fork ... join_none.
Mistake #3: No way to end the simulation
A testbench whose only processes are forever loops runs until you kill the simulator. Why? A free-running clock always has a future event scheduled, so the simulator never runs out of work. Always provide a $finish, or in UVM, drop all objections, once the test is done.
Practice Exercise
Challenge: 200 MHz clock that stops itself
Write a testbench that generates a 200 MHz clock with a forever loop and ends the simulation after exactly 20 rising edges.
Hint
200 MHz means a 5 ns period, so the half-period delay is 2.5 ns. You need a `timescale with a precision fine enough for 2.5 ns, and repeat to count the edges.
Solution
`timescale 1ns/1ps
module tb;
bit clk;
initial forever #2.5 clk = ~clk; // 2.5 ns half period = 5 ns period (200 MHz)
initial begin
repeat (20) @(posedge clk); // count 20 rising edges
$finish; // 20th edge is at 2.5 + 19*5 = 97.5 ns
end
endmodule
The clock loop and the edge counter run as two separate processes. The counter is what ends the test, because the clock loop never would.
Summary
In this tutorial, you learned:
foreverrepeats its body indefinitely and is equivalent towhile (1)- Every pass must advance simulation time, through
#delayor@(event), or the simulator hangs - Unlike
always,forevercan be used inside tasks and classes, which is why drivers and monitors use it - Start long-running
forevertasks withfork ... join_noneso the calling block can continue - A
foreverloop ends only throughbreak,disableor$finish foreveris not synthesizable; RTL usesalways_ffandalways_combinstead