Difficulty: Hard · Puzzle 6 of 6 · Topic: APB Protocol Puzzles
Three APB reads (10 cycles) from a slave that drives garbage on PRDATA until the transfer completes. Bridge A samples PRDATA in the first ACCESS cycle; bridge B samples it in the completing ACCESS cycle (PSEL && PENABLE && PREADY). Third read ends with PSLVERR=1. What does each bridge capture for each read, and which captured values may the scoreboard compare?
`timescale 1ns/1ns
module tb;
localparam int N = 10;
// cycle: 0123456789
localparam bit [0:N-1] PSEL = 10'b0111011110;
localparam bit [0:N-1] PENABLE = 10'b0011001010;
localparam bit [0:N-1] PREADY = 10'b0001001010;
localparam bit [0:N-1] PSLVERR = 10'b0000000010;
localparam bit [79:0] PRDATA = {8'h00, 8'h00, 8'hEE, 8'h11, 8'h00, 8'h00, 8'h22, 8'h00, 8'hBA, 8'h33};
bit clk = 0;
int cyc = 0, reads = 0;
always #5 clk = ~clk;
wire psel = PSEL[cyc], penable = PENABLE[cyc], pready = PREADY[cyc], pslverr = PSLVERR[cyc];
wire [7:0] prdata = PRDATA[(N-1-cyc)*8 +: 8];
bit p_setup = 0;
always @(posedge clk) begin
if (psel && penable && p_setup) begin // bridge A: samples PRDATA in the first ACCESS cycle
$display("A (first ACCESS cycle) cycle %0d: PRDATA=0x%0h", cyc, prdata);
end
if (psel && penable && pready) begin // bridge B: samples PRDATA when the transfer completes
reads++;
if (pslverr) $display("B (completion) cycle %0d: read #%0d PSLVERR=1, PRDATA=0x%0h is don't-care, not compared", cyc, reads, prdata);
else $display("B (completion) cycle %0d: read #%0d PRDATA=0x%0h", cyc, reads, prdata);
end
p_setup <= psel && !penable; // previous cycle was a SETUP cycle
cyc <= cyc + 1;
end
initial #(10*N) $finish;
endmoduleFind each read's SETUP, wait and completion cycles from PENABLE and PREADY. PRDATA is only required to be valid in the completion cycle (and even then not on an error).
1) Read 1: SETUP cycle 1, wait in cycle 2 (PRDATA=0xEE, garbage), completes cycle 3 (PRDATA=0x11).
2) Read 2: SETUP cycle 5, completes at once in cycle 6 (PRDATA=0x22). No wait state.
3) Read 3: SETUP cycle 7, completes in cycle 8 with PSLVERR=1 (PRDATA=0xBA).
4) A (first access cycle) captures 0xEE, 0x22, 0xBA. B (completion) captures 0x11, 0x22, 0xBA.
5) A is wrong for read 1 (it caught the wait-state garbage); it only works when the slave has no wait states. For read 3 the data is a don't-care because the transfer failed.Answer: A: EE, 22, BA. B: 11, 22, BA. Only B is right (read 1 = 0x11, read 2 = 0x22); read 3's PRDATA is not compared because PSLVERR=1 makes it a don't-care.
Checked by running the code in Verilator 5; the printed output supports the answer above. Bridge A catches wait-state garbage 0xEE; bridge B catches the true 0x11. The error read's data is treated as a don't-care.
Sampling at the first access cycle passes every test against a zero-wait slave (read 2 matches), so the bug appears only when a slower slave is added. And a scoreboard comparing PRDATA on an error read will report a false mismatch: the data is undefined by the protocol.
How would you make a bridge testbench catch the early-sampling bug without waiting for a slow real peripheral? Model answer: Drive random wait states with a junk pattern on PRDATA while PREADY is low (a constrained slave model), so any sample taken before the completing cycle returns a wrong value on the first run.