Verilog delay statements can have delays specified either on the left hand side or the right hand side of the assignment operator.

Inter-assignment Delays


	// Delay is specified on the left side
	#<delay> <LHS> = <RHS>

An inter-assignment delay statement has delay value on the LHS of the assignment operator. This indicates that the statement itself is executed after the delay expires, and is the most commonly using form of delay control.


module tb;
  reg  a, b, c, q;
  
  initial begin
    $monitor("[%0t] a=%0b b=%0b c=%0b q=%0b", $time, a, b, c, q);
    
    // Initialize all signals to 0 at time 0
    a <= 0;
    b <= 0;
    c <= 0;
    q <= 0;
    
    // Inter-assignment delay: Wait for #5 time units
    // and then assign a and c to 1. Note that 'a' and 'c'
    // gets updated at the end of current timestep
    #5  a <= 1;
    	c <= 1;
    
    // Inter-assignment delay: Wait for #5 time units
    // and then assign 'q' with whatever value RHS gets
    // evaluated to
    #5 q <= a & b | c;

    #20;
  end
  
endmodule

Note that q becomes 1 at time 10 units because the statement gets evaluated at 10 time units and RHS which is a combination of a , b and c evaluates to 1.

 Simulation Log
xcelium> run
[0] a=0 b=0 c=0 q=0
[5] a=1 b=0 c=1 q=0
[10] a=1 b=0 c=1 q=1
xmsim: *W,RNQUIE: Simulation is complete.

Intra-assignment Delays


	// Delay is specified on the right side
	<LHS> = #<delay> <RHS>

An intra-assignment delay is one where there is a delay on the RHS of the assignment operator. This indicates that the statement is evaluated and values of all signals on the RHS is captured first. Then it is assigned to the resultant signal only after the delay expires.


module tb;
  reg  a, b, c, q;
  
  initial begin
    $monitor("[%0t] a=%0b b=%0b c=%0b q=%0b", $time, a, b, c, q);
  
	// Initialize all signals to 0 at time 0  
    a <= 0;
    b <= 0;
    c <= 0;
    q <= 0;
    
    // Inter-assignment delay: Wait for #5 time units
    // and then assign a and c to 1. Note that 'a' and 'c'
    // gets updated at the end of current timestep
    #5  a <= 1;
    	c <= 1;

    // Intra-assignment delay: First execute the statement
    // then wait for 5 time units and then assign the evaluated
    // value to q
    q <= #5 a & b | c;
    
    #20;
  end
endmodule

Note that the assignment to q is missing in the log !

 Simulation Log
xcelium> run
[0] a=0 b=0 c=0 q=0
[5] a=1 b=0 c=1 q=0
xmsim: *W,RNQUIE: Simulation is complete.

This is because at 5 time units, a and c are assigned using non-blocking statements. And the behavior of non-blocking statements is such that RHS is evaluated, but gets assigned to the variable only at the end of that time step.

So value of a and c is evaluated to 1 but not yet assigned when the next non-blocking statement which is that of q is executed. So when RHS of q is evaluated, a and c still has old value of 0 and hence $monitor does not detect a change to display the statement.

To observe the change, let us change assignment statements to a and c from non-blocking to blocking.


	...
	
	// Non-blocking changed to blocking and rest of the
	// code remains the same
    #5  a = 1;
    	c = 1;
    
    q <= #5 a & b | c;
    
   	...
 Simulation Log
xcelium> run
[0] a=0 b=0 c=0 q=0
[5] a=1 b=0 c=1 q=0
[10] a=1 b=0 c=1 q=1
xmsim: *W,RNQUIE: Simulation is complete.