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. Secured Debug and Debug Power
On this page

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

    Secured Debug and Debug Power

    Locked when it must be, usable when it counts: debug authentication by lifecycle state and always-on power.

    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 same path that lets bring-up read every register lets an attacker do the same, and the SRAM1 contents that the secure filter protects on the mission path are wide open on an unlocked debug path. Yet locking debug completely bricks failure analysis on returned parts. NanoSoC v1 shows how thin the protection already is: the secure filter protects SRAM1 only against masters whose security attribute software cannot choose, and the stream bridge's attribute can be rewritten from a non-secure register slot. A debug master must not add a second hole of the same kind. The compromise has to be designed once and enforced in hardware: what each lifecycle state allows, how bring-up authenticates, and which power keeps the path alive when the chip sleeps.

    The core idea

    Debug permission follows the lifecycle state of the extension, which a lifecycle register and fuse-backed shadow registers would hold: in development everything is open, in production the secure regions are closed unless an authenticated unlock succeeds, and for a returned part a limited window reopens under a challenge-response owned by the product team. The enforcement point matters. The debug master drives AxPROT from the lifecycle and unlock state, and the interconnect and APB decoder filters deny it exactly as for a mission master. Duplicating the filter inside the access port would create two filters that can disagree, so there is one rule set and the debug master is simply another master whose attribute the software cannot choose. Power follows the same always-on rule as the access path: the debug logic, the unlock state and the wake-capable triggers live in the always-on domain on the peripheral clock, so sleep never locks out the debugger and the debugger never blocks sleep without an explicit debug power request the software can see.

    Diagram
    # not-run: secured-debug permission table for the debug extension, illustrative
    development:   AxPROT[1] = 0 (secure): all four regions allowed, trace all sources
    production:    AxPROT[1] = 1 (non-secure) until an authenticated unlock; SRAM1 and RSTPWR denied
    returned part: as production; a challenge-response unlock drives AxPROT[1] = 0
    enforcement:   the existing interconnect and APB decoder filters; no second filter in the port
    power:         debug logic and unlock state in PD_AON on clk_per; survives sleep
    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
    # Lifecycle x region matrix, derived from the real filter rule and checked against the table.
    REGIONS = ("rom", "sram0", "sram1", "rstpwr")
    SECURE_ONLY = {"sram1", "rstpwr"}                  # NanoSoC: AxPROT[1] = 0 required
    
    def debug_axprot1(state, unlocked):
        """The debug master drives the attribute from lifecycle and unlock state."""
        return 0 if (state == "development" or unlocked) else 1
    
    def filter_allows(axprot1, region):                # the existing interconnect/APB rule
        return not (region in SECURE_ONLY and axprot1 == 1)
    
    def matrix(state, unlocked):
        return {r: filter_allows(debug_axprot1(state, unlocked), r) for r in REGIONS}
    
    EXPECT = {  # written independently, from the permission table
        ("development", False): dict(rom=True, sram0=True, sram1=True, rstpwr=True),
        ("production", False):  dict(rom=True, sram0=True, sram1=False, rstpwr=False),
        ("production", True):   dict(rom=True, sram0=True, sram1=True, rstpwr=True),
        ("returned", False):    dict(rom=True, sram0=True, sram1=False, rstpwr=False),
    }
    for key, want in EXPECT.items():
        assert matrix(*key) == want, key
    denied = [r for r, ok in matrix("production", False).items() if not ok]
    assert len(denied) == 2                             # two denied cells in production
    
    # a second, disagreeing filter inside the access port would be caught by the same table
    def port_filter_allows(axprot1, region):            # forgets RSTPWR
        return not (region == "sram1" and axprot1 == 1)
    mismatch = [r for r in REGIONS
                if port_filter_allows(1, r) != filter_allows(1, r)]
    assert mismatch == ["rstpwr"]
    print("PASS: 4 states match the table; production denies 2 cells; a disagreeing second filter is caught")

    What the review looks for

    • The permission table above with each cell traced to a hardware enforcement point, not a software promise, and the enforcement shared with the mission filters.

    • The unlock mechanism with its authentication strength stated and its failure mode closed, failed unlocks deny, never retry forever.

    • Debug power in the always-on domain confirmed, with the debug power request visible to the power controller when debug holds the chip awake.

    Verify and debug

    Test the locks from the debug side, not the mission side: attempt SRAM1 and reset-controller accesses in each lifecycle state with and without unlock, and confirm denial is clean with an error response rather than a hang. Enter sleep with the debugger attached and confirm the path survives and the wake triggers fire; then confirm the chip can still reach its deepest sleep with debug detached. A debug path that blocks sleep is a power-budget bug wearing a debug badge.

    Security attribute dropped at a bridge or converter: a debug access port that does not propagate the protection sideband reaches secure regions its mission equivalent cannot. Caught by sideband connectivity checks from the lint topic applied to the debug path; fixed by carrying the sideband end to end and filtering at the slave, debug transactions included.

    If asked how you keep debug open for bring-up and closed for attackers, answer with the table: state by state, what is allowed and where it is enforced. Then say the sentence that matters: the debug master drives its protection attribute from the lifecycle and unlock state and the existing filters deny it, so the debug path cannot be more privileged than the mission path.

    Check yourself Production silicon hangs in secure firmware and the debugger cannot read SRAM1 to diagnose it. Correct behaviour or bug?

    Correct, provided the state table says so: production denies secure regions without unlock. The remedy is the authenticated unlock or the returned-part flow, not a wider-open default. Convenience that bypasses the table is the vulnerability.

    Related topics

    • Trace and Cross-Triggers

    • Next: Safety and Fault Architecture

    • Verification First Principles: Security Verification

    Previous

    189 / 289

    Next: SoC Verification Strategy

    Up next

    Up nextSoC Verification Strategy

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Debug Access and TAP Chaining