OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [docs/] [datasheet/] [soc_xip.adoc] - Rev 70

Go to most recent revision | Compare with Previous | Blame | View Log

<<<
: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_sdi_i` | 1-bit serial data input
|                          | `xip_sdo_o` | 1-bit serial data output
| Configuration generics:  | _IO_XIP_EN_ | implement XIP module when _true_
| CPU interrupts:          | none | 
|=======================


**Overview**

The execute in place (XIP) module is probably one of the more complicated modules of the NEORV32. The module
allows to execute code (and read constant data) directly from a SPI flash memory. Hence, it uses the standard
serial peripheral interface (SPI) as transfer protocol under the hood.

The XIP flash is not mapped to a specific region of the processor's address space. Instead, the XIP module
provides a programmable mapping scheme to allow a flexible user-defined mapping of the flash to _any section_
of the address space.

From the CPU side, the modules provides two different interfaces: one for transparently accessing the XIP flash and another
one for accessing the module's control and status registers. The first interface provides a _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 data accesses to the XIP module's
configuration registers.

[TIP]
An example program for the XIP module is available in `sw/example/demo_xip`.

[WARNING]
Debugging XIP code execution using the on-chip debugger is constrained. The debugger cannot insert breakpoints
(`ebreak` instructions) into XIP code as the XIP access is read-only.

[NOTE]
Quad-SPI (QSPI) support, which is about 4x times faster, is planned for the future. 😉


**SPI Protocol**

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 clock speed of the interface (`xip_clk_o`)
is defined by a three-bit clock pre-scaler configured using the _XIP_CTRL_PRSCx_ bits:

.XIP 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 _XIP_CTRL_PRSCx_ configuration the actual XIP SPI clock frequency f~XIP~ is derived from the processor's
main clock f~main~ and is determined by:

_**f~XIP~**_ = _f~main~[Hz]_ / (2 * `clock_prescaler`)

Hence, the maximum XIP clock speed is f~main~ / 4.

.High-Speed SPI mode
[TIP]
The module provides a "high-speed" SPI mode. In this mode the clock prescaler configuration (_XIP_CTRL_PRSCx_) is ignored
and the SPI clock operates at f~main~ / 2 (half of the processor's main clock). High speed SPI mode is enabled by setting
the control register's _XIP_CTRL_HIGHSPEED_ bit.

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.


**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 `NEORV32_XIP.DATA_LO` and
`NEORV32_XIP.DATA_HI` are provided to send up to 64-bit of SPI data. The `NEORV32_XIP.DATA_HI` register is write-only,
so a total of 32-bit 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 - `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.


**Address Mapping**

The address mapping of the XIP flash is not fixed by design. It can be mapped to _any section_ within the processor's
address space. A _section_ refers to one out of 16 naturally aligned 256MB wide memory segments. This segment
is defined by the four most significant bits of the address (`31:28`) and the XIP's segment is programmed by the
four _XIP_CTRL_XIP_PAGE_ bits in the unit's control register. All accesses within this page will be mapped to the XIP flash.

[NOTE]
Care must be taken when programming the page mapping to prevent access collisions with other modules (like internal memories
or modules attached to the external memory interface).

Example: to map the XIP flash to the address space starting at `0x20000000` write a "2" (`0b0010`) to the _XIP_CTRL_XIP_PAGE_
control register bits. Any access within `0x20000000 .. 0x2fffffff` will be forwarded to the XIP flash.
Note that the SPI access address might wrap around.


**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]
There is no _continuous read_ feature (i.e. a burst SPI transmission fetching several data words at once) implemented yet.

[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.

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. 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 programmed XIP memory segment are ignored
by the module and might be forwarded to the processor's external memory interface (if implemented) or will cause a bus
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 raise a bus exception.

[TIP]
It is highly recommended to enable the <<_processor_internal_instruction_cache_icache>> to cover some
of the SPI access latency.


.XIP register map (`struct NEORV32_XIP`)
[cols="<2,<2,<4,^1,<7"]
[options="header",grid="all"]
|=======================
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
.16+<| `0xffffff40` .16+<| `NEORV32_XIP.CTRL` <|`0`  _XIP_CTRL_EN_    ^| r/w <| XIP module enable
                                              <|`1`  _XIP_CTRL_PRSC0_ ^| r/w .3+| 3-bit SPI clock prescaler select
                                              <|`2`  _XIP_CTRL_PRSC1_ ^| r/w
                                              <|`3`  _XIP_CTRL_PRSC2_ ^| r/w
                                              <|`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
                                              <|`24:21` _XIP_CTRL_XIP_PAGE_MSB_ : _XIP_CTRL_XIP_PAGE_LSB_ ^| r/w <| XIP memory page
                                              <|`25` _XIP_CTRL_SPI_CSEN_  ^| r/w <| Allow SPI chip-select to be actually asserted when set
                                              <|`26` _XIP_CTRL_HIGHSPEED_ ^| r/w <| enable SPI high-speed mode (ignoring _XIP_CTRL_PRSC_)
                                              <|`29:27`                   ^| r/- <| _reserved_, read as zero
                                              <|`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` | `NEORV32_XIP.DATA_LO` |`31:0` | r/w | Direct SPI access - data register low
| `0xffffff4C` | `NEORV32_XIP.DATA_HI` |`31:0` | -/w | Direct SPI access - data register high; write access triggers SPI transfer
|=======================

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.