SPI (Serial Peripheral Interface), is a useful communication style originally developed by Motorola. It uses four communication pins along with a power and ground pin so SPI is easily used with the 6 pin as well as the 12 pin Pmod standard. In SPI there is generally a “master” device (the host board) and a “slave” device (the Pmod) that communicate with one another.
To do so, the “master” will select one of its “slaves” with it's slave select (SS) communication line to indicate to the Pmod that it is going to communicate with it. The master and the slave will then simultaneously communicate with each other (a full duplex operation) on the MOSI (Master Out Slave In) and the MISO (Master In Slave Out) data lines. Both the master and the slave send one bit of information to each other after the master sends out a clock pulse on the SCK line to ensure that the timing of the data transfer is correct. Once a full byte, or eight bits of information have been sent to each other, the master (based on whatever code the programmer chooses) can communicate again with the slave device or stop its communication with the slave device.
With its full duplex capability, SPI is a fast communication standard. It can also support having multiple slave devices, but additional SS data lines would need to be added which takes up Input/Output pins on the host board which could have been used for other operations.
Actually sending out the data
Here, we will explain how one would actually get their system board to use the SPI protocol from a microcontroller standpoint. Note that this example will be for a general case and is not guaranteed to be applicable for every situation; please check the reference manual of your specific Pmod or module for more details.
In order to let the on-board chip know that it is going to be communicating with the master, the host board must bring the Chip Select line to a low voltage state and maintain that low voltage state throughout the entire communication session. Data can then be simultaneously transferred one bit at a time between the two devices with the host board controlling the timing of the transfer.
Commonly, the SPI protocol transfers one bit of data on the falling edge of Serial Clock signal that is generated by the master device. Consequently, data must be made available/readied to be placed on to the data line prior to the falling clock edge, as well as the necessity that the clock line must be at a high voltage state prior to being able to “fall” to a low voltage state. This can be done with a microcontroller by changing the voltage state of the MOSI data line prior bringing the clock signal to a low voltage state.
The cycle of changing the bit value (voltage) on the data line and pulsing the Serial Clock line can then be continued until the appropriate number of bits, dependent on what the on-board chip expects to send/receive, have been transferred. The Chip Select line will then need to be brought to a high voltage state to let the on-board chip know that communication has been terminated so that it can process information for another transfer.
Both the master and the slave device must send a bit to each other in order for the SPI protocol to work as designed, even if you as the user are only intending to just receive or just send data. However, it is perfectly viable to send “junk data” as the required counterpart to the incoming (or outgoing) bit. It is also possible to simply have the unneeded data line unconnected, leaving the two devices to read the “junk voltage value” that is on the floating line.
Unlike other communication protocols, SPI is rather versatile in the fact that it is able to transfer data in a variety of ways. Naturally, this will depend on how each on-board chip on the Pmod wants to receive the data, but information can either be sent with the most significant bit (MSB) first or the least significant bit (LSB) first.
Additional versatility comes with the four different SPI clock modes that are available to choose from. These modes adjust if the clock signal starts at a high or low voltage value and if bits of data are transferred as the clock signal transitions to its high state or transferred as the clock transitions to its low state. The configuration of each of these clock modes are outlined in the table below. Again, each of these modes are chosen based on how the device expects to receive the information.
|Clock Starting Position||Data is placed on the||Data is received on the|
|SPI Mode 0||Low||Falling edge of the clock||Subsequent rising edge of the clock|
|SPI Mode 1||Low||Rising edge of the clock||Subsequent falling edge of the clock|
|SPI Mode 2||High||Falling edge of the clock||Subsequent rising edge of the clock|
|SPI Mode 3||High||Rising edge of the clock||Subsequent falling edge of the clock|
So, if we wanted two devices to send to each other a value of 210 via SPI, with the most significant bit first and the data placed on the falling clock edge, we would first have the master bring the chip select line low, then bring the clock signal high, have each device “load” the appropriate bit onto the data lines (to ensure that the data available to be placed on the line), and then have the master bring the clock signal low. Both devices can then “collect” the bit of data that was on the line. This would be repeated until all the bits have been transferred and then the master would finally bring the chip select line high again to end the communication. An (admittedly) exaggerated timing diagram of how this might look is provided below.
What pins do I use
While it's one thing to understand how SPI works and know that it's full duplex and even the different possible SPI modes that are available, all of that knowledge is next to useless if you don't know how or where to connect your SPI compatible module to your host board. We will focus on how to determine where we need to connect our SPI module to a microcontroller, since you are able to assign the pin locations yourself for an FPGA.
There are two ways to implement SPI on a microcontroller: you can use a hardware implementation of SPI (which is one of the benefits of a microcontroller, having hardware implementations of common interfaces such as SPI) or “bit-bang” SPI by implementing and controlling each of the SPI lines through software. With bit-banging, you can choose which digital pins to implement your SPI pins. With the hardware implementation you have a specific set of pins that you need to use in order to implement your communication protocol. To figure out which pins you need to use on your host board, it is best to look at the reference manual for your system board.
Say you have a Digilent's chipKIT WF32. If you go to the reference manual, you can go to the Peripheral IO Functions and find the SPI section. Here we can see that the default DSPI0 (Digilent SPI 0) is located on pins 10, 11, 12, and 13 for SS, MOSI, MISO, and SCLK, respectively.
More details about the SPI protocol that go beyond the scope of this article can be found on SPI's Wikipedia page.
A list of Digilent Pmods that use the SPI protocol (or a related variant) are listed below (and to be filled out in the near future):
|SPI compatible Pmods|
|Pmod Name||Variant in Protocol?|
|PmodALS||Only sends data to the host|
|PmodDA1||Only receives data from the host|
|PmodDA3||Only receives data from the host|
|PmodDA4||Only receives data from the host|
|PmodDPOT||Only receives data from the host|
|PmodMIC||Only sends data to the host|
|PmodOLED||On receives data from the host|
|PmodTC1||Only sends data to the host|