Difference between revisions of "ZX SPI"

From Spectrum
Jump to navigation Jump to search
(Created page with "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. ''F...")
 
 
(12 intermediate revisions by the same user not shown)
Line 2: Line 2:


''Features:''
''Features:''
* SPI clock from 1.75MHz to some absurdly low frequency (up to 16 stages of division, that would make 26 hertz!)
* SPI clock from 3.5MHz to 14kHz
* Supports CPOL 0 (normal clock polarity) and CPOL 1 (inverted clock polarity)
* Supports CPOL 0 (normal clock polarity) and CPOL 1 (inverted clock polarity)
* Full duplex
* Four chip selects
* Synchronous design that should work fine with an FPGA
* Synchronous design that should work fine with an FPGA
* Requires 81 macrocells.
* Requires 62 macrocells (fits an XC9572)


''Caveats:''
''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.
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.


The code can be obtained [http://spectrum.alioth.net/svn/listing.php?repname=ZXSPI&path=%2Ftrunk%2Fise%2F#path_trunk_ise_ here, from WebSVN]
The Verilog code and Xilinx ISE project file can be obtained [http://spectrum.alioth.net/svn/listing.php?repname=ZXSPI&path=%2Ftrunk%2Fise%2F#path_trunk_ise_ here, from WebSVN]
 
There's a demonstration of it in action on YouTube here: [https://www.youtube.com/watch?v=ptBa7qrxDao ZX SPI and Nixie display]


== Using ZXSPI ==
== Using ZXSPI ==
Line 24: Line 28:


  bit 7  - not used
  bit 7  - not used
  bit 6   - not used
  bit 6-5 - SPI chip select to use
  bit 5   - set to 1 to initiate an SPI read.
  bit 4   - 1 = use clock divider, 0 = don't use clock divider
  bit 4-1 - set clock speed
  bit 3-1 - set clock speed (bit 4 must be set to 1 to use this)
  bit 0  - select clock polarity (0 = CPOL 0, 1 = CPOL 1)
  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.
After the Spectrum is powered up or reset, the defaults are: Clock speed 3.5MHz, CPOL 0, using chip select 1.
 
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:
When reading from the register, the following bits are defined:


  bit 7  - 1 = Ready to read or write (0 = currently reading or writing)
  bit 7  - 1 = Busy, 0 = Ready for a new read/write operation
  bit 6   - 1 = SPI read has completed and there is data available
  bit 6-5 - SPI chip select in use
  bit 5   - Always zero
  bit 4   - 1 = using clock divider, 0 = not using clock divider
  bit 4-1 - Current clock speed
  bit 3-1 - Current clock speed
  bit 0  - Current clock polarity
  bit 0  - Current clock polarity


=== Setting SPI clock speed ===
=== 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 of the control register (0x053B) set the SPI serial clock speed. If bit 4 is set to 0, then the clock divider is bypassed and the 3.5MHz CPU clock is used as the SPI serial clock. Otherwise, if bit 4 is set to 1, the serial clock speed is determined by a simple 8 stage clock divider. The fastest speed (1.75MHz) is basically the Z80 clock divided by two. Here's a table of the speeds selectable when bit 4 is set:


  Bits 4-1  Speed
When bit 4 is set to 1:
  Bits 3-1  Speed
  0          1.75MHz
  0          1.75MHz
  1          875kHz
  1          875kHz
Line 54: Line 58:
  6          27kHz
  6          27kHz
  7          14kHz
  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!
=== Chip selects ===
 
There are four chip selects, so you can have up to 4 SPI devices. The active chip select is specified by bits 6 and 5 of the control register. The mapping looks like this:
 
Bit 6  Bit 5  Chip select
  0      0        1
  0      1        2
  1      0        3
  1      1        4
 
Chip select pins on the ZX Breakout will be 67, 68, 71 and 74 for chip select 1 to 4 in that order.


=== Writing to 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.
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 1, then it's still busy sending. Once bit 7 goes back low you can send a new byte.


=== Reading from an SPI device ===
=== 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.  
Reads happen simultaneously to writes. SPI devices don't have an explicit RD or WR signal to specify which one is being done. When you write to an SPI device you get a read for free. If you need to read from a device, but it's not expecting to be written to, then write whatever the device's idle state (for example, 0xFF) is when you write to port 0x043B which will initiate the operation. The data sheet for the SPI device should specify what this is. Once the SPI operation is complete, and the 'busy' bit (bit 7 of the control register) has returned to zero, then reading port 0x043B will return whatever the SPI device deposited on the MISO line.
 
The same comments about multiple writes in the above section (checking the control register's bit 7) applies to reading too, since they are effectively the same operation.
 
=== Speed of INI/OUTI versus SPI operations ===
 
The SPI read/write operation starts on the next rising clock edge (don't forget that the edge connector CLK signal is inverted with respect to the clock the CPU sees) after the IO write completes. The I/O operation is performed on the 4th M cycle of an INI or OTI instruction. The fastest possible read and write you will be able to do is something like this:
 
    ld bc, 0x053B    ; B must be 1 greater than I/O port
    ld hl, ptr
    outi            ; write (hl) to port 0x043B
    inc b            ; SPI write will begin during execution of this instruction
    outi
    inc b
    outi
    ...
 
The SPI operation takes 8 T-states to complete at full speed, since one bit is read/written to MOSI and MISO per T-stat. This starts on the next rising edge of the internal SPI clock, which will be halfway through the first T-state of INC B. Therefore the SPI operation is guaranteed to have completed before the next OUTI writes to the device. The INC B and first 3 M-cycles of OUTI will require 16 T-states to complete, and the IORQ line doesn't go low until the 17th T-state. This will mean that a 1.75MHz serial clock should be usable in the code above. In this case:


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.
    ld bc, 0x043B
    out (c), a
    out (c), d
    out (c), e
 
only the 3.5MHz serial clock is fast enough for the SPI operation to complete before the next OUT. The OUT (C), r instruction has 3 M-cycles, each 4 T-states long, so there will be 9 T-states from IORQ going high until the next OUT operation beginning.
 
At lower speeds you'll either need to calculate how many T-states it'll take to complete the SPI operation, and see if your code takes longer than this in between subsequent I/O operations. In the case of a slow SPI serial clock, for a machine code program you'll probably need to check the contents of bit 7 of the status register (0x053B) before starting a new I/O operation.
 
You can ignore contention - except on a +3 or +2A/B - because the serial clock is directly derived from the CPU clock, and so while the CPU clock is halted during contention periods, then so will the serial clock. However, this is not the case on a +3 or +2A/B since the CPU clock keeps running and contention is achieved by other means. So for these machines you'll need to use uncontended memory if you want your T-state calculations versus SPI operation calculations accurate.


== Default pins ==
== 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.
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 and the adjacent pins on the top row.


The pin assignments by default are:
The pin assignments by default are:
Line 78: Line 116:
  64  MOSI (master out slave in)
  64  MOSI (master out slave in)
  66  MISO (master in slave out)
  66  MISO (master in slave out)
  67  Chip select (active low)
  67  Chip select 1 (active low)
 
68  Chip select 2 (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.
71  Chip select 3 (active low)
74  Chip select 4 (active low)


[[Category:ZX Breakout]]
[[Category:ZX Breakout]]

Latest revision as of 21:34, 25 June 2013

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 3.5MHz to 14kHz
  • Supports CPOL 0 (normal clock polarity) and CPOL 1 (inverted clock polarity)
  • Full duplex
  • Four chip selects
  • Synchronous design that should work fine with an FPGA
  • Requires 62 macrocells (fits an XC9572)

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.

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

There's a demonstration of it in action on YouTube here: ZX SPI and Nixie display

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-5 - SPI chip select to use
bit 4   - 1 = use clock divider, 0 = don't use clock divider
bit 3-1 - set clock speed (bit 4 must be set to 1 to use this)
bit 0   - select clock polarity (0 = CPOL 0, 1 = CPOL 1)

After the Spectrum is powered up or reset, the defaults are: Clock speed 3.5MHz, CPOL 0, using chip select 1.

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

bit 7   - 1 = Busy, 0 = Ready for a new read/write operation
bit 6-5 - SPI chip select in use
bit 4   - 1 = using clock divider, 0 = not using clock divider
bit 3-1 - Current clock speed
bit 0   - Current clock polarity

Setting SPI clock speed

Bits 4-1 of the control register (0x053B) set the SPI serial clock speed. If bit 4 is set to 0, then the clock divider is bypassed and the 3.5MHz CPU clock is used as the SPI serial clock. Otherwise, if bit 4 is set to 1, the serial clock speed is determined by a simple 8 stage clock divider. The fastest speed (1.75MHz) is basically the Z80 clock divided by two. Here's a table of the speeds selectable when bit 4 is set:

When bit 4 is set to 1:

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

Chip selects

There are four chip selects, so you can have up to 4 SPI devices. The active chip select is specified by bits 6 and 5 of the control register. The mapping looks like this:

Bit 6   Bit 5   Chip select
  0       0         1
  0       1         2
  1       0         3
  1       1         4

Chip select pins on the ZX Breakout will be 67, 68, 71 and 74 for chip select 1 to 4 in that order.

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 1, then it's still busy sending. Once bit 7 goes back low you can send a new byte.

Reading from an SPI device

Reads happen simultaneously to writes. SPI devices don't have an explicit RD or WR signal to specify which one is being done. When you write to an SPI device you get a read for free. If you need to read from a device, but it's not expecting to be written to, then write whatever the device's idle state (for example, 0xFF) is when you write to port 0x043B which will initiate the operation. The data sheet for the SPI device should specify what this is. Once the SPI operation is complete, and the 'busy' bit (bit 7 of the control register) has returned to zero, then reading port 0x043B will return whatever the SPI device deposited on the MISO line.

The same comments about multiple writes in the above section (checking the control register's bit 7) applies to reading too, since they are effectively the same operation.

Speed of INI/OUTI versus SPI operations

The SPI read/write operation starts on the next rising clock edge (don't forget that the edge connector CLK signal is inverted with respect to the clock the CPU sees) after the IO write completes. The I/O operation is performed on the 4th M cycle of an INI or OTI instruction. The fastest possible read and write you will be able to do is something like this:

    ld bc, 0x053B    ; B must be 1 greater than I/O port
    ld hl, ptr
    outi             ; write (hl) to port 0x043B
    inc b            ; SPI write will begin during execution of this instruction
    outi
    inc b
    outi
    ...

The SPI operation takes 8 T-states to complete at full speed, since one bit is read/written to MOSI and MISO per T-stat. This starts on the next rising edge of the internal SPI clock, which will be halfway through the first T-state of INC B. Therefore the SPI operation is guaranteed to have completed before the next OUTI writes to the device. The INC B and first 3 M-cycles of OUTI will require 16 T-states to complete, and the IORQ line doesn't go low until the 17th T-state. This will mean that a 1.75MHz serial clock should be usable in the code above. In this case:

   ld bc, 0x043B
   out (c), a
   out (c), d
   out (c), e

only the 3.5MHz serial clock is fast enough for the SPI operation to complete before the next OUT. The OUT (C), r instruction has 3 M-cycles, each 4 T-states long, so there will be 9 T-states from IORQ going high until the next OUT operation beginning.

At lower speeds you'll either need to calculate how many T-states it'll take to complete the SPI operation, and see if your code takes longer than this in between subsequent I/O operations. In the case of a slow SPI serial clock, for a machine code program you'll probably need to check the contents of bit 7 of the status register (0x053B) before starting a new I/O operation.

You can ignore contention - except on a +3 or +2A/B - because the serial clock is directly derived from the CPU clock, and so while the CPU clock is halted during contention periods, then so will the serial clock. However, this is not the case on a +3 or +2A/B since the CPU clock keeps running and contention is achieved by other means. So for these machines you'll need to use uncontended memory if you want your T-state calculations versus SPI operation calculations accurate.

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 and the adjacent pins on the top row.

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 1 (active low)
68   Chip select 2 (active low)
71   Chip select 3 (active low)
74   Chip select 4 (active low)