<<<
:sectnums:
==== External Interrupt Controller (XIRQ)

[cols="<3,<3,<4"]
[frame="topbot",grid="none"]
|=======================
| Hardware source files:  | neorv32_xirq.vhd   |
| Software driver files:  | neorv32_xirq.c     |
|                         | neorv32_xirq.h     |
| Top entity ports:       | `xirq_i`           | External interrupts input (32-bit)
| Configuration generics: | `XIRQ_NUM_CH`      | Number of external IRQ channels to implement (0..32)
| CPU interrupts:         | fast IRQ channel 8 | XIRQ (see <<_processor_interrupts>>)
| Access restrictions:  2+| privileged access only, non-32-bit write accesses are ignored
|=======================


**Overview**

The external interrupt controller provides a simple mechanism to implement up to 32 platform-level / processor-external
interrupt request signals. The external IRQ requests are prioritized, queued and signaled to the CPU via a
_single_ CPU fast interrupt request channel.


**Theory of Operation**

The XIRQ provides up to 32 external interrupt channels configured via the `XIRQ_NUM_CH` generic. Each bit in the
`xirq_i` input signal vector represents one interrupt channel. If less than 32 channels are configured, only the
LSB-aligned channels are used while the remaining ones are left unconnected internally.

The external interrupt controller features four interface registers:

[start=1]
. external interrupt channel enable (`EIE`)
. external interrupt source (`ESC`)
. trigger type configuration (`TTYP`)
. trigger polarity configuration (`TPOL`)

The actual interrupt trigger type can be configured individually for each channel using the `TTYP` and `TPOL`
registers. `TTYP` defines the actual trigger type (level-triggered or edge-triggered), while `TPOL` defines
the trigger's polarity (low-level/falling-edge or high-level/rising-edge). The position of each bit in these
registers corresponds the according XIRQ channel.

.XIRQ Trigger Configuration
[cols="^2,^2,<3"]
[options="header",grid="all"]
|=======================
| `TTYP(i)` | `TPOL(i)` | Resulting trigger of `xirq_i(i)`
| `0`       | `0`       | low-level
| `0`       | `1`       | high-level
| `1`       | `0`       | falling-edge
| `1`       | `1`       | rising-edge
|=======================

Each interrupt channel can be enabled or disabled individually using the `EIE` register. If the trigger of a
disabled channel fires the interrupt request is entirely ignored.

If the configured trigger of an _enabled_ channels fires, the according interrupt request is buffered internally
and an interrupt request is sent to the CPU. If more than one trigger fires at one a prioritization is used:
the channels are prioritized in a static order, i.e. channel 0 (`xirq_i(0)`) has the highest priority and channel
31 (`xirq_i(31)`) has the lowest priority.

The CPU can determine the most prioritized external interrupt request by reading the interrupt source register `ESC`.
This register provides a 5-bit wide ID (0..31) identifying the currently firing external interrupt source channel as
well as a single bit (the MSB) that
Writing _any_ value to this register will acknowledge and clear the _current_ CPU interrupt (so the XIRQ controller
can issue a new CPU interrupt).


**Register Map**

.XIRQ register map (`struct NEORV32_XIRQ`)
[cols="^4,<2,^2,^2,<14"]
[options="header",grid="all"]
|=======================
| Address | Name [C] | Bit(s) | R/W | Description
| `0xfffff300` | `EIE`  | `31:0` | r/w | External interrupt enable register (one bit per channel, LSB-aligned)
.3+^| `0xfffff304` .3+<| `ESC` ^| `31`   ^| r/c <| XIRQ interrupt when set; write any value to this register to acknowledge the current XIRQ interrupt
                               ^| `30:5` ^| r/- <| _reserved_, read as zero
                               ^| `4:0`  ^| r/c <| Interrupt source ID (0..31) of firing IRQ (prioritized!)
| `0xfffff308` | `TTYP` | `31:0` | r/w | Trigger type select (`0` = level trigger, `1` = edge trigger); each bit corresponds to the according channel number
| `0xfffff30c` | `TPOL` | `31:0` | r/w | Trigger polarity select (`0` = low-level/falling-edge, `1` = high-level/rising-edge); each bit corresponds to the according channel number
|=======================
