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
    • IP Collateral and Versioning
    • Wrappers and Adapters
    • Integration Lint and Connectivity Checks
    • Top-Level SDC and Constraint Merge
    • DFT Integration
    • Debug Infrastructure
      • Debug Access and TAP Chaining
      • Trace and Cross-Triggers
      • Secured Debug and Debug Power
    • Safety and Fault Architecture
  • Top-Level Verification and Bring-up21
  • Package, Pads and I/O18
  • Chip Signoff and Tapeout18
  • SoC Interview Prep16
  • Capstone: Integrate NanoSoC14
Loading lesson

←Debug Infrastructure
  1. Topics
  2. SoC Design
  3. IP Integration and Handoff
  4. Debug Infrastructure
  5. Debug Access and TAP Chaining
On this page

    Part 9 of 14, lesson 16 of 21Part 9 of 14/IP Integration and Handoff/Lesson 16 of 21All levels

    Debug Access and TAP Chaining

    One path in: pins, chain order, the always-on bypass, and the reset and clock rules that keep it alive.

    Extension topic: NanoSoC v1 has no debug hardware. This lesson uses the NanoSoC debug extension described in the Debug Infrastructure overview; numbers marked illustrative belong to that extension only.

    Why it matters

    The structured hang triage in The Chip Hangs: What Do You Do? starts with debug access: halt the CPU, read the fabric status, find the outstanding transaction. If the access port sits behind a gated clock, shares its reset with the logic being debugged, or chains in an order nobody recorded, the first hang is also the first discovery that debug was never integrated. NanoSoC makes the point sharply, because PD_SW, which holds the CPU and the fabric, can be switched off while the always-on peripherals keep running. The path has to keep working across that switch.

    The core idea

    The external pins enter a serial chain of test access ports, one per debug domain. The extension has three: tap_aon in the always-on domain (reset and power controller, peripherals), and tap_cpu and tap_sys inside the switchable domain PD_SW. The always-on TAP sits nearest the pins, and every switchable-domain TAP can be bypassed, so powering a domain down shortens the chain instead of breaking it. In a serial TDI-to-TDO chain a link that cannot shift stops everything behind it, so order alone cannot make a failure graceful.

    The bypass has to live in the right domain. A bypass register inside a powered-down domain is itself unpowered and cannot shift. What keeps the chain intact is a chain-level bypass: a multiplexer in the always-on domain routes TDI straight to the next link when the domain is off, and the unpowered TAP's TDO is clamped, exactly like any other signal leaving PD_SW. The bypass register of a powered TAP is a different, one-bit thing, used when software deselects that TAP. A single debug access port then translates external transactions into register and memory accesses through the same decode the mission uses.

    Three rules keep the path alive. The debug logic resets from power-on and the test reset, never from the functional resets it observes: asserting the system reset must not clear the debugger's breakpoints. The debug clock runs whenever debug is enabled, independent of the CPU and system clock gates, so halting a gated domain does not blind the debugger. And the chain order, the access-port address map and the reset assignment are recorded in the connectivity table the earlier topic owns, checked by the same checker.

    tap_bypass.sv
    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
    // Two pieces of the chain. Simplified: the one-bit bypass register does not
    // load 0 in Capture-DR and TDO is not retimed on the falling edge of TCK.
    // 1) bypass register of a powered TAP (selected when software deselects it)
    module tap_bypass (
      input  logic tck,
      input  logic trst_n,
      input  logic shift_dr,
      input  logic tdi,
      output logic tdo
    );
      logic bypass;
      always_ff @(posedge tck or negedge trst_n) begin
        if (!trst_n)
          bypass <= 1'b0;
        else if (shift_dr)
          bypass <= tdi;
      end
      assign tdo = bypass;
    endmodule
    
    // 2) chain-level bypass, placed in the ALWAYS-ON domain around a switchable TAP:
    //    domain off -> TDI goes straight to the next link, the TAP's TDO is clamped.
    module chain_link_bypass (
      input  logic tdi,
      input  logic tap_tdo,      // from the switchable TAP (undefined when unpowered)
      input  logic domain_on,    // from the power controller, always-on
      output logic tdo_next
    );
      logic tap_tdo_clamped;
      assign tap_tdo_clamped = tap_tdo & domain_on;       // clamp to 0 when off
      assign tdo_next = domain_on ? tap_tdo_clamped : tdi;
    endmodule
    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
    # Chain model: powering a switchable domain down must shorten the chain.
    DR_BITS = 32                                  # illustrative data-register length per TAP
    CHAIN = ["tap_aon", "tap_cpu", "tap_sys"]     # always-on TAP nearest the pins
    DOMAIN = {"tap_aon": "AON", "tap_cpu": "SW", "tap_sys": "SW"}
    
    def chain_len(sw_on, chain_bypass_mux):
        n = 0
        for tap in CHAIN:
            if DOMAIN[tap] == "AON" or sw_on:
                n += DR_BITS
            elif chain_bypass_mux:
                n += 1                            # one bypass bit in the always-on mux path
            else:
                return None                       # unpowered link: nothing shifts through it
        return n
    
    assert chain_len(True, True) == 96
    assert chain_len(False, True) == 32 + 1 + 1   # PD_SW off: the chain is shorter, still works
    assert chain_len(False, False) is None         # bypass inside the dead domain: chain broken
    
    AP_WINDOWS = {"tap_aon": (0x00, 8), "tap_cpu": (0x10, 8), "tap_sys": (0x20, 8)}
    def window_problems(w):
        bad = [t for t, (b, s) in w.items() if b % s]
        spans = sorted(w.values())
        bad += ["overlap" for (b1, s1), (b2, _s) in zip(spans, spans[1:]) if b2 < b1 + s1]
        return bad
    assert window_problems(AP_WINDOWS) == []
    assert window_problems(dict(AP_WINDOWS, tap_sys=(0x14, 8))) != []   # overlap and misalignment caught
    
    RESETS = {"tap_aon": ["por_n", "trst_n"], "tap_cpu": ["por_n", "trst_n"],
              "tap_sys": ["por_n", "trst_n"]}
    FUNCTIONAL = {"rst_sys_n", "rst_cpu_n", "rst_per_n", "pad_rst_n", "sw_rst"}
    def reset_problems(r):
        return [t for t, srcs in r.items() if FUNCTIONAL & set(srcs)]
    assert reset_problems(RESETS) == []
    assert reset_problems(dict(RESETS, tap_cpu=["rst_cpu_n"])) == ["tap_cpu"]
    print("PASS: chain 96 bits, 34 with PD_SW off; dead-domain bypass, overlap and functional reset are each caught")

    What the review looks for

    • The chain order drawn and recorded: the always-on TAP first, every switchable-domain TAP bypassable.

    • The chain-level bypass multiplexer and the TDO clamp for each switchable TAP, placed in the always-on domain and listed with the other clamps.

    • Debug reset assignment proven independent of every functional reset it must survive, with power-on as an explicit source.

    • The access-port address map checked with the same alignment and overlap discipline as the mission map.

    Verify and debug

    Test the debug path before any mission test in simulation: enter with the CPU clock gated, with the system in reset, and with PD_SW powered down, and confirm the always-on link still responds through the chain bypass and the chain is shorter by the right number of bits. If the debugger loses the chip exactly when the failure of interest occurs, read the reset assignment first: debug on a functional reset goes blind at the interesting moment by construction. For the TAP basics underneath see JTAG TAP Architecture and for the access port Debug Access Port.

    Debug access lost in a low-power state: the debug logic sits in a gated domain, so the debugger disconnects on sleep and the wake event cannot be caught. Caught by a low-power debug test; fixed by placing the access path and the chain bypass in the always-on domain or providing a debug power request, which the third lesson designs.

    If asked why debug has its own reset, answer: the debugger must survive the resets it observes, including the system reset asserted mid-debug, so it resets from power-on and the test reset only. Then say what shares and what does not: the access port may use the mission decode to reach registers, but never the mission resets or the mission clock gates.

    Check yourself PD_SW is powered down and its TAPs no longer shift. Must the rest of the chain still work?

    Yes, through the chain bypass: a multiplexer in the always-on domain routes TDI straight to the next link when the domain is off, and the unpowered TAP's TDO is clamped. The bypass register inside a powered-down domain cannot do this, because it is off too.

    Related topics

    • Next: Trace and Cross-Triggers

    • DFT: JTAG TAP Architecture

    • DFT: Debug Access Port

    Previous

    187 / 289

    Next: Trace and Cross-Triggers

    Up next

    Up nextTrace and Cross-Triggers

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Secured Debug and Debug Power