CMOS Nixie Tube Clock Project: Part 2
It's all just logic
This is Part 2 of a multi-part series on my most ambitious electronics project to date: building a CMOS logic-based clock with a Nixie tube display. Part 1 covered the basic design goals and desired features. Today we're going to be diving right in to the design of the logic circuits. Don't worry, it's not that bad. I'll be going through the design from the bottom up, explaining the circuit and pointing out road blocks that tripped me up when I started trying to figure out how to put this thing together.
If you're completely unfamiliar with logic circuits, I suggest looking through this series of logic gate tutorials. They explain what logic gates are, how each gate works, and give typical equivalent transistor circuits.
Wait a second...
A clock is nothing but a device that counts the number of times something happens and does the necessary division to turn that raw count into seconds, minutes, and hours. So let's start with how you divide down your time base into a 1 Hz tick for your seconds counter. One of the easiest ways to do this is with a flip-flop. There are many variations on this basic logic circuit, as you will see if you follow that link to the Wikipedia article. But we'll just concern ourselves with specifically the D-type flip-flop, which changes state every time you pulse the CLOCK input. In other words, if you feed it a string of pulses, the output will be a string of pulses with exactly half the frequency. So now let's say you have a crystal with a frequency of 32,768 Hz. If you run it through a flip flop chip, you'll get an output frequency of 16,384 Hz. If you run it through another flip flop, you get a frequency of 8,192 Hz. If you do that 13 more times (and this is why clock makers pick this particular frequency crystal oscillator), you get a train of pulses with a frequency of...(drum roll)...1 Hz.
Weirdly, you can't actually buy a single chip with 15 flip flops on it, but you can buy one with 14 on it: the CD4060B. Helpfully, this chip also has the facility to drive your oscillator circuit, so with a single chip, three resistors, two capacitors and a clock crystal, you can generate a 2 Hz pulse train with a frequency accuracy within 1 ppm. Since we're left with a 2 Hz signal, we need one more flip flop to divide it down to the 1 Hz we need for our clock. You can't seem to buy chips with single flip flops on them, either but that's OK since we also need a flip flop to turn our AM/PM indicator light on and off (waste not, want not). And so you get the pictured timebase circuit that outputs a 1 Hz pulse train that we can now use to count minutes and hours.
Give me a minute
Before we can count minutes, we have to count to 60 seconds, and every time we get there, output a pulse (to tick the minute counter over by one) and reset to zero. And we do that with (you might have already guessed) a bunch of flip flops, because another way to think of a bunch of flip flops strung together in series is a binary counter, just like the one pictured. The right-most digit (the "ones" place) ticks back and forth between 1 and 0. The second digit from the right is the second flip flop in the series, and it only flips back and forth between 1 and 0 when the first flip flop resets, in other words, every time you count to two. The third flip flop switches state every time the second one counts to two, or every time the first digit counts to two twice. You may see where this is going. Each digit represents the number of times (between 0 and 1) a given power of 2 has been counted to. You might notice, however, that the pictured counter can only count up to 31 (2^5) before it resets to zero, which tells us that in order to count all 60 seconds in a minute, we will need one more flip flop to enable our binary counter to count to 2^6, or 64. But they don't sell 6 bit binary counters in the CD4000 series; they sell 7 bit binary counters (CD4024B). Oh well, let's just roll with it.
So now we have a chip that will count to 128 for us and then reset. Great! Let's feed our 1 Hz signal from our timebase into the CLOCK input. There's only one problem: there aren't 128 seconds in a minute. There aren't even 128 seconds in two minutes. We need a way to make the chip reset to zero before it actually gets to its maximum value. Fortunately, those clever chip designers thought of that, too, and all you have to do is pulse the RESET pin "high" and the chip will reset to zero. Now all we need to do is add some circuitry to generate a reset pulse when our counter gets to 60, or in binary 0b111100 (binary numbers are typically indicated by preceding them with "0b", just so binary 100, which equals 4, isn't confused with decimal 100, which obviously does not equal 4). In other words: when output pins Q3, Q4, Q5, and Q6 on the counter chip all are outputting a "high" voltage. And there's no better way to do that than with a 4-input AND gate (well, there might be). The AND gate will only output a "high" signal when Q3, Q4, Q5, and Q6 are all "high", which will immediately reset the counter to zero. Now we just need a clock signal with a 1/60 Hz frequency to send to the minutes counter. I chose to use the output of Q6. This pin is "low" for the first 32 seconds of any given minute and "high" for the last 28 seconds of any given minute, giving you a 1/60 Hz pulse with slightly less than a 50% duty cycle.
Turning to the minutes counter, I'm going to switch things up on you a little bit. You might think that since there are also 60 minutes in an hour, we can just duplicate the circuit I just described and feed it the output of the first circuit. And you'd be right. But there's a reason we're not doing that: we eventually want to display the number of minutes that have passed in decimal form, and it's harder to find chips that convert 6 bit binary into decimal than it is to find chips that convert 4 bit "binary coded decimal" (BCD) into decimal. What is "binary coded decimal"? you might ask. And don't feel bad for asking that; I had no idea this was a thing, either, but it's actually pretty helpful.
Instead of encoding the whole number in binary like we were with the seconds counter, we encode each digit of the decimal number individually in its own 4 bit binary counter. So instead of encoding 45 as 0b101101, you would encode it as two separate numbers 0b0100 (4) and 0b0101 (5). You might be asking, "What the hell? That takes up more space!" At least, I did. But think of it this way: your decimal display is broken up into separate digits, so it actually makes sense to have one 4 bit binary counter count to 10 (for the "ones" place in your decimal display) and then reset and increment the next 4 bit binary counter (for the "tens" place). And so a BCD counter is just a 4 bit binary counter that already contains the logic to reset the counter at 10 instead of 16. And a "dual BCD counter" like the CD4518B in the pictured minutes counter circuit is just a single chip that contains two BCD counters, which is handy because the number of minutes (in decimal notation) is never more than a two digit number.
I should pause here and mention a small subtlety in the design of this particular chip that we're using. The chip has three input pins: a CLOCK, an ENABLE, and a RESET. We're already familiar with the CLOCK and RESET pins from the seconds counter, but what does the ENABLE pin do? Well, it enables and disables the CLOCK pin. When ENABLE is high, a transition from "low" to "high" (but not the other way around) on the CLOCK pin increments the counter, and when ENABLE is "low", nothing happens. But there's one extra subtlety: if the CLOCK pin is "low", and the ENABLE pin transitions from "high" to "low" that also increments the counter. This turns out to be useful to us. Remember the output of our seconds counter? It's a pulse that is "low" for the first 32 seconds of a minute and then "high" and transitions back to "low" at the end of the minute. If we just hook our one-minute pulse up to the CLOCK input of our BCD, the minute counter would increment at the 32 second mark when our pulse transitions from "low" to "high". We can't be having that! Our clock would always be off by 32 seconds! But if we just wire our CLOCK input to ground and feed our one-minute pulse into the ENABLE input instead, we get the behavior we want: as soon as the seconds counter hits 60 and resets, the minute counter increments by one.
We now need two more things to make our minute counter complete: connect the two BCD counters on the chip together in series and add logic to reset the counter to zero when it gets to 60 (rather than the default of 100). The first thing is easy: just connect the output of Q4A (the most significant digit of the first binary counter) to the ENABLE input of the second binary counter, and wire the CLOCK pin to ground. Now when the first counter resets to zero (transitioning the Q4A pin from "high" to "low"), the "tens" digit of our minute counter will increment. To reset the whole counter at 60, we'll use the other 4-input AND gate on our CD4082B chip. The criterion for reset is the "tens" digit counter incrementing to 6, or 0b0110. So we wire the Q2B and Q3B pins to our AND gate. To make sure the other two inputs to the AND gate are always "high" (and thus effectively turn our 4-input AND gate into a 2-input gate), all we have to do is wire those pins to the power bus, which by definition is always "high".
Voila! A circuit that counts the number of minutes that have passed.
Hours of Fun
With all that behind us, the hour counter isn't all that complicated, as long as you are using 24 hour time. It's basically the exact same as the minute counter, but instead of resetting when the counter reaches 60, it will reset when it reaches 24. Easy peasy. 12 hour time, on the other hand, is tricksy. You might be tempted as I was initially to just wire it up to reset when it gets to 12, and that almost gets us the behavior we want. But unlike 24 hour clocks, in 12-hour time 0 o'clock isn't a thing. Well crap. How do we make our counter not do that? We fake it.
When the counter gets to 12, it resets to zero, but we put a couple extra logic chips in the way of the outputs from the counter. Specifically, the least significant digit in the "tens" place counter and the second digit in the "ones" place counter (the pins that would be high had we not reset it when it got to 12). These pins are labeled "U_12HR_Tens_A" and "U_12HR_Ones_B" in the circuit diagram to differentiate them from the corrected values that will eventually get sent to the display.
First, we use a dual 4-input NOR gate to check whether all four pins in each counter are low (i.e. the counter is reading zero). We check that both counters are reading zero by using one of the gates on our quad 2-input AND gate. Finally, we don't want to completely supersede the output of the original pins so we OR the output of our AND gate with the original pins to generate the corrected output. If we don't do this last step, at 2 o'clock and 10 o'clock the clock would read 0 o'clock, and at 11, it would read 1 o'clock. The OR gate allows the "high" state of the original counter pins through, so if the counter reads "10" or "11", the 12_HR_Tens_A pin will still be high, and if the counter reads "2" the 12_HR_Ones_B pin will still be high, allowing the binary decoder in the display circuit to show the correct time.
The final thing we need is an indicator light for AM/PM. This can be done with a flip flop connected to the output of our 12-hour correction signal. This signal will be high starting at 12 o'clock and transition to low at 1 o'clock. Our flip flop will transition on the low-high transition, exactly as the AM/PM indicator light is supposed to do.
That's all for clock design today. I hope you enjoyed this post, and remember to stay tuned for Part 3, in which I'll go over the user interface buttons and the display circuitry. If you'd like to use my design, you can download the KiCAD schematic and board files from my GitHub page. Everything is licensed under Creative Commons Non-Commercial Attribution Share-Alike 4.0.
I'm very much a n00b at this, so feedback is encouraged! Feel free to leave comments on this post or contact me on Twitter or YouTube if you use the design, find something wrong, have a question about something, or just want to say 'hi'.