Verilog Always Block: Master It With This Simple Guide
The Verilog Hardware Description Language (HDL) provides engineers with a powerful tool for designing digital systems. Xilinx, a leading FPGA vendor, relies heavily on Verilog for its programmable logic devices. One fundamental construct within Verilog is the verilog always block, which enables the modeling of sequential and combinational logic. Behavioral modeling using the always block allows designers to describe the functionality of circuits without explicitly defining their gate-level implementation, streamlining the design process. Mastering the usage of the verilog always block is crucial for success in digital design, from simple logic gates to complex processor cores.

Image taken from the YouTube channel Shreyas Nisal , from the video titled Verilog #3: The Always Block .
Mastering the Verilog Always Block: A Simple Guide to Effective Hardware Modeling
This guide provides a structured approach to understanding and effectively utilizing the always
block in Verilog. We will explore its syntax, functionality, sensitivity lists, and common use cases to enable you to write robust and predictable hardware descriptions.
Understanding the always
Block
The always
block is a fundamental construct in Verilog used to model the behavior of digital circuits. It defines a block of code that executes repeatedly, driven by changes in specified signals or conditions. Think of it as a continuously running process reacting to its inputs. The key to mastering the always
block lies in understanding its sensitivity list and how it affects the simulation and synthesis results.
Basic Syntax
The basic syntax of an always
block is as follows:
always @ (sensitivity_list)
begin
// Sequential logic statements
end
always
keyword: This keyword initiates the block.@
symbol: This indicates the start of the sensitivity list specification.sensitivity_list
: This is a list of signals that trigger the execution of the block when they change.begin
andend
keywords: These delimit the block of sequential statements that will be executed.
Sensitivity List Explained
The sensitivity list is crucial. It defines under which conditions the statements inside the always
block will be executed.
-
Edge-triggered sensitivity (posedge/negedge): Reacts to specific transitions of signals. For instance,
posedge clock
triggers the block execution only when theclock
signal transitions from 0 to 1.negedge clock
reacts to the transition from 1 to 0. -
Level-sensitive sensitivity (signal_name): Reacts to any change (either 0 to 1 or 1 to 0) in the specified signal. Using
a or b or c
means the block will execute ifa
,b
, orc
changes. This construct is crucial for modeling combinational logic. -
always @*
(oralways @(*)
in SystemVerilog): This construct infers the sensitivity list automatically based on the variables used inside thealways
block. It’s the most convenient way to define a sensitivity list for combinational logic, as it automatically updates if you change the internal logic. -
always @(posedge clock, negedge reset)
(Example of mixed sensitivity): This block executes on the positive edge of the clock or the negative edge of the reset signal.
Blocking vs. Non-Blocking Assignments
Within the always
block, you’ll primarily use two types of assignment operators:
-
Blocking Assignments (
=
): Execute in the order they appear. The next statement waits for the previous one to complete. Primarily used for modeling combinational logic. -
Non-Blocking Assignments (
<=
): Execute concurrently. All assignments are scheduled to happen at the end of the current simulation time step. Crucial for modeling sequential logic to prevent race conditions.
Assignment Type | Symbol | Execution Order | Best Used For |
---|---|---|---|
Blocking | = |
Sequential | Combinational Logic |
Non-Blocking | <= |
Concurrent | Sequential Logic |
Modeling Combinational Logic with always
The always
block can effectively describe combinational circuits.
Guidelines for Combinational Logic
- Use
always @*
(oralways @(*)
). This ensures that any change in the input signals to the combinational logic will trigger the block’s execution. - Use blocking assignments (
=
). This ensures that the logic is evaluated in the order it appears, reflecting the immediate response of combinational circuits. - Ensure all outputs are explicitly assigned values under all possible input conditions. Failing to do so can result in unintended latch inference.
Example: Simple AND Gate
module and_gate (input a, input b, output reg out);
always @*
begin
out = a & b;
end
endmodule
Modeling Sequential Logic with always
The always
block is also essential for modeling sequential circuits such as flip-flops, registers, and state machines.
Guidelines for Sequential Logic
- Use edge-triggered sensitivity lists (e.g.,
posedge clock
). - Use non-blocking assignments (
<=
). This prevents race conditions and ensures that the assignments are updated at the end of the clock cycle. - Include a reset condition to initialize the circuit to a known state.
Example: D Flip-Flop
module d_flip_flop (input clk, input reset, input d, output reg q);
always @(posedge clk or negedge reset)
begin
if (!reset)
q <= 0;
else
q <= d;
end
endmodule
Common Mistakes and How to Avoid Them
Several common mistakes can occur when using the always
block. Understanding these pitfalls can save significant debugging time.
Latch Inference
Latch inference occurs when an always
block intended to represent combinational logic does not assign a value to an output under all possible input combinations. This creates a latch, a memory element, which may not be the intended behavior. To avoid latch inference:
- Ensure that all output signals are assigned values in every possible execution path of the
always
block, often through the use ofelse
statements.
Sensitivity List Errors
An incomplete or incorrect sensitivity list for combinational logic can lead to simulation mismatches and incorrect hardware behavior.
- Use
always @*
(oralways @(*)
in SystemVerilog) for combinational logic to automatically infer the sensitivity list. - Double-check the sensitivity list for sequential logic to ensure it accurately reflects the trigger conditions for the circuit’s behavior.
Mixing Blocking and Non-Blocking Assignments Inappropriately
Using the wrong type of assignment operator can lead to unexpected behavior, especially in sequential logic.
- Use non-blocking assignments (
<=
) for sequential logic to prevent race conditions and ensure predictable behavior. - Use blocking assignments (
=
) for combinational logic to reflect the immediate response of the circuit to input changes. Avoid mixing assignment types within the samealways
block.
FAQs: Mastering the Verilog Always Block
This FAQ section answers common questions related to understanding and using the Verilog always block effectively, as discussed in our guide.
What exactly is a Verilog always block and what’s its purpose?
The always
block in Verilog is a procedural construct used to define a block of code that executes repeatedly based on sensitivity list or other conditions. Its primary purpose is to model sequential logic, state machines, and combinational circuits. You use the Verilog always block to define how signals change over time.
What’s the difference between always @(*)
and always @(posedge clk)
?
always @(*)
infers combinational logic. This means the block executes whenever any signal on the right-hand side of an assignment within the block changes. always @(posedge clk)
infers sequential logic. The code within the block executes only on the rising edge of the clock signal clk
.
What happens if I forget to include all the signals used in a combinational Verilog always block in the sensitivity list?
If you don’t include all signals used in a combinational Verilog always block in the sensitivity list (and you are not using always @(*)
), you will likely create a latch or incorrect behavior in your synthesized hardware. Synthesis tools might not properly infer the logic, leading to unexpected and potentially problematic circuit functionality.
Can I have multiple Verilog always blocks in a single module?
Yes, you can have multiple Verilog always blocks in a single module. This is a common practice, especially when modeling complex systems. Each always block operates independently, modelling different parts of the circuit with potentially different sensitivity lists or trigger conditions.
Alright, that wraps up our deep dive into the verilog always block! Hopefully, you’re feeling a little more confident tackling your next design. Keep experimenting, and don’t be afraid to get your hands dirty with some code!