always_comb, always_ff, and always_latch
Choose the right procedural block and avoid multiple drivers, unintended latches, and sensitivity mistakes.
State what the block represents
Verilog uses always for several kinds of logic. SystemVerilog provides three specialized forms:
always_combfor combinational logic;always_fffor registers and flip-flops;always_latchfor an intentional latch.
These blocks describe intent and enable extra checks. A variable written in one of them should not also be written elsewhere.
Combinational logic
always_comb automatically builds its sensitivity from the signals that are read, including signals read by a called function. The block also runs once at the beginning of simulation.
module alu4 (
input logic [3:0] i_a,
input logic [3:0] i_b,
input logic [1:0] i_op,
output logic [3:0] o_y
);
always_comb begin
o_y = '0;
case (i_op)
2'b00: o_y = i_a + i_b;
2'b01: o_y = i_a - i_b;
2'b10: o_y = i_a & i_b;
2'b11: o_y = i_a | i_b;
endcase
end
endmoduleThe default value ensures an assignment on every path. Without it, an incomplete if or case can request storage of the previous value and infer a latch.
Blocking assignments = fit combinational calculations because statements in the block can build ordered intermediate results.
Sequential logic
always_ff accepts a clock event and, depending on the chosen style, an asynchronous reset event.
always_ff @(posedge i_clk or negedge i_rst_n) begin
if (!i_rst_n)
o_q <= '0;
else if (i_enable)
o_q <= i_d;
endNonblocking assignments <= model registers updating together after the edge. No else branch is needed when i_enable is low because a flip-flop naturally holds its value.
Use a latch only on purpose
always_latch states that level-sensitive storage is intentional.
always_latch begin
if (i_gate)
o_q <= i_d;
endLatches need careful timing analysis and are rarely needed in a typical FPGA flow. If an always_comb block infers a latch, look for a missing assignment instead of simply changing the keyword to always_latch.
Key points
- A specialized block lets tools check intent more closely.
always_combremoves the need for a handwritten sensitivity list.- Every combinational output needs a value on every path.
- Use nonblocking assignments in
always_ff. - Use
always_latchonly when the architecture really calls for a latch.
📝 Test your knowledge - Chapter quiz