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.

 

JK Master/Slave Flip Flop

Introduction

I’m sure readers are becoming bored with Flip Flops by now, but bear with me.  The previous JK flip flop was a simple 4-NAND gate device, this circuit is the standard two flip flop device that is more stable when used in toggle mode.

The Circuit

The Master/Slave flip flop circuit is a bit more complex:

master_slave_circuit

The basic idea of this circuit is to latch the data into the first flop flop, then transfer to the second flip flop when the clock goes from high to low.  The truth table for this flop flop is the same as the JK flip flop demonstrated in my last blog post:

jk_flip_flop_truth_table

When this circuit is executed with perfect logic gates, the following signal is generated:

jk_master_slave_perfect

As you can see the Q and Q-bar outputs change states or “toggle” when the clock signal goes from a high to a low.  This circuit assumes that the logic gates have no delay.  For a circuit using normal TTL delay times, this is the generated output:

jk_master_slave_normal

The delay from the clock transition to the Q and Q-bar is quite pronounced.  In fact the output isn’t switched until after the signal goes back high again.  Let’s slow the clock speed down to make sure that the Q and Q-bar are switching on the falling edge transition.  The above diagram uses a 20ns clock timing, the diagram below uses 40ns:

jk_master_slave_normal_40ns

That pretty much verifies that the Q and Q-bar are triggered from the falling edge of the clock.  Notice how Q-Bar is out of sync with Q.  That’s due to the cross-wiring between the two.  There is a delay that occurs in gate 1 to gate 2 and there’s a delay from gate 5 to 6 and vice versa.

Purpose

The purpose of this software and the whole exercise of verifying the behavior is to build a simulator that can simulate a digital circuit as close to the real circuit as possible.  My next task will be to make it possible to create modules of circuits and then wire them together to run everything as one large circuit.  With the basic 1-bit full adder circuit, I should be able to put multiple instances of the full-adder into an 4-bit adder circuit and emulate the TTL 7483.  Adding TTL circuits to my toolbox will allow me to build a real device out of TTL chips and just simulate how it should work in real life.  Of course, real-life doesn’t work exactly like a simulator.  There are factors that I still have not accounted for.  Such as the difference in delay of a falling edge signal verses a rising edge signal or maximum fan-out capacity.  Once I get to this point, I’m going to start building the real circuit to verify that the signals match.

If you’re interested in learning about the TTL circuits that are on the market, you can go to the wiki page here.

Where to get the latest code

You can download the latest copy at my GitHub account by clicking here.

 

JK Flip Flop Simulator

Introduction

I’ve been working on a simulation of the JK flip flop for quite some time now.  I had to tweak my algorithms a bit to overcome problems with an unstable condition that I’ll discuss in this blog post.

 

Handling Unknown Inputs

One of the problems with circuits that contain feed back connections is that there is an unknown startup state.  In the world of electronics, imperfections in the transistor circuit will cause the condition to be a one or a zero almost immediately.  If all transistors were perfect a race condition can occur and in fact, many circuits experience race conditions for a short period as the circuit stabilizes.

As I thought deeper about unknown inputs I decided that the output of a gate can still be known if some of it’s inputs are unknown.  For example, and AND gate needs all inputs to be a true in order for the output to be a true.  So in that instance, all inputs need to be known for the output to be a true.  For a false output to occur, only one input needs to be false.  This also means that if one or more inputs are false, then unknown inputs don’t matter, because we know the output will be false.  Here’s the logic table for a 3-input AND gate:

3inputnand

You’ll notice that only one combination requires all the inputs to be known in order to get a known output.  With this knowledge, we can propagate signals through a circuit by ignoring unknown inputs until we hit a wall where we can’t predict the output of one or more gates.  The NAND gate is identical to AND except for the output.  For an OR gate, we can predict the output depending on one or more true inputs, all inputs must be false in order to get a false output:

3inputor

The inverter has no equivalent.  The input must be known for the output to be known.  The same for the exclusive OR gate.

 

The JK Circuit

Here’s the JK Flip Flop circuit (and logic table) that I constructed virtually using NAND gate:

jkff

In order to test the circuit, I started with perfect TTL NAND gates (no delay) and ran the circuit.  This produced a problem where I had an unknown circuit path.  At first, I propagated all the inputs right up to the gate inputs (red wires represent a 5 input or a true condition, black wires are uknown):

jkff_01

This created a problem where gates 3 and 4 cannot propagate the signal any further.  Their inputs are basically a true, true and unknown.  So I decided to propagate a circuit as a zero when this condition occurs.  I represented the zero as a blue line:

jkff_02

That seems to take care of the log jam because now, we can compute NAND gate 3 as a true output, and we can compute gate 1 as a true output, etc, until we get this condition:

jkff_03

Now you can see that the circuit is invalid.  Gate 2 should have a true output.  So this is an unstable starting condition.

 

Setting the Latch

Next, I tried to start the circuit with J false and K true, clock starts at true.  I end up with this circuit condition:

jkff_04

Initially, gate 4 has all three true inputs if gate 1 is producing a true output.  That will cause gate 4 to go false and gate 2 will output a true.  Gate 3 is forced to have a true output because J is false, therefore gate 1 will have two true inputs and a false output.  This causes gate 4 to turn back off or produce a true.  But this is a stable latch condition.

The reset operation is the same:

jkff_05

 

The Toggle State

For the perfect circuit, the toggle state, as shown earlier is unstable and this is the output from the simulator:

jk_perfect_toggle

The Q Bar output will not stabilize and always returns to the true state.  When I set the gates to normal TTL delay and adjust the clock to 5 ns (shorter than the delay) the instability is obvious:

jk_normal_toggle_short_clk

With a longer clock (20 ns):

jk_normal_toggle_long_clk

 

Conclusion

I’m going to run with this circuit emulation for now.  I have a choice to make, allow one or more gates to have an invalid output given it’s inputs, or allow an invalid wire to exist (where it has 5 volts at one end and zero at the other).  Either situation is not normal and this circuit is known to have a stability problem when starting up.  What I’m going to do next is wire up a virtual JK Master/Slave flip-flop.  This circuit fixes the inherent instability of the JK circuit.  I’ll show how that circuit works in my next post.