A project to produce a kit for experimenting with z80 CPUs - More an embedded board than a PC
the list of things to investigate is growing faster than I can dig through it!
Until now the interface to the AVR has been a text interface. This was great for initial debugging but it gets tedious to have to paste hex into a console, and isn’t great for machine control. I’ve designed a rough binary protocol for this, and I’ve started writing a library and GUI utility to implement it. The idea is the library can also be built into command line tools for uploads
Speaking of testing and debugging, the memory programming seems to be a little broken. Not sure what happened there but I need to figure it out at some point.
I stumbled upon z88dk and it looks like it might be quite useful as a way to make C programming for the platform easier, while still allowing calling precanned rom utilities.
Hmm many things to look into!
I've spent quite a bit of time so far this weekend trying to interface to the MCP23017 I hope to use to interface to the address bus. The ATMega328p documentation on the TWI (Two Wire Interface) are a little dense, yet missing some useful details.
Anyway I have something working on a breadboard now to prove the concept of controlling the external pins.
The thinking is I can use one of these and the similar MCP23008 to interface to the address and data busses, freeing up MCU pins and also allowing me to use a smaller, newer and cheaper AVR.
I think one of the next tasks is going to be to rework the comms protocol to make it less string-based. This is mostly to make it easier to control via software rather than via a serial terminal app. This would make it easier to upload code to the board than my current copying and pasting of hex files into a console!
I got the buttons working! I needed to add some pulldown resistors (not sure how I thought it would work without them!) but it’s all fine.
It got me thinking a bit though and while I was lying awake thinking about z80 instructions rather than sleeping, I had a bit of a thought explosion about this.
Note: This post is a bit of a ramble so feel free to skip ahead to the summary at the end if you get bored!
The more I think about it, the PIO isn't the best choice for interfacing on this project. It was originally chosen since it is the companion chip for the Z80 for IO in a parallel form, however it's relatively expensive and only provides 8 bits of input or output. It does have some fairly fancy features like interrupt support but to be honest, I'm not really sure how useful they'll be in practice on this project. It's also a fairly big 40 pin IC so isn't exactly great for board space efficiency.
The more I think about it, some discrete logic could do the same thing practically but significantly cheaper and probably easier to work a board design around. As a bonus, it would be easier to program for though it wouldn't support more advanced use cases
Expansion Ports and Usability
The first iteration of the design has a 50 pin IO port exposing various z80 bus pins (think address bus, data bus, various other interface pins and some spare CPLD lines lablled nominally as chip select lines)
This isn't a bad start, but I think I can do better. I was thinking about what it would take to port CP/M or one of the BASIC variants to the board, and then I realised I'd wandered into the early PC territory I said I wasn't targeting. It got me thinking about what would make this board more useful than just something to blink LEDs as a response to switch presses. At that point I realised it needs more IO.
I'm thinking as well as the LEDs it should have 8-16 inputs and outputs exposed on a header for simple external control. This would make it more like a z80-powered development board rather than something you talk to over serial or a keyboard.
That's not to preclude making it run BASIC or something, but it does give me some interesting ideas in terms of the hardware design.
Programming The Thing
Originally I'd envisaged a fairly bare metal programming style where the user's code runs straight away at boot and includes the hardware setup. This setup code could, of course be included from a library of snippets - I had thought about providing some files to include for this. The more I thought though, the more I think it makes sense to provide more than this.
One of the aims for this is to make the Z80 as easy to work with as possible and to demonstrate the different parts of a computer in a fairly simplistic form. It would be useful to provide a library of functions for the user to be able to call into, to save time and also to make it easier to get going. Of course they would be more than welcome to code from scratch if they wanted to, but the more I think about it, they shouldn't have to. I mean, they would still be coding in Z80 assembler, but at least they wouldn't have too much boilerplate to worry about.
Then it occurred to me that there's no need for the user's code to even include these libraries - by default the EEPROM could have the setup code on it that rarely changes and the user could just upload their own code to a known location. Of course there would need to be an easy way to upload the boot code as well in case they accidentally or intentionally overwrite it, but it would make it easier for the user to focus on their own code.
Then I started thinking even more, and it occurred to me there could be a whole library of code present on the board for the user to call into. In order to leave space on the EEPROM for user code, this could either be some snippets that get pulled in on demand or another idea I had was to include some flash memory that gets bank swapped in when the user wants to call into it. Flash...Read more »
After an Easter weekend spent mostly debugging circuits and sleeping, I finally have blinking LEDs - about three hour shifts after I probably should have gone to bed...
Anyway, the biggest problem I faced was the PIO not working. In the end, I used a CPLD dev board I had handy to make a simple latch, figuring it would be easier to debug the IO writes with that. After some playing around, I finally remembered that The high half of the address bus on IO reads/writes actually comes from other registers. I tweaked the address decoder to ignore the high bits on IO activity and it worked! Even better, when I went back to the PIO it was working too!
I’m not sure I have input sorted yet but it’s certainly progress.
I already have a pile of small improvements (and some not so small) that I would like to make to the circuit so I’ll be exploring those ideas soon.
the boards arrived today just in time for some Easter weekend fun!
I’ve assembled one and after some slightly tricky messes with the CPLD (firstly I forgot to configure the pin mappings when loading the completely untested VHDL file, secondly some pins got slightly bent on the socket so didn’t make contact) it generally seems to work as intended!
I haven’t tried actually programming the Z80 yet but the AVR is working as expected and the Z80 seems to be doing something in its unprogrammed state.
I’ve already decided the chip select lines need pull-ups - the issues with the cpld meant sometimes multiple chips were trying to drive the data bus which isn’t good (I first noticed when power consumption was slightly higher than expected!)
Next step I guess is to write some Z80 code! Or maybe procrastinate on that by working on the AVR uploaded more!
The only other issue I need to think about right now is that CPLD - it’s actually an end of life part, which means I’m having to use some programming software from 2013 and also of course it may be hard to get in future.
It’s not a huge issue for now but I will probably be looking for alternatives - there’s a Microchip part that might be suitable so I guess we’ll see. Part of me is tempted to make a partial address decoder out of discrete logic but that’s quite inflexible and would probably make this already relatively large circuit board even larger!
Since the last log I’ve mostly finished the AVR code for loading data into the EEPROM. Then things slowed down a lot. Firstly, I wanted to build some of the circuit on strip board however the piece of strip board I have is a bit too small and it’s a very tedious design to prototype this way. Likewise with breadboarding - there would just be a sea of wires! Yes I could do it, but the data sheets are clear enough I decided I’d just send off boards for production - Chinese PCB services are cheap enough to take a chance on (and I have done this a few times now for my other project, an LED matrix controller so I’m not sure why I wa so keen to prototype this the hard way)
But then another thing came up: I wanted to make a change to the design to make the AVR more capable - there aren’t quite enough pins available for it to control some of the lines. In the end I decided this can wait until a second revision. The design change in question is to add a tristate shift register or three to act as a port expander. This would also potentially allow for using a smaller AVR to make up for the board space taken up by the shift registers.
Then came the next challenge - Chinese New Year would slow down board production - I wanted to get an order in before then but in the end doubted myself enough that I didn’t - I was still thinking about that design change!
After that life (by which I mostly mean my day job) somewhat got in the way and nothing happened. Anyway a couple of weeks ago I tidied up the board design and today I finally submitted the order!
I decided to start by developing the AVR-based programmer for a couple of reasons. Firstly, I’m somewhat more familiar with AVRs than z80s. Secondly, the z80 parts will be much easier to develop if it can be done without ripping the eeprom out all the time.
It’s coming along nicely, despite some infuriating bugs and kinda awkward birds nests of address lines on the breadboard!
I still intend to try using some shift registers on the address and data lines, but I’ll get it working without then look into that - it should be a relatively simple code change once I get the wiring sorted.
Next I need to write something to receive dats over serial and write it to the eeprom - I’m thinking it might make most sense to just send intel hex format over serial. I actually have some software flow control implemented, so hopefully I won’t lose any bytes!
a large pile of components were delivered today. Unfortunately I have to go to work :(
Things to test/do in no specific order:
I suspect I can do this as two separate projects then bring them together later - the only thing that actually ties them together is the busreq and busack lines to coordinate bus access. Well, that, and the fact that programming the z80 is that bit more difficult when you have to pull the ROM off a breadboard - it shouldn’t be too bad.
It might not be a bad idea for the AVR to be able to reset the CPU - though like many of my ideas it would require a set of shift registers for port expansion to actually be able to do that. I guess that’s something else to try!
The code is basically a bunch of C so it shouldn’t be too hard to support both modes for testing if I wanted to.
I have done an initial PCB layout (Thanks to Diptrace’s autorouter!) and started writing some AVR C for the programmer.
I have been working on a PCB layout - I haven’t spent too much time on it so far, but I do think what I have would work quite well. Obviously, it is not the final design - for that I’ll need to do some extra tests on a breadboard first!
The usual wisdom is to avoid the autorouter, but for this board it seems to be the best option - there are so many through hole components I was struggling to route it by hand. I might be able to do better on another attempt, but it at least proves the board is routable! I’ll come back to this later.
As mentioned before, the design currently includes an ATmega8515 as an EEPROM programmer for downloads of z80 code. The 8515 is an older part, but is about the only thing with enough pins for this. Initially I chose it because it’s cheap, but actually, all other parts have A/D converters on - and therefore you lose a pin or two to Things like ARef. This does mean I need to be fairly careful to make sure my code fits into the 8Kb of program flash - That said it isn’t looking too bad so far as long as I am careful. Link time optimisation helps a lot here.
I have a suspicion I’ll end up using tristate shift registers as a port expander - however that’s not without its own problems - not least that it adds cost and components. The other option would be to disable in circuit programming (probably not actually incredibly useful if the microcontroller has a boot loader on it) but that would me a anyone wanting to use a blank Atmega8515 would need to be able to program it in parallel mode, raising the barrier to entry somewhat. Still, it’s an option though it wouldn’t be perfect since it wouldn’t allow me to both use a different AVR and drive more pins at the same time- only one or the other. That might be fine, but I can’t shake the idea that using a different AVR might be advantageous somehow.
Ive been writing and testing some of the code using the ATmega328 currently on a spare arduino board - it provides enough (power, serial) to be able to test some of the code - and I can’t get going on testing the meat of programming the EEPROM until my component order arrives anyway - and the ATmega8515 is in the same order.
It’s beginning to take shape nicely. I do wonder if I’m worrying too much about the whole pin count thing on the AVR - it’s a somewhat theoretical problem right now!
I have been thinking I probably need to use a boot loader on the AVR - tho is would make future updates a whole lot easier since it wouldn’t require a separate programmer.
Another idea I had would be to clock the AVR faster (I currently have it using the same 8MHz clock as the Z80) and use software USB instead of serial. It might allow faster data transfers and be easier to work with - on the other hand, serial is easier to use - but would probably require some form of serial to USB converter! Hmm, decisions... Clocking the AVR faster might also allow it to monitor the busses in real time - though I’m not sure how fast it would have to be - and given I might have to use a shift register it might need to be quite a bit quicker to be useful. Again, more tests and thinking needed here.
I’ve been researching and playing around with schematics for a few days now and I think I’m getting somewhere. A non-exhaustive list of what I have is:
One of the things I’d like to have in this design is an easy way to program the EEPROM within the circuit to create something more self contained. Currently I have an ATmega 8515 in the design - mainly because it’s the cheapest AVR on RS with enough pins to do this. It sits on the address and data busses so it should be possible to have it read and write the SRAM as well. Unfortunately it can’t use the IO components because there weren’t enough pins on the microcontroller for the IO toggle line. I have an idea though that might allow it access to more pins - or maybe even allow using a smaller microcontroller. The only issue is it requires some extra ICs and the part count is getting quite high!
In no particular order, the next steps are:
Right now there are a few things that need more thought: