Version 1.2: spi_master.vhd (8.9 KB)
SCLK immediately assumes the value of the CPOL input when the bus is idle
Version 1.1: spi_master_v1_1.vhd (8.8 KB)
Corrected ModelSim simulation error (explicitly reset clk_toggles signal)
Version 1.0: spi_master_v1_0.vhd (17.0 KB)
Initial Public Release
- VHDL source code of a Serial Peripheral Interface (SPI) master component
- Configurable number of slaves
- Configurable data width
- Selectable polarity and phase
- Selectable speed
- Continuous Mode for lengthy data streams
This details an SPI master component for use in CPLDs and FPGAs, written in VHDL. The component was designed using Quartus II, version 9.0. Resource requirements depend on the implementation (i.e. the desired number of slaves and data width). Figure 1 illustrates a typical example of the SPI master integrated into a system.
Figure 1. Example Application
An SPI communication scheme is a full-duplex data link, using four wires. The master initiates the transaction by pulling the Slave Select (SS) wire low. A Serial Clock (SCLK) line, driven by the master, provides a synchronous clock source. The master transmits data via the Master Out, Slave In (MOSI) line and receives data via the Master In, Slave Out (MISO) line.
A master can communicates with multiple slaves via a variety of techniques. In the most common configuration, each slave has an independent SS line but shares the SCLK, MISO, and MOSI lines with the other slaves. Each slave ignores the shared lines when its SS line is not pulled low. This topology is shown in Figure 1 above.
SPI has four modes of operation, based on two parameters: clock polarity (CPOL) and clock phase (CPHA). Master and slave must use the same mode to communicate articulately. If CPOL is zero, then SCLK is normally low, and the first clock edge is a rising edge. If CPOL is one, SCLK is normally high, and the first clock edge is a falling edge. CPHA defines the data alignment. If CPHA is zero, then the first data bit is written on the SS falling edge and read on the first SCLK edge. If CPHA is one, data is written on the first SCLK edge and read on the second SCLK edge. The timing diagram in Figure 2 depicts the four SPI modes.
Figure 2. SPI Timing Diagram
Table 1 describes the SPI master’s ports. The number of slaves is declared in the ENTITY by the GENERIC parameter slaves, and the transmit and receive data bus widths are declared by the GENERIC parameter d_width.
Table 1. Port Descriptions
The clock and clk_div inputs define the frequency of SCLK (i.e. the SPI data rate). clock is the system clock used to operate the synchronous logic inside the component. The clk_div integer input allows the user to set the relative speed at which the current transaction occurs. clk_div is the number of clock periods between SCLK transitions, as described by Equation 1.
When the clk_div port is set to 1, the SCLK frequency is half the clock frequency and is set at the maximum achievable data rate. The enable pin latches the value of clk_div into the component to begin each transaction, so it is possible to adjust the data rate for individual slaves.
Setting the clk_div port to a constant value permanently sets the data rate. If clk_div is set to 0, the component assumes a value of 1. Therefore, tying the clk_div port low configures the component to always operate at maximum speed.
The enable pin latches in the standard logic values of cpol and cpha at the start of each transaction. This allows communication with individual slaves using independent SPI modes. If all slaves require the same mode, cpol and cpha can simply be tied to the corresponding logic levels.
A low logic level on the busy output port indicates that the component is ready to accept a command. The component latches the settings, address, and data for a transaction on the first rising edge of clock where the enable input is asserted. On the following clock, the component asserts the busy signal and begins performing the transaction. Once complete, the component outputs the received data on the rx_data port. This data remains on the port until the component receives new data from a subsequent transaction. The component sets busy low to notify the user when the data is available, and the component is immediately ready for another instruction.
Figure 3 shows the timing diagram for a typical transaction. This SPI master is instantiated with four slaves and a four bit data width. It transmits the data “1001” to slave 2, which operates in SPI mode 3 (CPOL = 1, CPHA = 1). The master receives the “1010” data.
Figure 3. Typical Transaction Timing Diagram
During the final receive bit, the SPI master reads the cont flag. If low, the component completes the communication as described above. If high, the component latches in data on the tx_data port and seamlessly continues the transmission with the new data once the current data is exhausted. When the last bit of the current data finishes (i.e. when the first bit of new data appears on the mosi port), the component outputs the first block of received data on the rx_data port and deasserts the busy signal for one clock cycle to indicate this receive data is available. The receive data remains on the rx_data port until the new data communication completes and the component presents the successive block of receive data.
Figure 4 depicts the timing diagram for a transaction using continuous mode. This SPI master is instantiated with four slaves and a two bit data width. Once the component latches the initial data “10,” the cont port remains high and the tx_data port presents the new data “01.” After the component latches the new data, it sets the busy port low, which signals that the cont and tx_data ports can be cleared and that the first receive data “01” is present on the rx_data port. When the transaction completes, the busy signal again deasserts, and the new rx_data “10” is available.
Figure 4. Transaction Timing Diagram with Continuous Mode
Continuous Mode can transact very long data streams by being perpetually implemented. Tying the cont port low disables continuous mode.
The reset_n input port must have a logic high for the SPI master component to operate. A low signal on this port asynchronously resets the component. During reset, the component holds the busy port and all ss_n outputs high. The mosi output assumes a high impedance state, and the rx_data output port clears. Once released from reset, the busy port deasserts on the following clock, indicating the SPI master’s readiness to communicate.
This SPI master is a flexible programmable logic component that accommodates communication with a variety of slaves via a single parallel interface. It allows communication with a user specified number of slaves, which may require independent SPI modes, data widths, and serial clock speeds.
Accelerometer ADXL345 Pmod Controller (VHDL) – This design uses the SPI Master component described on this page to communicate with an Analog Devices ADXL345 Accelerometer. It also demonstrates the use of the Continuous Mode feature of this SPI Master.
Accelerometer ADXL362 Pmod Controller (VHDL) – This design uses the SPI Master component described on this page to communicate with an Analog Devices ADXL362 Accelerometer. It also demonstrates the use of the Continuous Mode feature of this SPI Master.
Ambient Light Sensor Pmod Controller (VHDL) – This design uses the SPI Master component described on this page to communicate with a Texas Instruments ADC081S021 analog-to-digital converter to gather data from Vishay Semiconductor’s TEMT6000X01 ambient light sensor.
ADC AD7476A Pmod Controller (VHDL) – This design uses a version of this SPI Master component that has been modified to include a second MISO data line. With 2 data input lines, the design communicates with (receives data from) 2 separate Analog Devices AD7476A 12-bit ADCs simultaneously.
DAC AD5541A Pmod Controller (VHDL) - This design uses the SPI Master above to communicate with an Analog Devices AD5541A single-channel, 16-bit digital-to-analog converter.
DAC AD5628 Pmod Controller (VHDL) - This design uses the SPI Master above to communicate with an Analog Devices AD5628 12-bit digital-to-analog converter. It configures the converter and sends commands, addresses, and data to control the converter’s 8 channels.
DAC AD7303 Pmod Controller (VHDL) - This design uses a version of this SPI Master component that has been modified to include a second MOSI data line. The design controls 2 separate Analog Devices AD7303 dual-channel, 8-bit DACs simultaneously.
DAC DAC121S101 Pmod Controller (VHDL) - This design uses a version of this SPI Master component that has been modified to include a second MOSI data line. With the 2 data output lines, the design sends data to 2 separate Texas Instruments DAC121S101 12-bit digital-to-analog converters simultaneously.
Digital Potentiometer AD5160 Pmod Controller (VHDL) - This design uses the SPI Master above to control the resistance of an Analog Devices AD5160 digital pot.
Gyro L3G4200D Pmod Controller (VHDL) - This design uses the SPI Master above to configure and retrieve information from an ST Microelectronics L3G4200D Gyro. It also demonstrates the use of the Continuous Mode feature of this SPI Master.
Joystick JSTK2 Pmod Controller (VHDL) - This design uses the SPI Master above to send commands and retrieve data from a PIC16F1618 microcontroller embedded in a joystick module.
NAV Pmod Controller (VHDL) - This navigation design uses the SPI Master above to retrieve data from an ST Microelectronics LPS25HB pressure sensor and LSM9DS1 iNEMO inertial module (3-axis accelerometer, gyro, and magnetometer), providing a total of 10 degrees of freedom.
Thermocouple Pmod Controller (VHDL) - This design uses the SPI Master above to retrieve information from a Maxim MAX31855 thermocouple-to-digital converter.