🔁 always_ff
vs always @(posedge clk)
#
✅ Why always_ff
is Superior#
SystemVerilog’s always_ff
is a strictly enforced sequential logic block that eliminates common pitfalls of Verilog’s always @(posedge clk)
:
- Compiler-enforced rules:
- Only non-blocking assignments (
<=
) allowed. - Prohibits mixing combinational/sequential logic.
- Accepts only variables (no
wire
assignments).
- Only non-blocking assignments (
- Guaranteed synthesis-simulation alignment.
always_ff @(posedge clk or posedge rst) begin
if (rst)
q <= 0;
else
q <= d;
end
⚠️ Critical: Using blocking assignments (
=
) inalways_ff
causes a compiler error.
⚙️ always_comb
vs always @(*)
#
✅ Key Advantages of always_comb
#
Feature | always @(*) (Verilog) | always_comb (SystemVerilog) |
---|---|---|
Sensitivity | Incomplete (heuristic-based) | Perfect (all signals tracked) |
Assignments | Allows both = and <= | Enforces blocking (= ) |
Latch Detection | Tool-dependent | Warns on incomplete branches |
Function Tracking | ❌ Misses signals inside functions | ✅ Tracks all function-internal signals |
Time-0 Evaluation | No | ✅ Executes once at simulation start |
always_comb begin
y = my_func(sel); // Auto-tracks ALL inputs (even in `my_func`).
end
🚫 Restriction: No delays (e.g.,
#5
) allowed inalways_comb
.
🧠 Hidden Pitfall: Function Sensitivity in always @(*)
#
❌ Buggy Verilog Example#
function logic [3:0] my_func(input logic flag);
if (flag) return a + b; // `a` and `b` NOT in sensitivity list!
else return a - b;
endfunction
always @(*) begin
y = my_func(sel); // ❌ Fails if `a`/`b` change (no re-evaluation).
end
✅ Fixed with always_comb
#
always_comb begin
y = my_func(sel); // ✅ Auto-detects `a`, `b`, and `sel`.
end
🕳️ always_latch
– Intentional Latch Design#
🎯 When to Use#
Only for explicit level-sensitive latches:
always_latch begin
if (en) q = d; // Latches value when `en` is low.
end
🔍 Tool Warnings:
- Triggers if edge-sensitive logic (e.g.,
posedge
) is used.- Infers latches on incomplete branches (no
else
).
📚 Quick Reference Table#
Block Type | Purpose | Assignments | Key Rules |
---|---|---|---|
always_ff | Sequential (flip-flops) | <= | No = , no wire , no mixed logic. |
always_comb | Combinational | = | No latches, no delays, time-0 execution. |
always_latch | Intentional latches | = | Requires if -without-else for inference. |
always @(*) | Legacy combinational | = /<= | Avoid (misses function signals). |
always @(posedge clk) | Legacy sequential | <= /= | Prefer always_ff for new designs. |
✅ Best Practices#
- Always prefer
always_ff
/always_comb
over legacy Verilog. - Never mix
=
and<=
in the same block. - Default assignments: Initialize outputs in
always_comb
to avoid latches. - Functions/Tasks: Use
always_comb
to auto-track all dependencies.
🔥 SystemVerilog’s
always_*
blocks are industry standards for unambiguous, synthesis-safe RTL design.