Build A Digital Clock

The Logical Design

Posted by Bryan B. Harper On Tuesday 19th of January 2016



Recommended Free-ware:

The Big Picture:

Here's a list of functions a digital clock must perform:

  • Count the passing minutes, hours etc. (i.e., track the passage of time).
  • Display the time visually.
  • Adjust the 'current' time through user interaction.

To realize these functions electronically, we will need the following types of logic circuits and electronic elements:

  • A Clock Signal — like the pendulum in an analog clock, something needs to be the "heartbeat" of our digital clock.
  • Counters — circuits that count each passing time interval (seconds, minutes, hours) in binary.
  • 7-Segment Displays — to display the time (other types of display would suffice, but these are common and easy to use).
  • Decoders — a circuit which translates binary number signals to 7-segment display inputs.
  • Buttons — for setting the time.

With all this in mind, a diagrammatic representation of our digital clock might be as follows:

There are four 7-segment displays—two displays represent each digit of the hour, and two others display each minute digit. For clarity, let's denote the most significant hour digit as $H_{1}$ and the least significant hour digit as $H_{0}$. Likewise for the minutes (i.e, $M_{1}$ and $M_{0}$).

Each display is driven by a counter, intermediated by a decoder. The counters output a binary digit, and the decoders translate binary to something decipherable by the 7-segment display.

Note the way the counters are arranged in a cascading fashion, starting with the clock signal and ending with the AM / PM indicator. The clock signal iterates the 0-9 counter (representing $M_{0}$) once each minute ($\frac{1}{60} \, Hz$). Each time the 0-9 counter iterates from $M_{0}=9$ to $M_{0}=0$ it sends out a signal that iterates the 0-5 counter (representing $M_{1}$). A similar process takes place for the 1-12 counter and AM / PM indicator.

A couple of notes about this diagrammatic sketch: first, there are any number of ways we might sketch out and design our digital clock. This is simply the simplest I could come up with. Second, you might be wondering why the $H_{1}$ and $H_{0}$ digits are together driven by a single counter, whereas the $M_{1}$ and $M_{0}$ are individually driven by two separate counters. Again, this isn't the only possible choice, but I'll explain why I did this in a later section.

The 0-9 Counter:

A counter circuit is a sequential logic circuit. Thus, we could design synchronous or asynchronous versions of the circuit. For this first counter I'll illustrate both methods: we'll find that asynchronous counters are generally simpler, so I'll only provide asynchronous designs for the 0-5 and 1-12 counters.

Synchronous Design:

Generally, a sequential circuit requires the use of flip-flops. For our design, I have chosen to use T (or toggle) flip-flops. (The choice of flip-flop is, to a degree, arbitrary, as various flip-flops can be constructed from one another. However, certain pragmatic concerns may make one the better option. I have chosen T flip-flops simply because I like them).

The T flip-flop's logic circuit, block diagram, and excitation table are shown on the right. When the T input of the the T flip-flop is '1' (true or high), the current state of the flip flop, Q, toggles to its logical opposite on each clock pulse. If the T input is ' $0$ ' (false or low) the state of the flip-flop is unchanged. Lastly, if the Preset or Reset inputs are '1', the state will asynchrnous (i.e., instantly, irrespective of clk) become '1' or '0' respectively.

As always in digital electronics, we'll be doing our counting in binary. For the 0-9 counter, the largest number we will need to represent is $9_{10}$, which in binary is four bits, $1001_{2}$. Each bit will be expressed by the output, $Q$, of a flip flop. So we'll need four flip-flops.

Let's enumerate the flip-flop inputs and outputs for ease of communication. We'll denote the output of the flip-flop representing the least significant bit as $Q_{0}$ and its corresponding input as $T_{0}$. The next input-output pair will be $Q_1$ and $T_1$, and so on. Thus, if we want to represent the number $ 5_{10} $ (i.e., $0101_2$), then the output of each flip-flop should be $Q_{3}=0$, $Q_{2}=1$, $Q_{1}=0$, and $Q_{0}=1$.

Now we have all the information we need to compose an excitation table for our 0-9 counter circuit:

For each value represented by the current state $Q_{3}(t)Q_{2}(t)Q_{1}(t)Q_{0}(t)$ the corresponding next state $Q_{3}(t+1)Q_{2}(t+1)Q_{1}(t+1)Q_{0}(t+1)$ must represent the current value plus one (i.e., we're counting).

To determine the value of a given $T_{k}$ we consult the T flip-flop's excitation table. If $Q_{k}(t) \neq Q_{k}(t+1)$, then $T_{k} = 1$. If $Q_{k}(t) = Q_{k}(t+1)$, then $T_{k} = 0$.

The Clk Out values are determined merely by recalling that we want the circuit to send out a clock signal whenever it has flipped from its highest to lowest numeric value.

Finally, the 'x's denote "don't care" conditions; if our circuit has been properly designed, the inputs with the "don't care" conditions will never occur, so we can safely assume that a given 'x' is either a '1' or '0', whichever simplifies our function most.

Now we utilize the excitation table to derive boolean functions for each T input in terms of each Q output. The most efficient method to do this is by means of Karnaugh map minimization. You can do this by hand, or use this software (K-Map Minimizer). I have provided my K-map analysis below.

If you are unfamiliar with K-map minimization, read through this wikipedia page or download Maurice Karnaugh's original 1953 paper.

The resulting equations are as follows:

  • $ T_{3}=Q_{3}Q_{0}+Q_{2}Q_{1}Q_{0} $
  • $ T_{2}=Q_{1}Q_{0} $
  • $ T_{1}=\overline{Q_{3}}Q_{0} $
  • $T_{0} = 1$

A similar analysis yields the function for the output clk signal:

  • $ \text{Clk Out} = \overline{Q_{3}} \, \overline{Q_{2}} \, \overline{Q_{1}} \, \overline{Q_{0}}$

All that is left to do is to implement these equations into a logic circuit with our four flip-flops (below).

The 0-9 counter is now complete! The Clk In terminal connects to the $\frac{1}{60} Hz$ (1 min) clk signal. Clk Out will connect to the input clock of the next counter (which we're building next). The $Q_{3}$, $Q_{2}$, $Q_{1}$, and $Q_{0}$ outputs will eventually connect to a decoder circuit (which we will build later). For now, however, if you want to see the 0-9 counter in action, connect each of the $Q$ outputs to an LED or probe in order to see the circuit count in binary.

If you aren't already doing so, download this free software to construct your circuit virtually.

Asynchronous Design:

Consider the 4 bit counting sequence below. Note that $Q_{1}$ changes exactly half as often as $Q_{0}$, $Q_{2}$ changes half as often as $Q_{1}$, and so on.

Now, if each $Q_{k}$ is the output of a T flip-flop, consider when it would be necessary that the corresponding clock signal $\text{clk}_{k}$ triggers. The timing diagram is shown below. Again we see that $\text{clk}_{1}$ changes exactly half as often as $\text{clk}_{0}$, $\text{clk}_{2}$ half as often as $ckl_{1}$, and so on. This makes sense because a flip-flop can only change on a clock signal (with the exception of the Present and Reset inputs).

If we overlay these two images, we see that there is an inherent symmetry at work.

We can utilize that symmetry to greatly simply our counter design. By simply making the output of each $Q_{k}$ the input of the subsequent $\text{clk}_{k+1}$ we create a $0-15_{10}$ counter!

This is nice and all, but of course we don't actually want to count all the way up to $15_{10}$. Rather, we want to reset back to $0_{10}$ after we've reached $9_{10}$.

The solution is simple! We simply need to set each $\text{Reset}_{k}$ to '1' at the appropriate moment. In this case, that moment would be the instance our circuit tries to count to $10_{10}$.

Utilizing a truth table (left) with the properties specified above, and some Karnaugh minimization we can derive the requisite boolean function for the Reset inputs:

  • $\text{Reset}=Q_{3}Q_{1}$

And don't forget that we need an output clock signal for the 0-5 counter. Since this signal should occur at exactly the same time as $\text{Reset}_{k}$ occurs, the function is identical:

  • $\text{Clk Out}=Q_{3}Q_{1}$

All that is left to do is assemble the circuit (below).

It's clear that when it comes to counting circuits, because of the correspondence between when bits flip and when clk-signals must occur, employing an asynchronous design yields a more compact circuit. Thus, for all subsequent counters we will only go over asynchrnous designs. (Note that the output clock signal is not visible in the circuit below because it occurs for only a fraction of a second).

The 0-5 Counter:

The procedure here is exactly like before. The only notable difference is that in order to represent our largest number $5_{10}$ we only need 3 bits $101_{2}$ and thus only 3 flip flops.

The 1-12 Counter:

Recall from The Big Picture that the $H_{1}$ and $H_{0}$ digits are together driven by a single counter, whereas the $M_{1}$ and $M_{0}$ were individually driven by two separate counters. Why have I designed it this way?

Well, imagine for a moment designing the hour counters such that one counter drove $H_{1}$ and another drove $H_{0}$, as we did with the minutes. This would require the $H_{0}$ counter to count from 1 to 9, then from 1 to 2 (and repeat). And the $H_{1}$ counter would have to count from 0 to 1, but at irregular intervals. These would make for some pretty unwieldy circuits. Counters like this could be built (probably synchronously), but it would be a somewhat awkward and confusing procedure.

We can greatly simplify matters by having a single circuit that counts from 1-12. However, in order to have this single counter drive two 7-segment displays (one for $H_{1}$ and one for $H_{0}$), we'll later have to construct a decoder the splits the outputs into to two separate sets. But we'll cross that bridge when we get there.

The procedure here is very much that same as with our previous counters, with two exceptions:

  • First, when our 1-12 counter resets it flips to $1_{10}$ rather than $0_{10}$. This translates to the necessity that $Q_{0}=1$ whenever we begin a new cycle. To do this, instead of connecting a wire to $\text{Reset}_{0}$, we connect it to $\text{Preset}_{0}$, which will instantly set $Q_{0}=1$ when the wire is 'ON'.
  • Second,the output clock signal should trigger when the counter reaches $12_{10}$ rather than when the hours reset to $1_{10}$ (because... twelve hour clocks are weird. Seriously, wouldn't it make more sense if the am/pm switch happened at 1am/pm?!).

The circuit is below:

The Minute Decoders:

Our counters output numbers in binary, but if you look at the average 7-segment display, binary is "unintelligible" to it. Most 7-segment displays are constructed such that each segment of the display is controlled by a single input (it's a common convention that each of these inputs is named with a letter, e.,g A, B, C,... etc.).

To translate from binary to individually lit segments we need a decoder circuit. A decoder is simply a circuit that takes a set of inputs operating in one convention, and translates (or 'decodes') them into a set of outputs operating in another convention. For example, you might use a decoder to go from binary to one-hot encoding, or grey code.

Since both the $M_{1}$ and $M_{0}$ decoders translate binary digits to a single 7-segment display, we can use the same design for both.

Decoders use Combinational Logic. So, we'll need a truth table. (Note: I appear to have been a bit lazy in making the truth table below; interpret blank spaces as zeros).

In order to fill out the truth table, it helps have on hand which segments need to be illuminated in order to represent each number:

  • $9_{10} = ABCDFG $
  • $8_{10} = ABCDEFG$
  • $7_{10} = ABC $
  • $6_{10} = ACDEFG$
  • $5_{10} = ACDFG$
  • $4_{10} = BCFG$
  • $3_{10} = ABCDG$
  • $2_{10} = ABDEG$
  • $1_{10} = BC$
  • $0_{10} = ABCDF$

Each input to the decoder $I_{3},$ $I_{2},$ $I_{1},$ and $I_{0}$ corresponds to the outputs of the counter, $Q_{3},$ $Q_{2},$ etc..

Utilizing K-Map minimization again we derive the following output equations:

  • $A=I_{2}I_{0}+\overline{I_{2}}\,\overline{I_{0}}+I_{3}+I_{1} $
  • $B=I_{2}I_{0}+\overline{I_{2}}\,\overline{I_{0}}+\overline{I_{2}}$
  • $ D = I_{2}+\overline{I_{1}}+I_{0} $
  • $ E = (\overline{I_{2}}+I_{1})\overline{I_{0}} $
  • $ F = ( \overline{I_{1}}+\overline{I_{0}})I_{2}+\overline{I_{1}}\,\overline{I_{0}}+I_{3} $
  • $G = (\overline{I_{1}}+\overline{I_{0}})I_{2} + \overline{I_{2}}\,\overline{I_{1}} + I_{3} $

And finally, we can construct the circuit... it's a large cumbersome thing, but it gets the job done.

The Hour Decoder:

Exactly the same principles are employed to design the hour decoder as were used with the minute decoders. However, in this case there will be two sets of outputs. Thus, our truth table and circuit will be twice as large and cumbersome as last time. They are included below.

In the circuit and truth table the $A_{1},$ $B_{1},$ $C_{1},$... etc. outputs all go to the $H_{1}$ display, and the $A_{0},$ $B_{0},$ $C_{0},$... etc. outputs all go to the $H_{0}$ display. (Once again, blanks are to be interpreted as zeros).

Putting It All Together:

We've built everything we need! Now it's just a matter of putting it all together. Below is a gif of the fully assembled (virtual) clock showing a taste of it in action (I can only make gifs so long).

A couple of things to note:

  • First, I've added 'Set Hour' and 'Set Minute' buttons XOR-ed with clock inputs of the $M_{0}$ and $H_{0}$ counters. This enables us to bypass the clock signals and get to the desired time with the push of a button (well, several pushes).
  • Second, the $Q_{3}$ input to the $M_{1}$ decoder is connect to ground (or zero). This is because the $M_{1}$ counter only uses 3-bits, so we'll never need to set $Q{3}=1$.

That's it! Feel free to comment below with any questions.


I'm frequently asked for the Logisim files for the completed project. Thus, I'm including a download link below. Be sure to have Logisim installed.