Recall: What is Verilog?
Verilog serves two roles:
Note that the term compiles actually just mean turning Verilog hardware description code into gates (synthesize).
The constructs are syntax used in Verilog that are generally synthesizable. Which means they have an equivalent gate-level implementation of the construct.
alwaysblocks such as:
The always / process blocks are an exception.
The synthesis tool tries its best to find hardware implementation that matches the behavior described in the process using Pattern Matching.
There are three patterns that ALL synthesis tool can understand:
Thus, any process must be one of these three patterns.
The important rule for synthesizing
Every process must fall exactly into one of these three categories!
A Pure combinational block’s output only depends on the current input. There are several rules for purely combinational blocks:
Every input to the process must be in the sensitivity list.
The sensitivity list can be denoted like:
In Verilog 2001, a
* can be used in the sensitivity list. If this a referenced signal is not in the sensitivity list, Quartus will sometimes throw a warning. In SystemVerilog, a
always_comb can be used instead.
Every output must be assigned a value for every possible combinational inputs. (Every possible path through the process must have a designated output value)
always @(A or B or SEL) if (SEL == 1) C = A; else C = B;
Missing items in the sensitivity list will cause undefined behavior!
If not all cases are covered, such as a bad example as shown below. Then a warning is raised in Verilog 2001 and inferred latches is synthesized - something that we don’t want. In SystemVerilog, an error is thrown and the synthesis is stopped.
always_comb if (SEL == 1) C = A; // Error thrown when trying to compile
Each output chances ONLY on the rising or falling edge of a single clock. There are two rules:
Only the clock edge signals should be in the sensitivity list
Only signals that change on the same edge of the same clock should be part of the same always block
An example is:
always @(posedge CLK) // Some sequential logic ehre
Note: sequential circuit with synchronous reset falls under this category.
In System Verilog, it is advised to use
always_ff instead. An example use would be:
always_ff @(posedge CLK); Q <= D;
We need reset because when a system is powered up, it could start at some random state, and we need to go back to a known starting point. Systems are not perfect, and we also need a way to reset.
For debugging, it’s convenient to have an option to reset to try again.
There are two kinds of resets:
Here’s an example implementation:
always @(posedge CLK) if (RESET == 1) Q <= 0; // Reset case else Q <= D; // Normal case
Recall that asynchronous reset is sensitive to the clock and the reset signal. There is one rule:
Sensitivity list includes clock and reset
always @(posedge CLK or posedge RESET) if (RESET == 1) // reset assignments // reset case else Q <= D; // normal operation
Processes are concurrent statements
The order of concurrent statements don’t matter. Thus changing the order of always blocks won’t change the synthesis result.
Do not drive a signal from multiple processes
An example of a wire being driven by multiple signals:
module BAD(input A, input B, input C, input D, output F); always @(C, D) F = C | D; always @(A, B) F = A & B; endmodule