Day 68: generate blocks and parameterization patterns
generate blocks and parameterization
When you need N copies of a structure, don't copy-paste — use a generate block with a genvar loop to instantiate them programmatically. Combined with parameters, this makes modules that scale: an N-lane byte enable, a width-parameterized shifter, an array of synchronizers. Parameterization is what turns a one-off module into a reusable library block.
module adder_n #(parameter W = 32) (
input [W-1:0] a, b,
input cin,
output [W-1:0] sum,
output cout
);
wire [W:0] c;
assign c[0] = cin;
genvar i;
generate
for (i = 0; i < W; i = i + 1) begin : fa
assign sum[i] = a[i] ^ b[i] ^ c[i];
assign c[i+1] = (a[i] & b[i]) | (c[i] & (a[i] ^ b[i]));
end
endgenerate
assign cout = c[W];
endmoduleNamed generate blocks aid debugging
Label generate loops (begin : fa) — the label becomes part of the hierarchical name (fa[3].c), which makes waveforms and synthesis reports readable. Anonymous generate blocks produce cryptic auto-names. Small habit, big payoff when you're debugging a 32-instance array.
Before moving on, you should be able to
What does a Verilog generate block with a genvar loop let you do?