Verilog · Chapter 14.7.3 · Behavioural Modeling
Generate case in Verilog — Selecting Structure Variants by Parameter
The generate case construct picks one hardware implementation from several, chosen by a parameter when the design is elaborated. It is the multi-way version of generate if. Instead of including or excluding a single block, generate case lets you select among variants, such as a fast multiplier versus a small one, a vendor primitive versus a plain behavioural model, or a different datapath per mode. Only the matching variant is built, so the others produce no gates at all. This makes it the natural tool for implementation and platform selection in parameterized, portable RTL, letting one module choose the right structure for its configuration. This lesson walks through the syntax, how selection works, and common variant patterns.
Foundation10 min readVeriloggenerate caseVariant SelectionParameterPortable RTL
Chapter 14 · Section 14.7.3 · Behavioural Modeling
1. The Engineering Problem
A parameterized module needs to pick one of several implementations by configuration — a fast vs small multiplier, a vendor primitive vs a behavioural model. generate case selects the variant:
generate caseselects among structural variants based on a parameter, at elaboration — only the chosen variant is built. The multi-way counterpart togenerate if.
This page drills generate case and its variant-selection use.
2. Mental Model — Select One Structure Variant by Parameter
3. The generate case
generate
case (IMPL)
"FAST": begin : gen_fast
fast_mult u (.a(a), .b(b), .y(y)); // single-cycle multiplier
end
"SMALL": begin : gen_small
iterative_mult u (.a(a), .b(b), .clk(clk), .y(y));
end
default: begin : gen_default
behavioural_mult u (.a(a), .b(b), .y(y));
end
endcase
endgenerateThe IMPL parameter selects which multiplier structure to build — fast, small, or default. Only the chosen variant is elaborated; the others produce no hardware. This picks an implementation per configuration. (Name the generate blocks for hierarchy, 14.7.1.)
4. Platform and Implementation Variants
The canonical generate case use — selecting structure by platform or implementation:
// platform primitive selection (Xilinx / Altera / ASIC):
generate
case (VENDOR)
"XILINX": begin : g xilinx_ram u (...); end
"ALTERA": begin : g altera_ram u (...); end
default: begin : g behavioural_ram u (...); end
endcase
endgenerateSelecting a vendor primitive (a Xilinx BRAM vs an Altera memory vs a portable behavioural model) by a VENDOR parameter — one source that targets multiple platforms, building only the matching primitive. This is how portable, parameterized IP adapts its structure to its target. (Related to the `ifdef VENDOR_* build-target pattern of 7.4, but parameter-driven at the language level.)
Visual A — generate case selects a variant
generate case — one variant by parameter
data flow5. Common Mistakes
- Runtime selector in
generate case— the selector must be a parameter/constant (likegenerate if, §2). - Using a runtime
casefor variant structure — builds all variants as mux inputs; usegenerate caseto build only one (14.5.2 vs here). - Unnamed generate blocks — name them for hierarchy (14.7.1).
6. Debugging Lab
One generate-case debug post-mortem
Pitfall — an unexpected parameter value silently builds the wrong variant
module mult #(parameter IMPL = "FAST") (input [7:0] a, b, output [15:0] p);
generate
case (IMPL)
"FAST": fast_mult u (a, b, p); // single-cycle DSP variant
"SMALL": iterative_mult u (a, b, p); // multi-cycle area-saving variant
default: fast_mult u (a, b, p); // fallback
endcase
endgenerate
endmodule
// A top-level instantiation overrides IMPL but with a value that matches NO
// case item:
// mult #(.IMPL("LOW_POWER")) u_mult (...); // typo / wrong string
//
// 'generate case' selects STRUCTURE at elaboration by exact parameter match.
// "LOW_POWER" matches neither "FAST" nor "SMALL", so the DEFAULT variant
// (fast_mult) is built — silently. There is no runtime "wrong opcode" to
// catch; the elaborated hardware is simply the default, not the intended
// low-power block. The design synthesizes cleanly and simulates, but the
// WRONG hardware variant is in the chip — a configuration bug that no
// functional test of the (working) default variant will reveal.A configurable module is instantiated with a particular implementation parameter, but the synthesized/elaborated design uses a different variant than intended (here, the default fast multiplier instead of a low-power one). The design works functionally — it just isn't the variant that was asked for — so area/power/timing come out wrong and the mismatch is found late, in synthesis reports or silicon characterization, not in simulation.
generate case selects a STRUCTURE by EXACT parameter match at ELABORATION, and falls through to 'default' for any unmatched value. The override value "LOW_POWER" matches no case item, so the default variant is elaborated. Unlike a runtime case (where an unexpected selector might drive an output to a defined-but-wrong value you could observe), a generate-case mismatch is an elaboration-time decision: the wrong block is simply built, with no runtime signal to flag it. A permissive 'default' that silently accepts unknown configurations therefore hides typos and unsupported settings.
generate case selects STRUCTURE, not BEHAVIOUR — so getting the parameter wrong does not produce a runtime error; it produces the wrong hardware.
module mult #(parameter IMPL = "FAST") (input [7:0] a, b, output [15:0] p);
generate
case (IMPL)
"FAST": fast_mult u (a, b, p);
"SMALL": iterative_mult u (a, b, p);
// No silent default: fail loudly on an unsupported configuration.
default: $error("mult: unsupported IMPL=%s", IMPL);
endcase
endgenerate
endmodule
// Replace the permissive fallback with an elaboration-time assertion
// ($error / $fatal in the default) so an unrecognized IMPL stops the build
// instead of quietly selecting a variant. Now "LOW_POWER" (or any typo) is
// caught at elaboration, naming the offending value — the configuration bug
// surfaces immediately instead of shipping the wrong variant.7. Interview Q&A
8. Exercises
Exercise 1 — Variant selection
Write a generate case that selects between a ripple_adder and a cla_adder instance based on an ADDER_TYPE parameter.
Exercise 2 — generate case vs runtime case
Why does generate case build only one variant while a runtime case builds all branches?
9. Summary
The generate case selects a structural variant by parameter:
- Parameter-driven, elaboration-time — picks one variant; only it is built, the rest produce no hardware.
- The multi-way
generate if— for choosing among several implementations. - Use for implementation selection (fast/small) and platform/vendor variants in portable IP.
The last generate sub-topic combines techniques: Chapter 14.7.4 Generate Advanced Techniques covers nested generate, named scopes and hierarchy, and combining for/if/case.
Related Tutorials
- Generate if — Chapter 14.7.2; the two-way conditional structure.
- Generate Block — Chapter 14.7; the generate overview.
- Case Statements — Chapter 14.5.2; the runtime
casecontrasted. - parameter — Chapter 6.1; the parameter selector.