103 lines
5.9 KiB
Plaintext
103 lines
5.9 KiB
Plaintext
<<<
|
|
:sectnums:
|
|
==== Serial Data Interface Controller (SDI)
|
|
|
|
[cols="<3,<3,<4"]
|
|
[frame="topbot",grid="none"]
|
|
|=======================
|
|
| Hardware source file(s): | neorv32_sdi.vhd |
|
|
| Software driver file(s): | neorv32_sdi.c |
|
|
| | neorv32_sdi.h |
|
|
| Top entity port: | `sdi_clk_i` | 1-bit serial clock input
|
|
| | `sdi_dat_o` | 1-bit serial data output
|
|
| | `sdi_dat_i` | 1-bit serial data input
|
|
| | `sdi_csn_i` | 1-bit chip-select input (low-active)
|
|
| Configuration generics: | `IO_SDI_EN` | implement SDI controller when `true`
|
|
| | `IO_SDI_FIFO` | data FIFO size, has to a power of two, min 1
|
|
| CPU interrupts: | fast IRQ channel 11 | configurable SDI interrupt (see <<_processor_interrupts>>)
|
|
|=======================
|
|
|
|
|
|
**Overview**
|
|
|
|
The serial data interface module provides a **device-class** SPI interface and allows to connect the processor
|
|
to an external SPI _host_, which is responsible for triggering (clocking) the actual transmission - the SDI is entirely
|
|
passive. An optional receive/transmit FIFO can be configured via the _IO_SDI_FIFO_ generic to support block-based
|
|
transmissions without CPU interaction.
|
|
|
|
.Device-Mode Only
|
|
[NOTE]
|
|
The NEORV32 SDI module only supports _device mode_. Transmission are initiated by an external host and not by the
|
|
the processor itself. If you are looking for a _host-mode_ serial peripheral interface (transactions
|
|
initiated by the NEORV32) check out the <<_serial_peripheral_interface_controller_spi>>.
|
|
|
|
The SDI module provides a single control register `CTRL` to configure the module and to check it's status
|
|
and a single data register `DATA` for receiving/transmitting data.
|
|
|
|
|
|
**Theory of Operation**
|
|
|
|
The SDI module is enabled by setting the `SDI_CTRL_EN` bit in the `CTRL` control register. Clearing this bit
|
|
resets the entire module including the RX and TX FIFOs.
|
|
|
|
The SDI operates on byte-level only. Data written to the `DATA` register will be pushed to the TX FIFO. Received
|
|
data can be retrieved by reading the RX FIFO via the `DATA` register. The current state of these FIFOs is available
|
|
via the control register's `SDI_CTRL_RX_*` and `SDI_CTRL_TX_*` flags. The RX FIFO can be manually cleared at any time
|
|
by setting the `SDI_CTRL_CLR_RX` bit.
|
|
|
|
.MSB-first Only
|
|
[NOTE]
|
|
The NEORV32 SDI module only supports MSB-first mode.
|
|
|
|
.Transmission Abort
|
|
[NOTE]
|
|
If the external SPI controller aborts an transmission (by setting the chip-select signal high again) _before_
|
|
8 data bits have been transferred, no data is written to the RX FIFO.
|
|
|
|
|
|
**SDI Clocking**
|
|
|
|
The SDI module supports both SPI clock polarity modes ("CPOL") but regarding the clock phase only "CPHA=0" is supported
|
|
yet. All SDI operations are clocked by the external `sdi_clk_i` signal. This signal is synchronized to the processor's
|
|
clock domain to simplify timing behavior. However, the clock synchronization requires that the external SDI clock
|
|
(`sdi_clk_i`) does **not exceed 1/4 of the processor's main clock**.
|
|
|
|
|
|
**SDI Interrupt**
|
|
|
|
The SDI module provides a set of programmable interrupt conditions based on the level of the RX & TX FIFOs. The different
|
|
interrupt sources are enabled by setting the according control register's `SDI_CTRL_IRQ` bits. All enabled interrupt
|
|
conditions are logically OR-ed so any enabled interrupt source will trigger the module's interrupt signal.
|
|
|
|
Once the SDI interrupt has fired it will remain active until the actual cause of the interrupt is resolved; for
|
|
example if just the `SDI_CTRL_IRQ_RX_AVAIL` bit is set, the interrupt will keep firing until the RX FIFO is empty again.
|
|
Furthermore, an active SDI interrupt has to be explicitly cleared again by writing zero to the according
|
|
<<_mip>> CSR bit.
|
|
|
|
|
|
**Register Map**
|
|
|
|
.SDI register map (`struct NEORV32_SDI`)
|
|
[cols="<2,<1,<4,^1,<7"]
|
|
[options="header",grid="all"]
|
|
|=======================
|
|
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
|
|
.16+<| `0xfffff700` .16+<| `CTRL` <|`0` `SDI_CTRL_EN` ^| r/w <| SDI module enable
|
|
<|`1` `SDI_CTRL_CLR_RX` ^| -/w <| clear RX FIFO when set, bit auto-clears
|
|
<|`3:2` _reserved_ ^| r/- <| reserved, read as zero
|
|
<|`7:4` `SDI_CTRL_FIFO_MSB : SDI_CTRL_FIFO_LSB` ^| r/- <| FIFO depth; log2(_IO_SDI_FIFO_)
|
|
<|`14:8` _reserved_ ^| r/- <| reserved, read as zero
|
|
<|`15` `SDI_CTRL_IRQ_RX_AVAIL` ^| r/w <| fire interrupt if RX FIFO is not empty
|
|
<|`16` `SDI_CTRL_IRQ_RX_HALF` ^| r/w <| fire interrupt if RX FIFO is at least half full
|
|
<|`17` `SDI_CTRL_IRQ_RX_FULL` ^| r/w <| fire interrupt if if RX FIFO is full
|
|
<|`18` `SDI_CTRL_IRQ_TX_EMPTY` ^| r/w <| fire interrupt if TX FIFO is empty
|
|
<|`22:19` _reserved_ ^| r/- <| reserved, read as zero
|
|
<|`23` `SDI_CTRL_RX_AVAIL` ^| r/- <| RX FIFO data available (RX FIFO not empty)
|
|
<|`24` `SDI_CTRL_RX_HALF` ^| r/- <| RX FIFO at least half full
|
|
<|`25` `SDI_CTRL_RX_FULL` ^| r/- <| RX FIFO full
|
|
<|`26` `SDI_CTRL_TX_EMPTY` ^| r/- <| TX FIFO empty
|
|
<|`27` `SDI_CTRL_TX_FULL` ^| r/- <| TX FIFO full
|
|
<|`31:28` _reserved_ ^| r/- <| reserved, read as zero
|
|
| `0xfffff704` | `DATA` |`7:0` | r/w | receive/transmit data (FIFO)
|
|
|=======================
|