There is one aspect of logic design I’ve been totally neglecting, at least until now. It is related to unconnected (floating) inputs of certain families of 74-series chips. I realized this having read a couple of articles on the web, particularly this article comparing TTL and CMOS families, this class on allaboutcircuits.com, and this paper from Texas Instruments. I am not an electrical engineer, so this aspect of logic design was new to me.
Since I am using only 74-series TTL chips in CPU prototype (LS-type, bipolar), I could safely leave the pins of unused gates unconnected, as TTL inputs have a tendency to float to a logic high level when nothing drives the line. However, this is not the case for CMOS chips (HC-, AC-type and alike). It is strongly inadvisable to leave floating inputs of CMOS gates, and no assumptions should be made as to the logic level of such inputs. Even worse, however, floating inputs of CMOS tend to fall into unstable state, causing the device to oscillate, drawing lots of current and affecting the entire circuit. I observed this phenomenon with a scope using a simple 74-series HC chip on a breadboard, and the noise it caused in a simple AND gate was truly horrible. The reason why CMOS gates behave in a different manner than TTL is a type of transistor used internally in these (BJT for TTL vs. MOSFET for CMOS). This is thoroughly explained in multiple papers on the web, so I won’t even try to explain the concepts I just barely grasp. If you’re interested, just google ‘TTL vs CMOS’, and you’ll get dozens of useful resources.
Despite my unawareness and lack of experience, I’ve been lucky to stay out of trouble until now, because I am using mostly TTL parts in the prototype, and any CMOS parts I have (memory, microcode ROM) have all their inputs always connected and in determined states. However, I am planning to build the PCB version using CMOS chips for better speed and noise immunity. In this case, extra care needs to be taken in order to make sure all unused gates are connected to either power or ground (see picture) to prevent them from floating, and the circuit from intermittent oscillation. Connecting unused inputs is the easy part. The hard part is related to buses. Consider a bus system with several devices driving the bus. If there is always some device driving the bus, there is no problem. Yet, if all bus drivers are in inactive (high impedance) condition, the bus floats. In this case devices connected to the bus have their inputs in an undetermined state. They may fall into oscillation, which will cause unacceptable voltage drops and the entire system immediately malfunctions. In my design I have identified three cases when buses are floating:
Memory is read, and bus interface (8-bit DBUS to 16-bit ALUBUS) drives high byte of ALUBUS with DBUS value. This happens whenever higher byte of register is loaded from memory, e.g. when microcode instruction HI(A)<-MEM(SP) or alike is executed. In this case low 8-bits of ALUBUS remain floating. In contrast, when low byte is loaded to a register, the high 8-bits are driven with the sign bit of low byte (for sign extension), and no floating occurs.
8-bit MSW drives 16-bit RBUS. MSW was originally planned to be full-width, but ended as an 8-bit register (despite its name, instead of being a machine status word, it is rather a machine status byte). Whenever it’s read, it drives the low byte of right ALU bus (operand B). The high byte of the bus remains floating.
Memory address which maps to a write-only register or device is read. There are some memory regions, which are of special purpose. See this post for examples. Memory address decoder may map these addresses onto write-only registers or write-only devices. When read operation from such addresses is attempted, no device is enabled and nothing drives the data bus (DBUS). It remains floating for the entire clock cycle.
Without any precautions, my CPU would never work when built entirely of CMOS chips. The solution to this is a bus-hold. Bus-hold is a circuit whose only role is to keep the bus in a determined state at all times, even when there is no device driving the bus. There are also other methods to make a signal level always-determined. The easiest would be to employ pull-up resistors on every line of the bus. Whenever all bus drivers are inactive, pull-up resistors make sure the state of the line is high. Seems easy, but there is a trick. There exists a trade-off which makes this approach barely usable. Pull-up registers affect signal rise and fall times. The higher the resistance of pull-up resistors, the greater the effect. The lower the resistance, the greater power consumption. Detailed calculations (see Texas Instruments’ paper) suggest resistor values of around 100 ohm, enough to keep reasonable maximum signal rise time, way to low when you consider increased power draw.
A much better solution is a true bus-hold. Bus-hold is any circuit that feeds back the output signal of a gate through a resistor, to its input. As a result, the line is always driven by a hold circuit. On the other hand the effect is so week that whenever a real driver attempts to drive the bus, bus-hold immediately changes its state (the driver overrides a weak feedback). In this case, propagation delay is not so important, neither is signal rise time, so high value resistors may be used. You only need to make sure that the voltage drop across the resistor ensures acceptable logic levels. A good starting point is a 10k resistor. Any non-inverting logic gate may be used as bus-hold. For buses it is most convenient to use a buffer, e.g. 74244 or 74541 (functionally equivalent to 244, but with different pinouts). The picture below presents my bus-hold circuit for the data bus.
I am not going to implement bus-hold circuits now for the three cases described above. As said, I have built the prototype with TTL parts so this would have little or no effect on my system’s stability and performance. Besides, I have almost run out of board space. However, the updated schematics will contain bus-hold circuits, and all unused gates will be connected to power or ground, to make the design CMOS compatible (for now, at least in theory). I should be posting the schematics shortly, as soon as I have completed hardware testing. I am almost there, currently trying to fix last known bugs. Time permitting I should be ready to declare construction completed in January.