logic, always_comb, and always_ff

How SystemVerilog logic, always_comb, and always_ff map onto the Verilog wire, reg, always @(*), and always @(posedge clk) you already know.

Updated 2026-07-28

SystemVerilog's logic type replaces the wire-versus-reg distinction Course 1 spent real time teaching, for the common case: a signal with exactly one driver. Instead of choosing a type based on how that signal will be driven, most ports, internal wires, and registers can be declared logic. The one rule that mattered for reg still applies: a logic signal cannot be driven by more than one continuous or procedural source at once — that limitation is why plain wire has not gone away. Nets that genuinely need more than one driver (a shared bus, a tri-state line) still use wire, so "just use logic everywhere" is a useful starting habit, not an absolute rule.

Two always variants replace the general-purpose ones:

  • always_comb is the explicit form of always @(*). It exists only to describe combinational logic, so a tool can flag a block that looks combinational but is missing an assignment on some path — the exact Module 2 latch trap, caught automatically instead of silently.
  • always_ff is the explicit form of always @(posedge clk). It exists only to describe clocked logic, so a tool can flag a signal accidentally written outside a clocked block.

Nothing about the discipline changes: default-at-top inside always_comb, non-blocking assignment inside always_ff. Only the keywords get more specific about what each block is allowed to contain.