I smell a mistake

Using the PB-503 proto-board I did a bit of testing with the 74HCT parts that I had ordered. Things worked very well. I got a 4-bit counter going and was able to feed 4-bit data into a register and use the bus drivers to get the data out. Doing it in slow-motion (1 to 5 Hz clock) I could see the data was correct on a row of LEDs. Then I did something that I have never done with digital chips before; I connected an output to my oscilloscope, and my jaw hit the ground. This is what I saw:

Output of 74HCT chip at 100KHz

Output of 74HCT chip at 100KHz

Now I didn’t get into university to study electronics like I wanted to, I’m self-taught by experimentation and the Internet, so I didn’t get a very rounded education. I always thought digital signals were… well… digital. Like, square waves. That thing on my screen was not a proper square wave. It had spikey things in it. What troubled me was the max and min voltage readings. Almost seven volts from a 5V power supply? Where was that coming from? And what the hell was that -1.68V negative spike? I had used bypass capacitors like you’re meant to. I never really understood why you needed them but always did it anyway. Wasn’t that meant to prevent this kind of thing? Just for fun I increased the clock to 1MHz and got this:

Output of 74HCT chip at 1MHz

Output of 74HCT chip at 1MHz

This made my blood run cold. How was this possible? If you are an experienced digital electronics engineer, you are laughing at me because you know why this was happening. Well, I didn’t, and I had to find out. Zooming in, I recognised the effect as a kind of ‘ringing’ which I am used to seeing coming out of my analogue synth – but my synth is meant  to do that; it has filters in it designed to muck up your square wave so it sounds cool. I want my digital square waves to be perfect. Why was there analogue stuff in them? I Googled something like “TTL output ringing” and over the next few days I read a lot about things I had never even dreamed of existed. ‘Ringing’, ‘ground bounce’, ‘noise’, ‘crosstalk’, ‘stray capacitance’ and a few other horrors that I forget. I also found out why you need bypass caps, which is nothing to do with this ringing problem. I realised I was in for a ton of random problems if I didn’t learn how to avoid those things. It seems you can’t just plug a load of digital stuff into each other without considering all kinds of weird analogue stuff that can happen to your signals. But I had done that. I had built digital stuff before, clocks and things. I had no scope to show me scary stuff and I always visualised the pulses as perfect square waves. What a poor fool I had been all these years. But wait — my circuits had worked, right? So my circuit would still work; just pretend I’d never looked at the waveform and move on. But I couldn’t. That would be like me pretending my variables were properly initialised in my code. No way, I couldn’t ignore this. I was going to have to find out and try to follow all the established rules for minimising this and any other horrors that were waiting for me. After I calmed down a bit it started to seem rather straightforward. Keep wires as short as possible, don’t run signal wires too close to each other, separate ribbon cable signals with interleaved ground signals, and so on. But this test was on a single output. It wasn’t crosstalk, it was most likely an impedance mismatch from what I could understand. Apparently fixable with resistors. But you don’t see tons of resistors in digital circuits preventing this kind of thing so that couldn’t be it either.

After a while I found that this particular ringing issue is probably nothing much to worry about. I’ve read other people’s CPU blogs and no one seems to care or mention this stuff. I’m probably over-analysing it as I have a tendency to do. For one thing, the evil-looking negative spike is dealt with by internal diodes in the chip inputs. I’m still not sure how the over-supply spike is handled by the chip, if at all. Still, maybe I’ll just have to ignore it and follow best practises.

My reading led me to find out a lot more things that I wouldn’t have known. Without some understanding of these issues I might have ended up with a CPU that kind of worked a bit, sometimes, at slow clock speeds or something equally useless. At least now I have a fighting chance of making it work properly. But all the reading led me to a new issue, the issue of choosing HCT chips over HC. I read a paper by Texas Instruments entitled SN54/74HCT CMOS Logic Family Applications and Restrictions and found, at the end, the following: “…employing HCT instead of HC devices in pure CMOS systems cannot be recommended. […] Due to the lower noise margin, there is an increased risk of interference caused by crosstalk, especially when the lines on the printed circuit board exceed a certain length. Moreover, the reduced switching threshold no longer ensures faultless operation of advanced bus systems used in microprocessor applications today.” I started to think I had made a mistake choosing HCT parts, as I had suspected earlier. My decision was stupid. I should have just found out if I could get all the parts in HC and then built the whole thing with HC instead of wondering if I would be able to, or if I would need to fall back on LS parts. I’m kind of troubled by how I let this happen. It’s not like me to plan something so badly. I had become a bit excited and got carried away. Not the sign of a good engineer. I had to stop and think about this all some more. I went to bed and slept on it.


Design decisions: Electronics

By the time I had finished the first draft of the simulation, I really felt like it would be possible to implement LEO-1 with real electronics. I had tested the simulator by spending a few days writing an assembler so that it would be easier to test by copying and pasting the assembler output into Logisim instead of having to work it out on paper and type the 16-bit instruction codes in. Now I had a simple assembler which I could use to program the real thing. I had to try and build it for real.

As I’ve mentioned before, I’m not totally new to digital electronics. I designed and built a digital clock in 1978 or so and I designed and built a decoder and display for the (now defunct) ‘Maplin Rugby Clock receiver’. I felt confident that I could get back into this fairly easily. I already had a soldering iron, multimeter, wire, basic tools and a cabinet full of spare electronic parts that I’d collected over the years. How hard could it be? I decided to find out by seeing if I could come up with a design for a single one of the 16-bit registers LEO-1 needs.

I had already decided that the 74 series chips was the way to go, just because I’ve always liked them (after I got over hating them), I’ve never really felt comfortable with the 4000 series CMOS parts, and many mini and mainframe computers like the ones I worked with in the 80s were made out of them. I read through this page to refamiliarise myself with some of the parts I was going to need and started to realise that in the last 20 years, things have changed a bit. Originally, in the 70s, I used plain old 74xx parts. These were the real TTLs. They got warm during use and were rather robust. Some were even made of ceramic instead of plastic.

Pictures I took of the clock project I did in 1993 show that I used 74HCxx parts. I’m not sure that at the time I knew that these parts are actually implemented with CMOS and are not really TTL compatible. The project worked because I used all the same kind (HC) and 5 volts (the standard TTL supply)  works for CMOS as well. What’s changed for the better is that there now also exist 74HCTxx parts which are implemented as CMOS but have a completely TTL-compatible interface. By using these, you get compatibility with old TTL parts like 74LSxx but they use less power. I needed to choose between HC and HCT. My decision was influenced by something (that I should have, but didn’t) expect: many of the 74 series are now obsolete and either very difficult or impossible to get. If I went with HC parts (which are ‘preferred’ for new designs), I would be locked into them and if a part was not available, I would be royally screwed. If however, I went with HCT parts, I would have the option of falling back on LS for difficult-to-get items. I decided to go with HCT for this reason. The only downside I could see was HCT’s ‘lower immunity to noise’. I’m not sure if that will affect what I’m doing; I hope not. In retrospect I think I may have made a mistake as I probably won’t need to interface to any LS chips and HC would have been a better choice, but I’m not going back now.

Anyway, after choosing 74HCT chips I ordered a few parts for prototyping the register board. While I was at it I looked into the kind of memory (RAM, ROM) I might want to try. I found a static RAM chip which provides 512k x 8 bits and figured I could use two of those to make a 16-bit memory. As for ROM, I’d like to try EEPROM (i.e., Flash memory in a chip) but I’m still doing research on that because of the need for a programming device to get the code into the chip. There are two options for this: build my own, or buy one. I think I’m going to have to go for option 2 on that. Still thinking about it though. Once I know which device I want to use, I can try and find an affordable programmer that supports it.

So, what do I need for a single register? It turns out that a pair of 74273 octal registers will do the trick. They latch the data in on a positive-going clock edge which is what my design needs, and they have two-state outputs. LEO-1 has four internal register buses which I called RIN, ABUS, BBUS and CBUS. The RIN bus is the register input bus and it will be constantly connected to all register inputs. The other three are the register output buses. ABUS and BBUS go to the inputs of the ALU and CBUS is used for writing a register to memory. This means that the output of every register has to be connected to three bus drivers which will enable any register value to be output to any of the A, B or C buses. The instruction decoder will ensure that only one register at a time can get onto a bus by selecting only one of the eight registers for each case of A, B and C. I chose the 74244 octal bus driver chip for this purpose. The 273 and 244 being octal (8-bit) chips means I have to ‘bit-slice’ to get 16-bits from pairs of 8-bit chips. So, one half (low 8 bits) of a register will need a 74273 register and three 74244 bus drivers, and the other half (high 8 bits) will need the same. This gives a total of eight chips per register for a total of 64 chips across all eight registers. While I was designing LEO-1 in the simulator, I didn’t give this kind of thing much thought. I’m now glad I didn’t try to design a 32-bit machine! Here’s a picture of the chips attached to a bit of static-proof foam:

Register chips

Register chips