Welcome To Real Digital
Welcome To Real Digital
SPI Controller
BLACKBOARD’S SPI
Con�guring and using the SPI bus on ZYNQ BUSSES
FIFOS
15928
CONFIGURING ZYNQ’S
SPI CONTROLLER
Overview
The Serial Peripheral Interface (SPI) bus is a four-signal, point-to-point, single master synchronous RESET SPI MODULE
bus commonly used for low to medium speed communications (up to about 5Mbytes/s). The four CHIP SELECTS
signals, Master Out Slave In (MOSI), Master In Slave Out (MISO), Serial Clock (SCLK), and Slave
Select (SS) are all unidirectional and single-ended (ground referenced). The bus master always CONTROLLING SPI
drives SS, MOSI, and SCLK, and the slave device drives MISO back to the master. TRANSFERS
SPI busses are commonly used by microcontrollers to communicate with peripheral devices like TRANSFER MODES
memories, analog-to-digital converters, sensors, motor controllers, etc. You can read more about
CONFIGURING THE SPI
SPI busses here: The SPI BUS
BUS ON THE
BLACKBOARD
select signals (SS), and both can use clocks that range from 83MHz down to 650KHz. ZYNQ’s SPI WRITING TO A REGISTER
controllers are typically used in “master mode”, meaning the ZYNQ drives the MOSI, SCLK, and SS
TRANSFERING MULTIPLE
signals, and the slave responds by driving the MISO signal (the controllers can be put in slave
BYTES
mode as well).
On the Blackboard, SPI0 is connected to a sensor chip that includes an accelerometer, gyroscope, BACK TO TOP
and magnetometer (an ST Micro LSM9SDS1), and the SPI1 is connected to the ESP32 WIFI radio.
The WIFI radio SPI signals are connected directly to processing system pins using the MIO
interface, but the ST Micro device SPI signals are connected through the FPGA using the EMIO
interface (all connections are con�gured in the standard Blackboard con�guration �le).
SS0 SS0 K17 CS_A/G
SS1 SS1 K16 CS_M
SCLK SCLK H20 SPC SPI
MOSI MOSI J19 SDA Port
MISO_AG J20 SD0_A/G
MISO MOSI_M L17 SD0_M
SPI0 Controller
Clock Management
The SPI controllers use a 166MHz master clock input that can be divided by an user-
programmable three-bit parameter N according to the formula:
where BAUDDIV is a 4-bit programmable �eld in the SPI con�guration register. The SPI clock
divider can produce 16 frequencies, ranging from 83MHz down to 650KHz.
FIFOs
Each controller includes a 128 byte send FIFO, and a separate 128 byte receive FIFO. Each FIFO is
accessed by a single 8-bit port, and several status signals/interrupts are available to indicate the
state of the FIFOs (empty, full, almost full, etc.). Data placed in the transmit FIFO will be
automatically serialized and sent out on the MOSI pin. Note that transmit data can be written into
the FIFO much faster than it can be sent out, so if more than 128 bytes must be written, the
transmit FIFO must be managed by polling status bits or setting up interrupts. Data arriving in the
receive FIFO can be read after checking status bits (to con�rm new data is available) or in
response to an interrupt. You can learn more about FIFOs here: MANAGED HARDWARE FIFOs
From ARM To ARM
SPI FIFOs
Address offset Address offset
0x0000 001C 0x0000 0020
128 Bytes
Transmit Receive
FIFO FIFO
Shift Registers
MOSI MISO
Registers
MF: ModeFail generation enable (in slave mode, indicates SS was deasserted) (1 to enable, o to
disable
MS: Manual Start Command (1 to start transmission)
EN: Manual Start Enable (1 to enable manual start)
CS: Enable Manual Chip Select (Slave Select) (1 to enable)
SS: Slave selects: xxx0 slave 0; xx01 slave 1; 0x011 slave 2; 0111 reserved; 1111 no slave selected
ED: Enable external decode (1 to allow external 3:8 decoder on SS lines)
CK: Master reference clock select (must be 0 to use SPI reference clock; 1 not supported)
Bauddiv: Baud rate divisor (000 not supported; otherwise divide by 2 ^ (N + 1))
PH: Clock Phase (1 to make clock inactive outside word; 0 to make active outside word)
PL: Clock Polarity (1 for quiescent high, 0 for quiescent low)
M: Mode select (1 for master mode, 0 for slave mode)
SPI_SR (0x00000004): Status register for reading FIFO �ag status (write a ‘1’ to any bit to clear)
31 7 6 5 4 3 2 1 0
Not Used TU RFRN TF TNMVRO
SPI_IER (0x00000008): Interrupt enable register (write ‘1’ to enable interrupt source)
31 7 6 5 4 3 2 1 0
Not Used TU RFRN TF TNMVRO
SPI_IDR: (0x0000000C): Interrupt disable register (write ‘1’ to disable interrupt source)
31 7 6 5 4 3 2 1 0
Not Used TU RFRN TF TNMVRO
SPI_IDR: (0x00000010): Interrupt mask register (write ‘1’ to mask/disable interrupt, ‘0’ to enable/
unmask)
31 7 6 5 4 3 2 1 0
Not Used TU RFRN TF TNMVRO
TXD: 8-bit transmit data sent to transmit FIFO
ICLK: Number of SPI clocks that must pass (idle) before slave detects a start
SPI_TXWR (0x00000028): De�nes threshold level for transmit FIFO not full (read/write)
31 7 6 0
Not Used THLVL
THLVL: Threshold level at which transmit FIFO not full interrupt is generated
SPI_RX_THRES (0x0000002C): De�nes threshold level for receive FIFO not empty (read/write)
31 7 6 0
Not Used THLVL
THLVL: Threshold level at which receive FIFO not empty interrupt is generated
Before the SPI module can be con�gured for use, it must be reset by writing to Zynq’s System
Level Control Registers (SLCR) block. SLCR’s are protected registers that can only be accessed
after they are “unlocked” by writing a special key value (0xDF0D) to the unlock register at address
0xF8000008. After unlocking the SLCRs and using them as needed, they should be immediately
relocked by writing the lock key (0x767B) to the lock register at 0xF8000004.
//SLCR addresses for SPI reset
#define SLCR_LOCK *( (uint32_t *) 0xF8000004)
#define SLCR_UNLOCK *( (uint32_t *) 0xF8000008)
#define SLCR_SPI_RST *( (uint32_t *) 0xF800021C)
void reset_SPI(void)
{
int i=0; //i for delay
SLCR_UNLOCK = UNLOCK_KEY; //unlock SLCRs
SLCR_SPI_RST = 0xF; //assert SPI reset
for(i=0;i<1000;i++); //make sure Reset occurs
SLCR_SPI_RST = 0; //deassert
SLCR_LOCK = LOCK_KEY; //relock SLCRs
}
Once unlocked, the SPI reset signal can be asserted by setting the lower four bits of the SLCR SPI
reset register at address 0xF800021C. After a small delay (around 100us), you can clear the bits
and the reset process will be complete. The example code below illustrates the SPI reset process.
Chip selects
An SPI slave is enabled (selected) when the SPI master asserts its “slave select” (SS) signal.
ZYNQs SPI controllers can each drive three different SS signals, so they can communicate with
three different, independent slave devices. The SS signals must be treated as mutually exclusive.
As the MISO input to the module is shared between external devices, driving multiple select lines
could result indamage to the slave devices. Four bits in the con�guration register determine which
SS signal is active, and it is not possible to drive two of them at the same time.
The Zynq’s SPI Module supports both automatic and manual control of the module’s device select
lines.
AUTOMATIC CHIP SELECT
In automatic mode the module controls the select lines during a SPI transfer: When the module
starts shifting out data on the MOSI pin, the module will automatically assert the con�gured
select line. When the transmit FIFO becomes empty or module is disabled, the select will
deassert. Automatic select is best for small transfer of a known data length, where the transmit
data can �t inside the tx FIFO.
MANUAL CHIP SELECT
Manual chip select allows software to control the chip select lines independent of the SPI module.
The SPI transmitter logic will still serialize data in the FIFO when enabled, but the chip-selects will
always re�ect the state con�gured in the module’s control register. Manual select can be used for
longer transfers where the chip select may need to remain asserted when the transmitter is not
actively shifting bits (the SPI CLK is stopped). For longer length or unknown length transfers this
allows the slave device to remain selected even if the transmit FIFO is empty.
As an example, an SD card in SPI mode can transfer multiple 512-byte blocks in a single SPI
transfer. The card can keep sending contiguous blocks as long as the chip select is asserted and
the SPI Master is supplying the card with a transfer clock.
Manual Start
The SPI Module can be con�gured to start transmitting only after a manual-start command is
issued to the module. This allows software to queue up bytes in the FIFO before initiating a
transfer. Once the transmit FIFO is empty the transfer will end, software can then queue more data
into the FIFO and initiate another transfer. With auto chip-select, the con�gured CS line will only go
low after the transfer is initiated.
Auto Start
In automatic start mode, the transmitter will begin to transmit data when at least one byte is in the
transmit FIFO. When the transmit FIFO is empty the transmitter will pause the SPI clock signal (it
will also deassert chip-selects if the module is con�gued for auto-CS).
Transfer Modes
The Zynq SPI Module supports various con�gurations to work with SPI devices which have
different protocols within the SPI standard. Transfers in two common con�gurations are detailed
below.
This con�guration is useful for �xed length transfers where data is queued in the transmit FIFO
prior to initiating the transfer. This is recommended for communicating with the LSM9DS1. In the
SPI control register, con�gure the baud rate, phase, and polarity as desired. Clear the manual CS
bit (SPI_CR[14]=0), and set the manual start enable bit (SPI_CR[15]=1).
Initiating a transfer
1. Queue initial data to be transmitted in the SPI transmit FIFO. The ‘TX FIFO not full’ bit
(SPI_SR[2]) in the status register can be used to check if there is room for more transmit
data.
2. Set the chip select to be driven by con�guring the appropriate bits in the control register
(SPI_CR[13:10]).
3. Initiate the SPI Transfer by setting the manual start command bit in the control register
(SPI_CR[16]).
The SPI Module will assert the programmed chip select and start transmitting and receiving data.
Receive data will be availible in the receive FIFO once the module has transmitted at least 1 byte.
The ‘RX not empty’ bit (SPI_SR[4]) in the status register can be used to determine if there is data
which can be read.
Completing a transfer
If no data is added to the transmit FIFO, the transfer will end once the TX FIFO is empty and the
last bit is transmitted by the SPI module. The module will stop the SPI clock and deassert the
chip-select.
Transfers can be extended by writing additional bytes to TX FIFO before the end of the current
transfer. When extending transfers, make sure there is su�cient room in the RX FIFO to receive
additional bytes. Data can be read out of the TX FIFO during a transfer to ensure there is no
over�ow.
Once a transfer completes, another transfer will not begin until it is initiated through the manual
start command bit.
Most SPI slaves consider a transfer complete when the chip-select is deasserted. Using manual
CS allows the processor to add additional bytes to a transfer without needing to ensure the TX
FIFO remain �lled. For longer transfers, this also allows the processor time to read data out of the
RX FIFO before continuing the transfer. In auto-start mode, the module will begin transmitting data
once it is enqueued in the TX FIFO.
In the SPI control register, con�gure the baud rate, phase, and polarity as desired. In manual CS
mode, the chip select will always re�ect the selected line in the control register. Before enabling
manual CS, make sure no slave is selected (SPI_CR[13:10] = 4b1111). Now, set the manual CS bit
(SPI_CR[14]=1), and clear the manual start enable bit ( SPI_CR[15]=0).
Software now has control of the chip select lines through the control register ( SPI_CR[13:10]).
Transfers can be started by placing data in the TX FIFO.
The ZYNQ is the SPI bus master, so bit 0 in the control register must be set to ‘1’. Note the SPI
controller can be put in slave mode – that would be useful if another processor wanted to treat
the ZYNQ device as an SPI slave.
The Inertial Module Uses SPI Mode 3 for communication (CPOL=1 and CPHA = 1). That means
data is shifted out on the falling edge of SCLK, and the slave latches data on the next rising SCLK
edge.
The LMS9DS1 has a max SPI clock speed of 10MHz, any clock speed below 10MHz will work as
well. The SPI controllers clock divider can only divide the input clock by powers of 2 according to
the formula Baud_clk = 166MHz / 2^(n+1). A divider value of 32 (n = 4) gives ~5.2MHz, which
falls below the 10MHz requirement.
To communicate with the accelerometer/gyro in the LSM9DS1, SS0 must be selected, and to
communicate with the magnetometer, SS1 must be selected. These signals are driven directly
(and not through an external decoder), so the decoder option should not be enabled.
The chip select mode can be set to automatic by clearing bit 14 in the CR. With auto-CS is
enabled, the chip select will only drive when an SPI transaction is active.
In summary, to communicate with the LSM9DS1, you could con�gure the SPI module as such:
Once Con�gured the module can be enabled by writing 1 to the SPI Enable Register.
As mentioned, data protocols are not de�ned in the SPI standard, and they differ from device to
device. You must read the data sheet for any given device to learn how it communicates. Often,
manufactures de�ne different protocols and timings for different operations (single byte read/
write, multibyte, etc). The data protocols for the LSM9DS1 device on the Blackboard are described
here: Blackboard’s Interial Module
After completing an SPI read transaction, data will be available in the SPI RXD FIFO. Most reads
have 16 data bits, so after an SPI read the RXD FIFO will generally contain three bytes - the �rst
byte can be ignored, as it contains data read from the inertial module while the bus master was
sending the address. The next two bytes will contain the actual data for the register requested.
The accelerometer/gyroscope portion onboard nav chip handles SPI transfers in 2 phases. First
the SPI Master provides an address and indicates the type of transfer: read or write. The 7-bit
address is concatenated with a read/write bit to make up �rst byte of the SPI transfer (The read/
write bit is sent �rst, followed by the 7-bit address). In the data phase of the transfer the bus
master or the LSM9DS1 send bytes of data. There is a minimum of one data byte transferred, and
further data in the transfer will be read/written from registers at addresses indexed from the �rst
address.
Reading a Register
To read from a single register in the accelerometer, the SPI module needs to transmit 2 bytes. The
�rst byte contains a bit with the value of 1 (indicating a read), followed by the desired 7-bit register
address. The second byte is necessary as the SPI module only receives data when it is
transmitting. The data sent is irrelevant to the accelerometer, and thus can have any value. As the
SPI Module has sent out 2 bytes, it will also receive 2 bytes. As the data from the requested
register is received in the 2nd byte, the �rst byte read can be discarded.
Writing to a Register
A write to the accelerometer has the read/write bit set to 0. The data sent to the accelerometer in
the 2nd byte will be written to the requested register. As with all transfers, the SPI module will
receive as many bytes as are transmitted. While the bits received from the accelerometer during a
write are irrelevant, they will still be placed in the receive FIFO and should be �ushed from the FIFO
by being read.
Reading multiple bytes from the accelerometer will read from multiple registers; Each additional
byte will have the address read from incremented by 1.
As the data for each axis is held in registers with neighboring addresses this can be used to read
all the whole 16-bit reading for an axis in one SPI transfer. Furthermore, the addresses for the 3
different axes of the accelerometer are contiguous (This is the same for the gyroscope’s 3 axes
registers as well).