Monday, March 14, 2011

Remembering classic logic... (part3)

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.

In the last post we looked at the 74x74 (the d flip-flop) and it's set of similar relatives.  Here we are going to look at the 74x76 (the jk flip flop) and it's derivatives.  The 74x76 is a JK flip-flop (the substantive difference to the d flip-flop is that when both the inputs are high (J and K) then the output will toggle to opposite state (outQ becomes the current invQ and invQ becomes the the current outQ).

In the last post I used the original logic (6 nand gates) to make the module when there were too many signals that can act async. to change the state rather than to use an edge triggered conditional definition.  This time I'll explain how to integrate multiple async. signals in a way that's easier to adapt and modify that using only raw assigns...
  always @ (negedge Aclk or posedge Aset) begin
      if (Aset) begin
         // if preset or clear states indicate we should set intent
         Aintent <= AoutQ;
      end
      else if (!Aset) begin
         if (AinJ & AinK) begin
            Aintent <= ~Aintent;       
         end
         else if (!AinJ & AinK) begin
            Aintent <= 1'b0;   
         end
         else if (AinJ & !AinK) begin
            Aintent <= 1'b1;
         end
      end
   end
  
   always @* begin     
         if (!Apre & !Aclr) begin
            // both outputs high
            AoutQ <= 1'b1;
            AinvQ <= 1'b1;
            Aset  <= 1'b0;
         end
         else if (Apre & !Aclr) begin
            // set output high
            AoutQ   <= 1'b1;
            AinvQ   <= 1'b0;   
            Aset    <= 1'b1;
         end
         else if (!Apre & Aclr) begin  
            // clear output
            AoutQ   <= 1'b0;
            AinvQ   <= 1'b1;
            Aset    <= 1'b1;
         end
         else  begin
            // JK signals active to change state
            AoutQ <=  Aintent;
            AinvQ <= ~Aintent; 
            Aset  <= 1'b0;
         end
   end // always @ *
By using a new internal register (Aset) we can integrate other async. signals (Apre and Aclr) to allow the relevant changes in their state to allow the conditional where the clocked signals (AinJ and AinK) set the intended output (Aintent) to also alter the intent register (effectively setting or clearing the state).  If you put all the conditions where each signal would be relevant into one giant conditional then timing becomes very difficult to determine.  By breaking logical groups of signals into different conditionals and then lacing them together where only one controls the true output state timing is easy to determine and adjustments are easy to make.

When pin count is limited, decisions need to be made about which connections are the most critical to retain and which can be left out... The 74x78 removes two pins by using a common clock and a common clear (reset) for both JK flip-flops in the package.

always @ (negedge clock or posedge Aset) begin
      if (Aset) begin
         // if preset or clear states indicate we should set intent
         Aintent <= AoutQ;
      end
      else if (!Aset) begin
         if (AinJ & AinK) begin
            Aintent <= ~Aintent;       
         end
         else if (!AinJ & AinK) begin
            Aintent <= 1'b0;   
         end
         else if (AinJ & !AinK) begin
            Aintent <= 1'b1;
         end
      end
   end
  
   always @* begin     
         if (!Apre & !clear) begin
            // both outputs high
            AoutQ <= 1'b1;
            AinvQ <= 1'b1;
            Aset  <= 1'b0;
         end
         else if (Apre & !clear) begin
            // set output high
            AoutQ   <= 1'b1;
            AinvQ   <= 1'b0;   
            Aset    <= 1'b1;
         end
         else if (!Apre & clear) begin  
            // clear output
            AoutQ   <= 1'b0;
            AinvQ   <= 1'b1;
            Aset    <= 1'b1;
         end
         else  begin
            // JK signals active to change state
            AoutQ <=  Aintent;
            AinvQ <= ~Aintent; 
            Aset  <= 1'b0;
         end
   end // always @ *

   always @ (negedge clock or posedge Bset) begin
      if (Bset) begin
         // if preset or clear states indicate we should set intent
         Bintent <= BoutQ;
      end
      else if (!Bset) begin
         if (BinJ & BinK) begin
            Bintent <= ~Bintent;       
         end
         else if (!BinJ & BinK) begin
            Bintent <= 1'b0;   
         end
         else if (BinJ & !BinK) begin
            Bintent <= 1'b1;
         end
      end
   end // always @ (negedge clock or posedge Bset)
  
   always @* begin     
         if (!Bpre & !clear) begin
            // both outputs high
            BoutQ <= 1'b1;
            BinvQ <= 1'b1;
            Bset  <= 1'b0;
         end
         else if (Bpre & !clear) begin
            // set output high
            BoutQ   <= 1'b1;
            BinvQ   <= 1'b0;   
            Bset    <= 1'b1;
         end
         else if (!Bpre & clear) begin  
            // clear output
            BoutQ   <= 1'b0;
            BinvQ   <= 1'b1;
            Bset    <= 1'b1;
         end
         else  begin
            // JK signals active to change state
            BoutQ <=  Bintent;
            BinvQ <= ~Bintent; 
            Bset  <= 1'b0;
         end
   end // always @ *
The 74x113 just leaves out the reset (clear) lines completely (and is therefore simpler to implement in verilog).

// neg edge JK with preset... straightforward to do...
   always @ (negedge Aclk or negedge Apre) begin
      if (!Apre) begin
         AoutQ   <= 1'b1;
      end
      else if (Apre) begin
         if (AinJ & AinK) begin
            AoutQ <= ~AoutQ;       
         end
         else if (!AinJ & AinK) begin
            AoutQ <= 1'b0;   
         end
         else if (AinJ & !AinK) begin
            AoutQ <= 1'b1;
         end
      end
   end
I have a few other variants in my box at the moment.  The 74x114 includes the reset but combines the clocks to a common pine to make a pin available for the reset (clear) line.  The 74x112 variation has independent lines for all the inputs (clock, clear, J, K, reset) but otherwise looks like the 74x76.  The 74x109 is interesting in that the J and K lines are active on the positive edge of the clock rather than the negative edge.


Like the D flip-flops the JK flip-flops can be used as single bits of memory (retaining the state of an input line after it's left) but the ability to toggle the state as well makes them a bit more useful when multiple sequences of events need to occur after an event.