-
Notifications
You must be signed in to change notification settings - Fork 14
Hardware Design Notes
Several other people had the idea to combine an AVR with a Z80 before me, but these projects either didn't share any code or didn't provide all the capabilities that I wanted. I have taken inspiration from these projects but I designed this specific circuit and software implementation myself. The innovations not present in previous projects are described below.
The ATmega1284p doesn't have enough I/O to interface with all of the Z80's bus lines, so I used an I/O expander to provide two additional 8-bit I/O ports. I have tried to optimize performance by connecting the most frequently-changed signals directly to the AVR, and connecting those less-frequently changed to the I/O expander. The AVR has direct connections for the LSB of the address bus, the data bus, and following control lines: MREQ, IORQ, RD, WR, M1 and HALT.
The MSB of the address bus, the 3-bit bank address for the 512K SRAM, and the remaining control lines--INT, NMI, RESET, BUSRQ, and BUSACK--are on the I/O expander. This arrangement allows the AVR to do faster DMA than would be possible if the entire address bus were on the I/O expander. With just the upper 8 bits of the address on the expander, the AVR only has to use the slower SPI interface to change the MSB of the address bus once every 256 bytes of memory instead of for every byte.
The AVR produces a 10MHz clock signal for the Z80 using hardware PWM. However, care must be taken to avoid bus contention when switching the bus directions. Therefore, the AVR brings the clock under software control to perform cycle-exact timing when responding to I/O requests. Software control of the clock also allows the bus state to be traced for each clock cycle if desired. Under software control, the clock can achieve a maximum frequency of about 4MHz. When tracing information is being logged, the attainable clock rate slows down to several hundred KHz.
Because the AVR cannot respond to an I/O request quickly enough to satisfy the timing demands of the Z80, the IORQ line also sets a flip-flop that asserts the WAIT line on the Z80 to add wait states until the AVR can respond. The AVR polls the IORQ line in a tight loop and services the request when IORQ goes low. When the AVR has finished servicing the I/O request, it brings the reset line on the flip-flop low to deassert the WAIT line on the Z80. It then manually clocks the Z80 until the IORQ line goes high. At this point, it ensures that its data port is in input mode, releases the reset line on the flip flop, and restarts the PWM clock, allowing the Z80 to continue execution at full speed.
The HALT input on the AVR is connected to the Z80 through a diode so that it can also be grounded using a push button without shorting the halt pin on the Z80. Thus, it is possible to return to the AVR-based monitor system automatically when the Z80 executes a halt instruction, or manually by pressing the halt button. PB6 has the manual pullup resistor enabled so that the halt signal is high (inactive) when neither the HALT signal is asserted by the Z80 nor the button is pressed.
PB0 on the AVR is used as an output to flash an LED by the bootloader, so it cannot safely be connected to an output signal on the Z80. In the current design, it is connected to the IOACK line on the 74HCT139, so it can be safely used as an output during the boot process.
I have added a 74HCT139 decoder to allow the AVR to be assigned to none, all, or a selectable block of 64 I/O ports ($00-$3F, $40-$7F, $80-$BF and $C0-$FF). The flip flop will only trigger a wait state if the I/O address is within the selected range. This will allow the use of other peripherals alongside the AVR. I'm using half of a 74HC139 dual 2-to-4 decoder to do this, and the other half is used as an SPI chip select multiplexer to allow the AVR to control up to 4 SPI peripherals with just 2 I/O pins. The SPI signals are exported to the user pins on the RC2014 bus. The RC2014 bus lines USER1-6 are connected to SCK, MISO, MOSI, IO expander chip select, and 2 unassigned chip select lines, respectively. The traces to these pads can be cut or the pins can be omitted if this is not desired. The MCP23S17 I/O expander has a 3-bit serial addressing scheme so it should be possible to add up to 7 additional I/O expanders to the bus with only a single chip select line shared between all 8 I/O expanders. The I/O expander on the z80ctrl board is hardcoded to address 0.