Serial peripheral interface (SPI) host
The SPI in Sonata only has the capability to be a host. This is a simple hardware IP block that can transmit and receive bytes over SPI.
In Sonata, there are multiple uses for SPI:
- LCD screen
- Ethernet
- Flash
- Raspberry Pi hat
- Arduino shield
- mikroBUS
The current Sonata system configuration has two SPI instantiations, one for the LCD screen and one for Flash. The Sonata top-level will need modification to add more SPI blocks for other uses.
The offset for each of the blocks is shown below, with each additional block having a 0x1000
offset from the previous.
SPI Instance | Offset (from SPI base) |
---|---|
Flash | 0x0 |
LCD Screen | 0x1000 |
Ethernet MAC | 0x2000 |
Raspberry Pi HAT SPI0 | 0x3000 |
Raspberry Pi HAT SPI1 | 0x4000 |
Arduino Shield | 0x5000 |
mikroBUS Click | 0x6000 |
Overview
Each SPI block has a two 64 entry FIFOs one for transmit and one for receive.
To begin an SPI transaction write to the START
register.
Bytes do not need to be immediately available in the transmit FIFO nor space available in the receive FIFO to begin the transaction.
The SPI block will only run the clock when its able to proceed.
Note that the CS pin is not handled by the SPI block and must be dealt with via GPIO and controlled with software.
Note Interrupts are not yet implemented
Register Table
Name | Offset | Length | Description |
---|---|---|---|
spi.INTR_STATE | 0x0 | 4 | Interrupt State Register |
spi.INTR_ENABLE | 0x4 | 4 | Interrupt Enable Register |
spi.INTR_TEST | 0x8 | 4 | Interrupt Test Register |
spi.CFG | 0xc | 4 | Configuration register. Controls how the SPI block transmits |
spi.CONTROL | 0x10 | 4 | Controls the operation of the SPI block. This register can |
spi.STATUS | 0x14 | 4 | Status information about the SPI block |
spi.START | 0x18 | 4 | When written begins an SPI operation. Writes are ignored when the |
spi.RX_FIFO | 0x1c | 4 | Data from the receive FIFO. When read the data is popped from the |
spi.TX_FIFO | 0x20 | 4 | Bytes written here are pushed to the transmit FIFO. If the FIFO |
INTR_STATE
Interrupt State Register
- Offset:
0x0
- Reset default:
0x0
- Reset mask:
0x1f
Fields
[{"name": "rx_full", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "rx_watermark", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "tx_empty", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "tx_watermark", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "complete", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"bits": 27}]
Bits | Type | Reset | Name | Description |
---|---|---|---|---|
31:5 | Reserved | |||
4 | rw1c | 0x0 | complete | On-going SPI operation has completed and the block is now idle |
3 | ro | 0x0 | tx_watermark | Transmit FIFO level is at or below watermark |
2 | ro | 0x0 | tx_empty | Transmit FIFO is empty |
1 | ro | 0x0 | rx_watermark | Receive FIFO level is at or above watermark |
0 | ro | 0x0 | rx_full | Receive FIFO is full |
INTR_ENABLE
Interrupt Enable Register
- Offset:
0x4
- Reset default:
0x0
- Reset mask:
0x1f
Fields
[{"name": "rx_full", "bits": 1, "attr": ["rw"], "rotate": -90}, {"name": "rx_watermark", "bits": 1, "attr": ["rw"], "rotate": -90}, {"name": "tx_empty", "bits": 1, "attr": ["rw"], "rotate": -90}, {"name": "tx_watermark", "bits": 1, "attr": ["rw"], "rotate": -90}, {"name": "complete", "bits": 1, "attr": ["rw"], "rotate": -90}, {"bits": 27}]
Bits | Type | Reset | Name | Description |
---|---|---|---|---|
31:5 | Reserved | |||
4 | rw | 0x0 | complete | Enable interrupt when INTR_STATE.complete is set. |
3 | rw | 0x0 | tx_watermark | Enable interrupt when INTR_STATE.tx_watermark is set. |
2 | rw | 0x0 | tx_empty | Enable interrupt when INTR_STATE.tx_empty is set. |
1 | rw | 0x0 | rx_watermark | Enable interrupt when INTR_STATE.rx_watermark is set. |
0 | rw | 0x0 | rx_full | Enable interrupt when INTR_STATE.rx_full is set. |
INTR_TEST
Interrupt Test Register
- Offset:
0x8
- Reset default:
0x0
- Reset mask:
0x1f
Fields
[{"name": "rx_full", "bits": 1, "attr": ["wo"], "rotate": -90}, {"name": "rx_watermark", "bits": 1, "attr": ["wo"], "rotate": -90}, {"name": "tx_empty", "bits": 1, "attr": ["wo"], "rotate": -90}, {"name": "tx_watermark", "bits": 1, "attr": ["wo"], "rotate": -90}, {"name": "complete", "bits": 1, "attr": ["wo"], "rotate": -90}, {"bits": 27}]
Bits | Type | Reset | Name | Description |
---|---|---|---|---|
31:5 | Reserved | |||
4 | wo | 0x0 | complete | Write 1 to force INTR_STATE.complete to 1. |
3 | wo | 0x0 | tx_watermark | Write 1 to force INTR_STATE.tx_watermark to 1. |
2 | wo | 0x0 | tx_empty | Write 1 to force INTR_STATE.tx_empty to 1. |
1 | wo | 0x0 | rx_watermark | Write 1 to force INTR_STATE.rx_watermark to 1. |
0 | wo | 0x0 | rx_full | Write 1 to force INTR_STATE.rx_full to 1. |
CFG
Configuration register. Controls how the SPI block transmits and receives data. This register can only be modified whilst the SPI block is idle.
- Offset:
0xc
- Reset default:
0x20000000
- Reset mask:
0xe000ffff
Fields
[{"name": "HALF_CLK_PERIOD", "bits": 16, "attr": ["rw"], "rotate": 0}, {"bits": 13}, {"name": "MSB_FIRST", "bits": 1, "attr": ["rw"], "rotate": -90}, {"name": "CPHA", "bits": 1, "attr": ["rw"], "rotate": -90}, {"name": "CPOL", "bits": 1, "attr": ["rw"], "rotate": -90}]
Bits | Type | Reset | Name |
---|---|---|---|
31 | rw | 0x0 | CPOL |
30 | rw | 0x0 | CPHA |
29 | rw | 0x1 | MSB_FIRST |
28:16 | Reserved | ||
15:0 | rw | 0x0 | HALF_CLK_PERIOD |
CFG . CPOL
The polarity of the spi_clk signal. When CPOL is 0 clock is low when idle and the leading edge is positive. When CPOL is 1 clock is high when idle and the leading edge is negative
CFG . CPHA
The phase of the spi_clk signal. When CPHA is 0 data is sampled on the leading edge and changes on the trailing edge. The first data bit is immediately available before the first leading edge of the clock when transmission begins. When CPHA is 1 data is sampled on the trailing edge and change on the leading edge.
CFG . MSB_FIRST
When set the most significant bit (MSB) is the first bit sent and received with each byte
CFG . HALF_CLK_PERIOD
The length of a half period (i.e. positive edge to negative edge) of the SPI clock, measured in system clock cycles reduced by 1. At the standard Sonata 50 MHz system clock a value of 0 gives a 25 MHz SPI clock, a value of 1 gives a 12.5 MHz SPI clock, a value of 2 gives a 8.33 MHz SPI clock and so on.
CONTROL
Controls the operation of the SPI block. This register can only be modified whilst the SPI block is idle.
- Offset:
0x10
- Reset default:
0x0
- Reset mask:
0xfff
Fields
[{"name": "TX_CLEAR", "bits": 1, "attr": ["wo"], "rotate": -90}, {"name": "RX_CLEAR", "bits": 1, "attr": ["wo"], "rotate": -90}, {"name": "TX_ENABLE", "bits": 1, "attr": ["rw"], "rotate": -90}, {"name": "RX_ENABLE", "bits": 1, "attr": ["rw"], "rotate": -90}, {"name": "TX_WATERMARK", "bits": 4, "attr": ["rw"], "rotate": -90}, {"name": "RX_WATERMARK", "bits": 4, "attr": ["rw"], "rotate": -90}, {"bits": 20}]
Bits | Type | Reset | Name |
---|---|---|---|
31:12 | Reserved | ||
11:8 | rw | 0x0 | RX_WATERMARK |
7:4 | rw | 0x0 | TX_WATERMARK |
3 | rw | 0x0 | RX_ENABLE |
2 | rw | 0x0 | TX_ENABLE |
1 | wo | 0x0 | RX_CLEAR |
0 | wo | 0x0 | TX_CLEAR |
CONTROL . RX_WATERMARK
The watermark level for the receive FIFO, depending on the value the interrupt will trigger at different points:
- 0: 1 or more items in the FIFO
- 1: 2 or more items in the FIFO
- 2: 4 or more items in the FIFO
- 3: 8 or more items in the FIFO
- 4: 16 or more items in the FIFO
- 5: 32 or more items in the FIFO
- 6: 56 or more items in the FIFO
CONTROL . TX_WATERMARK
The watermark level for the transmit FIFO, depending on the value the interrupt will trigger at different points:
- 0: 1 or fewer items in the FIFO
- 1: 2 or fewer items in the FIFO
- 2: 4 or fewer items in the FIFO
- 3: 8 or fewer items in the FIFO
- 4: 16 or fewer items in the FIFO
CONTROL . RX_ENABLE
When set incoming bits are written to the receive FIFO. When clear incoming bits are ignored.
CONTROL . TX_ENABLE
When set bytes from the transmit FIFO are sent. When clear the state of the outgoing spi_cipo is undefined whilst the SPI clock is running.
CONTROL . RX_CLEAR
Write 1 to clear the receive FIFO.
CONTROL . TX_CLEAR
Write 1 to clear the transmit FIFO.
STATUS
Status information about the SPI block
- Offset:
0x14
- Reset default:
0x0
- Reset mask:
0x7ffff
Fields
[{"name": "TX_FIFO_LEVEL", "bits": 8, "attr": ["ro"], "rotate": 0}, {"name": "RX_FIFO_LEVEL", "bits": 8, "attr": ["ro"], "rotate": 0}, {"name": "TX_FIFO_FULL", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "RX_FIFO_EMPTY", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "IDLE", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 13}]
Bits | Type | Reset | Name | Description |
---|---|---|---|---|
31:19 | Reserved | |||
18 | ro | x | IDLE | When set the SPI block is idle and can accept a new start command. |
17 | ro | x | RX_FIFO_EMPTY | When set the receive FIFO is empty and any data read from it will be undefined. |
16 | ro | x | TX_FIFO_FULL | When set the transmit FIFO is full and any data written to it will be ignored. |
15:8 | ro | x | RX_FIFO_LEVEL | Number of items in the receive FIFO |
7:0 | ro | x | TX_FIFO_LEVEL | Number of items in the transmit FIFO |
START
When written begins an SPI operation. Writes are ignored when the SPI block is active.
- Offset:
0x18
- Reset default:
0x0
- Reset mask:
0x7ff
Fields
[{"name": "BYTE_COUNT", "bits": 11, "attr": ["wo"], "rotate": 0}, {"bits": 21}]
Bits | Type | Reset | Name | Description |
---|---|---|---|---|
31:11 | Reserved | |||
10:0 | wo | 0x0 | BYTE_COUNT | Number of bytes to receive/transmit in the SPI operation |
RX_FIFO
Data from the receive FIFO. When read the data is popped from the FIFO. If the FIFO is empty data read is undefined.
- Offset:
0x1c
- Reset default:
0x0
- Reset mask:
0xff
Fields
[{"name": "DATA", "bits": 8, "attr": ["ro"], "rotate": 0}, {"bits": 24}]
Bits | Type | Reset | Name | Description |
---|---|---|---|---|
31:8 | Reserved | |||
7:0 | ro | x | DATA | Byte popped from the FIFO |
TX_FIFO
Bytes written here are pushed to the transmit FIFO. If the FIFO is full writes are ignored.
- Offset:
0x20
- Reset default:
0x0
- Reset mask:
0xff
Fields
[{"name": "DATA", "bits": 8, "attr": ["wo"], "rotate": 0}, {"bits": 24}]
Bits | Type | Reset | Name | Description |
---|---|---|---|---|
31:8 | Reserved | |||
7:0 | wo | 0x0 | DATA | Byte to push to the FIFO |