Digital Design / Module 12: Projects and interview preparation
65. Minor project: SPI controller
Handle clock modes and shift timing.
Lab: Protocol waveforms
The goal
Build an SPI controller: a simple, fast, synchronous serial interface used for flash, sensors and displays. The controller generates a clock, so timing is easier than with UART. The challenge is getting the four modes right.
The signals
SCLK: clock, from the controllerMOSI: controller to peripheralMISO: peripheral to controllerCS_n: chip select, active low, usually one per peripheral
The four modes
| Mode | CPOL (idle level) | CPHA | Data sampled on |
|---|---|---|---|
| 0 | 0 | 0 | Rising edge |
| 1 | 0 | 1 | Falling edge |
| 2 | 1 | 0 | Falling edge |
| 3 | 1 | 1 | Rising edge |
CPHA = 0 samples on the first clock edge after CS falls, so the data must be valid before that edge. CPHA = 1 changes data on the first edge, and samples on the second. See the waveforms for each mode in the protocol lab.
Architecture
- A clock divider generates SCLK, usually with a programmable ratio.
- It also produces internal enables, marking which cycles are "sample" and "shift" points.
- hold transmit and receive data. Each transfer sends and receives at once.
- A small FSM goes through idle, chip-select setup, transfer and chip-select hold.
Don't use SCLK as an internal clock. Keep everything on the system clock, and use enables. This avoids a second .
Requirements for your project
- All four modes, chosen by configuration
- Programmable clock divider, and MSB or LSB first
- A valid/ready command interface
- A behavioural peripheral model in your testbench, which checks setup and hold
Common mistake
Forgetting the sampling delay on MISO at high speed. Your clock goes out, the peripheral responds, and the data returns, which takes real time. At high SCLK rates, the round trip eats into your sampling margin, so calculate it. Many controllers add an adjustable sampling delay for this reason.
Key ideas
- CPOL and CPHA define four modes.
- Generate SCLK from a divider.
- Check with a behavioural peripheral.
Your exercise
Interview questions
coreWhat do CPOL and CPHA set?
Idle clock level, and which edge samples data.
basicIn SPI mode 3, where does the clock rest, and on which edge is data sampled?
Mode 3 is CPOL = 1 and CPHA = 1. CPOL = 1 means SCLK rests high. With CPHA = 1, the first edge, which is falling, changes the data, and the second edge, which is rising, samples it. So data is sampled on the rising edge.
basicWhy is SPI called full duplex, and why does it not need oversampling like a UART?
The controller and the peripheral each have a shift register, and together they form a ring. On every clock, one bit leaves each side and one bit arrives, so a byte goes out on MOSI while a byte comes back on MISO. The controller sends the clock itself, so both sides know exactly when to sample, and there is no need to search for bit boundaries. That is why SPI can run much faster than a UART over short distances.
coreSCLK is made from a 100 MHz system clock by toggling every div system clocks, so the SCLK period is 2 x div x 10 ns. A peripheral allows at most 12 MHz. What is the smallest div, and what SCLK do you get?
SCLK at 12 MHz has a period of about 83.3 ns, so 2 x div x 10 ns must be at least 83.3 ns, which means div of at least 4.17. The smallest whole value is 5. That gives a 100 ns period, 10 MHz. div = 4 would give 12.5 MHz, over the limit.
coreWhy should the controller not use SCLK as a clock for its own shift registers?
SCLK is generated inside the controller, but using it as a clock creates a second clock domain, with its own skew, timing constraints and crossings back into the system clock. Instead, keep everything on the system clock and turn the divider's edges into enables, marking which system cycles are sample points and which are shift points. The shift registers are then ordinary flops with enables. This keeps the design in one clock domain and makes it far easier to time.
coreIn mode 0 the controller samples MISO half an SCLK period after the falling edge that launches it. SCLK takes 1.5 ns to reach the peripheral, the peripheral's clock-to-out is 7 ns, MISO takes 1.5 ns back, and the controller needs 1 ns of setup. Does 40 MHz work? What is the highest safe SCLK?
The round trip plus setup is 1.5 + 7 + 1.5 + 1 = 11 ns. At 40 MHz the half period is 12.5 ns, leaving 1.5 ns of margin. At 50 MHz the half period is 10 ns, so it fails by 1 ns. The highest SCLK with a half-period sample is 1 / (2 x 11 ns), about 45 MHz; beyond that, the controller must sample later, which is why many controllers have an adjustable sample delay.
coreA controller in mode 0 talks to a peripheral that expects mode 1. Nothing hangs, but the data is wrong. What does the wrong data typically look like?
The two sides disagree on which edge samples and which edge shifts, so bits are taken half a clock early or late. The usual symptom is data shifted by one bit position, so the byte looks almost right rather than random; for example 0x3C can come back as 0x1E. The peripheral may also be sampling MOSI exactly when the controller changes it. When SPI data looks slightly off, check the mode in the peripheral's data sheet first.
advancedIn CPHA = 0, the first clock edge samples. How does that affect when your controller loads the first MOSI bit?
Because the very first SCLK edge is a sample point, the first data bit must already be on MOSI before that edge, which means it must be driven when chip select falls, or during a setup time after it. So the shift register is loaded and its first bit presented when the transfer starts, and later bits are shifted on the trailing edges. In CPHA = 1, the first edge is a shift edge, so the first bit goes out on that edge instead. Getting this wrong typically loses or duplicates the first bit.
advancedWhy does an SPI controller's state machine usually have separate chip-select setup and hold states around the transfer?
Peripherals specify a minimum time from chip select falling to the first SCLK edge, and from the last edge to chip select rising, so they can prepare and finish the transfer. Many also require a minimum time with chip select high between transfers. Dedicated states with programmable counts let the controller meet these for any device, instead of assuming that one SCLK edge is enough. Checking these times is a job for the behavioural peripheral model in the testbench.