212 lines
13 KiB
Plaintext
212 lines
13 KiB
Plaintext
<<<
|
|
:sectnums:
|
|
==== Execute In Place Module (XIP)
|
|
|
|
[cols="<3,<3,<4"]
|
|
[frame="topbot",grid="none"]
|
|
|=======================
|
|
| Hardware source file(s): | neorv32_xip.vhd |
|
|
| Software driver file(s): | neorv32_xip.c |
|
|
| | neorv32_xip.h |
|
|
| Top entity port: | `xip_csn_o` | 1-bit chip select, low-active
|
|
| | `xip_clk_o` | 1-bit serial clock output
|
|
| | `xip_dat_i` | 1-bit serial data input
|
|
| | `xip_dat_o` | 1-bit serial data output
|
|
| Configuration generics: | `XIP_EN` | implement XIP module when `true`
|
|
| | `XIP_CACHE_EN` | implement XIP cache when `true`
|
|
| | `XIP_CACHE_NUM_BLOCKS` | number of blocks in XIP cache; has to be a power of two
|
|
| | `XIP_CACHE_BLOCK_SIZE` | number of bytes per XIP cache block; has to be a power of two, min 4
|
|
| CPU interrupts: | none |
|
|
|=======================
|
|
|
|
|
|
**Overview**
|
|
|
|
The execute in-place (XIP) module allows to execute code (and read constant data) directly from an external SPI flash memory.
|
|
The standard serial peripheral interface (SPI) is used as transfer protocol. All bus requests issued by the CPU
|
|
are converted transparently into SPI flash access commands. Hence, the external XIP flash behaves like a simple on-chip ROM.
|
|
|
|
From the CPU side, the modules provides two independent interfaces: one for transparently accessing the XIP flash and another
|
|
one for accessing the module's control and status registers. The first interface provides the _transparent_
|
|
gateway to the SPI flash, so the CPU can directly fetch and execute instructions and/or read constant data.
|
|
Note that this interface is read-only. Any write access will raise a bus error exception. The second interface is
|
|
mapped to the processor's IO space and allows accesses to the XIP module's configuration registers as well as
|
|
conducting individual SPI transfers.
|
|
|
|
The XIP module provides an optional configurable cache to accelerate SPI flash accesses.
|
|
|
|
.XIP Address Mapping
|
|
[NOTE]
|
|
When XIP mode is enabled the flash is mapped to fixed address space region starting at address
|
|
`0xE0000000` (see section <<_address_space>>) supporting a maximum flash size of 256MB.
|
|
|
|
.XIP Example Program
|
|
[TIP]
|
|
An example program is provided in `sw/example/demo_xip` that illustrate how to program and configure
|
|
an external SPI flash to run a program from it.
|
|
|
|
|
|
**SPI Configuration**
|
|
|
|
The XIP module accesses external flash using the standard SPI protocol. The module always sends data MSB-first and
|
|
provides all of the standard four clock modes (0..3), which are configured via the `XIP_CTRL_CPOL` (clock polarity)
|
|
and `XIP_CTRL_CPHA` (clock phase) control register bits, respectively. The flash's "read command", which initiates
|
|
a read access, is defined by the `XIP_CTRL_RD_CMD` control register bits. For most SPI flash memories this is `0x03`
|
|
for _normal_ SPI mode.
|
|
|
|
The SPI clock (`xip_clk_o`) frequency is programmed by the 3-bit `XIP_CTRL_PRSCx` clock prescaler for a coarse clock
|
|
selection and a 4-bit clock divider `XPI_CTRL_CDIVx` for a fine clock selection.
|
|
The following clock prescalers (`XIP_CTRL_PRSCx`) are available:
|
|
|
|
.XIP clock prescaler configuration
|
|
[cols="<4,^1,^1,^1,^1,^1,^1,^1,^1"]
|
|
[options="header",grid="rows"]
|
|
|=======================
|
|
| **`XIP_CTRL_PRSCx`** | `0b000` | `0b001` | `0b010` | `0b011` | `0b100` | `0b101` | `0b110` | `0b111`
|
|
| Resulting `clock_prescaler` | 2 | 4 | 8 | 64 | 128 | 1024 | 2048 | 4096
|
|
|=======================
|
|
|
|
Based on the programmed clock configuration, the actual SPI clock frequency f~SPI~ is derived
|
|
from the processor's main clock f~main~ according to the following equation:
|
|
|
|
_**f~SPI~**_ = _f~main~[Hz]_ / (2 * `clock_prescaler` * (1 + `XPI_CTRL_CDIVx`))
|
|
|
|
Hence, the maximum SPI clock is f~main~ / 4 and the lowest SPI clock is f~main~ / 131072. The SPI clock is always
|
|
symmetric having a duty cycle of 50%.
|
|
|
|
|
|
**High-Speed Mode**
|
|
|
|
The XIP module provides a high-speed mode to further boost the maximum SPI clock frequency. When enabled via the control
|
|
register's `XIP_CTRL_HIGHSPEED` bit the clock prescaler configuration (`XIP_CTRL_PRSCx` bits) is overridden setting it
|
|
to a minimal factor of 1. However, the clock speed can still be fine-tuned using the `XPI_CTRL_CDIVx` bits.
|
|
|
|
_**f~SPI~**_ = _f~main~[Hz]_ / (2 * 1 * (1 + `XPI_CTRL_CDIVx`))
|
|
|
|
Hence, the maximum SPI clock when in high-speed mode is f~main~ / 2.
|
|
|
|
|
|
**Direct SPI Access**
|
|
|
|
The XIP module allows to initiate _direct_ SPI transactions. This feature can be used to configure the attached SPI
|
|
flash or to perform direct read and write accesses to the flash memory. Two data registers `DATA_LO` and
|
|
`DATA_HI` are provided to send up to 64-bit of SPI data. The `DATA_HI` register is write-only,
|
|
so a total of just 32-bits of receive data is provided. Note that the module handles the chip-select
|
|
line (`xip_csn_o`) by itself so it is not possible to construct larger consecutive transfers.
|
|
|
|
The actual data transmission size in bytes is defined by the control register's `XIP_CTRL_SPI_NBYTES` bits.
|
|
Any configuration from 1 byte to 8 bytes is valid. Other value will result in unpredictable behavior.
|
|
|
|
Since data is always transferred MSB-first, the data in `DATA_HI:DATA_LO` also has to be MSB-aligned. Receive data is
|
|
available in `DATA_LO` only since `DATA_HI` is write-only. Writing to `DATA_HI` triggers the actual SPI transmission.
|
|
The `XIP_CTRL_PHY_BUSY` control register flag indicates a transmission being in progress.
|
|
|
|
The chip-select line of the XIP module (`xip_csn_o`) will only become asserted (enabled, pulled low) if the
|
|
`XIP_CTRL_SPI_CSEN` control register bit is set. If this bit is cleared, `xip_csn_o` is always disabled
|
|
(pulled high).
|
|
|
|
[NOTE]
|
|
Direct SPI mode is only possible when the module is enabled (setting `XIP_CTRL_EN`) but **before** the actual
|
|
XIP mode is enabled via `XIP_CTRL_XIP_EN`.
|
|
|
|
[TIP]
|
|
When the XIP mode is not enabled, the XIP module can also be used as additional general purpose SPI controller
|
|
with a transfer size of up to 64 bits per transmission.
|
|
|
|
|
|
**Using the XIP Mode**
|
|
|
|
The XIP module is globally enabled by setting the `XIP_CTRL_EN` bit in the device's `CTRL` control register.
|
|
Clearing this bit will reset the whole module and will also terminate any pending SPI transfer.
|
|
|
|
Since there is a wide variety of SPI flash components with different sizes, the XIP module allows to specify
|
|
the address width of the flash: the number of address bytes used for addressing flash memory content has to be
|
|
configured using the control register's _XIP_CTRL_XIP_ABYTES_ bits. These two bits contain the number of SPI
|
|
address bytes (**minus one**). For example for a SPI flash with 24-bit addresses these bits have to be set to
|
|
`0b10`.
|
|
|
|
The transparent XIP accesses are transformed into SPI transmissions with the following format (starting with the MSB):
|
|
|
|
* 8-bit command: configured by the `XIP_CTRL_RD_CMD` control register bits ("SPI read command")
|
|
* 8 to 32 bits address: defined by the `XIP_CTRL_XIP_ABYTES` control register bits ("number of address bytes")
|
|
* 32-bit data: sending zeros and receiving the according flash word (32-bit)
|
|
|
|
Hence, the maximum XIP transmission size is 72-bit, which has to be configured via the `XIP_CTRL_SPI_NBYTES`
|
|
control register bits. Note that the 72-bit transmission size is only available in XIP mode. The transmission
|
|
size of the direct SPI accesses is limited to 64-bit.
|
|
|
|
[NOTE]
|
|
When using four SPI flash address bytes, the most significant 4 bits of the address are always hardwired
|
|
to zero allowing a maximum **accessible** flash size of 256MB.
|
|
|
|
[NOTE]
|
|
The XIP module always fetches a full naturally aligned 32-bit word from the SPI flash. Any sub-word data masking
|
|
or alignment will be performed by the CPU core logic.
|
|
|
|
[IMPORTANT]
|
|
The XIP mode requires the 4-byte data words in the flash to be ordered in **little-endian** byte order.
|
|
|
|
After the SPI properties (including the amount of address bytes **and** the total amount of SPI transfer bytes)
|
|
and XIP address mapping are configured, the actual XIP mode can be enabled by setting
|
|
the control register's `XIP_CTRL_XIP_EN` bit. This will enable the "transparent SPI access port" of the module and thus,
|
|
the _transparent_ conversion of access requests into proper SPI flash transmissions. Hence, any access to the processor's
|
|
memory-mapped XIP region (`0xE0000000` to `0xEFFFFFFF`) will be converted into SPI flash accesses.
|
|
Make sure `XIP_CTRL_SPI_CSEN` is also set so the module can actually select/enable the attached SPI flash.
|
|
No more direct SPI accesses via `DATA_HI:DATA_LO` are possible when the XIP mode is enabled. However, the
|
|
XIP mode can be disabled at any time.
|
|
|
|
[NOTE]
|
|
If the XIP module is disabled (_XIP_CTRL_EN_ = `0`) any accesses to the memory-mapped XIP flash address region
|
|
will raise a bus access exception. If the XIP module is enabled (_XIP_CTRL_EN_ = `1`) but XIP mode is not enabled
|
|
yet (_XIP_CTRL_XIP_EN_ = '0') any access to the programmed XIP memory segment will also raise a bus access exception.
|
|
|
|
[TIP]
|
|
It is highly recommended to enable the <<_processor_internal_instruction_cache_icache>> to cover some
|
|
of the SPI access latency.
|
|
|
|
|
|
**XIP Cache**
|
|
|
|
Since every single instruction fetch request from the CPU is translated into serial SPI transmissions the access latency is
|
|
very high resulting in a low throughput. In order to improve performance, the XIP module provides an optional cache that
|
|
allows to buffer recently-accessed data. The cache is implemented as a simple direct-mapped read-only cache with a configurable
|
|
cache layout:
|
|
|
|
* `XIP_CACHE_EN`: when set to `true` the CIP cache is implemented
|
|
* `XIP_CACHE_NUM_BLOCKS` defines the number of cache blocks (or lines)
|
|
* `XIP_CACHE_BLOCK_SIZE` defines the size in bytes of each cache block
|
|
|
|
When the cache is implemented, the XIP module operates in **burst mode** utilizing the flash's _incremental read_ capabilities.
|
|
Thus, several bytes (= `XIP_CACHE_BLOCK_SIZE`) are read consecutively from the flash using a single read command.
|
|
|
|
The XIP cache is cleared when the XIP module is disabled (`XIP_CTRL_EN = 0`), when XIP mode is disabled
|
|
(`XIP_CTRL_XIP_EN = 0`) or when the CPU issues a `fence(.i)` instruction.
|
|
|
|
|
|
**Register Map**
|
|
|
|
.XIP Register Map (`struct NEORV32_XIP`)
|
|
[cols="<2,<1,<4,^1,<7"]
|
|
[options="header",grid="all"]
|
|
|=======================
|
|
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
|
|
.15+<| `0xffffff40` .15+<| `CTRL` <|`0` `XIP_CTRL_EN` ^| r/w <| XIP module enable
|
|
<|`3:1` `XIP_CTRL_PRSC2 : XIP_CTRL_PRSC0` ^| r/w <| 3-bit SPI clock prescaler select
|
|
<|`4` `XIP_CTRL_CPOL` ^| r/w <| SPI clock polarity
|
|
<|`5` `XIP_CTRL_CPHA` ^| r/w <| SPI clock phase
|
|
<|`9:6` `XIP_CTRL_SPI_NBYTES_MSB : XIP_CTRL_SPI_NBYTES_LSB` ^| r/w <| Number of bytes in SPI transaction (1..9)
|
|
<|`10` `XIP_CTRL_XIP_EN` ^| r/w <| XIP mode enable
|
|
<|`12:11` `XIP_CTRL_XIP_ABYTES_MSB : XIP_CTRL_XIP_ABYTES_LSB` ^| r/w <| Number of address bytes for XIP flash (minus 1)
|
|
<|`20:13` `XIP_CTRL_RD_CMD_MSB : XIP_CTRL_RD_CMD_LSB` ^| r/w <| Flash read command
|
|
<|`21` `XIP_CTRL_SPI_CSEN` ^| r/w <| Allow SPI chip-select to be actually asserted when set
|
|
<|`22` `XIP_CTRL_HIGHSPEED` ^| r/w <| enable SPI high-speed mode (ignoring `XIP_CTRL_PRSCx`)
|
|
<|`23:26` `XIP_CTRL_CDIV3 : XIP_CTRL_CDIV0` ^| r/- <| 4-bit clock divider for fine-tuning
|
|
<|`27:28` - ^| r/- <| _reserved_, read as zero
|
|
<|`29` `XIP_CTRL_BURST_EN` ^| r/- <| XIP burst mode enabled (if XIP cache is implemented)
|
|
<|`30` `XIP_CTRL_PHY_BUSY` ^| r/- <| SPI PHY busy when set
|
|
<|`31` `XIP_CTRL_XIP_BUSY` ^| r/- <| XIP access in progress when set
|
|
| `0xffffff44` | _reserved_ |`31:0` | r/- | _reserved_, read as zero
|
|
| `0xffffff48` | `DATA_LO` |`31:0` | r/w | Direct SPI access - data register low
|
|
| `0xffffff4C` | `DATA_HI` |`31:0` | -/w | Direct SPI access - data register high; write access triggers SPI transfer
|
|
|=======================
|