# Synchronous counters

*One shared clock, a count-enable chain, and clean cascading*

A synchronous counter is a counter in which every flip-flop shares one common clock so all bits update on the same edge, and a count-enable AND chain toggles bit k only when the enable and every lower bit are 1; a carry-out lets counters cascade, a direction control makes it count up or down, and a decoded synchronous clear or load makes it count through a chosen modulus.

Group: Processor
URL: https://digiwleea.wleeaf.dev/learn/synchronous-counters/

The [counter lesson](https://digiwleea.wleeaf.dev/learn/counter/) built two counters: a **ripple** counter, where each stage's output clocks the stage above it, and a **program counter**, a synchronous up-counter with an adder bolted on. This lesson stays with the **synchronous** family and fills in the machinery a real counter carries: a count **enable**, a **carry-out** for chaining, an **up or down** direction, and a clean way to count to any modulus. It leans on the toggle flip-flop from [flip-flop types](https://digiwleea.wleeaf.dev/learn/flip-flop-types/) (hold when `T = 0`, flip when `T = 1`) and on the clocked [state machine](https://digiwleea.wleeaf.dev/learn/state-machine/) idea (one shared clock stepping a register).

## One clock for every bit

The word *synchronous* means one thing here: **every flip-flop is driven by the same clock**. One clock wire fans out to all of them, and combinational logic in front of each bit decides whether that bit should toggle on the coming edge. Compare that with a ripple counter, where the system clock reaches only bit 0 and each stage's own output becomes the *clock* of the next stage. The two structures count the same `0, 1, 2, 3, ...` sequence, but they behave very differently in time.

- **Clock.** Ripple: the clock drives bit 0 only, and each stage's output clocks the stage above it. Synchronous: one clock wire reaches every flip-flop at once.
- **When bits move.** Ripple: one bit at a time, the change rippling upward from bit 0. Synchronous: all bits together, on the single edge.
- **Settling.** Ripple: the top bit lags by the sum of every stage's delay (about `n` flip-flop delays for `n` bits), and the outputs pass through wrong codes on the way (the glitch detail is in [the counter lesson](https://digiwleea.wleeaf.dev/learn/counter/)). Synchronous: one flip-flop delay plus the enable-logic delay, then every bit is valid at the same instant.
- **Cost.** Ripple: the fewest gates (just the toggle flip-flops). Synchronous: extra toggle-enable logic in front of each bit, in exchange for clean, glitch-free timing.

## The count-enable AND chain

A synchronous counter needs a rule that says *which* bits toggle on the next edge, and the rule is exact: **bit k toggles when the count enable and all bits below it are `1`**. Bit 0 toggles on every enabled edge; bit 1 toggles when bit 0 is `1`; bit 2 toggles when bits 0 and 1 are both `1`; and so on. That is just a binary carry reaching column `k`, spelled out as an AND. The master **count enable** `EN` gates the whole chain: with `EN = 0` no bit toggles, so the counter freezes and holds its value.

```
T0 = EN , T1 = EN AND Q0 , T2 = EN AND Q0 AND Q1 , ... , Tk = EN AND Q0 AND Q1 AND ... AND Q(k-1)
```

There is a tidy way to build that chain without a separate wide AND for every bit: carry the AND term along one stage at a time. Call the enable arriving at bit `k` its **enable-in** `e_k`, start with `e_0 = EN`, and pass `e_{k+1} = e_k AND Q_k` up to the next stage. Then `T_k = e_k`. Each stage adds just one 2-input AND. This chain looks like the ripple carry inside an [adder](https://digiwleea.wleeaf.dev/learn/adder8/), but it is **combinational**: it settles within one clock period, before the next edge, so all the flip-flops still fire together off the one clock. (A very wide chain adds delay and caps the clock rate, which is why big counters sometimes compute the enables with parallel look-ahead ANDs instead of a long serial chain.)

## A worked 3-bit synchronous counter

Take a 3-bit counter. Its toggle inputs are `T0 = EN`, `T1 = EN AND Q0`, and `T2 = EN AND Q1 AND Q0`. Add one more useful output, the **ripple-carry-out** `RCO = EN AND Q2 AND Q1 AND Q0`, which is high only when the counter is full (`111`) *and* enabled. Trace every count with `EN = 1`, then two rows with `EN = 0` to see it hold:

| EN | Q2 Q1 Q0 | T2 = EN·Q1·Q0 | T1 = EN·Q0 | T0 = EN | RCO = EN·Q2·Q1·Q0 | next |
| --- | --- | --- | --- | --- | --- | --- |
| 1 | 000 | 0 | 0 | 1 | 0 | 001 |
| 1 | 001 | 0 | 1 | 1 | 0 | 010 |
| 1 | 010 | 0 | 0 | 1 | 0 | 011 |
| 1 | 011 | 1 | 1 | 1 | 0 | 100 |
| 1 | 100 | 0 | 0 | 1 | 0 | 101 |
| 1 | 101 | 0 | 1 | 1 | 0 | 110 |
| 1 | 110 | 0 | 0 | 1 | 0 | 111 |
| 1 | 111 | 1 | 1 | 1 | 1 | 000 |
| 0 | 011 | 0 | 0 | 0 | 0 | 011 |
| 0 | 111 | 0 | 0 | 0 | 0 | 111 |

_A 3-bit synchronous up-counter with enable and carry-out. With EN = 1 the toggle-enables follow the AND rule and the count climbs 0 to 7 then wraps; every bit that changes changes on the same edge. RCO fires once, at 111, the count where the counter is full. With EN = 0 (last two rows) all toggle-enables are 0, so the counter holds its value no matter how many edges pass._

Read the `011` row: both lower bits are `1`, so `T2`, `T1`, and `T0` are all high and the count steps cleanly to `100` in one edge, not through the intermediate codes a ripple counter would flash. Read the `EN = 0` rows: the enable zeroes the whole chain, so the counter simply waits. That single enable line is what lets you **pause** a counter and, next, **chain** counters together.

## Cascading: the ripple-carry-out

To build a wider counter from narrow ones, wire the low counter's `RCO` into the high counter's `EN`, and give both counters the **same clock**. Now the high counter is enabled only on the one edge where the low counter is full and rolls over. Two 4-bit synchronous counters chained this way make an 8-bit synchronous counter: the low nibble counts `0` to `15`, and on the edge it wraps `1111` to `0000` its `RCO` is high, so the high nibble increments on that very edge.

> **TIP:** This is still fully **synchronous**, even though the signal is called ripple-carry-*out*. `RCO` feeds the next stage's **enable** (a data input the AND chain reads), never its **clock**. Both counters fire off the one shared clock, so there is no cumulative clock skew, unlike a ripple counter where a stage's output really is the next stage's clock. Same word, different wire: carry into the enable, not into the clock.

**Q (Try it):** A 4-bit synchronous up-counter has its `RCO` wired to the count-enable of a second 4-bit synchronous counter, both on the same clock, both starting at `0`. How many clock edges until the high counter first reads `1`? And why is this cascade still called synchronous even though we used a ripple-carry-out?

**A:** The low counter's `RCO` is high only when it holds `1111` (15) and is enabled, which happens after 15 edges (it counts `0` up to `15`). On the 16th edge the low counter wraps `1111` to `0000` and, because its `RCO` enabled the high counter for that edge, the high counter increments `0` to `1` at the same time. So it takes **16 edges**. It is synchronous because every flip-flop in both counters is clocked by the one shared clock; `RCO` only drives the high counter's **enable** (a data input), it is never used as a clock, so there is no accumulating skew.

## Counting up or down

Counting down flips the rule: **bit k toggles when all bits below it are `0`**, because a binary borrow reaches column `k` exactly when everything under it has run out. So a down-counter's chain uses the *complements* of the lower bits. Trace `EN = 1` counting down from `000`: `000, 111, 110, 101, 100, 011, 010, 001, 000`. At `000` every lower bit is `0`, so all three bits toggle and it wraps straight to `111`; after that only the bits whose lower neighbours are all `0` flip.

An **up/down counter** carries both rules and a direction line `DIR` (say `DIR = 1` counts up, `DIR = 0` counts down) that selects which one feeds each toggle input:

```
Tk = EN AND [ (DIR AND Q0 AND ... AND Q(k-1)) OR (NOT DIR AND NOT Q0 AND ... AND NOT Q(k-1)) ]
```

Bit 0 has no lower bits, so its AND terms are empty (`= 1`) and `T0 = EN` in both directions: bit 0 always toggles when enabled. For the cascade signal, an up-counter exports a **carry** (`EN AND` all bits `1`, high at the top count), and a down-counter exports a **borrow** (`EN AND` all bits `0`, high at `000` just before it wraps to all `1`s). Feed whichever one into the next stage's enable, exactly as before.

## Counting to N: mod-N synchronously

A plain 3-bit counter wraps after `2^3 = 8` values. To count **modulo N** (through `N` states `0` to `N - 1`, then wrap), detect the **last** value `N - 1` and use a **synchronous** clear or load so the wrap happens on the next edge, not the instant the value appears. For a **mod-6** counter (`0` through `5`), the last value is `5 = 101`. An [AND](https://digiwleea.wleeaf.dev/learn/and/) of `Q2` and `Q0` is high at `101`, and among the six counts the counter actually visits (`0` to `5`) only `5` sets both, so that one line flags the terminal count. Wire it to a synchronous clear, or to a load whose data input is `0`: on the next edge the count goes cleanly `5` to `0`, giving exactly six states `0, 1, 2, 3, 4, 5`.

The [counter lesson](https://digiwleea.wleeaf.dev/learn/counter/) built its mod-N the simpler way, by detecting `N` itself and clearing **asynchronously**, which works but lets the value `N` flash for one instant before it is wiped. Detecting `N - 1` and clearing **synchronously**, as here, never shows an out-of-range count: the clear is just another input to the flip-flops and only takes effect at the edge. Same modulus, cleaner timing.

> **TIP:** The same synchronous **load** input that resets a mod-N counter also lets it **start** anywhere: drive the load data with a preset value and pulse load, and the count begins there. That is the exact load path that turns the [program counter](https://digiwleea.wleeaf.dev/learn/counter/) into a jump-capable counter: count normally, or load a target address when a control line says so.

**Spot the fault** (Wrong logic level): Q1=1, Q0=0, T2 (should be Q1·Q0)=1. Look at T2.

`T2` is high even though `Q0` is `0`. Bit 2 must toggle only when **all** lower bits are `1` (`T2 = EN AND Q1 AND Q0`), but here it was wired to `Q1` alone, forgetting `Q0`. At count `010` bit 0 and bit 2 both toggle, so the count jumps to `111` instead of stepping to `011`. Fix: AND in every lower bit, not just the one immediately below.

> **WARN:** **Common mistakes.** Get the toggle condition right: bit k toggles when **all** lower bits are `1` (up) or all `0` (down), not just the single bit beneath it (the fault above). Gate the whole chain with the count **enable**: forget it and the counter free-runs and cannot be paused or cascaded. The enable AND chain is **combinational** and must settle inside one clock period, so a very wide serial chain limits the maximum clock rate (use parallel look-ahead ANDs for wide counters). When cascading, feed the carry-out into the next stage's **enable**, never its **clock**, or you have quietly rebuilt an asynchronous ripple counter. And mind the mod-N off-by-one: detect `N - 1` and clear or load on the **next** edge for a glitch-free wrap; detecting `N` with an async clear lets `N` flash for an instant (see [the counter lesson](https://digiwleea.wleeaf.dev/learn/counter/)).

> **KEY:** Synchronous timing is why real systems count this way. Every bit changes off one clock edge with a single, bounded settling delay, so a moment after the edge the whole count is valid and glitch-free, and you can decode it, compare it, or feed it to an address bus with no hazards. That predictability is what lets a synchronous counter drive [memory](https://digiwleea.wleeaf.dev/learn/ram/) addresses, act as a timer, and sequence a CPU's fetch-decode-execute without ever showing a wrong intermediate value. With the enable, carry-out, direction, and modulus in hand, the next step is the [memory](https://digiwleea.wleeaf.dev/learn/ram/) a counter's address selects.

### FAQ

**Q:** What is a synchronous counter?

**A:** A synchronous counter is a counter in which every flip-flop shares one common clock, so all bits update on the same edge. Combinational logic in front of each bit decides whether it toggles: bit k toggles when the count enable and all lower bits are `1`. Because there is no clock rippling from stage to stage (unlike a [ripple counter](https://digiwleea.wleeaf.dev/learn/counter/)), the outputs step atomically from one valid count to the next with no glitches.

**Q:** How does the count-enable AND chain decide which bits toggle?

**A:** Each bit has a toggle input `T_k = EN AND Q0 AND Q1 AND ... AND Q(k-1)`: bit 0 toggles on every enabled edge, and bit k toggles only when the enable `EN` and every lower bit are `1` (a binary carry reaching column k). The chain is usually built one stage at a time, `e_{k+1} = e_k AND Q_k`, so each bit adds just one AND gate. Holding `EN = 0` zeroes every toggle input, which freezes the counter.

**Q:** What is a ripple-carry-out and how do you cascade counters with it?

**A:** The ripple-carry-out `RCO = EN AND` (all bits `1`) is high for the single count where a counter is full and enabled. To make a wider counter, wire the low counter's `RCO` into the high counter's **enable** and give both the same clock: the high counter then advances only on the edge the low counter rolls over. It stays synchronous because `RCO` drives an enable input, not a clock, so no clock skew accumulates.

**Q:** How do you build a mod-6 (or mod-N) synchronous counter?

**A:** Detect the last value `N - 1` and use a synchronous clear or load so the wrap happens on the next clock edge. For mod-6, detect `5 = 101` (an AND of `Q2` and `Q0`, since among counts `0` to `5` only `5` sets both) and load `0` on the next edge, giving states `0, 1, 2, 3, 4, 5`. Detecting `N - 1` and clearing synchronously is glitch-free, unlike detecting `N` with an asynchronous clear, which lets `N` flash for an instant.
