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

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • RTL Foundations36
  • Combinational Design25
  • Sequential Design27
  • FSM & Control27
  • Timing & Clocking39
  • Reset & CDC34
  • Memory & Buses57
    • SRAM and ROM
    • Register Files
    • Valid/Ready Handshake
    • AXI-Lite
    • AXI-Stream
    • Bus Integration
      • Address Decode
      • Mux Trees and Read Paths
      • Error Paths and Timeouts
      • Arbitration
      • Integration Checklist
      • An End-to-End Bus Example
    • Synchronous FIFO
    • Register-Map and CSR RTL
    • Memory Reliability
    • Peripheral RTL Integration
    • Full AXI4: RTL Roadmap
  • Advanced RTL28
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

‹Bus Integration
  1. Topics
  2. RTL Design
  3. Memory & Buses
  4. Bus Integration
  5. Error Paths and Timeouts

Part 7 · Memory & Buses · Intermediate

Error Paths and Timeouts

SLVERR and DECERR policy, a timeout detector, and the separate recovery obligations.

On this page

    Why this matters

    An unmapped access that returns OKAY with garbage is read as valid data by software. A hung slave with no timeout stalls the master for good.

    After this lesson you can: map bad accesses to SLVERR or DECERR, and build a timeout monitor while saying what the monitor does not do.

    A timeout detector notices that a transaction has waited too long; a transaction engine decides what happens next. The bus_timeout module in this lesson is only the detector: it raises a level after LIMIT cycles, and every recovery step is the engine's job.

    Mapping bad accesses to errors

    The default slave returns an error response for illegal addresses. AXI names two of them: SLVERR for a slave-detected error and DECERR for a decode error on an unmapped address.

    Case

    Response

    Code

    Slave detects a bad access

    SLVERR

    2'b10

    Unmapped address at decode

    DECERR

    2'b11

    Hung transaction past the agreed limit

    System engine may synthesize one SLVERR completion; detector alone does not

    2'b10 under that policy

    Normal completion

    OKAY

    2'b00

    The detector

    Timeout monitors protect hung transactions in bring-up. A counter runs while a transaction is in flight and clears when the slave answers.

    timeout is a combinational level qualified by req && !ack: it asserts when the counter reaches LIMIT and drops immediately if ack arrives or req falls. It neither emits SLVERR nor remembers aborted ownership, quarantines late replies or authorises reuse.

    LIMIT must be at least 1; the procedural initial check reports an error at simulation time zero, not a portable elaboration guarantee.

    What the engine must do

    One hung transaction, from issue to reuse, shows every obligation the detector leaves to the engine.

    One hung transaction A: the detector fires after LIMIT = 8 cycles, and from then until a proven drain the engine sends one error, keeps admission closed, holds a new requester B and discards A's late reply

    Read the axis left to right. Everything after the timeout mark is work for the engine; the detector only supplies the mark.

    • Timeout for A: latch the decision and keep A's response context; produce at most one upstream error completion.

    • B arrives: keep admission closed while A's downstream request can still answer.

    • Late reply for A: consume and discard it under A's retained ownership, never as B's response. The raw ack that clears the detector's level must not clear the fault policy.

    • Reopen: only after a bounded drain, or a coordinated peer isolation or reset that proves old responses cannot return. Otherwise stay faulted.

    State diagram with three states. IDLE goes to BUSY when a request is issued. BUSY returns to IDLE on ack with the response forwarded, or goes to QUARANTINE on timeout with one error sent. QUARANTINE loops on itself when a late reply is discarded and returns to IDLE when drain or peer reset is proven.
    A minimal engine around the detector: BUSY ends with a forwarded response or a timeout, and QUARANTINE discards late replies until reuse is proven safe

    Choose the system policy explicitly. The engine above is a sketch of one policy, not part of the listing. Admission is open only in IDLE, so B waits through BUSY and QUARANTINE. See the sequencer's drain/fault/recover contract for a full version. A downstream reset alone cannot retract a response already queued in a bridge; include all owners and queues in the quiescence proof.

    Common mistakes

    Common pitfall

    OKAY plus garbage data on unmapped access: software may misinterpret it as valid. An error response is data too, and the default slave must produce it.

    Check yourself A slave sometimes answers after 100 cycles. Does timeout alone safely abort it?

    No. The agreed latency policy decides when to declare failure. An engine must latch that decision, issue one upstream completion and retain/quarantine downstream ownership until drain or coordinated isolation/reset. The detector cannot safely assign a late old reply to a new request.

    Check yourself Decode reports DECERR while the slave reports SLVERR for the same access. Which wins?

    DECERR. An unmapped address never reaches a slave, so the decode error is the true cause and the one software should see.

    Testbench

    The timeout monitor plus a testbench that proves a normal access never fires, a hung access fires exactly at cycle 8 and holds without re-firing, and dropping the request restarts the count.

    bus_timeout.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // bus_timeout: detects a hung transaction; recovery/response ownership are external.
    module bus_timeout #(
      parameter int LIMIT = 8   // must be at least 1
    )(
      input  logic clk, rst_n,
      input  logic req,          // transaction in flight
      input  logic ack,          // slave answered
      output logic timeout       // qualified level, not a sticky fault or response
    );
      // LIMIT = 0 would give W = $clog2(1) = 0, a zero-width counter and an illegal cast,
      // so the width stays elaborable and the check below rejects the configuration.
      localparam int W = (LIMIT > 0) ? $clog2(LIMIT + 1) : 1;
      initial begin
        if (LIMIT < 1) $error("bus_timeout: LIMIT must be at least 1");
      end
      logic [W-1:0] count;
      always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n)                        count <= '0;
        else if (!req || ack)              count <= '0;
        else if (count < LIMIT[W-1:0])     count <= count + 1'b1;
      end
      assign timeout = (count == LIMIT[W-1:0]) && req && !ack;
    endmodule
    

    Remember

    • DECERR means no slave matched the address. SLVERR means a slave detected the error.

    • The timeout counter runs while req && !ack, fires at LIMIT, and drops when ack arrives or req falls.

    • A monitor is a detector, not a transaction engine: it sends no error and does not quarantine late replies.

    Rule of thumb: an error response is data too, so the default slave must produce it.

    Keep going

    • Practice: AXI4-Lite slave with invalid address protection

    • Practice: Waveform debug: write transaction timeout

    • Interview: run a mock interview on this topic

    Related topics

    • Address Decode

    • Integration Checklist

    Previous

    212 / 350

    Next: Arbitration

    Up next

    Up nextArbitration

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Address Decode
    • Integration Checklist
    • An End-to-End Bus Example