ZX SPI

From Spectrum
Revision as of 21:40, 18 June 2013 by Winston (talk | contribs)
Jump to navigation Jump to search

ZXSPI is a Verilog project to allow the Spectrum with the ZX Breakout (or any other FPGA/CPLD board) to work as an SPI master without all that inelegant bit banging in code.

Features:

  • SPI clock from 1.75MHz to some absurdly low frequency (up to 16 stages of division, that would make 26 hertz!)
  • Supports CPOL 0 (normal clock polarity) and CPOL 1 (inverted clock polarity)
  • Synchronous design that should work fine with an FPGA
  • Requires 81 macrocells.

Caveats: I've not done a great deal of Verilog, so it's likely the implementation can be made a bit more efficient. In particular, the parallel to serial and serial to parallel shift registers are double buffered, it's the easiest way of separating the two clock domains (Z80 clock and SPI clock domains), but it's probably possible to do something more convoluted that uses fewer flip flops. I've also not had the opportunity to test SPI reads on real hardware, only on the ISE simulator. It *should* work, but I need to get an SPI device that can be read from to test it.

The Verilog code and Xilinx ISE project file can be obtained here, from WebSVN

Using ZXSPI

The project uses two IO ports, performing full 16 bit port decoding:

  • Port 0x043B: SPI read/write
  • Port 0x053B: Control and status register.

The control and status register

When writing to the register, the following bits are defined:

bit 7   - not used
bit 6   - not used
bit 5   - set to 1 to initiate an SPI read.
bit 4-1 - set clock speed
bit 0   - select clock polarity (0 = CPOL 0, 1 = CPOL 1)

After the Spectrum is powered up or reset, the defaults are: Clock speed 1.5MHz, CPOL 0.

If bit 5 is set to 1 when writing to the register, all other bits are ignored. This is to save the trouble of having to read the port back, merge in bit 5 and send it again (or storing the settings in memory).

When reading from the register, the following bits are defined:

bit 7   - 1 = Ready to read or write (0 = currently reading or writing)
bit 6   - 1 = SPI read has completed and there is data available
bit 5   - Always zero
bit 4-1 - Current clock speed
bit 0   - Current clock polarity

Setting SPI clock speed

Bits 4-1 of the control register (0x053B) set the SPI clock speed. The clock speed is determined by a simple 16 stage clock divider. The fastest speed (1.75MHz) is basically the Z80 clock divided by two. So to determine the amount that the 1.75MHz clock is divided by, take the value (0 to 15) and raise to the power of two. Here is a table of the most useful clock speeds:

Bits 4-1   Speed
0          1.75MHz
1          875kHz
2          438kHz
3          219kHz
4          109kHz
5           55kHz
6           27kHz
7           14kHz
8            7kHz
9          3.5kHz

The ludicrously low speeds when the divider is set from 10 to 15 may be helpful while debugging, but probably not for actually running an SPI device!

Writing to an SPI device

After setting the SPI clock to the desired speed, writing is simply a matter of sending the byte you want to send to port 0x043B. If you need to send several bytes, and you know that the 8 bits will be written out on the SPI bus before you send the next byte, you can just write again to port 0x043B. However, if your code is in a tight machine code loop and the SPI clock is a low enough speed, it's likely the SPI write won't have finished. (A future update may be to not transfer the byte into the shift register until the previous byte has been sent so that two may be sent at once, but this is currently not the case). To check whether you can send another byte, read the control and status register and check the state of bit 7. If bit 7 is zero, then it's still busy sending. Once bit 7 goes back high you can send a new byte.

Reading from an SPI device

This is a little more complex, since the SPI master (the Spectrum) must initiate the read. It's not like RS232 where the remote end can start sending at any moment and completely independently, an SPI master must generate the clock signal to read the byte and assert the chip select line.

To start the SPI read, write out a value to the control register (port 0x053B) with bit 5 set to 1. When this bit is set to 1, all the other bits are ignored so you won't overwrite the clock speed or polarity settings. Then read back the control register. If bit 6 is set to 1, the read has completed. You can then read port 0x043B to get the byte. Just like for writes, if you're confident that the SPI read will be complete by the time you need to read port 0x043B, you can skip the check of the control register.

Default pins

If you don't modify the UCF file in the project, the SPI pins appear on the connector on the right hand side of the board, on the innermost column of pins. These are pins 61, 64, 66 and 67 on the CPLD and are labeled as such on the ZX Breakout.

The pin assignments by default are:

61   SPI clock (often known as SCL)
64   MOSI (master out slave in)
66   MISO (master in slave out)
67   Chip select (active low)

More chip selects can be easily added with a small modification to the Verilog. It's suggested that writing to bits 7 and 6 of the control register select which chip select pin is active if this is done.