Fix a completer whose PSLVERR is gone by the only cycle in which the requester looks at it.
Hardware context: An APB completer that refuses some transfers. Fix a completer that raises PSLVERR in setup and wait cycles but not at completion.
This is a Fix problem: the completer in the editor has one realistic defect. Find it and fix it.
Software wrote a read-only ID register, got no error and carried on, and the same happened for every refused transfer. On the wires the completer did raise PSLVERR, as soon as it had decoded the address: during the setup cycle and the wait states. But it dropped PSLVERR in the cycle the transfer completed. The requester looks at PSLVERR only at the completion edge, where PSEL, PENABLE and PREADY are all 1, and ignores it everywhere else (lesson P3.4, IHI 0024E 3.4).
The fixture runs scripts of up to six transfers with a correct requester and reports, for every transfer, whether it ended with an error, plus the wait cycles and the last two good reads. Make the error arrive where it counts.
Signals in the Timeline
| Signal | Width | Role |
|---|---|---|
n | 8 | input of each check |
script_first | 144 | input of each check |
script_last | 144 | input of each check |
Full specification
module apb_err (
input logic pclk,
input logic presetn, // active-low, asynchronous
input logic psel,
input logic penable,
input logic pwrite,
input logic [7:0] paddr, // byte address of the register
input logic [31:0] pwdata,
input logic [3:0] pstrb,
output logic pready,
output logic [31:0] prdata,
output logic pslverr
);
// two fast and two slow registers
endmodule
| Address | Register | Wait states | Read | Write |
|---|---|---|---|---|
| 0x00 | CTRL | 0 | its value | all of PWDATA |
| 0x04 | ID | 0 | 1d1d1d1d | PSLVERR |
| 0x10 | SLOW | 2 | its value | all of PWDATA |
| 0x14 | SLOWID | 2 | 5e5e5e5e | PSLVERR |
| other | 2 from 0x10 to 0x1f, else 0 | PSLVERR | PSLVERR |
PSLVERR is valid only in the last cycle of a transfer, when PSEL, PENABLE and PREADY are all 1; outside it the requester ignores it and the specification recommends driving it low. A transfer that fails changes nothing in this block.
The result is {transfers_done[3:0], wait_cycles[5:0], error_bits[5:0], read_before_last[31:0], last_read[31:0]}: the transfers completed, the wait cycles the requester saw, one bit per transfer that ended with PSLVERR (bit i for transfer i), and the data of the last two reads that completed without an error.
Examples
Example 1
A Refused Write to ID- Input
write 0x04 = 00000001; write 0x00 = 00000077; read 0x00
- Output
transfers_done = 3, wait_cycles = 0, error_bits = 'b000001, read_before_last = 0x0, last_read = 0x77
The write to 0x04 ends with PSLVERR: error bit 0. The write of 77 to CTRL succeeds and reads back. The shipped completer shows no error bit at all.
Example 2
A Refused Write with Wait States- Input
write 0x14 = 00000001; write 0x10 = 00000055; read 0x10; read 0x14
- Output
transfers_done = 4, wait_cycles = 8, error_bits = 'b000001, read_before_last = 0x55, last_read = 0x5e5e5e5e
SLOWID is slow: two wait cycles per access, eight in all. The write to it fails (bit 0); SLOW takes 55 and SLOWID reads 5e5e5e5e.
Example 3
An Unmapped Read- Input
read 0x08; read 0x04; read 0x14
- Output
transfers_done = 3, wait_cycles = 2, error_bits = 'b000001, read_before_last = 0x1d1d1d1d, last_read = 0x5e5e5e5e
The read of 0x08 fails (bit 0); ID and SLOWID read 1d1d1d1d and 5e5e5e5e.
Constraints and Contract
- Scripts have at most six transfers and follow the protocol; read data that comes with PSLVERR is not graded.
- Keep the module name and the ports. The wait states and the register map are correct as shipped.
Hints
Hint 1
Run the first example. The write to ID should set error bit 0, and it does not. When is PSLVERR 1 in the shipped design?
Hint 2
The requester samples PSLVERR together with PREADY. Any error that is not 1 at that edge is lost.
Hint 3
Tie the error to the completion: PSLVERR = done && bad, where done is PSEL && PENABLE && PREADY.
What the grader checks: The completer runs seven directed scripts and eight seeded ones; the error bit of every transfer, the wait cycles and the last two good reads are compared with a model of the register map. Passing shows errors arrive at the completion edge of the right transfer for these scripts.
15 checks on Icarus Verilog · browser. Run the examples first, then check the full regression. The suite is local and inspectable. A passing result establishes the tested cases, not a proof for all possible inputs.
See all 1 steps and the final capstone