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
  • Memory Maps and Address Decode26
  • Interconnect and Bus Fabrics26
  • Clock and Reset Architecture24
  • Power Architecture21
  • Interrupts, DMA and Peripherals15
    • Interrupt Controller Integration
    • Interrupt Routing and Latency
    • DMA Integration
    • Peripheral Subsystem
    • Pad Muxing and GPIO
      • Pin-Mux Tables and Function Select
      • Reset States, Pulls and GPIO Direction
      • Package, Ball-Out and Simultaneous Switching
  • 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

←Pad Muxing and GPIO
  1. Topics
  2. SoC Design
  3. Interrupts, DMA and Peripherals
  4. Pad Muxing and GPIO
  5. Package, Ball-Out and Simultaneous Switching
On this page

    Part 7 of 14, lesson 15 of 15Part 7 of 14/Interrupts, DMA and Peripherals/Lesson 15 of 15All levels

    Package, Ball-Out and Simultaneous Switching

    Counting pads, sizing the supply pads from current, placing the I/O supply pairs and bounding the noise when many outputs switch together.

    Why it matters

    This lesson has one job: close the topic at the package with a pad count that adds up and a switching-noise story that holds. Pads are not free: every signal needs power and ground neighbours, the supplies need their own pads sized from current, and sixteen GPIOs switching together can bounce the on-chip ground enough to flip an input threshold. The integrator sizes the pad ring, spreads the supply pairs and sets the drive-strength rule; the board team trusts those numbers when they route. All counts and limits here are NanoSoC teaching values, consistent across the course and labelled as such.

    The core idea

    The pad count has two parts and no more. Signal pads are the package-visible nets, each counted once: sixteen GPIO pads (the UART transmit and receive and the four SPI signals ride on P0 to P5, so they are counted there and nowhere else), the active-low RESET_N and the two crystal pads, nineteen in all. Supply and ground pads come from current and from switching, not from counting signals. The core rail needs four vdd_core pads and four vss_core pads: the RUN power of 82.74 mW at 0.9 V is 91.93 mA on average, with an illustrative limit of 50 mA per supply pad that needs ceil(91.93 / 50) = 2 pads, and an illustrative peak factor of 2 gives 183.87 mA, which needs ceil(183.87 / 50) = 4. The I/O rail needs two vdd_io and two vss_io pads, sized by simultaneous switching and not by current. That is 12 supply pads, and 19 + 12 = 31 pads in all. There is no JTAG, no TEST_MODE, no BOOT_MODE and no analog supply pad: the crystal oscillator and the PLL run from vdd_core, and the always-on and switchable core domains share one supply pad group because the power switch is on the die.

    Simultaneous switching noise is the reason the I/O supply pairs are spread around the ring, not clustered. When many outputs switch the same way in the same cycle, the shared ground inductance turns the current slew into a voltage bounce, and an input sampled during the bounce can read wrong. Three defences share the duty: cap the number of simultaneously switching outputs per vdd_io and vss_io pair, spread the pairs around the ring so no cluster of outputs sits far from a return, and slow the drive on pads that do not need speed, because slew is the noise source. For NanoSoC the teaching limit is 8 outputs per pair at the default drive (an illustrative 4 mA, medium slew) and 4 per pair at a stronger fast drive. There are 2 pairs, so the capacity is 16. The worst case is one APB write of 0xFFFF to DATA_OUT with DIR at 0xFFFF, which flips all 16 GPIO pads on one clock edge. Each pad uses its nearest pair along the ring: pair 0 serves P0 to P7 and pair 1 serves P8 to P15, so the worst case is 8 and 8 against a limit of 8. That passes, with zero margin: any new output pad, or a switch to the fast drive, fails and needs a third pair. The peripheral functions use at most 4 outputs (uart_tx, spi_sck, spi_mosi, spi_cs_n), so the bound that matters is the GPIO write, not the peripherals.

    Diagram
    # NanoSoC teaching values for the pad count
    Signal pads: 16 GPIO (UART and SPI inside P0-P5) + RESET_N + 2 crystal = 19
    Supply pads: 4 vdd_core + 4 vss_core + 2 vdd_io + 2 vss_io = 12
    Total: 19 + 12 = 31 pads
    Core current: 82.74 mW / 0.9 V = 91.93 mA average; 183.87 mA peak (factor 2, illustrative)
    vdd_core pads: ceil(183.87 / 50) = 4 at an illustrative 50 mA per pad
    SSO: P0-P7 on pair 0, P8-P15 on pair 1: 8 and 8 against a limit of 8 (zero margin)

    Worked example: the pad-count and switching calculator

    The script below implements the method: signal pads from the table, supply pads from current over current per pad rounded up, the perimeter test and a per-pair simultaneous-switching check that takes the limit as an input from the package team. It then proves it is awake: a ninth switcher on one pair, a fast drive, both I/O supply pairs placed side by side so that 13 outputs share one pair (the clustered ring) and an undersized core rail all fail.

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    import math
    GPIO_PADS = [f"P{i}" for i in range(16)]
    SIGNALS = len(GPIO_PADS) + 1 + 2           # GPIO pads (UART, SPI inside) + RESET_N + 2 crystal
    P_RUN_MW, V_CORE = 82.74, 0.9
    I_PER_PAD_MA = 50.0                        # illustrative, package-team input
    PEAK_FACTOR = 2.0                          # illustrative
    SSO_LIMIT, SSO_LIMIT_FAST = 8, 4           # illustrative, per vdd_io/vss_io pair
    
    i_avg = P_RUN_MW / V_CORE
    i_peak = i_avg * PEAK_FACTOR
    n_core = math.ceil(i_peak / I_PER_PAD_MA)  # pads per rail
    assert (round(i_avg, 2), round(i_peak, 2)) == (91.93, 183.87)
    assert (math.ceil(i_avg / I_PER_PAD_MA), n_core) == (2, 4)
    n_io = 2                                   # sized by SSO, not by current
    supplies = 2 * n_core + 2 * n_io           # vdd and vss of each rail
    total = SIGNALS + supplies
    print(f"signals {SIGNALS} + supplies {supplies} = {total} pads; {i_avg:.2f} mA avg, {i_peak:.2f} mA peak")
    assert (SIGNALS, supplies, total) == (19, 12, 31)
    
    # Perimeter test (pitch 80 um, corner keep-out 60 um, die side from 0.940 mm2)
    side = math.sqrt(0.940) * 1000
    slots = 4 * math.floor((side - 120) / 80)
    assert slots == 40 and total <= slots
    print(f"die side {side:.1f} um; {slots} slots; {slots - total} spare: core-limited, not pad-limited")
    
    def worst_per_pair(pair_of, limit):
        counts = {}
        for p in GPIO_PADS:                    # all 16 pads flip on one edge
            counts[pair_of[p]] = counts.get(pair_of[p], 0) + 1
        return counts, [k for k, n in counts.items() if n > limit]
    
    nearest = {p: (0 if int(p[1:]) < 8 else 1) for p in GPIO_PADS}
    counts, bad = worst_per_pair(nearest, SSO_LIMIT)
    print("pair counts:", counts, "limit", SSO_LIMIT, "-> OK" if not bad else "-> VIOLATION")
    assert counts == {0: 8, 1: 8} and bad == []           # passes with zero margin
    assert worst_per_pair(nearest, SSO_LIMIT_FAST)[1] == [0, 1]   # a fast drive fails both pairs
    clustered = {p: (0 if int(p[1:]) < 13 else 1) for p in GPIO_PADS}   # both I/O pairs side by side
    counts_c, bad_c = worst_per_pair(clustered, SSO_LIMIT)
    assert counts_c == {0: 13, 1: 3} and bad_c == [0]
    assert math.ceil(i_peak / I_PER_PAD_MA) > math.ceil(i_avg / I_PER_PAD_MA)   # peak, not average, sets 4
    print("PASS: 31 pads; 8 and 8 against 8; fast drive and clustered pairs caught")

    Pad ring order is the physical form of those counts. NanoSoC places one vdd_io pair on the east side and one on the south side, so no GPIO is far from a return, and the crystal pads sit between a vss_core and a vdd_core pad so that noisy outputs are never their neighbours. The package is a conceptual 6 by 6 ball array: 36 sites, 31 assigned one-to-one and 5 left as no-connect, which a later revision can use as extra ground. Every signal pad cell carries its own ESD diode pair, and a rail clamp is built into every supply pad cell on the die; the package carries no clamp.

    Other chips would add pins. As an illustration only, a chip with a four-wire JTAG port, a TEST_MODE pin and two BOOT_MODE pins needs seven more pads, 38 in all, and would no longer fit a 36-ball array. NanoSoC has none of these, so for NanoSoC the count stays 31 and the package stays 6 by 6: the illustration shows how the method scales, not what NanoSoC has.

    What the review looks for

    • The pad list derives signals from the pad table and supplies from current arithmetic and the switching rule; the total is recomputed, never copied.

    • The core supply sizing quotes both the average and the peak current and says which one set the pad count.

    • Every output cluster sits beside an I/O supply pair on the ring drawing, and the per-pair worst case is counted on the actual ring order.

    • The simultaneous-switching limit is quoted as a package-team input with its drive condition, not as the integrator's assumption.

    Verify and debug

    Check the ball-out against the board netlist pad by pad with the same checker family as the mux table: the package pin map disagreeing with the board is the same bug one level out. On the bench, write 0xFFFF to DATA_OUT with all pads driving while a UART frame arrives and watch the quiet input pads: bounce beyond the input threshold means the supply pairing or the drive strength needs work, not the logic. If errors occur only on the board and only during that write, count the outputs per pair on the real ring: a pair that serves more than 8 pads is the bug, and moving a supply pair is cheaper than slowing the whole bus.

    Both I/O supply pairs placed next to each other in the ring: the nearest-pair rule then puts 13 GPIO outputs on one pair against a limit of 8, and a write of 0xFFFF to DATA_OUT causes framing errors on the board only, while simulation, even at gate level, is clean. Caught by counting outputs per pair on the ring order; fixed by putting one pair in each half of the ring.

    If asked how many pads a chip needs, answer signals plus supplies, derive core supplies from peak current over current per pad, size I/O supplies from the switching limit, and refuse to quote a switching limit from memory: name it as a package input. That refusal is the senior answer.

    Check yourself The package team halves the switching limit to 4 per pair by moving to a fast drive on all GPIO pads. What changes?

    Both pairs now carry 8 outputs against a limit of 4, so both fail. Either keep the default drive, add a third and a fourth pair (more supply pads, so more than 31), or restrict the number of GPIO outputs that may be driven together. The signal pad count does not change; the supply pads and the placement rules do.

    Related topics

    • Reset States, Pulls and GPIO Direction

    • PD: Package Constraints and Checks

    • PD: IO Ring Checks

    Previous

    150 / 289

    Next: Memories, Boot and Security

    Up next

    Up nextMemories, Boot and Security

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Pin-Mux Tables and Function Select