Line 19... |
Line 19... |
request signals. The external IRQ requests are prioritized, queued and signaled to the CPU via a
|
request signals. The external IRQ requests are prioritized, queued and signaled to the CPU via a
|
single _CPU fast interrupt request_.
|
single _CPU fast interrupt request_.
|
|
|
**Theory of Operation**
|
**Theory of Operation**
|
|
|
The XIRQ provides up to 32 interrupt _channels_ (configured via the _XIRQ_NUM_CH_ generic). Each bit in `xirq_i`
|
The XIRQ provides up to 32 interrupt _channels_ (configured via the _XIRQ_NUM_CH_ generic). Each bit in the `xirq_i`
|
represents one interrupt channel. An interrupt channel is enabled by setting the according bit in the
|
input signal vector represents one interrupt channel. An interrupt channel is enabled by setting the according bit in the
|
interrupt enable register _XIRQ_IER_.
|
interrupt enable register `IER`.
|
|
|
If the configured trigger (see below) of an enabled channel fires, the request is stored into an internal buffer.
|
If the configured trigger (see below) of an enabled channel fires, the request is stored into an internal buffer.
|
This buffer is available via the interrupt pending register _XIRQ_IPR_. A `1` in this register indicates that the
|
This buffer is available via the interrupt pending register `IPR`. A `1` in this register indicates that the
|
corresponding interrupt channel has fired but has not yet been serviced (so it is pending). Pending IRQs can be
|
corresponding interrupt channel has fired but has not yet been serviced (so it is pending). An interrupt channel can
|
cleared by writing `1` to the according pending bit. As soon as there is a least one pending interrupt in the
|
become pending if the according `IER` bit is set. Pending IRQs can be cleared by writing `0` to the according `IPR`
|
buffer, an interrupt request is send to the CPU.
|
bit. As soon as there is a least one pending interrupt in the buffer, an interrupt request is send to the CPU.
|
|
|
The CPU can determine firing interrupt request either by checking the bits in the _XIRQ_IPR_ register, which show all
|
[NOTE]
|
pending interrupt and does not prioritize, or by reading the interrupt source _XIRQ_SCR_ register.
|
A disabled interrupt channel can still be pending if it has been triggered before clearing the according `IER` bit.
|
|
|
|
The CPU can determine firing interrupt request either by checking the bits in the `IPR` register, which show all
|
|
pending interrupt channels, or by reading the interrupt source register `SCR`.
|
This register provides a 5-bit wide ID (0..31) that shows the interrupt request with _highest priority_.
|
This register provides a 5-bit wide ID (0..31) that shows the interrupt request with _highest priority_.
|
Interrupt channel `xirq_i(0)` has highest priority and `xirq_i(_XIRQ_NUM_CH_-1)` has lowest priority.
|
Interrupt channel `xirq_i(0)` has highest priority and `xirq_i(_XIRQ_NUM_CH_-1)` has lowest priority.
|
This priority assignment is fixed and cannot be altered by software.
|
This priority assignment is fixed and cannot be altered by software.
|
The CPU can use the ID from _XIRQ_SCR_ to service IRQ according to their priority. To acknowledge the according
|
The CPU can use the ID from `SCR` to service IRQ according to their priority. To acknowledge the according
|
interrupt the CPU can write `1 << XIRQ_SCR` to _XIRQ_IPR_.
|
interrupt the CPU can write `1 << SCR` to `IPR`.
|
|
|
|
In order to acknowledge the interrupt from the external interrupt controller, the CPU has to write _any_
|
|
value to interrupt source register `SRC`.
|
|
|
|
[NOTE]
|
|
An interrupt handler should clear the interrupt pending bit that caused the interrupt first before
|
|
acknowledging the interrupt by writing the `SCR` register.
|
|
|
**IRQ Trigger Configuration**
|
**IRQ Trigger Configuration**
|
|
|
The controller does not provide a configuration option to define the IRQ triggers _during runtime_. Instead, two
|
The controller does not provide a configuration option to define the IRQ triggers _during runtime_. Instead, two
|
generics are provided to configure the trigger of each interrupt channel before synthesis: the _XIRQ_TRIGGER_TYPE_
|
generics are provided to configure the trigger of each interrupt channel before synthesis: the _XIRQ_TRIGGER_TYPE_
|
and _XIRQ_TRIGGER_POLARITY_ generic. Both generics are 32 bit wide representing one bit per interrupt channel. If
|
and _XIRQ_TRIGGER_POLARITY_ generic. Both generics are 32 bit wide representing one bit per interrupt channel. If
|
less than 32 interrupt channels are implemented the remaining configuration bits are ignored.
|
less than 32 interrupt channels are implemented the remaining configuration bits are ignored.
|
|
|
_XIRQ_TRIGGER_TYPE_ is used to define the general trigger type. This can either be _level-triggered_ (`0`) or
|
_XIRQ_TRIGGER_TYPE_ is used to define the general trigger type. This can be either _level-triggered_ (`0`) or
|
_edge-triggered_ (`1`). _XIRQ_TRIGGER_POLARITY_ is used to configure the polarity of the trigger: a `0` defines
|
_edge-triggered_ (`1`). _XIRQ_TRIGGER_POLARITY_ is used to configure the polarity of the trigger: a `0` defines
|
low-level or falling-edge and a `1` defines high-level or a rising-edge.
|
low-level or falling-edge and a `1` defines high-level or rising-edge.
|
|
|
.Example trigger configuration: channel 0 for rising-edge, IRQ channels 1 to 31 for high-level
|
.Example trigger configuration: channel 0 for rising-edge, IRQ channels 1 to 31 for high-level
|
[source, vhdl]
|
[source, vhdl]
|
----
|
----
|
XIRQ_TRIGGER_TYPE => x"00000001";
|
XIRQ_TRIGGER_TYPE => x"00000001";
|
XIRQ_TRIGGER_POLARITY => x"ffffffff";
|
XIRQ_TRIGGER_POLARITY => x"ffffffff";
|
----
|
----
|
|
|
.XIRQ register map
|
.XIRQ register map (`struct NEORV32_XIRQ`)
|
[cols="^4,<5,^2,^2,<14"]
|
[cols="^4,<5,^2,^2,<14"]
|
[options="header",grid="all"]
|
[options="header",grid="all"]
|
|=======================
|
|=======================
|
| Address | Name [C] | Bit(s) | R/W | Function
|
| Address | Name [C] | Bit(s) | R/W | Function
|
| `0xffffff80` | _XIRQ_IER_ | `31:0` | r/w | Interrupt enable register (one bit per channel, LSB-aligned)
|
| `0xffffff80` | `NEORV32_XIRQ.IER` | `31:0` | r/w | Interrupt enable register (one bit per channel, LSB-aligned)
|
| `0xffffff84` | _XIRQ_IPR_ | `31:0` | r/w | Interrupt pending register (one bit per channel, LSB-aligned); writing 1 to a bit clears according interrupt; writing _any_ value acknowledges the _current_ CPU interrupt
|
| `0xffffff84` | `NEORV32_XIRQ.IPR` | `31:0` | r/w | Interrupt pending register (one bit per channel, LSB-aligned); writing 0 to a bit clears according pending interrupt
|
| `0xffffff88` | _XIRQ_SCR_ | `4:0` | r/- | Channel id (0..31) of firing IRQ (prioritized!)
|
| `0xffffff88` | `NEORV32_XIRQ.SCR` | `4:0` | r/w | Channel id (0..31) of firing IRQ (prioritized!); writing _any_ value will acknowledge the current interrupt
|
| `0xffffff8c` | - | `31:0` | r/- | _reserved_, read as zero
|
| `0xffffff8c` | - | `31:0` | r/- | _reserved_, read as zero
|
|=======================
|
|=======================
|