A parameter is an input to elaboration. The instantiating parent sets it with a named override.
Use parameters for externally configurable values like width or depth. Defaults in the declaration keep the common case short.
Kind | Set by | Example |
|---|---|---|
| The parent, at instantiation |
|
| Nobody: derived inside the module | Address bits from |
A localparam cannot be overridden from outside. It computes dependent dimensions in one place, so bus widths cannot mismatch.
Width math belongs here. One formula feeds every use, and the N equal to 1 case needs a guard:
// snippet
// Width math with the N = 1 guard ($clog2(1) is 0, so the
// unguarded range [$clog2(N)-1:0] would become [-1:0]).
localparam int AW = (DEPTH > 1) ? $clog2(DEPTH) : 1;
input logic [AW-1:0] addr;#(.DEPTH(4), .AW(2)) where AW is a localparam derived from DEPTH. What happens?The build fails at elaboration: overriding a localparam is an error (iverilog reports Cannot override localparam), not a silent ignore. Remove .AW(2) and pass only #(.DEPTH(4)); AW then recomputes from DEPTH on its own, so the address width always matches the depth.
[$clog2(N)-1:0] and N is 1. What is the range, and what is the fix?The range is [-1:0]. Use localparam int SW = (N > 1) ? $clog2(N) : 1; and declare [SW-1:0].
The lane array plus guarded DUT select ports for N=1 and N=5. The finite bench checks actual elaborated port sizes, every legal selection, and the defined zero result for spare binary codes. N and WIDTH must be positive.
module lane_array #(
parameter int LANES = 4,
parameter int WIDTH = 16
) (
input logic [LANES*WIDTH-1:0] in_flat,
output logic [LANES*WIDTH-1:0] out_flat
);
genvar i;
generate
for (i = 0; i < LANES; i++) begin : GEN_LANE
assign out_flat[i*WIDTH +: WIDTH] = in_flat[i*WIDTH +: WIDTH];
end
endgenerate
endmodule
module lane_select #(
parameter int N = 1,
parameter int WIDTH = 8,
localparam int SW = (N > 1) ? $clog2(N) : 1
) (
input logic [N*WIDTH-1:0] lanes,
input logic [SW-1:0] sel,
output logic [WIDTH-1:0] y
);
always_comb begin
y = '0;
if (sel < N) y = lanes[sel*WIDTH +: WIDTH];
end
endmodule
Testbench run with Icarus Verilog 13.0 (2026-10-16): prints PASS. It is a finite digital check of elaborated port sizes, every legal selection and the zero result for spare codes; it is not physical signoff.