Simulating TTL Circuits

Summary

I’m going to continue with my logic simulator project in this post.  This project has turned into a serious obsession, ahem, hobby.  My final goal is to be able to simulate a full computer circuit.

TTL Logic

As I’ve mentioned in my previous posts, there is a wiki page for TTL logic that lists all the 7400 series circuit numbers (click here).  Once you find the right package number you can search for the actual data sheet.  For example, the 7408 is a quad AND gate circuit.  Here’s a data sheet for the 7408 chip manufactured by Texas Instruments (click here).  To simulate a 7408 circuit, I created an object that has a super-class of the AND gate that I used earlier.  I also fixed the number of inputs to 2, since the 7408 contains only 2-input AND gates.  Technically, I should put 4 distinct AND gates inside the 7408, but for now I’m just going to create package names for the common circuits.  Any TTL package that is directly represented by a circuit I created before will become a trivial setup just like the AND gate / 7408 circuit.  For more complex circuits, I’m going to wire up entire circuits.

The first circuit I attempted was the 74157.  This is a selector/multiplexer circuit.  The reason I chose this circuit is because it has a simple connection pattern:

74157_circuit

In order to create the circuit, I numbered the gates that would be needed, then I created connections for each output, starting with the labelled inputs.  So A1 connects to AND gate 0, input number 0.  AND gate zero connects to OR gate 8 input 0.  Etc.

I setup some unit tests to make sure the circuit operated correctly.  The unit tests are not exhaustive, so there could be a wiring error, but it looks good for now.

Next up is the 7447.  This is a BCD to 7-segment decoder circuit.  The 7447 is the common anode version (there’s a common cathode version as well).  What that means is that the 7-segment outputs are reversed.  If the output is a zero, then the LED is on and if the output is a 5-volt output, then the LED is off.  Anyway, here’s the circuit:

ttl7447

The 7447 took some effort to troubleshoot.  One of the complexities of this circuit is the feedback into gate 9.  I was forced to rewrite the circuit emulator to make this work better.  The current algorithm runs like this:

  1. Propagate the input signals to the gates that they connect to.
  2. For each gate, in order, attempt to compute the output with the inputs given, then propagate to the next inputs.
  3. At the end of processing all gates, if there are unknown signals, go through the list of gates again.
  4. If, after 10 attempts to process all gates yields unknown signals, then go to the first signal and set it to a zero (this is for flip-flops).
  5. Attempt to process all gates again.

Some issues came up because I missed a connection.  This can cause a gate to have a missing input and the circuit never completes.  So I wrote a method called VerifyAllGateInputsConnected().  This method will make sure all inputs have at least one connection.  The purpose is only to verify the circuit is wired.  In the real world TTL inputs normally act as a high or 5 volt signal.  It’s not good practice to leave an input connection open.

Another check I perform is the CheckValidConnections check.  This method will make sure the source and termination of each signal is the same voltage after a circuit is run.  If these are different, then the signal was not propagated.  The only time this happens is when there is a feed-back circuit (like the feed-back to gate 9 above) that flips the output of the gate, but the new output is not propagated.

The last check that I will be coding (and have not completed yet) will involve the verification that there are no pair of outputs connected together.  One aspect of logic circuit is that one output can go to multiple inputs.  However, if the outputs of two gates get connected together, you form a short-circuit when one gate goes to 0 volts and the other goes to 5 volts.  So I’ll need to create a verify method that can test to see if two outputs go to the same gate input.

Feeling bold, I continued on to the next circuit.  The 74381 4-bit arithmetic logic unit.  This is a beast, and it took me 3 days to type in the connections between gates (and 2 days to fix the bugs).  Here’s the circuit:

ttl74381

Technically, there are two different chips here, the 74381 and 74382, but I just added both circuits to the same chip so I can use them interchangeably.  I have created unit tests for the mode selector (s0, s1 and s3 decoder) that is at the top of the circuit.  This unit test only checks to the outputs of the gates 19 through 22 and 14, 15 and 16:

ttl74381_mode_decoder

This was necessary in order to break the task of troubleshooting down to something that was bite-sized.  The truth-table to the left of the circuit is my hand-computed logic of what gates 19, 20, 21, 14, 15, 16, 22 would produce for different combinations of S0, S1 and S2 inputs.  This was used for the unit test inputs and expected outputs.

Once that circuit was tested, I proceeded to test one pair of inputs (starting with a0 and b0) for the ADD mode only.  Here’s a close-up:

one_add_circuit

I’m using Visio for my circuit, so I can change the color of my lines to red to represent a 1 (or 5-volts).  I set the corresponding outputs of gate 19 through 22 for the ADD mode.  I also set the carry input (Cn) to zero.  Then I used all 4 possible combinations of A0 and B0 to test each output of gate 63 and gate 64.  Gate 63 is the sum of the A and B inputs.  Gate 64 represents the possible carry.  So this circuit behaves like a full-adder circuit.  Therefore I know what the expected outputs should be:

adder_truth_table

One of the problems with the 74381 is that it’s not easy to find.  Jameco electronics doesn’t seem to sell them.  My real-world solution is to use a PLD or Programmable Logic Device.  Technically, I could incorporate multiple 74381s into a complete circuit of an 8, 16 or 32 bit ALU.  Before I build such a thing, I want to perform more simulations to determine what it would take to create the circuit.

One other thing of note: I have not tested this circuit with normal gate timing.  These TTL circuits are only tested from the unit tests using a perfect gate (i.e. no delay timing).  I’ll need to setup some signaling and run a normal TTL gate to see how the outputs behave in the real world.  I should also wire-up a few of these circuits and see if they behave identically.  This is how a simulation is normally validated.

I added a GateOutput method to the circuit object for troubleshooting purposes.  The first parameter is used to define which gate to read and the second parameter is the timing number (normally zero).  This allows me to read any gate output in a circuit for unit testing purposes.  That’s how I was able to unit test the sub-circuits above.

More Troubleshooting Needed

The current code (version 748a78f on GitHub) has a new bug with the JK Toggle.  This shows up in two unit tests that fail (jk_toggle_once and jk_toggle_twice).  I also noticed that there is an anomaly in the starting state of the Master/Slave Flip-Flop as you can see in this output waveform:

jk_flip_flop_anomaly

The Q and QBar should always be opposite.  It seems that the startup of the circuit did not propagate the gate outputs properly.  I’m assuming this is due to the connections being valid, but the gate outputs are not.  I think Flip-Flops are going to be the death of me!

What’s Next?

That’s a good question.  I have several ideas in my head:

  • Create a static RAM circuit and and EPROM circuit.  This will enable me to build a small simulated CPU.
  • Create more TTL circuits so I have a full library to work with.
  • Enhance the interface to show inputs and outputs.  Maybe some LED lights or 7-segment displays or even 16-segment displays.  I could also simulate a dot matrix output like a digital display device (color or black and white).
  • Complete the circuit-to-circuit capability.  I want to be able to wire circuits to each other and create larger circuits.
  • Create programmable gate array circuits.  I could feed a program mask as a set the fuses before running the circuit.
  • Store a circuit definition to a file and read it in when needed instead of creating new objects.

Where to get the code

You can go to my GitHub account by clicking here and download the latest version.  This project is in progress, so a newer version might be uploaded by the time you read this blog post.

 

Leave a Reply