Close

Z80 SIO Emulation by the PSoC

A project log for 3-Chip Z80 Design

Combining a Z80 retro design with a modern PSoC CPU.

land-boardscomland-boards.com 10/11/2019 at 18:150 Comments

This is the real meat of this project. Beyond the advantages of compact design, front panel, loadable firmware, etc., getting Z80 peripherals to work is key. What good is something that will run code if it can't deliver output and read input?

Grant's 9-Chip Design

Grant only has three I/O addresses mapped in his design:

  1. SIO (Two Channel UART)
  2. Bank Switch for CP/M
  3. I/O connector

I am not supporting an external I/O connector. I've got something in mind for the bank switching but don't need it yet. Bank switching isn't needed to run BASIC. So the only thing left is to get SIO emulation working.

Addresses

According to the schematic notes, the SIO base address is 0x00-0x07.  The address range is actually 4 addresses, not 8 addresses.

The lowest two address lines connect as follows:

A/B* selects between the two UARTS and C/D* selects between control and data. The monitor uses these addresses:

0071   0000             SIOA_D        .EQU    $00
0072   0000             SIOA_C        .EQU    $02
0073   0000             SIOB_D        .EQU    $01
0074   0000             SIOB_C        .EQU    $03

 A very quick look makes me think that the BASIC relies on the monitor for I/O so there's no need to support A2 (addresses 0x04-0x07).

PSoC Polling the I/O Interface

My first cut is that the PSoc will monitor the IOREQ* line to handle I/O. The PSoC is doing nothing presently once the Front Panel routine is done.

A second cut could be to do this with interrupts, but I'm not going that way until polling works.

PSoC Z80 Peripheral Emulation Hardware

The hardware has a mailbox for communication with the Z80.

The data from the Z80 is clocked into the Z80_Data_Out status register which can be read by the PSoC. Writing to the Z80_Data_In control register from the PSoC will allow data to be returned to the Z80. Direction control (output enable to the Z80) is enabled when the Z80 asserts both IORQ* and CPURD*.

The controller is a bit more complicated. It asserts WAIT* when there's an I/O request and removes WAIT* when the transfer is complete.

The IO_Stat_Reg lets the PSoC read the values of the IORQ*, CPURD*, CPUWR* and M1* lines. The M1 value determines if the IO access is an interrupt acknowledge cycle or a regular I/O cycle.

The IO_Ctrl_Reg is used to clear the IO Interrupt and deassert WAIT* by resetting the R-S flip flop. The d0 bit of the register is set up to cause a pulse when written which will deassert WAIT*. This is set up in the register configuration as:

There's also a status register (AdrLowIn) that has the Z80 address lines A0-A7. The address is latched at the falling edge of IORQ*.

Discussions