Day 8 · Hierarchy & Reuse

Module Hierarchy

Video 1 of 4 · ~10 minutes

Dr. Mike Borowczak · Electrical & Computer Engineering · CECS · UCF

HierarchyParametersGenerateReuse

🌍 Where This Lives

In Industry

A modern SoC has millions of gates arranged in a hierarchy 10+ levels deep. The top-level module of an Apple M-series chip probably fits on one page — it instantiates ~50 major blocks (CPU clusters, GPU, memory controller, NPUs), each a module, each decomposed into sub-modules, all the way down to leaf cells. Without hierarchy, no one person could understand a chip.

In This Course

Day 5 button pipeline: sync + debounce + edge-detect are three modules. Day 7 traffic light used a sub-module timer. Day 11 UART top has TX + RX + control as sub-modules. Day 12 SPI is the same. The pattern scales from this week to the capstone.

⚠️ Named Ports Are Mandatory

❌ Wrong Model

counter c1 (clk, rst, en, count); — positional connection. Shorter, right?

✓ Right Model

counter u_cnt0 (.i_clk(clk), .i_reset(rst), .i_enable(en), .o_count(count));named port connection. If someone adds a port, swaps an order, or adds an input, positional connections silently break. Named connections fail at compile — fast, loud, fixable.

The receipt: Every industry Verilog style guide forbids positional connections above trivial cases. Lint tools flag them. Code reviews catch them. Today's lab forbids them. Every module instance in this course uses .port(signal).

👁️ I Do — Instantiate a Debouncer

// Top-level module — uses debounce as a sub-module
module button_handler (
    input  wire i_clk, i_reset, i_btn_raw,
    output wire o_btn_clean
);
    // Instantiate the debounce module by name
    debounce #(.CLKS_STABLE(500_000)) u_debounce_sw1 (
        .i_clk   (i_clk),
        .i_reset (i_reset),
        .i_noisy (i_btn_raw),
        .o_clean (o_btn_clean)
    );
endmodule
My thinking: Three disciplines on display. (1) Descriptive instance nameu_debounce_sw1, not u1; when a signal appears in a waveform labeled u_debounce_sw1.r_count you know exactly what it is. (2) Parameter override#(.CLKS_STABLE(500_000)). (3) Named port connection.i_clk(i_clk).

🤝 We Do — Naming Conventions

ConceptPrefix / PatternExample
Module inputi_i_clk, i_data
Module outputo_o_sum, o_valid
Module inout (rare)io_io_bus
Internal registerr_r_state, r_counter
Internal wirew_w_sum, w_carry
Module instanceu_u_debounce_sw1
Compile-time constantALL_CAPSCLKS_STABLE, WIDTH
Together: Consistent prefixes turn a waveform into a readable document. When you see u_uart_rx.r_state, you instantly know: this is a register inside the uart_rx instance. The conventions aren't arbitrary — they're the lowest-cost way to make signals navigable.

🧪 You Do — Spot the Bad Hierarchy

module top (input wire clk, input wire data_in, output wire done);
    wire x, y, z;
    submod1 u1 (clk, data_in, x);
    submod2 u2 (x, y);
    submod3 u3 (clk, y, z);
    submod4 u4 (z, done);
endmodule

List the code-review issues.

Issues:
  1. Positional port connections everywhere — fragile.
  2. Meaningless instance names (u1, u2, ...) — unreadable in waveforms.
  3. Meaningless wire names (x, y, z) — can't tell what they carry.
  4. Module names say nothing (submod1) — but that's a file-naming issue.
Fix: named .ports, meaningful instance names (u_decoder, u_filter), wires named after what they represent (w_decoded_byte, w_filtered_sample).
▶ LIVE DEMO

Build a Hierarchical Design

~5 minutes — sync + debounce + edge = button_handler

▸ COMMANDS

cd labs/week2_day08/ex1_hierarchy/
ls src/              # 4 module files
cat button_handler.v # top-level composition
make sim
make stat            # total for full hierarchy
make prog

▸ EXPECTED STDOUT

sync_2ff.v
debounce.v
edge_detect.v
button_handler.v

PASS: sync works
PASS: bounces filtered
PASS: 1-cycle pulses
=== 24 passed, 0 failed ===

Flattened: 42 cells
Per-instance breakdown:
  u_sync:    2 SB_DFF
  u_debounce: 37 cells
  u_edge:    1 SB_DFF + 1 LUT

🔧 Hierarchy Preserved or Flattened?

$ yosys -p "read_verilog *.v; hierarchy -top button_handler; synth_ice40; stat"

=== button_handler ===     ← top level
   Number of cells:       42
     $scopeinfo             3    ← hierarchy markers (retained)

=== debounce ===           ← sub-module, preserved
   Number of cells:       37
     SB_CARRY              18
     SB_DFFESR             20
     ...
What to notice: Yosys preserves hierarchy by default. The stat output shows each module's contribution separately. You can still inspect the 37-cell debouncer independently from the 3-cell sync and edge-detect. If you wanted to flatten everything into one pool for optimization, add flatten to the Yosys script — useful for critical-path analysis, costly to debug.
Pro tip: Keep hierarchy during simulation (navigability) and dev-stage synthesis. Flatten only when you need the absolute last 5% of area/timing from optimization passes.

🤖 Check the Machine

Ask AI: “I have sync_2ff.v, debounce.v, and edge_detect.v. Write a top-level button_handler module that instantiates all three in the correct order, using named port connections and descriptive instance names.”

TASK

AI composes 3 modules into a top.

BEFORE

Predict: wire chains from sync output → debounce input → edge input.

AFTER

Strong AI uses named ports + u_ instances. Weak AI uses positional.

TAKEAWAY

AI handles composition well if you give it the sub-module port lists.

Key Takeaways

 Hierarchy manages complexity. Real designs are 10+ levels deep.

 Always use named port connections (.port(signal)), never positional.

 Naming conventions: i_/o_/r_/w_/u_. Descriptive instance names.

 Yosys preserves hierarchy by default. Flatten only for optimization.

If a reviewer can't tell what a signal carries from its name, it's named wrong.

🔗 Transfer

Parameters & Parameterization

Video 2 of 4 · ~9 minutes

▸ WHY THIS MATTERS NEXT

You now instantiate modules. Next: how to make the same module serve different roles through parameters. One counter module that's 8-bit in one place, 16-bit in another, with any CLKS_STABLE value. This is IP reuse — and it's how industry scales.