The APB5 parity scheme for safety-critical SoCs — how odd parity protects every signal group, the Check_Type property, all 14 check signals with their exact coverage and enable conditions, error detection behaviour, and RTL implementation patterns.
Safety-critical applications (automotive ISO 26262, industrial IEC 61508, avionics DO-254) require the ability to detect faults on every signal path in the system. A single bit flip on a wire — caused by an alpha particle, EMI, or a manufacturing defect — must be detectable before it causes a silent data corruption or a control hazard.
Error Detection and Correction (EDC) is applied end-to-end through a system, but between components the simplest approach is parity: one or more check bits that allow the receiver to detect (though not correct) single-bit errors on the associated payload signals.
APB5 (Issue D, 2021) added a complete parity scheme covering every signal on the APB interface — from the address and data buses down to individual control signals like PSEL and PENABLE. This allows safety-critical SoC designs to use APB peripherals in Safety Integrity Level (SIL) qualified designs.
The presence and type of parity protection is controlled by the Check_Type interface property. This property is declared on the APB interface definition and determines which check signals are present.
| Check_Type value | Meaning | Check signals present? |
|---|---|---|
False |
No checking signals on the interface. Standard APB without parity. Default if Check_Type is not declared. | No |
Odd_Parity_Byte_All |
Odd parity checking is included for all signals. Each parity bit covers up to 8 payload bits. | Yes — all applicable check signals present |
When Check_Type = Odd_Parity_Byte_All, every signal group on the interface gets a corresponding check signal. The check signals are synchronous to PCLK and must be driven correctly every cycle in which their Check Enable condition is true.
Odd parity means that the total number of 1s across the payload bits AND the check bit is always odd. The check bit is chosen to make the count odd:
For a single-bit payload (e.g. PWRITE=1), odd parity gives check bit = 0 (since 1 is already odd). For PWRITE=0, check bit = 1. This means the single-bit check is simply the inversion of the signal it protects.
Check signals are not required to be driven correctly at all times — only when their associated payload signals are required to be valid. The Check Enable condition defines exactly when a check signal must carry a correct parity value. Outside this window the check signal may take any value (though driving it correctly at all times is recommended).
The Check Enable conditions directly mirror the signal validity rules (Appendix A of the spec):
| Check Enable condition | What it means | Check signals with this enable |
|---|---|---|
PRESETn |
Always valid after reset — these signals must always carry correct parity once the interface is out of reset | PSELxCHK, PWAKEUPCHK |
PSEL |
Valid when a transfer is in progress (Setup or Access phase) | PADDRCHK, PCTRLCHK, PENABLECHK, PAUSERCHK, PSTRBCHK |
PSEL & PWRITE |
Valid during write transfers in progress | PWDATACHK, PWUSERCHK |
PSEL & PENABLE |
Valid during the Access phase (PENABLE=1) | PREADYCHK |
PSEL & PENABLE & PREADY |
Valid only at transfer completion | PSLVERRCHK, PBUSERCHK |
PSEL & PENABLE & PREADY & !PWRITE |
Valid only at read transfer completion | PRDATACHK, PRUSERCHK |
Complete reference table for all APB5 parity check signals as defined in Table 5-1 of ARM IHI 0024E:
| Check signal | Payload covered | Width | Bits per check bit | Check Enable condition | Source |
|---|---|---|---|---|---|
PADDRCHK | PADDR | ⌈ADDR_WIDTH/8⌉ | 1–8 | PSEL | Requester |
PCTRLCHK | PPROT, PWRITE, PNSE | 1 | 1–5 | PSEL | Requester |
PSELxCHK | PSELx | 1 (per PSELx) | 1 | PRESETn | Requester |
PENABLECHK | PENABLE | 1 | 1 | PSEL | Requester |
PWDATACHK | PWDATA | DATA_WIDTH/8 | 8 | PSEL & PWRITE | Requester |
PSTRBCHK | PSTRB | 1 | 1–4 | PSEL & PWRITE | Requester |
PREADYCHK | PREADY | 1 | 1 | PSEL & PENABLE | Completer |
PRDATACHK | PRDATA | DATA_WIDTH/8 | 8 | PSEL & PENABLE & PREADY & !PWRITE | Completer |
PSLVERRCHK | PSLVERR | 1 | 1 | PSEL & PENABLE & PREADY | Completer |
PWAKEUPCHK | PWAKEUP | 1 | 1 | PRESETn | Requester |
PAUSERCHK | PAUSER | ⌈USER_REQ_WIDTH/8⌉ | 1–8 | PSEL | Requester |
PWUSERCHK | PWUSER | ⌈USER_DATA_WIDTH/8⌉ | 1–8 | PSEL & PWRITE | Requester |
PRUSERCHK | PRUSER | ⌈USER_DATA_WIDTH/8⌉ | 1–8 | PSEL & PENABLE & PREADY & !PWRITE | Completer |
PBUSERCHK | PBUSER | ⌈USER_RESP_WIDTH/8⌉ | 1–8 | PSEL & PENABLE & PREADY | Completer |
PCTRLCHK is the most interesting check signal because it covers multiple payload signals under a single check bit: PPROT[2:0], PWRITE, and PNSE — up to 5 bits total.
The spec states: “Parity signals that cover critical control signals are defined with a single parity bit. The single odd parity bit is the inversion of the original critical control signal.”
For PCTRLCHK covering 5 bits:
PCTRLCHK = ~(PPROT[2] ^ PPROT[1] ^ PPROT[0] ^ PWRITE ^ PNSE)
If PNSE is not present (RME_Support=False), it is treated as 0:
PCTRLCHK = ~(PPROT[2] ^ PPROT[1] ^ PPROT[0] ^ PWRITE)
If PPROT is also absent (APB4 interface), PCTRLCHK just covers PWRITE alone:
PCTRLCHK = ~PWRITE
The reason critical control signals are grouped under one check bit rather than getting individual check bits: critical control signals often have tighter timing constraints than data signals, and a single XOR tree with a small number of inputs (≤5 for PCTRLCHK) is much faster than a byte-wide tree with 8 inputs.
Check signals accompany their payload signals with exactly one clock cycle delay in a registered implementation (parity registered from a flop), or in the same cycle in a combinational implementation. The spec does not require a specific implementation — only that the check signals are correct during their Check Enable window.
The spec deliberately leaves error detection behaviour undefined at the system level: “This specification is not prescriptive regarding component or system behavior when a parity error is detected.” The rationale is that the appropriate response depends on the system safety architecture and the specific signal affected.
When a parity error is detected, the Completer can choose any of the following responses:
// Odd parity: check bit = ~(XOR of all payload bits in group)
assign PADDRCHK[0] = ~(^PADDR[7:0]);
assign PADDRCHK[1] = ~(^PADDR[15:8]);
assign PADDRCHK[2] = ~(^PADDR[23:16]);
assign PADDRCHK[3] = ~(^PADDR[31:24]);
// Covers PPROT[2:0], PWRITE, and PNSE (if present)
// If PNSE absent, treat as 0
assign PCTRLCHK = ~(PPROT[2] ^ PPROT[1] ^ PPROT[0] ^ PWRITE ^ PNSE);
// Single-bit inversion — must be correct at all times after reset
assign PSELxCHK = ~PSELx;
// Check: XOR of payload + check bit must be 1 (odd parity)
// If result is 0, even parity = error detected
wire paddr_err_b0 = ~(^{PADDR[7:0], PADDRCHK[0]});
wire paddr_err_b1 = ~(^{PADDR[15:8], PADDRCHK[1]});
wire paddr_err_b2 = ~(^{PADDR[23:16], PADDRCHK[2]});
wire paddr_err_b3 = ~(^{PADDR[31:24], PADDRCHK[3]});
wire paddr_parity_error = PSELx & (paddr_err_b0 | paddr_err_b1 |
paddr_err_b2 | paddr_err_b3);
The check enable condition (PSELx for PADDRCHK) gates the error flag — outside the Check Enable window the parity may be incorrect and the error flag must not fire.
// Register the parity output for better timing (adds 1 cycle pipeline)
always_ff @(posedge PCLK) begin
PADDRCHK <= {~(^PADDR[31:24]),~(^PADDR[23:16]),
~(^PADDR[15:8]),~(^PADDR[7:0])};
end
// Receiver must account for 1-cycle pipeline when checking
| Item | Rule |
|---|---|
| Parity introduced in | APB5 Issue D (2021) — not available in APB4 or earlier |
| Check_Type property | False (default, no parity) or Odd_Parity_Byte_All (full parity) |
| Parity type | Odd parity — always odd number of 1s across payload + check bit |
| Max bits per check bit | 8 — each check bit covers at most 8 payload bits |
| Check formula | CHK_bit = ~(^payload_bits) for odd parity |
| Verify formula | ^{payload, CHK} == 1 means no error; 0 means error detected |
| Total check signals | 14 (PADDRCHK, PCTRLCHK, PSELxCHK, PENABLECHK, PWDATACHK, PSTRBCHK, PREADYCHK, PRDATACHK, PSLVERRCHK, PWAKEUPCHK, PAUSERCHK, PWUSERCHK, PRUSERCHK, PBUSERCHK) |
| PCTRLCHK covers | PPROT[2:0] + PWRITE + PNSE — up to 5 bits under 1 check bit |
| PSELxCHK enable | PRESETn — must be correct at all times after reset (not just during transfers) |
| PADDRCHK enable | PSEL |
| PWDATACHK enable | PSEL & PWRITE |
| PREADYCHK enable | PSEL & PENABLE |
| PRDATACHK enable | PSEL & PENABLE & PREADY & !PWRITE |
| PSLVERRCHK enable | PSEL & PENABLE & PREADY |
| Absent payload → absent CHK | If a payload signal is absent, its check signal is also absent |
| Missing payload treated as | 0 (LOW) in parity calculation for grouped check signals |
| Error response | Not specified by APB spec — system/component dependent. Options: PSLVERR, interrupt, propagate, correct. |
| Registered vs combinational | Both are permitted. Registered parity adds 1 pipeline cycle but eases timing closure. |
| Check signals required at | Every cycle in which the Check Enable condition is TRUE |