Retro Z80: Input / Output

It has been a while but I am currently looking at a running Z80 with 64kb memory, running a small test loop-program. I have added some LEDs to the address and data buses to better see what is going on.

On the right is the System Controller (PSoC) with two USB links to the PC – one for programming the PSoC and one I use for communicating with the System Controller’s logic. In the middle, under that mess of wires is the Z80 (front) and a 64k RAM chip (back). Utmost left are the LEDs that show the address bus (front) and the data bus (back) as well as some other signals like, the clock, reset and halt (I use halt in test programs sometimes).



I have programmed the PSoC 5LP with a basic beginnings of a system terminal to interact with it from the PC. I currently have the following commands:

  • Memory-Write (mw)
    This allows you to send over a file that will be written to RAM. This is how I download a program or ‘program’ the Z80. The ‘mw’ command takes two parameters, first the start address in hex, second the number of bytes to expect and write (also in hex). I am planning to make the last parameter optional because it is a pain to have to specify that each time you want to write the entire program. The System Controller uses BUSREQ/BUSACK to gain access to the RAM chip.
  • Memory-Read (mr)
    This is the opposite of ‘mw’ and reads back what is in the RAM. Same two parameter also. The bytes are send back so you can display them in the terminal program that is running on the PC.
  • Clock-Mode (cm)
    This controls the clock that goes to the Z80. There are four modes: fast, slow, step and off. The fast clock runs in the MHz, the slow maxes out at 100Hz. The step mode is meant to manually pulse the clock with the ‘cp’ command (see below) and the off mode ensures no clock is sent out.
  • Clock-Divider (cd)
    The clock source (fast or slow) can be divided by 1, 2, 4 and 8. Gives you more to play with.
  • Clock-Pulse (cp)
    Pulses the clock line one time. It also sets the clock mode to step if that was not done yet. Unfortunately this does not work yet. I have not figured out how to reuse the same IO PSoC pin for a hardware connection and/or drive it in software. I also want to allow a mode that stops at every instruction (M1).
  • Reset (rst)
    This controls the reset line of the Z80. Issuing the ‘rst’ command without parameter will activate the reset for a fixed number (4) of clock-cycles. The Z80 needs a couple of cycles to properly reset. Using a numeric (decimal) parameter will use that value to wait with releasing the reset line. Using zero for the parameter, activates the reset line until another ‘rst’ command is issued. This is handy to halt (and reset) the Z80.

These command give me the basic tools to setup the Z80 (clock and reset), load the program in RAM (memory-write) and execute it (reset).

Input / Output

The next step is to allow the Z80 program to use input/output instructions to communicate with the outside world. I am currently trying to setup the System Controller to respond to IO address zero ($00) for debugging purposes. That will be the address the Z80 debug code will use to publish CPU register content etc.

The PSoC allows clocking in address (lsb) and data bus bits into status registers in hardware, which then can be read in an interrupt routing (on the PSoC) to further handle it and be ready for the next one. So the out-instruction will probably work pretty quick.

The in-instruction however, requires the System Controller (PSoC) to output data on the data bus when it has decoded the address. But that data has to be retrieved in software and will take relatively long to fetch. This will require the PSoC to activate the WAIT line on the Z80 to stall the CPU until the data has been fetched.


In the meantime I am also writing a bit Z80 assembly for the bios that will be running on the Z80. Nothing major yet. I have a routine that fills a memory area with $FF, which translates to the RST38 instruction. The idea is that when code jumps to an uninitialized RAM address, or IM1 is used by accident – I am planning on only using IM2 – it issues the RST38 instruction and there code runs that saves the CPU registers in a dedicated RAM block and communicates this fault to the System Controller (this is where I need the out instruction). I have also written a transparent assembly routine to save the CPU registers in RAM without affecting any of the register values. This also saves the alternate registers as well as IX, IY the stack pointer and the program counter.

Hardware Build

I just started to build a perf-board CPU module to migrate from my bread board setup to something more solid and less error prone. But this is not ready to receive the CPU and RAM yet.

All in all I am pleased with the progress. Most time is spent programming the hard- and software in the System Controller. Once I have the IO sorted out I hope to write more Z80 BIOS code to make at least the PC serial link available to the Z80 programs.



Published in: on February 13, 2016 at 4:22 pm  Leave a Comment  

The URI to TrackBack this entry is:

RSS feed for comments on this post.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: