Categories
Verilog coding styles

Verilog ‘if-else’ vs ‘case’ statements

Case’ statements in verilog or VHDL are more efficient than using ‘if-else‘ statements for parallel processing of data because ‘if-else’ can generate long combinatorial chains (priority scheme) of logic that can cause difficulties meeting timing.

It is worth noting here that the options of the ‘case’ statement must be mutually exclusive and all possible input values of the control expression must be included in the set of options (ie no incomplete assignments) to avoid the inference of unintended latches.

The following verilog code :

Will be synthesized to the following priority combinatorial logic :

All possible input values of the control expression must be included in the set of options (as shown above) to avoid the inference of unintended / accidental transparent latches.

However, if we recode the above verilog code to the following, it will direct the synthesis tool to implement parallel logic (fig2) rather than a priority scheme (fig1).

This will be synthesized to one multiplexer :

If a priority encoder is required (eg designing a priority interrupt control logic) this can be coded by using the nested if-else statements but need to be cautious & make sure that it will pass timing during synthesis at the maximum operating frequency of interest otherwise it will require re-designing/re-coding to try to resolve the timing issues.

Categories
Verilog coding styles

Verilog Blocking & Non-Blocking assignments elaborated

Blocking / Non-Blocking assignment rules

The main reason to use either Blocking or Non-Blocking assignments is to generate either combinational or sequential logic.

In non-blocking assignments (<=), all registers inside the always block are updated at the end. In blocking assignments (=), the registers are updated immediately.

Whether or not a flip-flop is inferred from a blocking assignment depends on whether or not the value of the variable being assigned needs to be remembered from one clock edge to the next.

It is good practice to separate combinational and sequential code as much as possible. In verilog, if we want to create sequential logic can use a clocked always block with non-blocking assignments. If on the other hand we want to create combinational logic can use an always block with blocking assignments. Best not to mix the two in the same always block but if they are mixed, need to be careful when doing this. Its up to the synthesis tools to determine whether a blocking assignment within a clocked always block will infer a flip-flop or not. If the signal is read before being assigned (eg fig2 below), the tools will infer sequential logic.

For simplicity purposes only showing in the verilog examples below the Always Block. These Always blocks are blocks of sequential logic since it involves a clock.

If on an active clock edge, the variable tmp is being assigned a value before it’s value is used (ie ‘write before read’ case) then no flip-flop is required & synthesis will not infer it as shown in fig1 below.

fig1

If the value of the reg is used before a new value is assigned to it (ie ‘read before write’ case), then the value that is used will be the value that was assigned on a previous clock. Therefore a flip-flop is required here as shown in fig2 below.

fig2

If all non-blocking assignments are used within the always block, it will look like :

or :

This image has an empty alt attribute; its file name is image-2.png
fig3

Non-blocking assignments always imply flip-flops (order of assignments doesn’t matter). Same block diagram is inferred on both cases as shown in fig3 above. They result in simultaneous or parallel statement execution.