Friday, March 28, 2025

Entry 14: Gated latches and flip-flops

In entry 13 we connected the output of a four D flip-flops (basic register) to the bus (through tri-state buffers). Now we want to do the reverse, connect the bus to the input of the register. The register designed in enty 9, QuadDFlipFlops,  will not quite work. 

This register will always load the data from the bus when the clock goes high. We need to be able to control when it will load data from the bus. We need an additional control line to the register, which we may call "load". The register shall only load data when load is high. It shall ignore the bus when load is low. A term for this feature is "Gated enable inputs" and the pin controlling the gate, the one I call "load", is also called "data enable".

Gated SR-latch

In order to make QuadDFlipFlops gated, we need to make a gated D flip-flop. D flip-flops are made from SR latches, so we need to go all the way back to these guys, and make them gated. This was the SR latches of the NAND type, that we created in entry 7:


We want to make this "gated" by adding a "Load pin". When Load is high (gate open), it should functions as before.  When Load is low (gate closed), there should be no change in the latch, no matter the values of Set and Reset. To accomplish this is simple, no need to ask Grok:


Note that when Load is 0, the two NAND gates on the left will always output 1 and there is "no change" in the latch. When Load is 1, the two NAND gates on the left will always output the values of Reset and Set. The latch then functions as before. This symbol makes sense for a gated NAND latch (L for Load):

Here is the full truth-table of the NAND latch with load.

These are the components I created:  

  • "NandLatchGated" with precisely this functionality, see ACEL
  • "NorLatchGated", a gated SR-latch based on NOR gates.
The pins are the same as for the andLatch and the NorLatch, but with the extra input pin "load". I am not going to test these, as they are very similar to the ungated versions, but you could certainly go ahead and do so. 

Gated D flip-flop

The D flip-flop we created in entry 8, DFlipFlop,  was "ungated". Creating a gated D flip-flop with an extra Load pin is simple. Just replace the slave SR latch with a gated one. The truth-table of a gated D flip-flop when Preset = 0 and Clear = 0 is then

As before, If Clear = 1, Q becomes 0 and if Preset = 1, Q becomes 1. This symbol makes sense for a gated D flip-flop (L for Load):

The name of this flip-flop in ACEL is DFlipFlopGated. Pins are:

  • Input pin: D
  • Input pin: Clock
  • Input pin: Clear
  • Input pin: Preset
  • Input pin: Load
  • Output pin: Q
  • Output pin: Q_Bar.

Again, I am not going to test this, as it is similar to the ungated version. I assume it will work.

In the next entry, I will create a new register based on four gated D flip-flops. I will also add four tri-state buffers to the output so that the output can be connected directly to the bus.

Entry 13: Connecting Register to Bus

Register output to bus

The goal of this entry is to make the first version of our register, "Quad D flip-flop" (see entry 9), "bus-friendly" by completing the following schematics we looked at in entry 12:

Each of the four tri-state buffers has an "enable", and all of them will be connected. This will make them all enabled or none of them enabled:

Quad three state switch

I combined four three state switches into a component QuadThreeStateSwitch.

  • Four D input pins: D[4] (by this I mean D[0], D[1], D[2], D[3])
  • Input pin: Enable (connected to all switches)
  • Four W output pins: W[4] (that is, W[0], W[1], W[2], W[3])

The data bus

The data bus is simply four wires that can be connected to various components. Each wire is tri-state, that is, it can be either connected to ground, to +5V, or be disconnected / floating (Z). I created a component with four wires, BusLineFour. To set and read the state of each wire, it has

  • Four connections X[4]. These are used when a component puts data onto the bus.
  • Four connections W[4]. These are used when a component reads data from the bus.
Only tri-state output can be connected to the bus X-input. For example, the output of a tri-state switch can be connected to an X-input. Even though each wire is tri-state, each W-output of the bus can be connected to non-tri-state input of a component. However, if the wire is in the Z-state, the component will read "garbage" (0 or 1 randomly). Only when the wire is "0" or a "1" will the component read a correct signal.

There is nothing to the BusLineFour. If you want to build something created using ACEL, BusLineFour would simply be replaced by four wires. 

Building and testing

We will use these three components:

  • QuadDFlipFlop, our first version register from entry 9.
  • QuadThreeStateSwitches.
  • BusLineFour.

To test this out:

  • Connect 4 DIP switches to the D-inputs of QuadDFlipFlop.
  • Connect a button to QuadDFlipFlop Clock
  • Connect the Q-outputs of QuadDFlipFlop to D-inputs of QuadThreeStateSwitches
  • Connect a button to QuadThreeStateSwitches Enable
  • Connect QuadThreeStateSwitches W-outputs to BusLineFour X-inputs. (we will not use the BusLineFour W-outputs in this example).

This will allow as to latch a number (0 to 15) into the flip-flops. When we set Enable = 1, this value will go onto the bus. When we set Enable = 0, the bus will be "disconnected", ZZZZ. We can check the state of the data bus using "Print".

Making four connections

Many of the connections that we need to make are in "sets of four". Instead of writing four "Connection", I created a "ConnectionFour". For example, if we define

  //Define chips
  auto* reg = new QuadDFlipFlop();
  auto* switches = new QuadThreeStateSwitches();
  auto* bus = new BusLineFour();

then the four connections between the register and the switches can be written

    new ConnectionFour(reg->Q, switches->D),

This is equivalent to four connections, Q[0] to D[0], and so on. Connection4 can also be used with Arduino pins. For example,

    new ConnectionFour(ard, 2, reg->D, 0),

will connect Arduino pin 2 to D[0], ...,  Arduino pin 5 to D[3]. 

    new ConnectionFour(ard, 2, reg->D, 1),

will reverse the order, Arduino pin 2 to D[3], ...,  Arduino pin 5 to D[0]. Here are all the connections:

  ConnectionBase* connections[] = {
    new ConnectionFour(ard, 2, reg->D, 1), //2,3,4,5 to D3, D2, D1, D0
    new Connection(ard, 6, reg->Clock),
    new Connection(ard, 7, switches->Enable),
    new ConnectionFour(reg->Q, switches->D),
    new ConnectionFour(switches->W, bus->X),
  };

Check it out on Wokwi, project "Register to Bus".


The register is not yet complete. The next step is the reverse, connecting the bus to the register allowing the register to get its data from the bus.