Verilog: Timing Controls

Timing Controls
Timing control statements are required in simulation to advance time. The time at which procedural statements will get executed shall be specified using timing controls. Delay based, event based and level sensitive timing controls are available in Verilog. Each of these are discussed below.
Delay Based Timing Control
In this, timing control is achieved by specifying waiting time to execution, when the statement is encountered. The sybmol "#" is used to specify the delay. There are 3 ways, delay based timing control can be specified.
Regular Delay Control
In this delay will be specified on the left of the procedural assignment as a non-zero number. In the below code, execution of line 11 to 14 statements are controlled by some delays. The statement b = 1 will be executed at time 10 and others at time 30,35 and 45. Refer simulation result for more details.
Intra-assignment Delay Control
In this case, delays will be specified on the right hand side of the assignment operation. The RHS expression will be evaluated at the current time and the assignment will be occurred only after the delay. The statement a = #5 (b + c) and rval = #20 L_DELAY + a - 4 are intra-assignment delay control statements. Value of b and c are evaluated at time 45, but assignment to 'a' will happen only at time 50. The same way L_DELAY + a - 4 will be calculated at time 50 and assignment to rval will happen at time 70.
module delay_control_check; parameter L_DELAY = 10;
reg a,b,c; reg[3:0] rval;
initial begin a = 0; b=0; c=0; rval = L_DELAY - 5;
//Regular Delay Control #10 b = 1; #20 c = a + b; #5 a = c; #10 rval = L_DELAY + a;
b= 0; c = 0; //Intra assignment a = #5 (b + c); rval = #20 L_DELAY + a - 4; end
initial begin $monitor($time,"Value a = %b, b= %b, c=%b rval=%d\n",a,b,c,rval); #500 $finish; end
endmodule /* Simulation result ncsim> run 0Value a = 0, b= 0, c=0 rval= 5
10Value a = 0, b= 1, c=0 rval= 5
30Value a = 0, b= 1, c=1 rval= 5
35Value a = 1, b= 1, c=1 rval= 5
45Value a = 1, b= 0, c=0 rval=11
50Value a = 0, b= 0, c=0 rval=11
70Value a = 0, b= 0, c=0 rval= 6
Simulation complete via $finish(1) at time 500 NS + 0 ./delay.v:25 #500 $finish; */
Zero Delay Control
Zero delay control statement specifies zero delay value to LHS of procedural assignment. This is a method to ensure that the statement is executed at the end of that simulation time. That means, zero delay control statement is executed only after all other statements in that simulation time are executed. Here, a,b,c are executed different values in two initial block, one using normal assignment and other using zero delay. This example shows that how assignments will happen in the simulation.
module zero_delay_check; reg a,b,c;
//initial block with zero delay initial begin
#0 a = 1; #0 b = 1; #0 c = 1; $display(" Zero delay control a= %b, b= %b, c=%b\n",a,b,c); end//initial block without zero delay initial c = 0;
initial begin a = 0; b = 0; $display("Non-zero delay control a= %b, b= %b, c=%b\n",a,b,c); end
endmodule
/* Simulation Result ncsim> run Non-zero delay control a= 0, b= 0, c=0
Zero delay control a= 1, b= 1, c=1 */
Event Based Timing Control
In this, execution of a statement or a block of a statement is controlled by an event. Regular, named and event OR control are different types of event based controls.
Regular event control
Execution of statement will happen on changes in signal or at a positive or negative transitions of signals. For example posedge of clock, negedge of reset etc.
eg: @(posedge clock) out = in; @(clock) z = n << 2;
Named Event Control
Event will be declared using keyword 'event' and is triggered by using the symbol ' -> '. In the below example the event 'received' is declared and is triggered when pkt_done is high. Once event is triggered, always block at line 23 will get executed.
module event_control(in,ctrl,clock,out);
input [31:0] in; input [2:0] ctrl; input clock; output [31:0] out;
reg [31:0] out; wire pkt_done;
event received;
assign pkt_done = ^ctrl;
always @(posedge clock) begin if(pkt_done) begin $display("Event : Triggered"); ->received; end end
always @(received) begin $display("Event : Received"); out = in + 100; end endmodule
//for testing
module test; reg [31:0] in; reg [2:0] ctrl; reg clock = 0;wire [31:0] out;
event_control ec(in,ctrl,clock,out);
always clock = #5 ~clock;
initial begin in = 32'd25; ctrl = 3'b100;
#10 in = 'd50; ctrl = 3'b101;
#10 in = 'd30; ctrl = 3'b001;
#10 in = 40; ctrl = 3'b010;
#10 in = 0; ctrl = 3'b000; end
initial begin $monitor($time,"clock=%b, in = %d, ctrl=%b out=%d\n",clock,in,ctrl,out); #50 $finish; end endmodule
/* Simulation Result ncsim> run 0clock=0, in = 25, ctrl=100 out= x
Event : Triggered Event : Received 5clock=1, in = 25, ctrl=100 out= 125
10clock=0, in = 50, ctrl=101 out= 125
15clock=1, in = 50, ctrl=101 out= 125
20clock=0, in = 30, ctrl=001 out= 125
Event : Triggered Event : Received 25clock=1, in = 30, ctrl=001 out= 130
30clock=0, in = 40, ctrl=010 out= 130
Event : Triggered Event : Received 35clock=1, in = 40, ctrl=010 out= 140
40clock=0, in = 0, ctrl=000 out= 140
45clock=1, in = 0, ctrl=000 out= 140
Simulation complete via $finish(1) at time 50 NS + 0 ./event.v:61 #50 $finish; ncsim> exit */
Event OR control
The transitions of signal or event can trigger the execution of statements as shown below.
always @(clock or in) //Wait for clock or in to change
OR
always @(clock, in)
Level Sensitive Timing Control
This waits for a certain condition to be true. In the below example, it waits for xor-ctrl bits to be 1, and then do the assignment to out.
module level_control(in,ctrl,out);
input [31:0] in; input [2:0] ctrl; output [31:0] out;
reg [31:0] out;
always begin wait (^ctrl) #2 out = in + 100; end endmodule
module test_level_control; reg [31:0] in; reg [2:0] ctrl; wire [31:0] out;
level_control ec(in,ctrl,out);
initial begin in = 32'd25; ctrl = 3'b100;
#10 in = 'd50; ctrl = 3'b101;
#10 in = 'd30; ctrl = 3'b001;
#10 in = 40; ctrl = 3'b011;
#10 in = 0; ctrl = 3'b100; end
initial begin $monitor($time,"in=%0d, ctrl=%b out=%0d\n",in,ctrl,out); #50 $finish; end
endmodule
/*
Simulation Result ncsim> run 0in=25, ctrl=100 out=x
2in=25, ctrl=100 out=125
10in=50, ctrl=101 out=125
12in=50, ctrl=101 out=150
20in=30, ctrl=001 out=150
22in=30, ctrl=001 out=130
30in=40, ctrl=011 out=130
32in=40, ctrl=011 out=140
40in=0, ctrl=100 out=140
42in=0, ctrl=100 out=100
Simulation complete via $finish(1) at time 50 NS + 0 ./level_sensitive.v:43 #50 $finish;
*/