Day 8: Hierarchy, Parameters, Generate & Design Reuse¶
Course: Accelerated HDL for Digital System Design¶
Week 2, Session 8 of 16¶
Student Learning Objectives¶
- SLO 8.1: Use named port connections and parameter overrides to instantiate and configure reusable modules.
- SLO 8.2: Design parameterized modules using
parameterand explain when parameterization is appropriate. - SLO 8.3: Use
generate forandgenerate ifto replicate hardware and conditionally include features. - SLO 8.4: Build a hierarchical top-level module that integrates multiple parameterized sub-modules.
- SLO 8.5: Use AI to generate testbenches for parameterized modules and evaluate whether AI correctly handles parameter overrides and width-dependent edge cases.
- SLO 8.6: Record and compare
yosys statresource utilization across parameter configurations (PPA thread).
Pre-Class Video (~50 min) ★ Revised lecture¶
| # | Segment | Duration | File |
|---|---|---|---|
| 1 | Module instantiation: positional vs. named ports (always use named!) | 10 min | video/day08_seg1_instantiation.mp4 |
| 2 | parameter and localparam: making modules reusable |
12 min | video/day08_seg2_parameters.mp4 |
| 3 | generate blocks: for-generate, if-generate, hardware replication |
13 min | video/day08_seg3_generate.mp4 |
| 4 | Recursive generate patterns: conditional features, nested structures ★ | 10 min | video/day08_seg4_recursive_generate.mp4 |
| 5 | Design for reuse: building a personal Verilog library | 5 min | video/day08_seg5_design_reuse.mp4 |
Segment 4 key points (new content):
- generate if for conditional feature inclusion (e.g., optional parity, configurable pipeline depth)
- Nested generate for for 2D structures (e.g., array of processing elements)
- The "recursive module" pattern: a module that instantiates itself with different parameters (tree adder preview)
Session Timeline¶
| Time | Activity | Duration |
|---|---|---|
| 0:00 | Warm-up: hierarchy questions, pre-class review | 5 min |
| 0:05 | Mini-lecture: parameterization, generate, PPA seed | 30 min |
| 0:35 | Lab Exercise 1: Parameterized N-bit counter | 20 min |
| 0:55 | Lab Exercise 2: AI-assisted parameterized TB | 25 min |
| 1:20 | Break | 5 min |
| 1:25 | Lab Exercise 3: Generate-based LED driver | 20 min |
| 1:45 | Lab Exercise 4: Hierarchical top module | 25 min |
| 2:10 | Lab Exercise 5: Resource comparison | 5 min |
| 2:15 | Lab Exercise 6 (Stretch): Parameterized LFSR | 10 min |
| 2:25 | Wrap-up and Day 9 preview | 5 min |
In-Class Mini-Lecture (30 min)¶
Hierarchy as the Key to Complexity (5 min)¶
- Top-down vs. bottom-up design approaches
- Named port connections:
.port_name(signal_name)— always, no exceptions - The difference between
parameter(overridable from outside) andlocalparam(internal constants)
Parameterization Philosophy (10 min)¶
- What to parameterize: width, depth, timing thresholds, feature enables
- What not to parameterize: fundamental architecture choices, protocol definitions
#(.WIDTH(8))override syntax- Live demo: parameterized N-bit counter, instantiated at WIDTH=4, 8, 16, 32
Generate Blocks (10 min)¶
generate for: compile-time loop that replicates hardwaregenerate if: conditional hardware inclusion — "same RTL, different hardware"- Think of
generateas instantiation automation, not a runtime loop - Live demo:
generate forto create N instances of a blink module
PPA Seed (5 min)¶
- After synthesizing the parameterized counter at WIDTH=4, 8, 16, 32:
- Run
yosys statfor each configuration - Show the resource scaling: how does LUT count grow with width?
- "Is it linear? What would this look like in an ASIC?"
- Plant the question — answer it fully on Day 10
Lab Exercises¶
Exercise 1: Parameterized N-Bit Counter (20 min)¶
Objective (SLO 8.1, 8.2): Build a reusable counter module that can be instantiated at any width.
Tasks:
1. Create a parameterized counter module with:
- parameter WIDTH = 8
- Synchronous reset, enable, rollover output
2. Instantiate as 8-bit, 16-bit, and 24-bit in a test top module.
3. Simulate all three instances in a single testbench. Verify rollover at the correct value for each width.
Checkpoint: Three counter instances, each rolling over at their respective max values.
Exercise 2: AI-Assisted TB for Parameterized Modules (25 min)¶
Objective (SLO 8.5): Use AI to generate a testbench that handles multiple parameter configurations.
Tasks:
1. Write a prompt specifying:
- Counter module interface (with parameter WIDTH)
- Request: test the counter at WIDTH=4, WIDTH=8, and WIDTH=16 in a single testbench
- Required checks: reset, count-up, rollover at 2^WIDTH - 1, enable toggling
2. Generate the testbench using AI.
3. Evaluate the AI output. Key questions:
- Does the AI correctly use #(.WIDTH(N)) parameter overrides?
- Does it test rollover at the right value for each width (not hardcoded)?
- Does it handle the different counter ranges properly?
4. Correct and annotate any issues.
5. Run the corrected testbench.
Deliverable for this exercise: Prompt + corrected AI TB with annotations.
Checkpoint: AI-generated TB correctly tests 3 width configurations.
Exercise 3: Generate-Based LED Driver (20 min)¶
Objective (SLO 8.3): Use generate for to replicate parameterized instances.
Tasks:
1. Create a parameterized blink module: takes parameter HALF_PERIOD and toggles an output.
2. Use generate for to instantiate 4 blink modules, each with a different HALF_PERIOD, driving the 4 Go Board LEDs.
3. Result: 4 LEDs blinking at 4 different rates from a single generate block.
4. Synthesize and program.
Checkpoint: Four LEDs blinking at visibly different rates on the Go Board.
Exercise 4: Hierarchical Top Module (25 min)¶
Objective (SLO 8.4): Integrate multiple modules into a clean hierarchical design.
Tasks: 1. Create a top module that instantiates: - Debouncer (from Day 5) for each button - Parameterized counter (from Exercise 1) — width controlled by buttons - 7-segment decoder (from Day 2) - LED blink generators (from Exercise 3) 2. Wire everything together using named port connections. 3. The design should have at least 3 levels of hierarchy. 4. Synthesize and program the Go Board.
Checkpoint: Hierarchical design running on hardware with button-controlled counter displayed on 7-seg.
Exercise 5: Resource Comparison (5 min)¶
Objective (SLO 8.6): Build PPA analysis habits by recording resource utilization.
Tasks:
1. Run yosys stat on the hierarchical design from Exercise 4.
2. Record: LUTs, FFs, and EBR counts.
3. Change the counter WIDTH parameter — does the resource count change as expected?
Checkpoint: Resource counts recorded. You'll reference these on Day 10.
Exercise 6 (Stretch): Parameterized LFSR with Generate (10 min)¶
Objective (SLO 8.2, 8.3): Combine parameterization and generate for a configurable pseudo-random generator.
Tasks:
1. Implement a parameterized LFSR where the feedback polynomial is configured via generate if based on WIDTH (e.g., different taps for 4-bit, 8-bit, 16-bit).
2. Verify each configuration produces a maximal-length sequence.
Deliverable¶
- Hierarchical design with 3+ levels of hierarchy running on the Go Board.
- AI-generated parameterized testbench with annotated corrections.
yosys statresource snapshot for the hierarchical design.
Assessment Mapping¶
| Exercise | SLOs Assessed | Weight |
|---|---|---|
| 1 — Parameterized counter | 8.1, 8.2 | Core |
| 2 — AI-assisted parameterized TB | 8.5 | Core |
| 3 — Generate-based LED driver | 8.3 | Core |
| 4 — Hierarchical top module | 8.4 | Core |
| 5 — Resource comparison | 8.6 | Core |
| 6 — Parameterized LFSR | 8.2, 8.3 | Stretch (bonus) |
⚠️ Common Pitfalls & FAQ¶
Day 8 is about building reusable, parameterized modules. The skills here directly affect your final project quality.
- Always use named port connections. From today forward, positional connections (where you just list signals in order) are not acceptable. A single misordered port creates a silent bug that's extremely hard to find. Named connections (
.i_data(my_data)) make the intent clear and catch errors at compile time. generate forgiving cryptic errors? Three things you must have: (1) agenvarvariable declaration, (2) the loop body wrapped inbegin : some_name ... end, and (3) the named block label. Without any of these, Icarus gives unhelpful error messages.- AI hardcodes values that should be parameterized? This is a common AI failure mode. If your module has
parameter WIDTH = 8, but the AI testbench checkscount == 255instead ofcount == (2**WIDTH - 1), the TB will break when you change WIDTH. Always review AI-generated code for hardcoded magic numbers. - LUT count doesn't exactly double when WIDTH doubles? That's expected — synthesis optimization can share logic across bits. The relationship is approximately linear but not exact. Noting and explaining this in your PPA observations is good practice for the final project.
🔗 Bigger Picture¶
This is the second day of the AI verification thread. The evaluation question shifts from "does it work?" to "does it handle configuration correctly?" — a harder problem for both humans and AI.¶
Preview: Day 9¶
Memory — RAM, ROM, and Block RAM. You'll model memory in Verilog, use $readmemh to initialize from files, and learn how to write Verilog that Yosys maps to the iCE40's Block RAM resources.