A race occurs when a result depends on an execution order that the design or testbench has not specified reliably. Processes that drive and sample the same signal on the same edge are a common source. Avoid relying on source ordering, simulator luck or a particular waveform viewer's display order.
Worked example
The testbench changes d while the clock is low, waits, then creates the sampling edge. A later delay allows nonblocking updates to settle before q is checked. This deliberately separates driving, sampling and observation.
module reg1(input clk,d,output reg q);
always @(posedge clk) q<=d;
endmodule
module tb;
reg clk,d;wire q;
reg1 dut(.clk(clk),.d(d),.q(q));
initial begin
clk=0;d=0;#2;d=1;#2;clk=1;#1;
$display("q=%b",q); // 1
$finish;
end
endmodule
What to watch for
Using nonblocking assignments in RTL does not automatically make arbitrary same-edge testbench stimulus race-free. The driver and checker still need a sampling agreement.
Try it yourself
Why is changing d in one posedge process while another samples it risky?
Answer: Both processes react to the same event. Without a defined discipline, the sampled value may depend on their relative execution order.
How to study this topic
Save the example in a .v file and identify its top module before compiling. Separate stimulus and observation from synthesizable RTL. Change one input, width or boundary condition at a time, predict the result, and compare that prediction with simulation. A syntax check does not establish synthesis support or timing closure.
Continue learning
Previous: Intra-assignment versus inter-assignment delays
Next: Simulation versus synthesis semantics
Browse the complete Verilog index
Explore related programmes
These recorded programmes are upcoming. This article is general educational content, not a syllabus or course sample.
Verilog