P3.4.1 The Error on the Wrong Cycle

EasyFixIcarus Verilog · browserReview the topic

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

SignalWidthRole
n8input of each check
script_first144input of each check
script_last144input of each check
Full specification
The completer (keep the ports)
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
AddressRegisterWait statesReadWrite
0x00CTRL0its valueall of PWDATA
0x04ID01d1d1d1dPSLVERR
0x10SLOW2its valueall of PWDATA
0x14SLOWID25e5e5e5ePSLVERR
other2 from 0x10 to 0x1f, else 0PSLVERRPSLVERR

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
Your code SystemVerilogSaved locally
Ln 1, Col 1Tab indents · Ctrl/⌘ + Enter runs samples
Not run yet

A Refused Write to ID

Input
write 0x04 = 00000001; write 0x00 = 00000077; read 0x00
Expected 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.

Run samples executes all 3 example checks. Check all tests runs 15 checks.

Icarus Verilog · browser