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
  • Reading Paths
  • Glossary
  • Metrics Reference
  • Formal Cheat Sheet
  • Formal Foundations19
  • Properties and SVA16
  • Property Development and Constraints19
  • Proof Engines and Convergence23
  • Formal Applications20
    • Connectivity Checking
    • Register (CSR) Verification
      • Register Table to Properties
      • W1C, Read-Only and Reset-Value Proofs
      • Access Timing and Error Responses
      • Hardware Set versus Software Clear Races
    • Deadlock, Livelock and Starvation Checks
    • Reset Determinism and X
    • Data, Handshake and Pipeline Property Sets
    • Other Applications, Honestly Scoped
  • Equivalence Checking14
  • Formal Coverage and Signoff15
  • Methodology and Debug13
  • Interview Prep15
  • Capstone: A Chip-Block Verification Lab24
Loading lesson

←Register (CSR) Verification
  1. Topics
  2. Formal Verification
  3. Formal Applications
  4. Register (CSR) Verification
  5. Access Timing and Error Responses
On this page

    Part 5 of 10, lesson 6 of 20Part 5 of 10/Formal Applications/Lesson 6 of 20All levels

    Access Timing and Error Responses

    Same-cycle error responses with zero wait states, and properties written so they do not fail while waiting.

    Why it matters

    The symptom is a hang or a missed error: software reads a faulty peripheral, the bus returns the error one cycle after the master gave up waiting, or the error never comes because the property that should have caught the timing was written for zero wait states and the design under check inserts one.

    The core idea

    State the cycle of the consequent explicitly. With zero wait states the error response is in the access cycle: request and error in the same cycle, an overlapped relationship. With wait states the request holds across several cycles and the error is due when the access completes, so the property must hold its antecedent through the wait instead of expecting the answer in a fixed cycle. The register block has no bus timing, so this lesson uses a small lesson-local access wrapper with a programmable wait count and an error-generating address.

    The textbook form uses implication: the overlapped operator checks the response in the completion cycle, the non-overlapped one a cycle after, which is the mistake shown failing below. The runnable front end does not accept implication, so this is a concept block and the Boolean forms are what runs:

    design.sv
    1
    2
    3
    4
    5
    6
    7
    // not-run: implication operators are not accepted by this front end
    // a_err_same_cycle: assert property (@(posedge clk) disable iff (rst)
    //   (psel && penable && pready && bad) |-> perr);     // overlapped: error in the completion cycle
    // a_err_next_cycle: assert property (@(posedge clk) disable iff (rst)
    //   (psel && penable && pready && bad) |=> perr);     // non-overlapped: one cycle later (the mistake)
    // a_no_early_err:   assert property (@(posedge clk) disable iff (rst)
    //   (psel && penable && !pready) |-> !perr);          // nothing while the access waits

    The runnable forms are Boolean: the same-cycle form checks perr in the cycle where the antecedent holds, and the next-cycle form reads the antecedent signals through $past and checks perr one cycle after. The cycle table shows the one-wait case on the wrapper (with zero waits the error is in the first access cycle, as the waveform shows):

    Step

    psel

    penable

    paddr

    pready

    perr

    What happens

    n

    1

    0

    3

    0

    0

    setup phase, wait count loaded as 1

    n+1

    1

    1

    3

    0

    0

    access waits: no error yet (the early-error check)

    n+2

    1

    1

    3

    1

    1

    access completes after one wait: error with the completion

    How to read it: the first access has its setup phase at step 2 and its access phase at step 3, where pready, completes_bad and perr all rise together and fall at step 4. The second access loads a wait count of 1 at step 5; at step 6 pready is low, waiting is high and perr stays low; at step 7 the access completes and perr rises in the same step. In both accesses perr follows completes_bad exactly and is never high while waiting is.

    Worked example: the wrapper and the same-cycle proof

    The wrapper answers every access, inserts the programmed number of wait cycles, and raises the error exactly when a held access to the unmapped offset completes. Two documented assumptions describe the bus master: an access phase follows a setup phase, and a waiting access is held with the same address until it completes. Without them the proof would check a bus no real master drives; each is owed as an assertion on the master's side. The proof passes with zero waits and with waits, because the property only demands the error when the access completes:

    apb_csr_access.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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    // formal: prove 4 expect pass slang top apb_csr_access
    `define FORMAL
    module apb_csr_access #(parameter BUG = 0, parameter CHECK = 0) (
      input  wire       clk,
      input  wire       rst,
      input  wire       psel,
      input  wire       penable,
      input  wire       pwrite,
      input  wire [1:0] paddr,
      input  wire [7:0] pwdata,
      input  wire [1:0] waits,
      output wire       pready,
      output wire       perr,
      output wire [7:0] prdata
    );
      reg [1:0] wleft;
      reg       active;
      reg       err_q;
      reg       waited;   // a wait cycle has already happened in this access
    
      wire setup  = psel && !penable;
      wire access = psel && penable;
      wire bad    = (paddr == 2'b11);               // the unmapped offset answers with an error
      wire done   = access && (wleft == 2'd0);      // completion cycle
    
      assign pready = done;
      assign perr   = (BUG == 1) ? err_q :          // BUG 1: error one cycle late
                      (BUG == 2) ? (access && bad)  // BUG 2: error raised while still waiting
                                 : (done && bad);   // correct: error together with the completion
      assign prdata = 8'h00;
    
      always @(posedge clk) begin
        if (rst) begin wleft <= 2'd0; active <= 1'b0; err_q <= 1'b0; waited <= 1'b0; end
        else begin
          if (setup && !active) begin wleft <= waits; active <= 1'b1; end
          if (done) active <= 1'b0;
          else if (access && wleft != 2'd0) wleft <= wleft - 2'd1;
          err_q <= done && bad;
          if (done) waited <= 1'b0;
          else if (access) waited <= 1'b1;
        end
      end
    
    `ifdef FORMAL
      reg init = 1'b1;
      always @(posedge clk) init <= 1'b0;
      always @(*) if (init) assume (rst);
    
      // documented bus contract, an assumption on the master: an access phase follows a setup phase,
      // and a waiting access is held with the same address until it completes
      reg       was_psel, hold;
      reg [1:0] addr_q;
      always @(posedge clk) begin
        was_psel <= psel;
        hold     <= access && !done;
        addr_q   <= paddr;
      end
      always @(*) if (!init) begin
        assume (!penable || was_psel);
        assume (!hold || (psel && penable && paddr == addr_q));
      end
    
      generate if (CHECK == 0) begin : g_ok
        always @(*) if (!init) begin
          a_err_same_cycle: assert (!(psel && penable && pready && bad) || perr);
          a_no_early_err:   assert (!(psel && penable && !pready) || !perr);
        end
      end else begin : g_late
        // the mistake: the error is demanded one cycle AFTER the completion
        always @(posedge clk) if (!init && !$past(rst)) begin
          a_err_next_cycle: assert (!($past(psel) && $past(penable) && $past(pready) && $past(bad)) || perr);
        end
      end endgenerate
    
      always @(*) if (!init) begin
        c_err_nowait:     cover (done && bad && !waited);
        c_err_after_wait: cover (done && bad && waited);
      end
    `endif
    endmodule

    Both covers are reached when the same module is run as a cover: the error with zero waits at step 1 and the error after a real wait cycle at step 3. The second cover is only satisfied after a cycle in which the access was waiting, so it is not satisfied by the wait count input alone:

    apb_csr_access.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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    // formal: cover 8 expect reached slang top apb_csr_access
    `define FORMAL
    module apb_csr_access #(parameter BUG = 0, parameter CHECK = 0) (
      input  wire       clk,
      input  wire       rst,
      input  wire       psel,
      input  wire       penable,
      input  wire       pwrite,
      input  wire [1:0] paddr,
      input  wire [7:0] pwdata,
      input  wire [1:0] waits,
      output wire       pready,
      output wire       perr,
      output wire [7:0] prdata
    );
      reg [1:0] wleft;
      reg       active;
      reg       err_q;
      reg       waited;   // a wait cycle has already happened in this access
    
      wire setup  = psel && !penable;
      wire access = psel && penable;
      wire bad    = (paddr == 2'b11);               // the unmapped offset answers with an error
      wire done   = access && (wleft == 2'd0);      // completion cycle
    
      assign pready = done;
      assign perr   = (BUG == 1) ? err_q :          // BUG 1: error one cycle late
                      (BUG == 2) ? (access && bad)  // BUG 2: error raised while still waiting
                                 : (done && bad);   // correct: error together with the completion
      assign prdata = 8'h00;
    
      always @(posedge clk) begin
        if (rst) begin wleft <= 2'd0; active <= 1'b0; err_q <= 1'b0; waited <= 1'b0; end
        else begin
          if (setup && !active) begin wleft <= waits; active <= 1'b1; end
          if (done) active <= 1'b0;
          else if (access && wleft != 2'd0) wleft <= wleft - 2'd1;
          err_q <= done && bad;
          if (done) waited <= 1'b0;
          else if (access) waited <= 1'b1;
        end
      end
    
    `ifdef FORMAL
      reg init = 1'b1;
      always @(posedge clk) init <= 1'b0;
      always @(*) if (init) assume (rst);
    
      // documented bus contract, an assumption on the master: an access phase follows a setup phase,
      // and a waiting access is held with the same address until it completes
      reg       was_psel, hold;
      reg [1:0] addr_q;
      always @(posedge clk) begin
        was_psel <= psel;
        hold     <= access && !done;
        addr_q   <= paddr;
      end
      always @(*) if (!init) begin
        assume (!penable || was_psel);
        assume (!hold || (psel && penable && paddr == addr_q));
      end
    
      generate if (CHECK == 0) begin : g_ok
        always @(*) if (!init) begin
          a_err_same_cycle: assert (!(psel && penable && pready && bad) || perr);
          a_no_early_err:   assert (!(psel && penable && !pready) || !perr);
        end
      end else begin : g_late
        // the mistake: the error is demanded one cycle AFTER the completion
        always @(posedge clk) if (!init && !$past(rst)) begin
          a_err_next_cycle: assert (!($past(psel) && $past(penable) && $past(pready) && $past(bad)) || perr);
        end
      end endgenerate
    
      always @(*) if (!init) begin
        c_err_nowait:     cover (done && bad && !waited);
        c_err_after_wait: cover (done && bad && waited);
      end
    `endif
    endmodule

    Worked example: the failing partners

    A proof of the same-cycle property can fail only if some variant breaks it. The first variant returns the error one cycle late (a registered copy), which fails the same-cycle check at the completion cycle. The second raises the error while the access is still waiting, which fails the no-early-error check. Both are bounded runs that find a counterexample:

    apb_csr_access.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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    // formal: bmc 8 expect fail slang top apb_csr_access define BUG=1
    `define FORMAL
    module apb_csr_access #(parameter BUG = 0, parameter CHECK = 0) (
      input  wire       clk,
      input  wire       rst,
      input  wire       psel,
      input  wire       penable,
      input  wire       pwrite,
      input  wire [1:0] paddr,
      input  wire [7:0] pwdata,
      input  wire [1:0] waits,
      output wire       pready,
      output wire       perr,
      output wire [7:0] prdata
    );
      reg [1:0] wleft;
      reg       active;
      reg       err_q;
      reg       waited;   // a wait cycle has already happened in this access
    
      wire setup  = psel && !penable;
      wire access = psel && penable;
      wire bad    = (paddr == 2'b11);               // the unmapped offset answers with an error
      wire done   = access && (wleft == 2'd0);      // completion cycle
    
      assign pready = done;
      assign perr   = (BUG == 1) ? err_q :          // BUG 1: error one cycle late
                      (BUG == 2) ? (access && bad)  // BUG 2: error raised while still waiting
                                 : (done && bad);   // correct: error together with the completion
      assign prdata = 8'h00;
    
      always @(posedge clk) begin
        if (rst) begin wleft <= 2'd0; active <= 1'b0; err_q <= 1'b0; waited <= 1'b0; end
        else begin
          if (setup && !active) begin wleft <= waits; active <= 1'b1; end
          if (done) active <= 1'b0;
          else if (access && wleft != 2'd0) wleft <= wleft - 2'd1;
          err_q <= done && bad;
          if (done) waited <= 1'b0;
          else if (access) waited <= 1'b1;
        end
      end
    
    `ifdef FORMAL
      reg init = 1'b1;
      always @(posedge clk) init <= 1'b0;
      always @(*) if (init) assume (rst);
    
      // documented bus contract, an assumption on the master: an access phase follows a setup phase,
      // and a waiting access is held with the same address until it completes
      reg       was_psel, hold;
      reg [1:0] addr_q;
      always @(posedge clk) begin
        was_psel <= psel;
        hold     <= access && !done;
        addr_q   <= paddr;
      end
      always @(*) if (!init) begin
        assume (!penable || was_psel);
        assume (!hold || (psel && penable && paddr == addr_q));
      end
    
      generate if (CHECK == 0) begin : g_ok
        always @(*) if (!init) begin
          a_err_same_cycle: assert (!(psel && penable && pready && bad) || perr);
          a_no_early_err:   assert (!(psel && penable && !pready) || !perr);
        end
      end else begin : g_late
        // the mistake: the error is demanded one cycle AFTER the completion
        always @(posedge clk) if (!init && !$past(rst)) begin
          a_err_next_cycle: assert (!($past(psel) && $past(penable) && $past(pready) && $past(bad)) || perr);
        end
      end endgenerate
    
      always @(*) if (!init) begin
        c_err_nowait:     cover (done && bad && !waited);
        c_err_after_wait: cover (done && bad && waited);
      end
    `endif
    endmodule
    apb_csr_access.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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    // formal: bmc 8 expect fail slang top apb_csr_access define BUG=2
    `define FORMAL
    module apb_csr_access #(parameter BUG = 0, parameter CHECK = 0) (
      input  wire       clk,
      input  wire       rst,
      input  wire       psel,
      input  wire       penable,
      input  wire       pwrite,
      input  wire [1:0] paddr,
      input  wire [7:0] pwdata,
      input  wire [1:0] waits,
      output wire       pready,
      output wire       perr,
      output wire [7:0] prdata
    );
      reg [1:0] wleft;
      reg       active;
      reg       err_q;
      reg       waited;   // a wait cycle has already happened in this access
    
      wire setup  = psel && !penable;
      wire access = psel && penable;
      wire bad    = (paddr == 2'b11);               // the unmapped offset answers with an error
      wire done   = access && (wleft == 2'd0);      // completion cycle
    
      assign pready = done;
      assign perr   = (BUG == 1) ? err_q :          // BUG 1: error one cycle late
                      (BUG == 2) ? (access && bad)  // BUG 2: error raised while still waiting
                                 : (done && bad);   // correct: error together with the completion
      assign prdata = 8'h00;
    
      always @(posedge clk) begin
        if (rst) begin wleft <= 2'd0; active <= 1'b0; err_q <= 1'b0; waited <= 1'b0; end
        else begin
          if (setup && !active) begin wleft <= waits; active <= 1'b1; end
          if (done) active <= 1'b0;
          else if (access && wleft != 2'd0) wleft <= wleft - 2'd1;
          err_q <= done && bad;
          if (done) waited <= 1'b0;
          else if (access) waited <= 1'b1;
        end
      end
    
    `ifdef FORMAL
      reg init = 1'b1;
      always @(posedge clk) init <= 1'b0;
      always @(*) if (init) assume (rst);
    
      // documented bus contract, an assumption on the master: an access phase follows a setup phase,
      // and a waiting access is held with the same address until it completes
      reg       was_psel, hold;
      reg [1:0] addr_q;
      always @(posedge clk) begin
        was_psel <= psel;
        hold     <= access && !done;
        addr_q   <= paddr;
      end
      always @(*) if (!init) begin
        assume (!penable || was_psel);
        assume (!hold || (psel && penable && paddr == addr_q));
      end
    
      generate if (CHECK == 0) begin : g_ok
        always @(*) if (!init) begin
          a_err_same_cycle: assert (!(psel && penable && pready && bad) || perr);
          a_no_early_err:   assert (!(psel && penable && !pready) || !perr);
        end
      end else begin : g_late
        // the mistake: the error is demanded one cycle AFTER the completion
        always @(posedge clk) if (!init && !$past(rst)) begin
          a_err_next_cycle: assert (!($past(psel) && $past(penable) && $past(pready) && $past(bad)) || perr);
        end
      end endgenerate
    
      always @(*) if (!init) begin
        c_err_nowait:     cover (done && bad && !waited);
        c_err_after_wait: cover (done && bad && waited);
      end
    `endif
    endmodule

    The late-error variant fails at the completion cycle: pready is 1 and perr is still 0, because the registered copy rises a cycle later. The early-error variant fails at the first waiting cycle, where perr is 1 while pready is 0.

    Worked example: the one-cycle-late mistake

    Writing the check as a non-overlapped relationship, expecting the error one cycle after the completed access, fails on the correct wrapper: the bus is idle again and the error flag is down. The property is wrong and the design is right, and the temptation is to 'fix' the design by delaying the error:

    apb_csr_access.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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    // formal: bmc 8 expect fail slang top apb_csr_access define CHECK=1
    `define FORMAL
    module apb_csr_access #(parameter BUG = 0, parameter CHECK = 0) (
      input  wire       clk,
      input  wire       rst,
      input  wire       psel,
      input  wire       penable,
      input  wire       pwrite,
      input  wire [1:0] paddr,
      input  wire [7:0] pwdata,
      input  wire [1:0] waits,
      output wire       pready,
      output wire       perr,
      output wire [7:0] prdata
    );
      reg [1:0] wleft;
      reg       active;
      reg       err_q;
      reg       waited;   // a wait cycle has already happened in this access
    
      wire setup  = psel && !penable;
      wire access = psel && penable;
      wire bad    = (paddr == 2'b11);               // the unmapped offset answers with an error
      wire done   = access && (wleft == 2'd0);      // completion cycle
    
      assign pready = done;
      assign perr   = (BUG == 1) ? err_q :          // BUG 1: error one cycle late
                      (BUG == 2) ? (access && bad)  // BUG 2: error raised while still waiting
                                 : (done && bad);   // correct: error together with the completion
      assign prdata = 8'h00;
    
      always @(posedge clk) begin
        if (rst) begin wleft <= 2'd0; active <= 1'b0; err_q <= 1'b0; waited <= 1'b0; end
        else begin
          if (setup && !active) begin wleft <= waits; active <= 1'b1; end
          if (done) active <= 1'b0;
          else if (access && wleft != 2'd0) wleft <= wleft - 2'd1;
          err_q <= done && bad;
          if (done) waited <= 1'b0;
          else if (access) waited <= 1'b1;
        end
      end
    
    `ifdef FORMAL
      reg init = 1'b1;
      always @(posedge clk) init <= 1'b0;
      always @(*) if (init) assume (rst);
    
      // documented bus contract, an assumption on the master: an access phase follows a setup phase,
      // and a waiting access is held with the same address until it completes
      reg       was_psel, hold;
      reg [1:0] addr_q;
      always @(posedge clk) begin
        was_psel <= psel;
        hold     <= access && !done;
        addr_q   <= paddr;
      end
      always @(*) if (!init) begin
        assume (!penable || was_psel);
        assume (!hold || (psel && penable && paddr == addr_q));
      end
    
      generate if (CHECK == 0) begin : g_ok
        always @(*) if (!init) begin
          a_err_same_cycle: assert (!(psel && penable && pready && bad) || perr);
          a_no_early_err:   assert (!(psel && penable && !pready) || !perr);
        end
      end else begin : g_late
        // the mistake: the error is demanded one cycle AFTER the completion
        always @(posedge clk) if (!init && !$past(rst)) begin
          a_err_next_cycle: assert (!($past(psel) && $past(penable) && $past(pready) && $past(bad)) || perr);
        end
      end endgenerate
    
      always @(*) if (!init) begin
        c_err_nowait:     cover (done && bad && !waited);
        c_err_after_wait: cover (done && bad && waited);
      end
    `endif
    endmodule

    Root cause: an overlapped response checked with non-overlapped timing. Fix the cycle, not the design: the check belongs in the access cycle.

    What the review looks for

    • Every property states its cycle: same-cycle or completion-cycle, never an implied one.

    • Wait-state behaviour has a cover that needs a real wait cycle, not just a non-zero wait input.

    • No property demands anything while the access waits: the antecedent repeats until completion, and an early error is itself a failure.

    • The bus assumptions are listed, each asserted on the master that owes it.

    Verify and debug

    Ask which cycle the specification promises (the completion cycle), then whether the trace has waits: a property written for zero waits fails on the first waited access. Check the waited-case cover before changing anything.

    A zero-wait property on a design with waits: the symptom is a failure the first time the interconnect inserts a wait state. The cause is a fixed-cycle consequent. The fix is conditioning the consequent on completion, as here, and covering the waited case.

    Expect: the error arrives with the response, not after it, for zero wait states. Say why: the access and its response occupy the same cycle, so a check one cycle later observes an idle bus. Then extend to waits: the check repeats with the access until it completes.

    Check yourself Why does the correct property condition on pready rather than counting cycles from the request?

    Counting assumes a fixed wait, which the interconnect does not promise. Conditioning on completion holds for any wait count, including zero, so one property covers every timing the bus allows.

    Related topics

    • W1C, Read-Only and Reset-Value Proofs

    • Next: Hardware Set versus Software Clear Races

    Previous

    88 / 183

    Next: Hardware Set versus Software Clear Races

    Up next

    Up nextHardware Set versus Software Clear Races

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Register Table to Properties
    clkpselpenablepaddr3waits010preadyperrcompletes_badwaiting
    Simulation output: two accesses to the unmapped offset 3, the first with zero wait states and the second with a programmed wait of 1