Theo Verelst Processor Card page

A short remark on the whole subject first: clearly it is possible to use an off the shelve microcontroller to do the stuff proposed here, and probably this is advantageous in various circumstances. The reason for taking the effort of to some extend documenting this design, apart from possible educational value (compare Z80 and 8051 instruction sets and it is soon clear why I say that) is that I found microcontrolers limiting in some respect, not as fast as I would have expected, and having no experience with them nor at this point the possibility of gaining it. Objectively speaking the cost of a design like this (depending on the price of the always needed anyway printed circuit board) in terms or parts compares not unfavorably to a microcontroller.
I built a working version design very similar to this on a breadboard a few years ago, to find out that my $2 cmos Z80 ran at least at 40MHz, and was amused enough to start a simple hand wired eurocard printed circuit board version. I found some very cheap connectors, prepared an analog card and a simple 68000 cmos card, to make create the basis for a stand alone system for IO, DCO and envelope generator, and other functions handy as a synthesizer or portable system substrate.
The test versions I did worked on solar powered rechargeable cells most of the time (keeping the clock rate down a bit). I interfaced parts to a acorn electron (I had no power at the time, all I used was a car battery, and the electron works fine on 12V), to tranfer data from the electron to the memory of the IO unit (in ill-fashioned but working shared memory mode). In fact I had to figure out the electrons IO mechanisms by using a professorically contructed 8 channel 30 MHz digital analizer driving the display unit, using some HC counters and a fast cache memory (fortunately low power as long as idle). Cracked the electron_write_out, and that sufficed. This to also make clear that having units of microprocessor logic may serve multiple services.
A part of the main sport in doing the design is allowing it to come to full clock stop with near zero power dissipation, which limits the use of pull-up resistors (a no no in cmos design anyway), and wired logic. What does an engineer kicked out of his university do.

A Z80 card design

The outline is as follows, and hardly surprising:

          |-------------|
          |    Clock    |
          |     and     |
          |    Reset    |
          |-------------|
                 |
                 |
                 V
          |-------------|
          |             |                 |------------|   |---------|
          |             |-----------------|            |---|         |
          |             |                 |            |   |         |
          |             |   Addres bus    |            |   |         |
          |             |                 |            |   |         |
          |             |-----------------|  Memory    |---|   IO    |
          |             |                 |            |   |         |
          |     Z80     |-----------------|            |---|         |
          |             |   Data bus      |            |   |         |
          |             |-----------------|            |---|         |
          |             |                 |------------|   |---------|
          |             |                         |  |       |  |
          |             |                         |  |       |  |
          |             |                        |----------------|
          |             |------------------------|   Addres       |
          |             |     Control signals    |   Decoder &    |
          |             |------------------------|   r/w logic    |
          |             |                        |----------------|
          |-------------|



It would be possible to use Z80 series PIO, UART, etc. but I wasn't aware of cmos versions for these, and they don't offer all the possibilities, flexibility and speed I wanted.

IO facilities

A major IO device I used for historical reasons is a 16 x 7 segment LED display unit with shared memory interface and autonomous multiplex circuitry, described here.
There are a ot more IO facils that I used, including hand-forced DMA to bootstrap the thing, lots of 74HC373's and 74HC573's to do buffered input and outputs (just a pitty that they have no zero power consumption with idle access lines, a mA or so remains), simply selected or clocked by a wired or gated nor-ed (don't rember) IOREQ and a simple IO 'device' selector (I may have used the dirty adress bit per device trick here, shh), and of course the circuitry behind these three state buffers such as a DA converter (see other page), a sample and hold clock generator, a midi output circuit, a large piano velocity sensitive keyboard access matrix driver and reader, a set of power mosfets for driving and pulse with modulating up to 50 Amp, per bit, and a set of comparator read back bits. I also had a single bit controling a audio channel by pulse width modulation, thats the nice part of a 40 instead of 2 MHz Z80.
The midi circuitry I did two ways: one way is simply to do a parallel serial conversion in software and us a single output bit to drive the midi channel over two 220ohm resistors, lets say the hardware cheap, software intensive way requiring a cristal locked clock. I didn't take time to debug this version, which could double as a midi-in, that midi pulse must be quite accurate, some midi devices bought it others didn't. The other way is an independent parallel-serial converter and start stop bit generator, that Id made for a trs80 clone years ago, simply by some coupled state machines implemented by random logic, counters and a shift register, unfortunately in power greedy ttl. Offer a byte, clock it in, and out goes the midi, just one out instruction in software, preferably with a readback of the busy bit, or a correctly timed delay loop not to mess with the current output word.
I didn't mention keyboard input yet, I used an old TI calculator matrix (non-capacitive) kayboard with 40 keys for the purpose, with nice 8 bit wide columns, that double as a binary word programmer interface when turned over 90 degrees, and connected it up with a trick, see below.

Bootstrapping and related circuitry

The main and easiest tricj is to start from reset (a wire or button in the breadboard) and force a dma straight away by pulling low the the n_dma request line. that renders all busses floating, and the advantage of having wired-ored and and-ed the control lines is, that you can make the pull up and down resistors force a state that makes the memory programmable, alternatively this can be forced by connecting the enable input of a 3 state buffer to the dma acknowledge out pin, connecting the control lines to its output, and adjust the inputs to achieve the right system state, by hand if needed. The prerequisite here is to have a clock pulse, otherwise the dma doesn't get activated in the 3d machine cycle (as I remember) of the first (random) instuction.
Te next thing is to program the memory to load a monitor, or, in my case, the little test programs of a few dozen instructions or so. This could be done in various ways, right until disconnecting the bus flatcables (assuming these are used), programming the ram by swithches or whatever, and reconnecting it. The most professional way I guess would be to make the dma acq also activate 3 state buffers to the address and data lines, and connect a nice address set and data set circuit to it. My cheap and simple way was to put the thing in dma mode, make sure the rm can be accessed, and have the keyboard input read buffer self latching to temporarily act as rs flip flops, forced up and down by two rows of keyboard switches, activated by a high and a low forced column. Sounds weard, but the idea is to have a 470k or so resistor feedback each output of the buffer to each corresponding input, to feedforward or latch. Then temporarily forcing a 1 or a 0 forces the bit up and down and the resistor keeps it there. the result is even debounced, although for this application that is not needed. To program the ram, its address bits must also be set, and this could be done by a 3 state register, a counter, or switches. I used trick here, because I had a 16 character LED display with a multiplex counter, so it seemed like a good idea to use the counter to step through the addresses and the displays as visual feedback device. I could have put a 3 state buffer between the counter output and the addres bus, and force the remaining bits to some value (0's for the zero page), but I used a rotary knob with binray coded outputs to force the upper address lines, a 16 word page, and simply connected the counter outputs to the bus by resistors (100k or so, don't remember). They won't interfere with normal operation, and cmos inputs are sensitive enough. Saved another 1mA for a 3 state buffer and board space, and had some more dynamically usefull advantages. A debounced 'memory location up' switch and a mode control flip flop to switch between run/program and simple or bootstrap programs can be entered memory location at the time by using the count up button (which I later also took from the calculator keyboard, just like the mode switch, by pressing two buttons at the same time), and for each bit setting the value by pressing the corresponding button in the 1 or 0 column. The display gives a feedback by lighting one of the seven segments or the decimal dot for each corresponding bit, and the display address corresponds to the memory address. Put the display in multiplex mode during progamming, and one page of memory is visible all at once, once you memorize which bit is which segment.
Remember I had this type of stuff figured out somewhere in the beginning of highschool when I realy needed to squeeze out all the possible functionality of every part I could afford. And in fact that display unit was supposed to be driven by an Intel 8080 processor, which had the annoying habit of multiplexing its databus with a processor status word containing some essential control information.

Memory

The main memory chips I used were battery backed 8k static cmos ram (6164 I think), which could easily be larger. The memory's R/W line can be (wired) or-ed with MEMREQ and WR processor line, and the select (and inv-sel.) lines can be directly with the MEMREQ and the adress decoder output line. The trick is to make sure the memeroy retention circuitry , consisting of a coupling of the VSS by diodes to both the 5V line and a 2.4V rechargable battery (kathodes to the memory supply lines of course. Sorry I don't have a graphical editor.) 1.2 seems to work fine as well, though outside offical specs, and in fact .1 volt didn't corrupt the data on room temperature either. A diode and charge resistor between the 5V and the battery makes sure it is recharged, and a capacitor duo (100uF and 100nF or so in parallel) make sure the memory works fine. Should mention I used germanium diodes for lower threshold, and that an alternative could be a fet coupling, or a spare 4066 gate. I experimented with other memories, of course similarly connected up, and even had a eeprom, but didn't program it yet, though lowering the clock rate to match the desired access speed should make it fairly easy to burn ina copy of the ram. The idea was to be able to exchange the bottom page of the progam memory by a few versions in ram (just fiddle top address line and accept a smaller addressable range, the way I did it, or smarter pertubate lower addresses), and in eeprom, simply by exchanging the zero page (of whatever fitting size).

Control and Address Decoder

The address decoder is basically simple, the Z80 seperates out an 8 bit IO address space parallel to the 64k memory address space by using n_MEMREQ and n_IOREQ lines. A bit unfortunately, they also double as DMA acknowledge lines when both applied, so some logic is needed to exclude unwanted memory access. Come to think of it maybe it was a different function: I have to do this from the top of my head, I checked the zilog pages to quickly reference the datasheets, but appearently the z80 is obsolete, or I just didn't take enough time to find it. Anyway some undesired control line combinations are needed to prevent bus clashes or undesired memory access. The rest straightforward, just carve out the desired address space sufficient for the applied RAM's size and enable the ram with it. Fortunately, the overlap of control and data timing is sucg that setup and hold times are easily met, and without doing a too detailed analysis, the resulting circuit works fine, right into the 40MHz range on a simple Z80A cmos version, and a 6116 70nS (I think it was) static ram. That is way outside spec (about 1.5 effective clock cycle per acces as I remember), but why not.
Talking about maximum operation speed, using ordinary random logic to do address decoding and access control may well be the speed bottleneck by messing up reliable memory access through control information delay and narrowed read write windows. Funny enough, using a breadboard and connecting parts up closely with the target pins to prevent paracitic C's, a wired or circuit on both the select and r/_w pin seemed to work fine, even with not too low pull up resistor values to keep power consumption down. I must mention I used a fairly old HC parts spec book, because I recently found that a few layers of modern HC would probably have sufficiently good delay and transient characteristics to work fine on speeds like this.
The 'mmu' in my version was extremely simple, just a split of the adress space in two by a top address bit, and sensing the MEMREQ.

Reset and clock

Using the standard 74HC16 schmitt triggers makes for easy clock generators and slow start reset pulses. Squeezing in a christal lock required some effort, I don't exactly recollect the resulting circuit, it was mainly a matter of matching the feedback resistor in the semi triange oscilator (and the of course) with the cristal impedance. I experimented with the maximum clock I could generate, because I wanted a divide by two two make a more symmetrical clock pulse (the schmitt triggers have unequal high and low output impedance, yielding and assymetrical pulse at the resistor values required for tens of megaherzes of clock pulses and a few tens of pF capacitors. At least I could get stable generator on a 3d overtone of somewhere in the 60MHz, and a breadboarded divider (74HC74?) worked fine, albeit at significant power consumption (and RF inerfearence..). The single gate oscillator version can easily be clocked down and up dynamically and doubles nicely as a debounce circuit for a single step mode.