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
  • Memories, Boot and Security21
  • IP Integration and Handoff21
  • Top-Level Verification and Bring-up21
  • Package, Pads and I/O18
    • I/O Ring and Pad Types
    • Pad Count and Simultaneous Switching
    • Package and Ballout
      • Package Types at a Conceptual Level
      • Ball Assignment Rules
      • Pinout Review and Escape Routing
    • Power Delivery Through Package and Bumps
    • ESD and Latch-Up at the Top
    • Test and Debug Pins (extension)
  • Chip Signoff and Tapeout18
  • SoC Interview Prep16
  • Capstone: Integrate NanoSoC19
Loading lesson

←Package and Ballout
  1. Topics
  2. SoC Design
  3. Package, Pads and I/O
  4. Package and Ballout
  5. Ball Assignment Rules
On this page

    Part 11 of 14, lesson 8 of 18Part 11 of 14/Package, Pads and I/O/Lesson 8 of 18All levels

    Ball Assignment Rules

    Assigning every NanoSoC pad to a ball: supplies first, signals by escape, quiet pins protected.

    Why it matters

    A ballout drawn by convenience, with signals in netlist order and supplies wherever they fit, gives the board an unroutable array and the supplies long detours. The NanoSoC ballout follows four rules in strict order, and this lesson applies them to all 31 pads of the 6 x 6 array: supplies first for short paths, fast signals where they escape cleanly, quiet pins guarded, and everything else in the space left over. Its job is the assignment; proving the board can route it is the next lesson.

    The core idea

    A box for the 36 ball sites (31 balls and 5 no-connect sites) points to a box for the 19 signal balls (16 GPIO pads, RESET_N and the two crystal balls) and a box for the 12 supply balls (four core pairs and two I/O pairs). The signal box points to a note that only P0 to P5 also carry UART and SPI.
    NanoSoC ball allocation census

    What to notice. The 36 sites are 31 balls plus 5 no-connect sites. UART and SPI add no balls, because they reuse GPIO pads; the supply pairs and the crystal are placement constraints, not decorative labels.

    Check yourself How many ball sites remain spare after the 31 NanoSoC pads are assigned?

    Five: the 6 by 6 array has 36 sites and 31 are assigned.

    The coordinates below are illustrative: the package description fixes only the 6 x 6 array, the 31 assigned balls and the 5 spare sites at corners and edges, and this table is one assignment that obeys those facts. Rule one: supplies take the best balls. The four core supply pairs are spread one per quadrant of the array, each VDD ball beside its own VSS ball, in the ring of balls just inside the outer row where the logic they feed is closest. The two I/O pairs sit beside the outputs they feed. Rule two: fast signals take the outer row or column, where they escape without vias, and within two balls of their I/O supply pair: the four SPI signals leave on the south edge beside pair 0. Rule three: quiet pins get quiet neighbours: the crystal balls sit in the north-west corner, and every ball that touches them is a core supply, the other crystal ball or an unconnected site, so no fast signal and no I/O supply is near. Rule four: slow control fills what remains, with the sixteen GPIO pads matched to their nearest I/O pair. The array has 36 balls, 31 are assigned and 5 stay spare: three corners and two edge sites, which sit on the outside of the array where they are least useful to the board and can be tied to ground in a later revision.

    Four boxes in a chain from top to bottom: supplies first, then fast signals, then quiet pins, then slow control.
    Ball assignment order for the NanoSoC teaching package: supplies, fast signals, quiet pins, slow control.

    Row \ column

    1

    2

    3

    4

    5

    6

    A

    XTAL_IN

    XTAL_OUT

    spare

    P8

    P9

    spare

    B

    spare

    VDD_CORE0

    VSS_CORE0

    P12

    P13

    P10

    C

    P14

    VSS_IO1

    VDD_IO1

    VSS_CORE1

    VDD_CORE1

    P11

    D

    P15

    VDD_CORE2

    VSS_CORE2

    VSS_CORE3

    VDD_CORE3

    RESET_N

    E

    P0 (TX)

    P1 (RX)

    VSS_IO0

    VDD_IO0

    P6

    P7

    F

    spare

    P2 (SCK)

    P3 (MOSI)

    P4 (MISO)

    P5 (CS_N)

    spare

    The assignment checker

    The script below holds that array as data and checks it through one function: all 31 pads placed once and exactly 5 spare; one core pair in each quadrant with its VSS beside its VDD; each I/O pair adjacent; SPI pads on the outer ring and within 2 balls of their pair; every other output within 4; and the crystal with only core supplies, the other crystal ball or unconnected sites around it and no SPI pad within 3 balls. It then moves the SPI clock into the centre, puts an I/O ground beside the crystal, and moves a spare site into the middle of the array, and requires all three to be rejected.

    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
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    GRID = [
        ["XTAL_IN", "XTAL_OUT", "NC", "GPIO8", "GPIO9", "NC"],
        ["NC", "VDD_CORE0", "VSS_CORE0", "GPIO12", "GPIO13", "GPIO10"],
        ["GPIO14", "VSS_IO1", "VDD_IO1", "VSS_CORE1", "VDD_CORE1", "GPIO11"],
        ["GPIO15", "VDD_CORE2", "VSS_CORE2", "VSS_CORE3", "VDD_CORE3", "RESET_N"],
        ["GPIO0", "GPIO1", "VSS_IO0", "VDD_IO0", "GPIO6", "GPIO7"],
        ["NC", "GPIO2", "GPIO3", "GPIO4", "GPIO5", "NC"],
    ]
    SPI = ["GPIO2", "GPIO3", "GPIO4", "GPIO5"]            # fast signals: SCK, MOSI, MISO, CS_N
    
    def where(grid):
        return {n: (r, c) for r, row in enumerate(grid) for c, n in enumerate(row) if n != "NC"}
    
    def dist(a, b):
        return abs(a[0] - b[0]) + abs(a[1] - b[1])
    
    def check(grid):
        pos = where(grid)
        nc = sum(row.count("NC") for row in grid)
        assert len(pos) == 31 and nc == 5, (len(pos), nc)
        outer = lambda rc: min(rc[0], rc[1], 5 - rc[0], 5 - rc[1]) == 0
        spares = [(r, c) for r, row in enumerate(grid) for c, n in enumerate(row) if n == "NC"]
        assert all(outer(rc) for rc in spares), "a spare site is not a corner or edge site"
        assert sum(1 for r, c in spares if r in (0, 5) and c in (0, 5)) >= 1, "no spare corner"
        quadrants = set()
        for k in range(4):
            v, g = pos["VDD_CORE%d" % k], pos["VSS_CORE%d" % k]
            assert dist(v, g) == 1, "core pair %d is split" % k
            quadrants.add((v[0] >= 3, v[1] >= 3))
        assert len(quadrants) == 4, "core pairs are not one per quadrant"
        for k in range(2):
            assert dist(pos["VDD_IO%d" % k], pos["VSS_IO%d" % k]) == 1, "I/O pair split"
        for i in range(16):
            pad = "GPIO%d" % i
            pair = 0 if i < 8 else 1
            d = min(dist(pos[pad], pos["VDD_IO%d" % pair]), dist(pos[pad], pos["VSS_IO%d" % pair]))
            assert d <= (2 if pad in SPI else 4), (pad, "too far from its I/O pair", d)
        for pad in SPI:
            r, c = pos[pad]
            assert min(r, c, 5 - r, 5 - c) == 0, pad + " is not on the outer ring"
        xo = pos["XTAL_OUT"]
        near = [n for n, p in pos.items() if n != "XTAL_OUT" and max(abs(p[0] - xo[0]), abs(p[1] - xo[1])) == 1]
        near += [n for n, p in pos.items() if max(abs(p[0] - pos["XTAL_IN"][0]), abs(p[1] - pos["XTAL_IN"][1])) == 1 and n not in near]
        for n in near:
            assert n.startswith(("VSS_CORE", "VDD_CORE", "XTAL")), (n, "is not a quiet neighbour of the crystal")
        assert any(n.startswith("VSS_CORE") for n in near), "crystal has no core ground beside it"
        for pad in SPI:
            assert dist(pos[pad], pos["XTAL_IN"]) >= 3 and dist(pos[pad], xo) >= 3
    
    check(GRID)
    moved = [row[:] for row in GRID]
    moved[5][1], moved[3][3] = "VSS_CORE3", "GPIO2"           # SCK moved to the centre of the array
    noisy = [row[:] for row in GRID]
    noisy[1][0], noisy[2][1] = "VSS_IO1", "NC"             # an I/O ground beside the crystal
    middle = [row[:] for row in GRID]
    middle[0][5], middle[3][3] = "VSS_CORE3", "NC"            # a spare site in the middle of the array
    for bad in (moved, noisy, middle):
        try:
            check(bad)
            raise SystemExit("a bad assignment was accepted")
        except AssertionError:
            pass
    print("PASS: 31 balls placed once, 5 spare; core pair per quadrant; SPI on the outer ring near its pair; crystal quiet; three bad ballouts rejected")

    What the review looks for

    • Supplies placed before signals, with each pair's feed named.

    • Fast signals on the outer ring, quoted by coordinate, not by intent.

    • Quiet pins with named guards, and no fast neighbour within the stated distance.

    • The spare balls listed, so a later change knows what is free.

    Verify and debug

    Diff the ballout against the pin database and the board netlist together: a ball the board team moved without telling the chip team is the classic divergence, and the diff catches it in seconds. If a late change moves a fast signal inward, the escape lesson re-prices the vias before the move is accepted.

    A ball assignment fixed on one side only: two functions end up on one pin, or the chip's map differs from the board design. The symptom is a signal on the wrong ball or noise on the I/O; it is caught by a pin-mux check against the ballout and the board netlist plus a board-team review, and fixed by one pin database and supply pairs spread across the array.

    If asked to ball out a small chip live, narrate the rule order as you place: supplies, fast, quiet, rest. A strong answer is judged by the order of placement and the reasons, more than by the final coordinates.

    Check yourself A GPIO is swapped with the SPI clock to shorten a board trace. Why refuse?

    Because the swap moves a fast signal away from the outer ring or from its supply pair: the board saves one trace while the chip spends escape vias and the noise budget the pairing lesson closed. Ball moves are priced on both sides before acceptance.

    Related topics

    • Package Types at a Conceptual Level

    • Next: Pinout Review and Escape Routing

    • Physical Design: IO Placement and Bump Assignment

    Previous

    221 / 294

    Next: Pinout Review and Escape Routing

    Up next

    Up nextPinout Review and Escape Routing

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error