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;

*/

5 comments on “Verilog: Timing Controls

  1. Gowri Shankar

    Hi

    Regards for the day.

    Please let me know the difference between

    always @ (posedge clock)
    and
    @(posedge clock)

    Because according to what i understand is both get triggered on positive edge then why use two different methods for same operation

    Thank you

    Reply
    1. Sini Balakrishnan Post author

      Hi Gowri Shankar,

      How did you use @(posedge clock) in your design ?

      In verilog this has to be used in either always or initial block.

      Difference between always @(posedge clock) and @(posedge clock) (in the initial block) is, in the first case, it executes whenever there is a change in the clock from 0 to 1. But in the second case it executes only for the first posedge change.

      In the below example
      check_posedge_clk_2 module uses @posedge of clk and
      check_posedge_clock uses always @posedge clock.

      check_posedge_clk_2 executes only once, but other one executes for all the posedge changes of the clock till $finish.

      Hope this helps.

      module check_posedge_clk_2(in,clock,out);
      
       input [31:0] in;
       input clock;
       output [31:0] out;
       reg [31:0] out;
        
      
       initial begin
       out = 1'd0;
       @(posedge clock) 
       $display("In always block - From check_posedge_clk_2 module");
       out = out + 5;
       end
      
         
      
      endmodule
      
      module check_posedge_clk(in,clock,out);
      
       input [31:0] in;
       input clock;
       output [31:0] out;
      
       reg [31:0] out = 1'd0;
        
       always @(posedge clock) 
       begin
       out = out + 5;
       $display("In always block");
       end
      endmodule
           
        
      module test;
        reg [31:0] in;
        reg clock = 0;
        
        wire [31:0] out;
        
        check_posedge_clk ec(in,clock,out);
        check_posedge_clk_2 ec_2(in,clock,out);
        
        always clock = #5 ~clock;
        
        initial begin
          $monitor($time,"clock=%b \n",clock);
          #50 $finish;
         end
        
      endmodule
      
      /*
      ncsim> run
                         0clock=0 
      
      In always block - From check_posedge_clk_2 module
      In always block
                         5clock=1 
      
                        10clock=0 
      
      In always block
                        15clock=1 
      
                        20clock=0 
      
      In always block
                        25clock=1 
      
                        30clock=0 
      
      In always block
                        35clock=1 
      
                        40clock=0 
      
      In always block
                        45clock=1 
      
      
      
      */
      
      Reply
  2. Rakesh

    dear prudhvi,
    | is a doing bit wise operation ; for example a is 4 bit and b is 4 bit it will gives another 4 bit output.

    or: here based on any one of the inputs of a,b changes it will occurs the below procedural code

    Reply
  3. TANMAY

    can event control statement as :-

    always @(posedge clk)
    begin
    @(a or b)
    begin
    k1 = a;
    k = 0;
    k2 = b;
    k3 = 0;
    end
    end
    is synthesizable?
    It is showing me some error as
    Multiple event control statements in one always/initial process block are not supported in this case.

    Reply

Leave a Reply to Sini Balakrishnan Cancel reply

Your email address will not be published. Required fields are marked *