Interrupts

1. Controllers

The SEP integrates a VeeR EL2 core with a built-in Programmable Interrupt Controller (PIC). All maskable external interrupt sources feed a single extintsrc_req bus; the memory-mapped meipl, meie, and meigwctrl registers configure priority, enable, and gateway polarity per source.

The PIC base address is 0xC008_0000; its register layout is described in the Register Interfaces section below.

2. Sources and Routing

The vector driven to the core, sep_internal_interrupts, is indexed from 0. Bit i of that vector is PIC source i + 1. The core’s extintsrc_req port is numbered from 1, and the core ties source 0 to zero, so the low bit of the driven vector is the first programmable source. The comment directly above NUM_INTERNAL_IRQS in sep_pkg.sv numbers sources by that vector index, one less than the PIC source in SEP PIC source assignments.

2.1. SEP CPU Interrupt Vector Map

The PIC supports 255 external sources. Slots 1–43 are individually assigned to specific peripherals and subsystems connected to the SEP, including both SEP-internal blocks (crypto engines, DMA, entropy) and cross-block sources (SMC mailboxes, SPI). Slots 44–255 are reserved for chip-level external inputs passed in at the SEP block boundary.

SEP PIC source assignments lists the assigned PIC sources and the range reserved for chip-level inputs.

Table 1. SEP PIC source assignments
PIC source Source Description

1

Mailbox interrupt 0

SMC-to-SEP mailbox channel 0 interrupt

2

Mailbox interrupt 1

SMC-to-SEP mailbox channel 1 interrupt

3

Mailbox interrupt 2

SMC-to-SEP mailbox channel 2 interrupt

4

Mailbox interrupt 3

SMC-to-SEP mailbox channel 3 interrupt

5

Mailbox interrupt 4

SMC-to-SEP mailbox channel 4 interrupt

6

Mailbox interrupt 5

SMC-to-SEP mailbox channel 5 interrupt

7

Mailbox interrupt 6

SMC-to-SEP mailbox channel 6 interrupt

8

Mailbox interrupt 7

SMC-to-SEP mailbox channel 7 interrupt

9

DMA transfer done

Secure DMA full-transfer-complete interrupt

10

DMA chunk done

Secure DMA chunk-transfer-complete interrupt

11

DMA error

Secure DMA error interrupt

12

DMA alert

Secure DMA aggregated alert (fault)

13

WDT alert

Watchdog timer aggregated alert. Note: the WDT bark goes to the NMI pin, not here; see Non-PIC Interrupt Paths.

14

SPI IRQ

SPI host controller interrupt

15

KM mailbox IRQ

Key Manager-to-SEP mailbox interrupt

16

Entropy source IRQ

OpenTitan entropy source interrupt

17

External TRNG IRQ

External TRNG interrupt; driven to zero in the current OSS integration

18

HMAC done

HMAC operation complete interrupt

19

HMAC FIFO empty

HMAC message FIFO empty interrupt

20

HMAC error

HMAC error interrupt

21

KMAC done

KMAC operation complete interrupt

22

KMAC FIFO empty

KMAC message FIFO empty interrupt

23

KMAC error

KMAC error interrupt

24

CSRNG command request done

CSRNG command request complete interrupt

25

CSRNG entropy request

CSRNG entropy request interrupt

26

CSRNG HW instance exception

CSRNG hardware instance exception interrupt

27

CSRNG fatal error

CSRNG fatal error interrupt

28

EDN command request done

Entropy Distribution Network command request complete interrupt

29

EDN fatal error

Entropy Distribution Network fatal error interrupt

30

OTBN done

OpenTitan Big Number Accelerator operation complete interrupt

31

KM unrecoverable error

Key Manager unrecoverable error interrupt; also exported as a SEP output port

32

KM recoverable error

Key Manager recoverable error interrupt; also exported as a SEP output port

33

Crypto alert

Combined OpenTitan crypto alert. SEP has no alert_handler; each accelerator has its own prim_alert_receiver channel(s) with ping disabled, and those pulses plus integrity-fails share this source. See OpenTitan Alert Termination.

34

Locked field access

eFuse locked-field access violation interrupt

35

Adams Bridge error

Adams Bridge (post-quantum accelerator) error interrupt

36

Adams Bridge notification

Adams Bridge (post-quantum accelerator) operation notification interrupt

37

Entropy pool low

Entropy pool FIFO low-water condition (informational: pool draining faster than filling)

38

Entropy pool fill stall

Entropy pool FIFO fill-path stall (fault: EDN not making progress)

39

Entropy pool pointer fault

Entropy pool FIFO read/write pointer integrity fault (fault). The pool’s pointer-integrity check is not built in the current configuration, so this source is tied to zero and never asserts; the slot is assigned anyway so that enabling the check later does not renumber the map. When live it is level-sensitive and holds until a TRNG_ENTROPY_CLEAR pool scrub resets the pointers; there is no write-one-to-clear.

40

Token match fault

eFuse token comparator redundancy fault (fault). The OR of the three sticky TOKEN_MATCH_FAULT bits. Those bits are software-read-only and clear only on reset, so this source stays asserted; there is no write-one-to-clear.

41

DMA register-path bus error

A CPU access to a Secure DMA register returned a TL-UL error response (unmapped or misaligned offset). The faulting access also received SLVERR synchronously. Latched and held until firmware writes DMA_BUS_ERR_CLEAR.clr.

42

DMA host-path integrity/bus fault

Either the fabric returned a non-OKAY AXI response to a DMA transfer, or a TL-UL command-integrity check failed on a command issued by the DMA. The integrity case is a fault-detection event with no other reporting path. Cleared by the same DMA_BUS_ERR_CLEAR.clr write.

43

Peripheral register-bridge fault

The OR of the per-block register-bridge error bits for AES, HMAC, KMAC, OTBN, CSRNG, EDN and the watchdog timer. PERIPH_BUS_ERR_STATUS identifies the block, and PERIPH_BUS_ERR_CLEAR clears one block’s bit at a time, so acknowledging one cannot discard another block’s fault. See Crypto Register-Bridge Faults.

[44–255]

Reserved (external band)

Chip-level external interrupt inputs

2.2. Non-PIC Interrupt Paths

Three CPU interrupt pins bypass the EL2 PIC entirely. The core also reports its own memory errors through a path that is neither a pin nor a PIC source; see Memory ECC Errors.

2.2.1. NMI — Watchdog Timer Bark

The VeeR EL2 nmi_int pin is wired to the watchdog timer bark signal from sep_wdt_wrap. When the bark fires, the CPU jumps to the NMI vector address held in the SEP_NMI_VEC register. The SEP_NMI_VEC_LOCK register prevents runtime modification of the vector once locked.

The NMI is non-maskable: it cannot be suppressed by mstatus.MIE or any PIC configuration register.

2.2.2. Timer and Software Interrupts

The timer_int and soft_int pins of the VeeR EL2 core are tied to zero at the SMU integration boundary. There is no external CLINT-style delivery path. The external pins drive mip.MTIP and mip.MSIP, respectively, so these pending bits remain inactive in this integration.

The two internal timers instead report mip.MITIP0 (bit 29) and mip.MITIP1 (bit 28). Enable them through mie.MITIE0 and mie.MITIE1 at the corresponding bit positions, together with mstatus.MIE. Their interrupt cause codes are 0x1D and 0x1C, respectively (with the interrupt bit set in mcause). Enabling mie.MTIE or mie.MSIE does not enable the internal timers.

2.2.3. Memory ECC Errors

The ICCM and DCCM are SECDED-protected. Neither reaches the PIC: the core reports these errors itself, correctable ones as a local interrupt and uncorrectable ones as a synchronous trap. No PIC register affects either, and there is no PIC source to enable or mask.

The SEP core is configured without an I-cache, so the I-cache parity counter MICECT (0x7F0) never increments. Only the two tightly-coupled-memory counters below are live.

Correctable (single-bit) errors

Hardware corrects the data and the access is retried, so no data is lost and no trap is taken. Each protected memory has a counter CSR (SEP correctable-error counters).

Table 2. SEP correctable-error counters
CSR Address Counts

MICCMECT

0x7F1

ICCM single-bit corrections

MDCCMECT

0x7F2

DCCM single-bit corrections

Bits [26:0] are the running count. Bits [31:27] hold a threshold exponent: the counter raises a request once the count reaches 2threshold. A written threshold above 26 is clamped to 26. The requests from both counters are ORed into mip[30] (MCEIP) and delivered when mie[30] (MCEIE) and mstatus.MIE are both set, with mcause = 0x8000_001E.

Counters and thresholds reset to zero, so a zero threshold raises the request on the first corrected error. mie[30] is clear at reset, and until it is set corrected errors are counted silently. MCEIP follows the threshold comparator and has no write-one-to-clear: it stays asserted until the count drops below the threshold. The memory error handling section of the Programmer’s Guide gives the enable and service sequence.

Uncorrectable (double-bit) errors

These cannot be masked and have no enable bit. The access returned no valid data, so the core traps on the instruction that hit the error (SEP uncorrectable-error traps).

Table 3. SEP uncorrectable-error traps
Access mcause Trap

Instruction fetch from ICCM

0x0000_0001

Instruction access fault

Load from DCCM

0x0000_0005

Load access fault

Store to DCCM

0x0000_0007

Store access fault

DCCM access on the fast-interrupt path

0xF000_1000

NMI, taken through SEP_NMI_VEC like the watchdog bark

mcause alone does not identify these as memory failures — a bad pointer and a failing SRAM both raise a load access fault. mscause (0x7FF) is what separates them: on an access fault, mscause = 1 means uncorrectable ECC. A handler that does not read mscause cannot distinguish a software bug from failing hardware.

The faulting access cannot be completed, and retrying it re-reads the same corrupted location.

An uncorrectable error on an externally initiated (DMA) access to either memory is not a CPU trap at all. It is returned as an error response on that transaction, and the initiator is responsible for reporting it.

Debug bus mirror

The ICCM and DCCM single- and double-bit error signals are also mirrored onto ext_debug_bus_o[367:364], most significant first: ICCM single, ICCM double, DCCM single, DCCM double. These are single-cycle pulses with no latch and no handshake, provided for external trace and bring-up observability. They are not a delivery path, so software must not rely on sampling them; use the CSRs above.

3. Software Handling

Interrupt source IDs are 1-based inside the PIC. Source 0 is permanently tied to zero inside the core. Firmware programs source N through the per-source arrays, each indexed at an offset of N * 4 from its region base: meipl at PIC base +0x0000, meie at +0x2000, meigwctrl at +0x4000 and meigwclr at +0x5000. Pending status is the exception — meip at +0x1000 is a bitmap rather than a per-source array, so source N is bit N % 32 of meip[N / 32].

Each per-source array carries an entry 0, so that the array index is the source ID and no off-by-one applies: meipl[7] is source 7. That entry is reserved and has no hardware behind it — the PIC decodes the address but ties the register off, so +0x0000, +0x2000, +0x4000 and +0x5000 read as zero and discard writes. It appears in the RDL, the generated headers and the UVM RAL only to preserve the indexing. The PIC section of the Programmer’s Guide gives the programming and per-source service rules.

Register tests that walk the whole PIC map must skip index 0 of meipl, meie, meigwctrl and meigwclr. The register model declares those entries read-write like every other element, but the hardware treats them as reserved, so a read-write check on them fails.

4. Memory Map and Register Reference

4.1. Memory Map

The EL2 PIC register block (meipl, meie, meigwctrl, meigwclr, and related registers) is documented in the register reference below.

The per-source arrays in that table are listed from index 0. Index 0 is the reserved entry described in Interrupts: it exists so the array index equals the interrupt source ID, and the first programmable source is index 1.

4.2. Detailed Register Map

EL2_PIC

VeeR EL2 Programmable Interrupt Controller (PIC) memory-mapped registers.
Supports up to PIC_TOTAL_INT external interrupt sources with 15 priority levels.

Register Arrays:

  • meipl[256]: 256 registers, base 0x0, stride 0x4
  • meip[8]: 8 registers, base 0x1000, stride 0x4
  • meie[256]: 256 registers, base 0x2000, stride 0x4
  • meigwctrl[256]: 256 registers, base 0x4000, stride 0x4
  • meigwclr[256]: 256 registers, base 0x5000, stride 0x4

Register List:

AddressNameAccessDescription
0x0 - 0x3FCmeipl[256]RWExternal Interrupt Priority Level Register. Sets the priority level for an interrupt source.
0x1000 - 0x101Cmeip[8]RExternal Interrupt Pending Register. Reports pending status of up to 32 interrupt sources.
0x2000 - 0x23FCmeie[256]RWExternal Interrupt Enable Register. Controls interrupt enable for a single source.
0x3000mpiccfgRWPIC Configuration Register. Used to select the operational parameters of the PIC.
0x4000 - 0x43FCmeigwctrl[256]RWExternal Interrupt Gateway Configuration Register. Controls interrupt type and polarity.
0x5000 - 0x53FCmeigwclr[256]WExternal Interrupt Gateway Clear Register. Writing any value clears the gateway's
interrupt pending (IP) bit for edge-triggered interrupts.

Register Details:

meipl[256]

BitsFieldAccessResetDescription
31:4Reserved--Reserved
3:0intpriorityRW0x0External interrupt priority level:
RISC-V standard order: 0=Never interrupt, 1..15=Priority (1 lowest, 15 highest)
Reverse order: 15=Never interrupt, 14..0=Priority (14 lowest, 0 highest)

meip[8]

BitsFieldAccessResetDescription
31:0intpendR0x0External interrupt pending bits. Bit Y indicates pending status for source X*32+Y.
0: Interrupt not pending
1: Interrupt pending

meie[256]

BitsFieldAccessResetDescription
31:1Reserved--Reserved
0intenRW0x0External interrupt enable:
0: Interrupt disabled
1: Interrupt enabled

mpiccfg

BitsFieldAccessResetDescription
31:1Reserved--Reserved
0priordRW0x0Priority order:
0: RISC-V standard compliant priority order (0=lowest to 15=highest)
1: Reverse priority order (15=lowest to 0=highest)

meigwctrl[256]

BitsFieldAccessResetDescription
31:2Reserved--Reserved
1irq_typeRW0x0External interrupt type:
0: Level-triggered interrupt
1: Edge-triggered interrupt
0polarityRW0x0External interrupt polarity:
0: Active-high interrupt
1: Active-low interrupt

meigwclr[256]

BitsFieldAccessResetDescription
31:1Reserved--Reserved
0clearW0x0Write any value to clear the interrupt pending bit in the gateway.
This register is write-only; reads return 0.