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
    • Topologies and Bridges
      • Shared Bus, Crossbar and Hierarchy
      • Inside the AXI to APB Bridge
      • Bridge Costs and Where Bridges Belong
      • Register Slices and Timing Closure
    • AXI Integration Details
    • Ordering and Deadlock at the Top
    • QoS and Arbitration
    • NoC Basics
    • Coherent Interconnect View
    • Firewalls and Protection
    • Bandwidth and Latency Verification
  • 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

←Topologies and Bridges
  1. Topics
  2. SoC Design
  3. Interconnect and Bus Fabrics
  4. Topologies and Bridges
  5. Register Slices and Timing Closure
On this page

    Part 4 of 14, lesson 4 of 26Part 4 of 14/Interconnect and Bus Fabrics/Lesson 4 of 26All levels

    Register Slices and Timing Closure

    Where to put a register slice on a fabric path, what it costs in latency, and which kind keeps full throughput.

    Why it matters

    NanoSoC closes timing at 96 MHz without help, but the fabric is the first thing to miss when the clock rises or the die grows: the address decode, arbitration and the data multiplexer of the crossbar sit in one cycle, and long wires between the crossbar and a far memory add to it. The standard repair is a register slice, a pipeline stage on a valid and ready channel, and the standard mistake is a slice that quietly halves the throughput of the link. This lesson places slices, prices them in NanoSoC numbers and shows the half-rate trap in a model that fails when it should.

    The core idea

    A register slice cuts one AXI channel with a register stage. AXI has five channels (AW, W, AR for requests, B and R for responses), each with its own valid and ready, so a slice is applied per channel and a full slice on a path costs one cycle on each direction that carries it. Three kinds exist. A forward slice registers valid and data and leaves ready combinational: it cuts the data path but not the ready path. A backward slice registers ready only. A full slice, two entries deep, registers both and keeps one beat per clock, at the price of one cycle of latency and a second storage entry. A single register with ready equal to not full is the trap: it accepts a beat only every second cycle, so throughput halves.

    Where slices go follows the failing path and the traffic. Put them on the long wire, not on every port: a slice between the crossbar and a far slave helps both directions of that slave only. Put them on the request channels of a path first (AR, AW, W) because they carry the address decode, then on the response side if the multiplexer is the problem. Never put one in a path whose latency budget has no room: the CPU's blocking reads feel every cycle, the SBR's streams do not.

    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
    # Illustrative: three ways to put one register stage on a valid/ready channel.
    # The source always has data and the sink always accepts: count beats in 100 cycles.
    def run(kind, cycles=100):
        delivered = 0
        full = [False, False] # up to two stored beats
        for _ in range(cycles):
            if kind == "none":
                delivered += 1
                continue
            if kind == "single": # one register, ready only when empty
                if full[0]:
                    delivered += 1
                    full[0] = False # sink takes it, no refill this cycle
                else:
                    full[0] = True # source loads it
            if kind == "skid": # two entries: ready stays high until both are full
                if full[0]:
                    delivered += 1
                    full[0], full[1] = full[1], False
                if not full[0]:
                    full[0] = True
                elif not full[1]:
                    full[1] = True
        return delivered
    
    none, single, skid = run("none"), run("single"), run("skid")
    assert none == 100
    assert skid >= 99 # full rate, one cycle of latency
    assert single == 50 # the trap: half throughput
    # NanoSoC cost of a full slice on both directions of the CPU path (illustrative)
    T_SYS = 1e9 / 96e6
    base = 93.75
    with_slice = base + 2 * T_SYS # one cycle on the request and one on the response
    assert abs(with_slice - 114.58) < 0.01 and abs(with_slice / base - 1 - 0.222) < 0.001
    # stages needed for a path that takes 14 ns (illustrative) at two clock rates
    import math
    need = lambda delay, period: math.ceil(delay / period) - 1
    assert need(14.0, 1e3 / 96) == 1 and need(14.0, 1e3 / 192) == 2
    print("PASS: full slice keeps 99 of 100 beats, single register halves to 50, CPU word 93.75 -> 114.58 ns")

    What the review looks for

    • Every slice names its channel, its kind (forward, backward or full) and the cycle it adds in each direction, and the latency budget table gains a row for it.

    • No slice is a single register with ready equal to not full on a path that must sustain one beat per clock; the throughput of the link with the slice is checked, not assumed.

    • A slice sits on the failing path and is removed again if the path later closes without it, so the latency is not paid for ever.

    Verify and debug

    Drive a long burst through the sliced channel with the sink always ready and count beats per window: a full slice must deliver one beat per clock after one cycle of fill, and a half-rate result names the single-register trap. Then stall the sink at random and check that no beat is lost or duplicated, which is where a slice with a broken skid entry fails. Finally re-time the CPU single-word read: it must grow by exactly the cycles the slices add, 20.8 ns for one full slice on both directions at 96 MHz.

    A slice that halves the throughput: a single register with ready tied to not full is inserted on the SBR read path to fix timing, the stream drops from 361.4 to about 180 MB/s with no error anywhere, and the budget check is the only thing that notices. Use a full slice (two entries) on any path that streams.

    If asked how to fix a failing fabric path, name the repair (a register slice on the failing channel), the price (one cycle each way, 20.8 ns on the CPU read at 96 MHz) and the trap (a one-entry slice that halves throughput). Then say where you would not put one: the latency-critical blocking path with no spare cycles.

    Check yourself A full slice is added on the SBR read channel only. What happens to the SBR stream rate and to the CPU read latency?

    The SBR stream keeps 361.4 MB/s and gains one cycle of first-beat latency, because a full slice sustains one beat per clock. The CPU read latency does not change, because the CPU does not use the SBR's channel.

    Related topics

    • Bridge Costs and Where Bridges Belong

    • Protocol First Principles: Register Slices

    • Protocol First Principles: Skid Buffers

    • Next: AXI Integration Details

    Previous

    62 / 289

    Next: IP-XACT and Automated Assembly

    Up next

    Up nextIP-XACT and Automated Assembly

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Shared Bus, Crossbar and Hierarchy
    • Inside the AXI to APB Bridge