Hierarchy, Parameters & generate
Reusable modules with parameters, localparam and $clog2, and generate loops and conditions that build hardware at elaboration time.
Real designs are trees of modules. Parameters make a module reusable at any width or size; generate builds repeated or optional hardware when the design is elaborated, before simulation or synthesis starts.
Parameters
max_unit works at any width W; the ports are W bits wide.
localparam BITS = $clog2(MAX + 1) computes the counter width from the maximum count.
generate for and generate if
defparam u1.W = 16;
max_unit #(.W(16)) u1 ( ... );
defparam overrides a parameter from elsewhere in the hierarchy and is deprecated. Pass parameters where the module is instantiated.
for (i = 0; i < 4; i = i + 1) // outside generate, i is integer full_adder fa ( ... );
genvar i; generate for (i = 0; i < 4; i = i + 1) begin : stage full_adder fa ( ... ); end endgenerate
Instances can only be replicated with a generate loop using a genvar, and the loop body should be named so the instances get readable names.
What is the difference between parameter and localparam?
A parameter can be overridden when the module is instantiated (#(.W(16))); a localparam cannot. Use localparam for constants derived from parameters or internal to the module.
What does $clog2(16) return, and $clog2(17)?
4 and 5. It is the ceiling of log2: 16 values fit in 4 bits; 17 need 5.