Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutRoadmapCareersInternshipsFAQContactPrivacyTerms
Skip to lesson

Course contents

  • How to Use This Course
  • The NanoSoC Tour
  • Reading Path
  • SoC Glossary10
  • SoC Metrics Reference
  • SoC Cheatsheet
  • What SoC Integration Is12
  • Architecture and Budgets21
    • Partitioning and Hierarchy
      • Flat Versus Hierarchical
      • Boundary Choices and Feedthroughs
      • NanoSoC Partition Rationale
    • Area Budgets
    • Timing Budgets Across Hierarchy
    • Power Budgets
    • Bandwidth Budgets
    • Budget Governance
    • Multi-Die and Chiplet View
  • Memory Maps and Address Decode26
  • Interconnect and Bus Fabrics26
  • Clock and Reset Architecture24
  • Power Architecture21
  • Interrupts, DMA and Peripherals15
  • Memories, Boot and Security21
  • IP Integration and Handoff21
  • Top-Level Verification and Bring-up21
  • Package, Pads and I/O18
  • Chip Signoff and Tapeout18
  • SoC Interview Prep16
  • Capstone: Integrate NanoSoC14
Loading lesson

←Partitioning and Hierarchy
  1. Topics
  2. SoC Design
  3. Architecture and Budgets
  4. Partitioning and Hierarchy
  5. Flat Versus Hierarchical
On this page

    Part 2 of 14, lesson 1 of 21Part 2 of 14/Architecture and Budgets/Lesson 1 of 21All levels

    Flat Versus Hierarchical

    When a design earns hierarchy, what it costs, and why NanoSoC is hierarchical at 16 blocks.

    Why it matters

    The first architecture argument on NanoSoC was whether to bother with hierarchy at all. Sixteen blocks on the list, one engineer, one synthesis run that finishes before lunch: flat is faster to start. The argument ended when the power plan landed. One power domain switches off while the other stays on, one clock segment runs at 24 MHz while the fabric runs at 96 MHz, and the APB peripherals sit behind a bridge with different timing. Flattening those seams would not remove them; it would only hide them inside one netlist where every tool must rediscover them. Hierarchy does not create the seams. It names them.

    The core idea

    Hierarchy pays when the design has seams that tools or teams must respect independently: separate clocks needing separate trees, separate power domains needing separate intent, separate protocols needing separate verification, or simply more gates than one run can hold. It costs interface effort at every boundary: budgeted timing, documented protocols, synchronisers for crossings, and verification that the two sides agree. The integrator's test is a balance: partition where the seam already exists for electrical reasons, and resist partitioning a uniform synchronous block just to mirror the org chart.

    Shape

    Pays when

    Costs

    NanoSoC example

    Flat

    One clock, one power domain, one owner, fits the tools

    Any seam is implicit and re-derived by every tool

    Would hide the PD_SW boundary inside one netlist

    Two-level hierarchy

    Seams follow clock, power or protocol lines

    Budgeted interfaces at each boundary

    System side versus peripheral side behind the APB bridge

    Deep hierarchy

    Many owners, reuse, very large gate count

    Feedthroughs, budget fragmentation, integration risk

    Not used on NanoSoC; would be overhead here

    How NanoSoC is split by clock side and power domain at the top.
    How NanoSoC is split by clock side and power domain at the top.

    Worked example: sizing the decision

    NanoSoC's gate count never forces hierarchy, so the decision rests on seams. Count them from the NanoSoC specification's crossing inventory: three clock domains, two power domains, two bus protocols plus two stream channels, and ten clock-domain crossings in ten groups (X1 to X10). A flat netlist still contains all ten crossings; the hierarchical one assigns each to a named bridge or synchroniser with an owner. The check below rebuilds that inventory by mechanism and proves every crossing names its mechanism — drop a row or blank a mechanism and it fails.

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    # NanoSoC specification, crossings: X1..X10 with from-domain, to-domain, mechanism.
    crossings = [
        ("X1", "clk_cpu", "clk_sys", "async-fifo"),
        ("X2", "clk_sys", "clk_cpu", "async-fifo"),
        ("X3", "clk_sys", "clk_per", "req-ack"),
        ("X4", "clk_per", "clk_sys", "req-ack"),
        ("X5", "clk_sys", "clk_per", "level-sync"),
        ("X6", "clk_per", "clk_cpu", "level-sync"),
        ("X7", "clk_per", "clk_sys", "reset-sync"),
        ("X8", "clk_per", "clk_cpu", "reset-sync"),
        ("X9", "pads", "clk_per", "other-single-bit"),
        ("X10", "clk_per", "clk_sys", "other-single-bit"),
    ]
    from collections import Counter
    counts = Counter(mech for _, _, _, mech in crossings)
    assert counts == {"async-fifo": 2, "req-ack": 2, "level-sync": 2,
                      "reset-sync": 2, "other-single-bit": 2}, counts
    assert len(crossings) == 10 and all(mech for *_, mech in crossings)
    assert [c[0] for c in crossings if c[1] == "pads"] == ["X9"]  # only X9 is external
    multi = [c for c in crossings if c[3] in ("async-fifo", "req-ack")]
    assert len(multi) == 4  # every multi-bit crossing has a FIFO or handshake
    print(f"PASS: 10 crossings by mechanism {dict(counts)}; each names its bridge")

    What the review looks for

    • Each partition is justified by a clock, power, protocol or ownership seam, named in one line.

    • No partition exists only to mirror team structure; uniform logic stays together.

    • The top level owns the seam inventory: every crossing names its bridge and its mechanism.

    Verify and debug

    List every top-level port and tag it with the seam it serves: clock, power, protocol or test. Any port with no tag is a candidate feedthrough, which the next lesson removes. Compare the partition list against the clock-domain plan and the power-state table; a domain with blocks in two partitions, or a partition spanning two power domains without an isolation plan, is a boundary drawn in the wrong place.

    Partitioning by owner instead of by seam. Two halves of one synchronous datapath become two partitions, and the timing budget for the cut dominates the project. Repartition along the nearest clock or protocol boundary, or keep the logic together.

    If asked flat or hierarchical, never answer with a side. Name the seams first — clocks, power, protocol, size — then let them decide. Offer NanoSoC's ten crossings as the worked case.

    Deep hierarchy has a failure mode worth naming: each extra level slices budgets thinner and breeds feedthroughs, so a five-deep tree of uniform logic pays integration tax for no electrical reason. The rule of thumb is two levels for a chip of this size — subsystem then block — with a third level only where a genuine seam (the power switch, the async bridge) demands its own budget. Count the levels on any proposal; beyond three, ask which seam each level serves.

    Check yourself NanoSoC has 16 blocks (15 modules plus the PLL macro). Why is it hierarchical?

    Because its seams are electrical, not organisational: three clocks, two power domains and three interface styles. Hierarchy names the ten crossings so each gets a bridge, a budget and an owner.

    Related topics

    • Next: Boundary Choices and Feedthroughs

    • PD: Partitioning a Block for Hierarchy

    • RTL: Top-Down vs Bottom-Up Integration

    • CDC & RDC: CDC-Aware Partitioning

    • CDC & RDC: Identifying Domains

    Previous

    18 / 289

    Next: Boundary Choices and Feedthroughs

    Up next

    Up nextBoundary Choices and Feedthroughs

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • NanoSoC Partition Rationale