• Sequential logic: solving the race hazard

    AlliedEnvy01/02/2022 at 22:49 0 comments

    We have solved the analog voltage levels, but a simulation of our D flip-flop still does not work as designed. What gives? This issue took a lot of time for me to figure out. Experienced logic designers likely saw the issue once I mentioned that the latch has 2 complementary clocks.

    The problem is that our design relies on 2 different signals switching at exactly the same time. In the real world, almost nothing happens at exactly the same time.

    This is especially the case when the clocks are coming from a previous counter stage, where one clock output comes from a flip-flop, and then goes through an inverter to the other clock output, experiencing one logic delay.

    We need to be especially concerned when the latch goes from enabled to disabled. Any glitches here could cause the latch to flip to the wrong state, and stay there. Let's take a look at our table again:

    Threshold !Trigger !Reset Output Discharge
    don't caredon't careLLon
    > C> C/2HLon
    < C> C/2Hstablestable
    don't care< C/2HHoff

    Recall that when the latch is enabled (i.e. in pass-through) Th is 1 and !Tr is 0.25. C is either 1/3 or 2/3. Let's play out a thought experiment with our clock changes to see how it goes.

    1. If C is high, i.e. 1/3 then !Tr > C/2 and O is L.
      1. If we first flip !Tr to 1, it's still > C/2. O is still L, so we are good to then flip Th to 0.25 to go stable.
      2. If instead we first flip Th to 0.25 then Th < C and !Tr was already > C/2 so we're now early in stable state and when !Tr next goes to 1, we're still stable.
      So the order of clocks change doesn't matter when C is low.
    2. Now let's consider C high, i.e. 2/3. !Tr < C/2 and O is H.
      1. If we first flip !Tr to 1, now !Tr > C/2 and Th was already > C. O goes L. Uh-oh. We shouldn't flip !Tr first.
      2. Let's see if we can flip Th first instead. If we flip Th to 0.25 then it's < C. !Tr is still < C/2 so O is still H when we next flip !Tr to 1 to go stable. Phew.
      So we must flip Th first.

    How do we make sure that Th always flips first? We take the Th input clock signal as early as we can in our chain of logic, and make sure that the !Tr is derived from the Th signal by going through an inverter, experiencing one logic delay. This will necessitate one extra 555 per counter.

  • Sequential logic: analog domain

    AlliedEnvy12/30/2021 at 04:26 0 comments

    In simulation, the D-latch does not work when provided with the intended inputs. This is because we did not take into account the analog behavior of the 555 when designing our digital model.

    For our next analysis, table 3 in the datasheet does not totally describe the behavior when the Control pin is being used.

    Observing Figure 1 from the datasheet shows that there is a voltage divider chain of 3 resistors connected between VDD and GND, with the Control pin connected to the node between the first and 2nd resistors. (This is one of the defining characteristics of the 555.)

    The Threshold pin's comparator's inverting input is taking from the same node the Control pin is connected to. And the !Trigger pin's comparator's non-inverting input is taken from a node that is between 2 resistors; one end of which is Control and the other is Ground.

    So when Control (C) is driven (not floating), the voltage that Threshold compares against is C, and !Trigger compares against C/2. Our new table is:

    Threshold !Trigger !Reset Output Discharge
    don't caredon't careLLon
    > C> C/2HLon
    < C> C/2Hstablestable
    don't care< C/2Hhoff

    We need to choose carefully our input voltages so that we obtain the desired D-latch behavior. For the sake of simplicity, we will assign VDD an imaginary voltage of 1 and GND an imaginary voltage of 0. When we get to our actual power supply, we can scale up accordingly.

    We only have one state we need to worry about when the latch is disabled; this is the "Output stable" state from our table.

    1. Th should always be below C, so let's make Th 0 and have C always be above 0
    2. !Tr should always be above C/2, so let's make !Tr 1 and C always be below 1.

    Now we need to think about the inputs when our latch is enabled and allowing the Data input to pass through to the output. This is rows 2 and 4 of our table (!Reset H, Output is either H or L).

    1. Th is "don't care" when Output is H, and above C when Output is L. So let's make Th 1 and have C always below 1.
    2. !Tr is the trickier one. It needs to be greater than C/2 when C is low, and less than C/2 when C is high.

    So assuming our C goes from 0 to 1, !Tr needs to be somewhere between 0 and 0.5. Let's give ourselves plenty of margin and split the difference, and have !Tr at 0.25.

    Of course, our C can't go to 0 or 1, per our previous constraints. Let's make it go from 0.2 to 0.8, again giving plenty of margin between the rails.

    Now, you may have noticed that our Th and !Tr are not exactly complementary anymore, and we relied on them being opposites when we built a D flip-flop from our D latches. We may have to have 4 clocks in to our D flip-flop, differing by going through a voltage divider or not.

    Then again, maybe we can figure out a way to keep our clocks complementary. Notice that when our latch is disabled, Th just needs to be below C. If we make C always above 0.25 then we can let Th be 0.25 and keep complementary clocks. Let's instead have C go between 1/3 and 2/3. And then when the latch is enabled, !Tr needs to be greater than 1/6 and less than 1/3. 1/4 is 3/12 which is exactly between 2/12 (1/6) and 4/12 (2/3) so we are good to have complementary clocks again.

    So how do we achieve these voltage levels? With resistive voltage dividers. For our clocks, we can use a pull-up value of 3R and a resistor value of R from the input clock signal. For our C signal (which is our data input), we use equal values for each of pull-up, pull-down, and resistor on our data line.

  • decoding and displaying the counters

    AlliedEnvy12/16/2021 at 23:18 0 comments

    The clock will use 7-segment LED displays for the time. We need to decode the state of the Johnson counters into one output per segment.

    The first task is to determine how to decode the bits of the Johnson counter into individual one-hot outputs. (We could, if we wanted, make a 4017 out of 555s this way).

    Here are the ten states of our decade counter (state number down the side, output along the top. !4 is on both sides for clarity.

     _     _
     4012344
    0-_____-
    1--____-
    2---___-
    3----__-
    4-----_-
    5_-----_
    6__----_
    7___---_
    8____--_
    9_____-_
    

    We can decode a state by detecting the rising edge (0-4) or falling edge (5-9). This is an ideal match for our ANDN gates -- one input detects the high of the edge, and the other detects the low. Furthermore, we can sometimes decode multiple states at one time by skipping outputs. For example, O0&!O3 decodes 1|2|3.


    Now that we can determine specific states, we need to decode to our seven segment display. Traditionally the segments are labeled a through g, going clockwise from 12:00 and g in the center. Another ASCII diagram:

     a   _       _   _       _   _   _   _   _  
    fgb | |   |  _|  _| |_| |_  |_    | |_| |_| 
    edc |_|   | |_   _|   |  _| |_|   | |_|   | 
    
    a = ~(1|4)
    b = ~(5|6)
    c = ~2
    d = ~(1|4|7|9)
    e = 0|2|6|8
    f = ~(1|2|3|7)
    g = ~(0|1|7)
    

    We'd like to use the Discharge pins to drive the segments, since they can sink several mA of current. This means that the outputs are active-low and the items above are inverted. With a bit of thinking and experimentation, we get:

    Likely some more optimization can be done, but this is a good start. Note that in addition to a-g outputs, we also have clocks out, and an output for decoded state 4 (this will be used to roll over hours at 24:00). Smaller decoded counters for tens places can be done by simplifying this decade counter.

  • 555 digital counters

    AlliedEnvy12/16/2021 at 20:38 0 comments

    The next building block needed is a counter, to keep track of time.

    We need a decade counter for the units places of seconds/minutes/hours and a few smaller counters for the tens places of seconds/minutes/hours. A few more counters will be needed in timebase oscillator section to divide down to 1Hz.

    There are a few options to consider:

    • A ripple counter uses toggle flip-flops, which can be created by running the Q output of a D flip-flop through an inverter and back into its own D input. This requires 555s per counter, so a decade counter needs 12 555s.
    • A ring counter uses D flip-flops, with their D inputs cascaded in a ring, and needs 1 DFF per state. Additional logic is required to make sure the ring gets reset to a consistent state. So somewhere over 2*n 555s are required, giving our decade counter 20+ 555s.
    • A twisted (or Johnson) ring counter adds an inverter in the feedback path of the regular ring counter. With this, 2n states occur for every n DFFs. So 555s are required, giving our decade counter 11 555s.

    A Johnson counter is the winner; even though it only saves 1 555 over the ripple counter, it is also synchronous, whereas the ripple counter is asynchronous. This is an advantage when it comes to stably decoding the state of the counter.

    Here is our decade counter, then:

    Exposing both O4 and !O4 will help to decode the counter, and also when we need to cascade into the clock inputs of the next counter down the line. And we can create longer or shorter counters by adding or removing additional DFF stages.

  • Basics: sequential 555 logic

    AlliedEnvy12/16/2021 at 20:01 0 comments

    Next up is sequential logic. We could make our own from ANDN gates, but since we have an RS latch already, this would be wasteful. We just need to figure out how to set the inputs to get our desired behavior.

    Let's look at our truth table again:

    !RCECTh!TrSetReset
    0xxxx01
    10x1101
    10x0100
    10xx010
    1100x00
    1101x01
    111x010
    111x100


    We'd like to create a basic D latch with an enable pin and a data pin. Data should be passed through when enable is high, and latched on the falling edge of enable. A reset pin would also be nice.

    Clearly, !R should be our reset. We can combine Th and !Tr as our enable, if we treat Th as En and !Tr as !En, making sure to always drive them opposite to each other (we can use an inverter for this if needed). C becomes our data pin.


    Latches are nice, but what would be nicer is a flip-flop. We can cascade two of our latches, with opposite clock polarities, to create a flip-flop:

    Note that the first latch is of opposite polarity to our standalone D latch, to allow the flip-flop to clock in data on the rising edge of the clock signal.

    We now have all the basic building blocks needed for our clock.

  • Basics: combinational 555 logic

    AlliedEnvy12/16/2021 at 18:10 0 comments

    Using our truth table, we can derive several logic gates using 555s. For combinational logic, we want to avoid any states where the RS latch remains unchanged (i.e. where Set and Reset are both 0).

    !RCECTh!TrSetReset
    0xxxx01
    10x1101
    10x0100
    10xx010
    1100x00
    1101x01
    111x010
    111x100


    The most basic are the 1-input gates, the buffer and the inverter.

    Since !Reset drives the output low, we can put the other inputs in a state to (otherwise) drive the output high, and use !Reset as the input for our buffer. Let's pull Tr and !Th low and leave C floating. The result:

    For the inverter, we can tie !R high and tie Th and !Tr together as the input:

    Next, we'll do a 2-input gate. It would be nice to have a functionally complete gate. We can combine our buffer and inverter to create an inhibit gate, A&!B, which is functionally complete. I'll be calling this ANDN for brevity's sake.

    Finally, since the Discharge pin is open-collector, we can tie multiple Discharge pins together with a pull-up resistor to make a wired-AND for almost free.

    We could explore other gates, but this is enough.

  • Basics: a digital model for the 555

    AlliedEnvy12/16/2021 at 00:31 0 comments

    To get started, we need to understand the 555 from a digital logic point of view.

    Throughout the project, I will refer to the ICM7555 datasheet1 from NXP (nee Philips Semiconductors, nee Signetics, the originators of the 555).

    From the functional diagram, the 555 can be thought of as a circuit with 3 stages, each feeding into the next:

    1. A combinational circuit with 4 inputs (one tristate) and 2 outputs.
    2. An RS latch (the cross-coupled NOR gates in the center).
    3. 2 output drivers.

    Most of our analysis will be on the first stage, so let's get the other two out of the way.

    The RS latch has its S (set) and R (reset) inputs coming from stage 1, and its Q and !Q outputs go to the output drivers.

    The two output pins are Output, a push-pull output driven by Q, and Discharge, an open-collector NPN/N-channel transistor driven by !Q. Discharge can sink a modestly larger amount of current compared to the rest of the pins.


    This leaves the combinational input stage 1. There are 4 input pins: !Reset, Threshold, !Trigger, and Control (Control being tristate). An exclamation mark (!) or overline in the diagram indicates the input is active-low.

    To simplify analysis, we will split Control into two inputs, Control and Control-Enable. When Control-Enable is low, Control is inactive, floating in high-Z state. When Control-Enable is high, the Control pin being actively driven high or low.

    Now we have 5 inputs, for a total of 32 (25) items in our truth table to suss out.

    From the functional diagram, we see Control has an effect on Threshold and !Trigger, but not !Reset. And from the function selection table, !Reset overrides all other inputs. So 16 of our truth table are:

    !RCECTh!TrSetReset
    0xxxx01


    Considering Control as disabled, our next rows from the function selection table are (giving another 8 entries in the truth table):

    !RCECTh!TrSetReset
    10x1101
    10x0100
    10xx010


    This leaves 8 states with CE enabled; 4 with C low and 4 with C high. Some experimentation and study of the functional diagram reveals that when C is low, !Tr is disabled, and when C is high, Th is disabled. Our remaining rows are:

    !RCECTh!TrSetReset
    1100x00
    1101x01
    111x010
    111x100


    Plugging this into Digital, we can synthesize a circuit from the truth table for simulation:

    Adding some circuitry to make CE from C, the remaining stages, and some delays to make changes propagate at the same time, I get:

    This is the model I'll be using to design the clock.


    [1] This is their CMOS 555; I couldn't find a bipolar 555 datasheet on NXP's site, but I'll be designing towards the CMOS 555 anyway.

  • Goals

    AlliedEnvy12/16/2021 at 00:12 0 comments

    I aim to create a digital clock using entirely 555 chips for the active circuits. Anywhere a semiconductor is needed, a 555 should be preferred, and care should be taken to minimize the number of non-555 semiconductors used.

    Limited exceptions can be made where 555s cannot handle the required current (e.g. in display circuitry and power rectification). Nevertheless, the simplest component needed for this application should be used. Perhaps parallel 555s can be used for this.

    For parts-count and board-area reasons, 556 parts (dual-555 timers in 1 package) are acceptable.

    For power-dissipation reasons, I intend to use CMOS 555s, but I aim to make the design accept the use of bipolar 555s without any circuit changes (except maybe in the power supply).


    In addition, the clock should keep good time. This means no RC delays should be used in the core timing functions, since they aren't precise or stable enough to rely upon. (Ironic, because typical uses of 555s need RC delays for monostable or astable operation.)

    Exceptions: I might use a couple monostable 555s as a filter in the first stage of the clock oscillator, and maybe as switch debouncers. And (stretch goal) an astable 555 with an LDR for PWM dimming the display brightness to accommodate room lighting changes. None of these applications require precise, stable timing.

  • Inspiration

    AlliedEnvy12/15/2021 at 23:21 0 comments

    It is known that digital logic can be implemented with 555 chips:

    Specifically, an A&!B gate (inhibit gate) can be constructed, which is functionally complete, and thus, 555 logic should be Turing-complete.

    We can do a little better than building an entire machine out of inhibit gates, however. The 555 also contains an RS latch which comes in handy when implementing sequential logic.


    There is also a long tradition of building clocks from (sometimes obscure) logic families. Some noteworthy examples:


    555 Time aims to follow in these footsteps by creating a clock entirely of 555 timer logic.