Search code examples
veriloghdl

Verilog always block properties - sequential vs. combinatorial


I understand that always block can be used to implement procedural and sequential logic.

  1. Will the gate-level realization of the following two codes be the same? If yes, what is the correct way of describing this continuous-time logic?

a.

module func(input a, input b , output reg o);
   always @(a,b)
    o=a&b;
endmodule

b.

module func(input, a, input b, output o);
   assign o = a & b;
endmodule

In (a), 'o' is a reg type and in (b) it is a wire. What does this difference mean?

  1. What are the required 'always' block properties for the synthesis tool to implement a FF? I know the following will result in a FF:
always @(posedge clk or negedge rst)
      [...]

But, I'm looking for a more in-depth understanding.


Solution

  • Your (a) and (b) codes are functionally equivalent. This means that they will simulate the same way and they will infer the same logic when synthesized.

    They use 2 different styles of modeling: (a) uses a procedural assignment because it uses an always block, whereas (b) uses a continuous assignment because there is no always block and it uses the assign keyword.

    In this simple case, there is no "correct" way; they are 2 different styles to achieve the same functionality. For such simple logic, it is preferable to use (b) because it uses less code and it is easier to understand. However, if your combinational logic were more complicated, the procedural approach might be easier to understand.

    In (a), the o signal must be a reg type since it is assigned inside a procedural logic block. There is no such requirement for continuous assignments. In this case, defining a reg type does not result in a flip-flop. A reg only infers a flip-flop when the always block describes sequential logic

    Synthesis tools look for specific types of patterns in Verilog code to infer sequential logic. The following will infer flip-flops with an asynchronous reset:

    always @(posedge clk or negedge rst)
        if (!rst) ...
        else ...
    

    The following will infer flip-flops with a synchronous reset:

    always @(posedge clk)
        if (!rst) ...
        else ...
    

    These are just a couple examples.