Somewhere right now an engineer maintains a module called sum4 and its near twin sum8, identical except for a size, and every fix must be applied twice. You know where this story goes, because this primer has told it twice already: pasted blocks became one task, pasted definitions became one package, and pasted copies always drift. Modules are where the pattern costs the most, whole files duplicated for want of one number. The parameter is the language's answer: a named knob on the module, so the size stops being written into the code and starts being chosen by whoever uses it. One module, every size, one place to fix.
A parameter is declared in the module header with a name and a default, for example a DEPTH of four, and from that point the name replaces the number everywhere the size appears: in the port that carries DEPTH elements, in the loop that walks DEPTH times, in every bound and every count. That everywhere matters more than it sounds. A parameterized module is only as general as its most hardcoded line, and a single leftover literal is a bet that the module will only ever be used at the size you happened to write. This lab is built to collect on exactly that bet.
Not every constant should be a knob. A parameter is an offer to the caller: override me at instantiation. A localparam is a decision made inside: a constant, often derived from the parameters, that no caller can touch. The working rule is about intent. If a user of your module could legitimately want a different value, make it a parameter; if the value follows from other choices or must never vary, make it a localparam, so the interface offers exactly the knobs that are safe to turn and nothing more. A module's parameter list is a promise about what may change; keep the promise short and honest, the same discipline that keeps a loop bound legible instead of a maze of magic numbers.
The payoff happens at instantiation: the caller sets the knob, per instance, and one body of code becomes two different machines. In this lab, code you never see will instantiate your module twice, once at depth four and once at depth eight, feed both known data, and check both totals. Here is the insight to carry out of the page: the dangerous mistake is not forgetting the parameter, the tool catches that loudly. The dangerous mistake is parameterizing almost everywhere, the port takes DEPTH, the loop still stops at four, because that module works perfectly at the size you tested and fails only at the size you did not. First instance right, second instance wrong is how this bug ships in real companies, and it is exactly the trap waiting in this lab.
The module below sums exactly four elements, and the number four is hardcoded in two places: the port and the loop. Generalize it: add a parameter named DEPTH with a default of four, and replace every hardcoded four so the module sums DEPTH elements at whatever depth its user chooses. Run and submit. The engine instantiates your module twice, at depth four and depth eight, and checks both totals. Leave one hardcoded four behind, and the first instance will pass while the second quietly sums half its data.
DEPTH instead. Declare the parameter in the module header with a default of four, then hunt down every literal four in the body. The engine tests two sizes precisely because the leftover four only breaks at the size you did not think about.Weekly intelligence on VLSI, AI for EDA, and chip careers. 20,000+ engineers already inside.