Skip to content

SPI

The serial port sends no clock, so both ends have to agree on a speed and the receiver has to find the middle of each bit for itself. Between chips on the same board there’s a simpler way: send the clock too. SPI, the Serial Peripheral Interface, does exactly that, and it’s how a CPU talks to flash memory, SD cards, small displays, converters and sensors. The UPduino’s FPGA loads its bitstream from a flash chip over SPI every time it starts; this page has the 6502 reading that same chip.

SPI has a controller (the CPU’s side, which drives the clock) and one or more devices, joined by:

  • SCK, the clock, from the controller;
  • MOSI, data from the controller to the device (“controller out, device in”, as the old names had it: master out, slave in);
  • MISO, data from the device back;
  • CS, chip select, one per device, low to say “you”.

Inside, the controller and the device each have an 8-bit shift register. MOSI joins the controller’s top bit to the device’s bottom end; MISO joins the device’s top bit to the controller’s. So the two registers make a ring of 16 bits, and every clock pulse moves the whole ring one place: a bit goes each way. After 8 pulses, the two have swapped bytes. SPI never just sends or just receives: every byte sent brings one back. To read from a device, the controller sends something (anything) and keeps what comes back.

One SPI byte, edge by edge. The CPU’s shift register (left) and the device’s (right) are joined in a ring by MOSI and MISO. Each bit takes two edges of SCK: on one, both sides read the bit on their incoming wire (●); on the other, both shift along and put out their next bit. After 16 edges the CPU has the device’s byte and the device has the CPU’s. Try each mode: they differ only in where SCK rests and which edge reads.

Because the clock comes with the data, nothing has to agree on a speed: the device simply follows SCK, and the controller can go as fast as the slowest part allows (flash chips manage tens of MHz; spi.v goes up to 6 MHz, half its 12 MHz clock), or stop half way through a byte and carry on later.

The one thing the two sides must agree on is which edges do what, and that’s where SPI gets fiddly. Two settings, inherited from the different chip makers who used it first:

  • CPOL, the clock’s polarity: SCK rests at 0 (CPOL 0) or at 1 (CPOL 1).
  • CPHA, the clock’s phase: data is read on the first edge of each bit (CPHA 0), so each bit has to be out half a clock before, or on the second edge (CPHA 1), with each bit put out on the first.

Their four combinations are the four modes, 0 to 3. A device’s data sheet says which it uses; flash chips take modes 0 and 3. Get it wrong and the two sides read each other’s bits half a clock out, and every byte comes out wrong (shifted by a bit, usually), which is what the emulator’s flash does in modes 1 and 2.

Several devices can share SCK, MOSI and MISO, each with its own CS line. Only the selected one listens to the clock, and only it drives MISO: the others leave it floating (tri-stated, as on Memory and buses), so they can’t fight.

CS does a second job: it marks where a conversation starts and ends. A device treats the first byte after CS goes low as a command, and everything after it as that command’s address or data, until CS goes high again. So reading a flash chip is:

  1. select it (CS low);
  2. send the command $03, “read”;
  3. send three bytes of address;
  4. send anything, as many times as you like: each brings back the next byte from memory;
  5. deselect it (CS high).

Here’s spi.v, the computer’s SPI port, as it goes on the board:

spi.v, simulated gate by gate. To send a byte as the CPU would: set a to 0, d to the byte, sel, we and ce to 1 and clock once; then set them back to 0 and clock 16 times more. sck toggles each clock (the fastest speed), mosi gives d’s bits highest first, and shift_in collects whatever is on miso at each reading edge. edges counts down from 16. With a set to 0, q is the byte received.

The UPduino’s flash holds 4 MB. When the board powers up, the FPGA is the SPI controller: it reads its bitstream from the start of the flash (104,090 bytes for the UP5K, as on Inside an FPGA) and becomes the computer. After that, the flash just sits there, with almost 4 MB to spare, and the computer can read it through its own SPI port: a place for programs, music, fonts, anything too big for the ROM’s 8 KB.

AddressRegister
$8050DATAwrite: send this byte (and receive one); read: the byte received
$8051STATUSbit 7: busy, still sending
$8052CTRLbit 0: CPHA; bit 1: CPOL; bits 4–7: the speed, 12 MHz / (2 × (n + 1)): 0 for 6 MHz
$8053SELECTbit 0: the flash (its CS low while this is 1); bit 1: the device on the SPI PMOD header

A byte at 6 MHz takes 1.33 µs: done before the 6502’s next instruction starts, so a program hardly needs to check STATUS (the programs here do, to be safe at slower speeds).

The computer with SPI at $8050 and the flash on select bit 0, printing on the serial terminal. Below the terminal, each byte sent and the byte that came back ([ and ] are select and deselect). The flash’s ID sends $9F, “who are you?”, and three bytes to clock the answer back: a maker’s code, the kind of chip, and its size as a power of two ($16 is 22: 2²² bytes, 4 MB). The emulator’s flash answers as a common 4 MB chip does; the UPduino’s may give a different maker’s code. Read from the flash reads a line of text stored a megabyte in, past the bitstream.

The first program sends $AB before anything else: “wake up”. A flash chip can be put into a deep sleep to save power, and a program can’t be sure what was done to it before it started; one byte makes sure.

On the UPduino the flash’s SPI pins are also the USB chip’s serial pins (it uses them to program the flash, and the same lines double as its serial port), so the computer can use one or the other: board.v has a switch for which.

  • SPI sends a clock with the data: SCK, MOSI, MISO and a chip select for each device.
  • The controller and the device each have a shift register, joined in a ring: every byte sent brings one back.
  • CPOL and CPHA make four modes, and both sides must use the same one.
  • Chip select picks the device and frames each command; a flash read is $03, an address, then as many bytes as you like.
  • Any SPI flash chip’s data sheet (the 25-series parts from several makers): the commands, the modes, and the timing.
  • Motorola’s M68HC11 Reference Manual: one of the first microcontrollers with SPI, and its CPOL and CPHA settings.