Wednesday, March 16, 2011

Remembering classic logic... (part 4)

Recently I pulled out my boxes of 7400 series logic (working on a few old school projects that were idled for a bit).  There's something special about these chips...

So, on a whim I thought that I'd bang out verilog modules for the chips I have on hand.  I'm putting the files for these modules in the tanukifu project here.

I'm going to start here with the 74x378 because it's the way I would do things now with programmable logic and then work back to simpler chips. 

There are times when one needs to retain the current state of a wire so that it persists after the original signal has changed.  When you are going to combine the outputs with more logic it becomes important to know exactly when the wire was "sampled"... as as you have guessed by now we are going to do it with as small an interval as we can measure (a clock edge).  In the 74x378 we have six inputs and six outputs and a clock.  One the positive edge of the clock the state of the inputs is retained an appears on the outputs and this state does not change until the next positive clock edge.  Because we can determine exactly when that edge will occur, we can model and predict how the resulting signal will affect other logic in the circuit.  The verilog is simple.

   always @ (posedge clock) begin
      Aout <= Ain;
      Bout <= Bin;
      Cout <= Cin;
      Dout <= Din;
      Eout <= Ein;
      Fout <= Fin;     
There are a number of other ways of sampling the state of a wire and the other chips we will look at do it without a clock.  Now there's nothing wrong by not using a clock, but the resolution of how well you can predict when the wire will be sampled is significantly lower.  When the state is sampled while a second line is high (or low) rather than on a signal edge you have a latch.  Most of the time you will get a warning with current logic tools when you use latches because the poor resolution makes it very hard to push the speed of circuits towards the upper speed limits with predictable outcomes.  The 74x533 is similar but has inverted outputs.

The verilog is straightforward.
   // Tristate based on outputenable
   assign Aout = (outputenable) ? 1'bz : Areg;
   assign Bout = (outputenable) ? 1'bz : Breg;
   assign Cout = (outputenable) ? 1'bz : Creg;
   assign Dout = (outputenable) ? 1'bz : Dreg;
   assign Eout = (outputenable) ? 1'bz : Ereg;
   assign Fout = (outputenable) ? 1'bz : Freg;
   assign Gout = (outputenable) ? 1'bz : Greg;
   assign Hout = (outputenable) ? 1'bz : Hreg;
   // Set registers when latchenable is high
   always @ * begin
      if (latchenable) begin
         Areg <= Ain;
         Breg <= Bin;
         Creg <= Cin;
         Dreg <= Din;
         Ereg <= Ein;
         Freg <= Fin;
         Greg <= Gin;
         Hreg <= Hin;  
   end // always @ *
There are other variants that have individual enables like the 74x125 - when enable is high then the state can be remembered and when low changes on the input don't affect the output (the 74x126 uses and enable that is active when low).

// Tristate based on outputenables
   assign Aout = (Aen) ? 1'bz : Ain;
   assign Bout = (Ben) ? 1'bz : Bin;
   assign Cout = (Cen) ? 1'bz : Cin;
   assign Dout = (Den) ? 1'bz : Din;
It's a very easy thing to build (and at times useful - but you have to be careful what the resulting signals are used for if you don't want metastability to ruin your day(s)).

The 74x240 (inverted outputs) and 74x241 (not inverted outputs) are rather interesting in that that split the 8 signals into 2 quads (each with an output enable line so they can be tristated).
// Tristate based on outputenables
assign Aout = !(outputenable1) ? 1'bz : ~Ain;
assign Bout = !(outputenable1) ? 1'bz : ~Bin;
assign Cout = !(outputenable1) ? 1'bz : ~Cin;
assign Dout = !(outputenable1) ? 1'bz : ~Din;
assign Eout = !(outputenable2) ? 1'bz : ~Ein;
assign Fout = !(outputenable2) ? 1'bz : ~Fin;
assign Gout = !(outputenable2) ? 1'bz : ~Gin;
assign Hout = !(outputenable2) ? 1'bz : ~Hin;

Being able to tristate an output and also to sample an input in groups made these some of the my favorite chips to build a bus - durable, dead simple and reliable to use...  There are other variants that have increased ability to sink or source current (which makes it easier when more and more chips are connected to a parallel bus), but the logic is exactly the same as these.

The 74x375 is probably one of the simplest (an useful) variants.  Here there are complementary outputs for each of four inputs (true and inverted) and rather than having the ability to put the outputs in high impedance there are two enables (1 for the first two inputs and 1 for the second two inputs).  This is one of the chips I always have stuck in a breadboard.
   // direct assigns for the compliments
   assign Ainv = !Aout;
   assign Binv = !Bout;
   assign Cinv = !Cout;
   assign Dinv = !Dout; 

   always @ (*) begin
      if (ABen) begin
     Aout <= Ain;
     Bout <= Bin;
      if (CDen) begin
     Cout <= Cin;
     Dout <= Din;

What none of the chips (buffers/latches) in this group can do is receive and send signals on the same bus... (next time we will look at simple transcievers).