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
    • Safety and Fault Architecture
      • What a Safety Goal Asks of the SoC
      • Fault Detection, Reaction and Reporting
      • Lockstep, Parity and Redundancy
  • Top-Level Verification and Bring-up21
  • Package, Pads and I/O18
  • Chip Signoff and Tapeout18
  • SoC Interview Prep16
  • Capstone: Integrate NanoSoC14
Loading lesson

←Safety and Fault Architecture
  1. Topics
  2. SoC Design
  3. IP Integration and Handoff
  4. Safety and Fault Architecture
  5. Fault Detection, Reaction and Reporting
On this page

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

    Fault Detection, Reaction and Reporting

    The chain that refuses silence: aggregation, priority, a second report path, and the latency budget recomputed.

    Extension topic: NanoSoC v1 has no fault controller or redundancy hardware. This lesson uses the NanoSoC safety extension described in the Safety and Fault Architecture overview; numbers marked illustrative belong to that extension only.

    Why it matters

    Detection without reporting is a flag in an empty room: the status bit that nobody polls while the corrupted words stream on. The fault controller of the extension is the room's alarm panel, collecting detection flags from every structure, prioritising them, and interrupting the CPU. But an alarm that arrives after the damage is history, so the chain owns a latency budget from fault to handler. And an alarm that depends on the CPU cannot report a fault in the CPU. The chain therefore needs a budget and a second path.

    The core idea

    Detection flags arrive as held levels, never single-cycle pulses, and are synchronised into the controller clock with the two-flop rule the crossings part of the course teaches. The controller sits in the always-on domain on clk_per, masks per input, prioritises with lower number winning exactly like the interrupt controller it mirrors, and latches one aggregated FAULT. NanoSoC has no fault input today, and interrupt input 0 is irq_pwr, the power-and-PLL priority. The extension ORs the aggregated fault into that input by adding a FAULT bit to PWR_IRQ, so irq_pwr = |PWR_IRQ still holds and the handler tells the two causes apart by reading the register. The spare inputs 6 and 7 are not used: they are the lowest priorities, and a fault report there would wait behind every peripheral.

    Software clears by writing the source status, which drops the level, then clears PWR_IRQ.FAULT, and reads back to flush any posted bridge write before returning. The interrupt path cannot report a fault in the CPU or the interrupt controller itself, so the extension adds a second report that uses neither: a dedicated fault output pin driven by the fault controller in the always-on domain, which a supervisor or the bench can see even when the CPU is hung. The budget below recomputes the worst-case reporting latency from the clock plan. It must include the fault controller's own synchroniser and output register, which the existing interrupt path (182.3 ns from a source in clk_sys to the CPU input) does not have, and the interrupt controller's own two stages on top.

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # Fault-report latency to the CPU interrupt input (extension, NanoSoC clocks).
    T_PER = 1e9 / 24e6          # 41.667 ns
    T_CPU = 1e9 / 192e6         # 5.208 ns
    stages = {
        "fault controller sync (2 clk_per)": 2 * T_PER,
        "fault controller register (1 clk_per)": 1 * T_PER,
        "interrupt controller input sync (2 clk_per)": 2 * T_PER,
        "interrupt controller output register (1 clk_per)": 1 * T_PER,
        "CPU sync (2 clk_cpu)": 2 * T_CPU,
        "alignment (1 clk_per + 1 clk_cpu)": T_PER + T_CPU,
    }
    worst_ns = sum(stages.values())
    assert abs(worst_ns - 307.29) < 0.01, worst_ns
    existing_path_ns = 182.292             # irq_dma to the CPU input in NanoSoC v1
    assert worst_ns > existing_path_ns     # the controller adds stages; the old number is not reused
    DEADLINE_US = 2.0                      # illustrative reporting deadline
    margin = DEADLINE_US * 1000 / worst_ns
    assert margin > 6.0 and margin < 7.0, margin
    print(f"PASS: worst case to the CPU interrupt input {worst_ns:.1f} ns; margin x{margin:.1f}")

    The result is the worst case to the CPU interrupt input, not to the first instruction of the handler: handler entry adds the CPU's own interrupt latency on top.

    What the review looks for

    • Every detection flag specified as a held level with its synchroniser, reviewed like any other crossing.

    • The aggregation into input 0 through the FAULT bit with the budget above recomputed for the shipped clock plan, stage by stage, and the CPU's own interrupt latency added separately.

    • The second report path (the fault output pin) present and shown to work with the CPU held in reset.

    • The software clear sequence documented per fault: which status, which order, with the read-back that prevents storms.

    Verify and debug

    Measure the budget, do not just compute it: inject a fault with a timestamp, toggle a GPIO in the handler's first lines, and time the interval on the bench or in simulation. Test the storm case explicitly: a fault whose source is not cleared must re-interrupt rather than wedge, and the handler must distinguish re-interrupt from a new fault by reading the source status first. Hold the CPU in reset and confirm the fault pin still rises.

    Interrupt storm from a level source not cleared: the handler returns, the level is still high, the handler runs again forever. In fault clothing this is the FAULT bit that never drops because software cleared the controller but not the source. Caught by software tests with the fault held; fixed by clearing at the source first with a read-back to flush posted writes.

    If asked how fast a fault must be reported, answer with the sum, stage by stage: both synchronisers, both registers, the CPU synchroniser and the alignment, 307 nanoseconds in the extension, then the margin against the deadline. Then say where the number lives: recomputed from the clock plan with every added stage, not copied from the nearest existing path.

    Check yourself Why must detection flags be held levels rather than pulses?

    Because the controller and the CPU run on different clocks from most sources, and a pulse shorter than two destination cycles can be missed entirely. A held level waits for the synchroniser; software clearing drops it only after handling.

    Related topics

    • What a Safety Goal Asks of the SoC

    • Next: Lockstep, Parity and Redundancy

    • Protocol First Principles: Interrupts and Notification

    Previous

    194 / 289

    Next: Lockstep, Parity and Redundancy

    Up next

    Up nextLockstep, Parity and Redundancy

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error