Tutorials

Learn More

Behavioral Modeling

On increasing digital design complexity, the designer has to find out the optimum algorithm and architecture to implement in hardware. Hence, the designer needs a way that can describe the design as per algorithm behavior. The Verilog provides the facility to represent the behavior of design at a high-level abstraction similar to C language programming.

Structured Procedure blocks

Verilog provides two structured procedural blocks.

  1. initial block
  2. always block

initial block in Verilog

The initial block executes only once and starts its execution at the beginning of a simulation.

  1. It is a non-synthesizable block and it can not contribute to building design schematic development.
  2. Multiple statements are enclosed within ‘begin’ and ‘end’ keywords and statements are executed sequentially.
  3. Multiple initial blocks are valid in a module and each block executes at zero simulation time. An individual block may finish their execution independently.
  4. Nested initial blocks are not valid.
  5. It can execute in zero time or take some time depending on the delay involved.

Syntax:

initial 
  <single statement>

initial begin
  <statement 1>
  <statement 2>
  <statement 3>
  ...
  ...
end

Use of initial block:

The initial block is used for 

  1. Initialize variables
  2. Implementing a testbench code
  3. Monitoring waveforms and other processes that are executed only once during the entire simulation.
  4. Drive ports with specific values.

Examples:

Basic initial block that executes in zero simulation time.

module tb;
  reg i1;
  reg [3:0] i2;
  
  initial begin
    i1 = 0;
    i2 = 4'h5;
    $display("i1 = %0h, i2 = %0h", i1, i2);
  end
endmodule

Output:

i1 = 0, i2 = 5

Multiple initial blocks

module tb;
  reg i1;
  reg [3:0] i2;
  
  initial    
    i1 = 0;
  
  initial begin
    i2 = 4'h5;
    $display("i1 = %0h, i2 = %0h", i1, i2);
  end

  initial begin
    #5;
    i1 = 1;
    i2 = 4'h8;
    $display("i1 = %0h, i2 = %0h", i1, i2);
  end
endmodule

Output:

i1 = 0, i2 = 5
i1 = 1, i2 = 8

Terminate simulation using $finish system task

module tb;
  reg i1;
  reg [3:0] i2;
  
  initial begin
    #5;
    i1 = 1;
    i2 = 4'h8;
    $display("i1 = %0h, i2 = %0h", i1, i2);
    #5 i1 = 0;
    i2 = 4'h2;
    $display("i1 = %0h, i2 = %0h", i1, i2);
  end
  
  initial
    #6 $finish;
  
endmodule

Output:

i1 = 1, i2 = 8
$finish called from file "testbench.sv", line 18.
$finish at simulation time 6

always block in Verilog

The always block starts its execution at the beginning of the simulation and continues to execute in a loop.

  1. Similar to the initial block, the always block is executed sequentially.
  2. Based on changes in single or multiple signals in the sensitivity list, always block is executed.
  3. If no sensitivity list is specified, always block executes repeatedly throughout the simulation.
  4. Multiple always blocks are valid in a module and each block executes independently.
  5. Nested always blocks are not valid.

Syntax:

always 
  <single statement>

always @(<sensitivity_list>)
  <single statement>

always @(<sensitivity_list>) begin
  <statement 1>
  <statement 2>
  <statement 3>
  ...
  ...
end

Use of always block

  1. To model repetitive activity in a digital design. Ex. clock generation.
  2. To implement combinational and sequential elements in digital circuits.

Sensitivity list

The sensitivity list can be a single or multiple signals placed within parentheses () after @ operator. Based on the change in any signal value, it allows executing the always block.

If the sensitivity list includes all inputs, then only ‘*’ is used to represent all inputs instead of writing all inputs.

always @(i1 or i2 or i3) begin
  <statements>
end

Based on the change in signal value in anyone of the i1, i2, or i3 signals, the always block will be executed.

Examples

Clock Generator

In the below example, the signal clk value changes after every 5 time-units.

The time period of the clock = 10 time-units.

module tb;
  reg clk;
  
  initial clk = 0;
  always #5 clk = ~clk;
  
  initial begin
    $monitor("At t = %0d, clk = %0b", $time, clk);
    #50 $finish;
  end
  
endmodule

Output:

At t = 0, clk = 0
At t = 5, clk = 1
At t = 10, clk = 0
At t = 15, clk = 1
At t = 20, clk = 0
At t = 25, clk = 1
At t = 30, clk = 0
At t = 35, clk = 1
At t = 40, clk = 0
At t = 45, clk = 1

It is mandatory to put a delay in always block while generating the clock otherwise, simulation hangs due to zero-delay infinite loop.

always clk = ~clk; // causes simulation hang

Always block with a sensitivity list

module and_gate(input i1, i2, i3, output reg out);
   
  always@(i1 or i2 or i3) begin
    out = i1 & i2 & i3;
  end
  
  // or
  //always @(*) out = i1 & i2 & i3;
  
endmodule

Output:

At T = 0: i1 = 0, i2 = 0, i3 = 0, out = 0
At T = 5: i1 = 0, i2 = 1, i3 = 0, out = 0
At T = 13: i1 = 1, i2 = 1, i3 = 0, out = 0
At T = 16: i1 = 1, i2 = 1, i3 = 1, out = 1