1 |
60 |
zero_gravi |
<<<
|
2 |
|
|
:sectnums:
|
3 |
|
|
==== Serial Peripheral Interface Controller (SPI)
|
4 |
|
|
|
5 |
|
|
[cols="<3,<3,<4"]
|
6 |
|
|
[frame="topbot",grid="none"]
|
7 |
|
|
|=======================
|
8 |
|
|
| Hardware source file(s): | neorv32_spi.vhd |
|
9 |
|
|
| Software driver file(s): | neorv32_spi.c |
|
10 |
|
|
| | neorv32_spi.h |
|
11 |
|
|
| Top entity port: | `spi_sck_o` | 1-bit serial clock output
|
12 |
65 |
zero_gravi |
| | `spi_sdo_o` | 1-bit serial data output
|
13 |
|
|
| | `spi_sdi_i` | 1-bit serial data input
|
14 |
60 |
zero_gravi |
| | `spi_csn_i` | 8-bit dedicated chip select (low-active)
|
15 |
|
|
| Configuration generics: | _IO_SPI_EN_ | implement SPI controller when _true_
|
16 |
|
|
| CPU interrupts: | fast IRQ channel 6 | transmission done interrupt (see <<_processor_interrupts>>)
|
17 |
|
|
|=======================
|
18 |
|
|
|
19 |
65 |
zero_gravi |
|
20 |
60 |
zero_gravi |
**Theory of Operation**
|
21 |
|
|
|
22 |
65 |
zero_gravi |
SPI is a synchronous serial transmission interface for fast on-board communications.
|
23 |
|
|
The NEORV32 SPI transceiver supports 8-, 16-, 24- and 32-bit wide transmissions.
|
24 |
|
|
The unit provides 8 dedicated chip select signals via the top entity's `spi_csn_o` signal, which are
|
25 |
|
|
directly controlled by the SPI module (no additional GPIO required).
|
26 |
60 |
zero_gravi |
|
27 |
66 |
zero_gravi |
[NOTE]
|
28 |
|
|
The NEORV32 SPI module only supports _host mode_. Transmission are initiated only by the processor's SPI module
|
29 |
|
|
(and not by an external SPI module).
|
30 |
|
|
|
31 |
65 |
zero_gravi |
The SPI unit is enabled by setting the _SPI_CTRL_EN_ bit in the `CTRL` control register. No transfer can be initiated
|
32 |
|
|
and no interrupt request will be triggered if this bit is cleared. Furthermore, a transfer being in process
|
33 |
|
|
can be terminated at any time by clearing this bit.
|
34 |
60 |
zero_gravi |
|
35 |
66 |
zero_gravi |
[IMPORTANT]
|
36 |
|
|
Changes to the `CTRL` control register should be made only when the SPI module is idle as they directly effect
|
37 |
|
|
transmissions being in-progress.
|
38 |
|
|
|
39 |
|
|
[TIP]
|
40 |
|
|
A transmission can be terminated at any time by disabling the SPI module
|
41 |
|
|
by clearing the _SPI_CTRL_EN_ control register bit.
|
42 |
|
|
|
43 |
65 |
zero_gravi |
The data quantity to be transferred within a single transmission is defined via the _SPI_CTRL_SIZEx_ bits.
|
44 |
66 |
zero_gravi |
The SPI module supports 8-bit (`00`), 16-bit (`01`), 24-bit (`10`) and 32-bit (`11`) transfers.
|
45 |
60 |
zero_gravi |
|
46 |
65 |
zero_gravi |
A transmission is started when writing data to the `DATA` register. The data must be LSB-aligned. So if
|
47 |
|
|
the SPI transceiver is configured for less than 32-bit transfers data quantity, the transmit data must be placed
|
48 |
|
|
into the lowest 8/16/24 bit of `DATA`. Vice versa, the received data is also always LSB-aligned. Application
|
49 |
|
|
software should only actually process the amount of bits that were configured using _SPI_CTRL_SIZEx_ when
|
50 |
|
|
reading `DATA`.
|
51 |
60 |
zero_gravi |
|
52 |
66 |
zero_gravi |
[NOTE]
|
53 |
|
|
The NEORV32 SPI module only support MSB-first mode. Data can be reversed before writing `DATA` (for TX) / after
|
54 |
|
|
reading `DATA` (for RX) to implement LSB-first transmissions. Note that in both cases data in ` DATA` still
|
55 |
|
|
needs to be LSB-aligned.
|
56 |
65 |
zero_gravi |
|
57 |
|
|
[TIP]
|
58 |
|
|
The actual transmission length is left to the user: after asserting chip-select an arbitrary amount of
|
59 |
|
|
transmission with arbitrary data quantity (_SPI_CTRL_SIZEx_) can be made before de-asserting chip-select again.
|
60 |
|
|
|
61 |
66 |
zero_gravi |
The SPI controller features 8 dedicated chip-select lines. These lines are controlled via the control register's
|
62 |
|
|
_SPI_CTRL_CSx_ bits. When a specific _SPI_CTRL_CSx_ bit is **set**, the according chip-select line `spi_csn_o(x)`
|
63 |
|
|
goes **low** (low-active chip-select lines).
|
64 |
65 |
zero_gravi |
|
65 |
66 |
zero_gravi |
[TIP]
|
66 |
|
|
The dedicated SPI chip-select signals can be seen as _general purpose_ outputs. These are intended to control
|
67 |
|
|
the accessed device's chip-select signal but can also be use for controlling other shift register signals
|
68 |
|
|
(like data strobe or output-enables).
|
69 |
65 |
zero_gravi |
|
70 |
|
|
|
71 |
|
|
**SPI Clock Configuration**
|
72 |
|
|
|
73 |
|
|
The SPI module supports all _standard SPI clock modes_ (0, 1, 2, 3), which is via the two control register bits
|
74 |
|
|
_SPI_CTRL_CPHA_ and _SPI_CTRL_CPOL_. The _SPI_CTRL_CPHA_ bit defines the _clock phase_ and the _SPI_CTRL_CPOL_
|
75 |
|
|
bit defines the _clock polarity_.
|
76 |
|
|
|
77 |
|
|
.SPI clock modes; image from https://en.wikipedia.org/wiki/File:SPI_timing_diagram2.svg (license: (Wikimedia) https://en.wikipedia.org/wiki/Creative_Commons[Creative Commons] https://creativecommons.org/licenses/by-sa/3.0/deed.en[Attribution-Share Alike 3.0 Unported])
|
78 |
|
|
image::SPI_timing_diagram2.wikimedia.png[]
|
79 |
|
|
|
80 |
|
|
.SPI standard clock modes
|
81 |
|
|
[cols="<2,^1,^1,^1,^1"]
|
82 |
|
|
[options="header",grid="rows"]
|
83 |
|
|
|=======================
|
84 |
|
|
| | Mode 0 | Mode 1 | Mode 2 | Mode 4
|
85 |
|
|
| _SPI_CTRL_CPOL_ | `0` | `0` | `1` | `1`
|
86 |
|
|
| _SPI_CTRL_CPHA_ | `0` | `1` | `0` | `1`
|
87 |
|
|
|=======================
|
88 |
|
|
|
89 |
|
|
The SPI clock frequency (`spi_sck_o`) is programmed by the 3-bit _SPI_CTRL_PRSCx_ clock prescaler.
|
90 |
|
|
The following prescalers are available:
|
91 |
|
|
|
92 |
60 |
zero_gravi |
.SPI prescaler configuration
|
93 |
|
|
[cols="<4,^1,^1,^1,^1,^1,^1,^1,^1"]
|
94 |
|
|
[options="header",grid="rows"]
|
95 |
|
|
|=======================
|
96 |
64 |
zero_gravi |
| **`SPI_CTRL_PRSCx`** | `0b000` | `0b001` | `0b010` | `0b011` | `0b100` | `0b101` | `0b110` | `0b111`
|
97 |
60 |
zero_gravi |
| Resulting `clock_prescaler` | 2 | 4 | 8 | 64 | 128 | 1024 | 2048 | 4096
|
98 |
|
|
|=======================
|
99 |
|
|
|
100 |
65 |
zero_gravi |
Based on the _SPI_CTRL_PRSCx_ configuration, the actual SPI clock frequency f~SPI~ is derived from the processor's
|
101 |
|
|
main clock f~main~ and is determined by:
|
102 |
60 |
zero_gravi |
|
103 |
|
|
_**f~SPI~**_ = _f~main~[Hz]_ / (2 * `clock_prescaler`)
|
104 |
|
|
|
105 |
65 |
zero_gravi |
Hence, the maximum SPI clock is f~main~ / 4.
|
106 |
60 |
zero_gravi |
|
107 |
70 |
zero_gravi |
.High-Speed SPI mode
|
108 |
|
|
[TIP]
|
109 |
|
|
The module provides a "high-speed" SPI mode. In this mode the clock prescaler configuration (SPI_CTRL_PRSCx) is ignored
|
110 |
|
|
and the SPI clock operates at f~main~ / 2 (half of the processor's main clock). High speed SPI mode is enabled by setting
|
111 |
|
|
the control register's _SPI_CTRL_HIGHSPEED_ bit.
|
112 |
65 |
zero_gravi |
|
113 |
70 |
zero_gravi |
|
114 |
65 |
zero_gravi |
**SPI Interrupt**
|
115 |
|
|
|
116 |
68 |
zero_gravi |
The SPI module provides a single interrupt to signal "transmission done" to the CPU. Whenever the SPI
|
117 |
69 |
zero_gravi |
module completes the current transfer operation, the interrupt is triggered and has to be explicitly cleared again
|
118 |
|
|
by setting the according `mip` CSR bit.
|
119 |
65 |
zero_gravi |
|
120 |
|
|
|
121 |
64 |
zero_gravi |
.SPI register map (`struct NEORV32_SPI`)
|
122 |
60 |
zero_gravi |
[cols="<2,<2,<4,^1,<7"]
|
123 |
|
|
[options="header",grid="all"]
|
124 |
|
|
|=======================
|
125 |
|
|
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
|
126 |
70 |
zero_gravi |
.19+<| `0xffffffa8` .19+<| `NEORV32_SPI.CTRL` <|`0` _SPI_CTRL_CS0_ ^| r/w .8+<| Direct chip-select 0..7; setting `spi_csn_o(x)` low when set
|
127 |
|
|
<|`1` _SPI_CTRL_CS1_ ^| r/w
|
128 |
|
|
<|`2` _SPI_CTRL_CS2_ ^| r/w
|
129 |
|
|
<|`3` _SPI_CTRL_CS3_ ^| r/w
|
130 |
|
|
<|`4` _SPI_CTRL_CS4_ ^| r/w
|
131 |
|
|
<|`5` _SPI_CTRL_CS5_ ^| r/w
|
132 |
|
|
<|`6` _SPI_CTRL_CS6_ ^| r/w
|
133 |
|
|
<|`7` _SPI_CTRL_CS7_ ^| r/w
|
134 |
|
|
<|`8` _SPI_CTRL_EN_ ^| r/w <| SPI enable
|
135 |
|
|
<|`9` _SPI_CTRL_CPHA_ ^| r/w <| clock phase (`0`=sample RX on rising edge & update TX on falling edge; `1`=sample RX on falling edge & update TX on rising edge)
|
136 |
|
|
<|`10` _SPI_CTRL_PRSC0_ ^| r/w .3+| 3-bit clock prescaler select
|
137 |
|
|
<|`11` _SPI_CTRL_PRSC1_ ^| r/w
|
138 |
|
|
<|`12` _SPI_CTRL_PRSC2_ ^| r/w
|
139 |
|
|
<|`13` _SPI_CTRL_SIZE0_ ^| r/w .2+<| transfer size (`00`=8-bit, `01`=16-bit, `10`=24-bit, `11`=32-bit)
|
140 |
|
|
<|`14` _SPI_CTRL_SIZE1_ ^| r/w
|
141 |
|
|
<|`15` _SPI_CTRL_CPOL_ ^| r/w <| clock polarity
|
142 |
|
|
<|`16` _SPI_CTRL_HIGHSPEED_ ^| r/w <| enable SPI high-speed mode (ignoring _SPI_CTRL_PRSC_)
|
143 |
|
|
<|`17:30` ^| r/- <| _reserved, read as zero
|
144 |
|
|
<|`31` _SPI_CTRL_BUSY_ ^| r/- <| transmission in progress when set
|
145 |
64 |
zero_gravi |
| `0xffffffac` | `NEORV32_SPI.DATA` |`31:0` | r/w | receive/transmit data, LSB-aligned
|
146 |
60 |
zero_gravi |
|=======================
|