Day 56: Verilog semantics I: modules, wires, regs, and the synthesizable subset
This is where you become dangerous
Everything you designed on paper (Stage 1) now becomes synthesizable RTL. The mental shift: Verilog is a *hardware description*, not sequential software. A module describes a block with ports; statements describe structure and behavior that all exist *simultaneously* in silicon. The synthesizable subset — the constructs that map to real gates and flip-flops — is a fraction of the language; the rest is for testbenches only.
module counter #(parameter W = 8) (
input clk,
input rst_n, // active-low reset
input en,
output reg [W-1:0] count,
output at_max // combinational
);
assign at_max = &count; // continuous assign: pure combinational
always @(posedge clk or negedge rst_n) begin
if (!rst_n) count <= '0; // reset
else if (en) count <= count + 1'b1;
end
endmoduleTwo worlds live in one file: `wire` nets driven by continuous assign (combinational), and `reg` values updated in always blocks (which may be combinational *or* sequential depending on the sensitivity list). The synthesizer turns assign into gates and clocked always blocks into flip-flops + logic. Anything with no hardware meaning (delays, $display) is simulation-only.
reg is not a register
The keyword reg only means 'assigned inside a procedural block' — it becomes a flip-flop *only* if driven by a clocked always. A reg in a combinational always @(*) is just a wire. This naming trap confuses beginners endlessly; think in terms of *how it's driven*, not the keyword.
Key terms
- Module
- The Verilog unit of hardware: a named block with input/output ports.
- Synthesizable subset
- The Verilog constructs a synthesizer can map to gates/flip-flops; the rest is testbench-only.
- wire vs reg
- wire is driven by continuous assign; reg is assigned in a procedural block (a flip-flop only if clocked).
- Continuous assign
- assign statement modeling combinational logic that is always active.
- Parameter
- A compile-time constant (e.g. width) making a module reusable.
Before moving on, you should be able to
In Verilog, when does a variable declared as reg actually become a hardware flip-flop?