10.4 Up Counter

Describe the next-state rule that defines an up counter, connect it to the carry-toggle pattern from binary addition, and apply it to real address-generation and loop-counting use cases.

An up counter is a counter whose next-state rule is simply 'add one, modulo the number of available states' — it counts 0, 1, 2, 3, and so on, wrapping back to 0 after reaching its maximum value. It exists because counting upward — tracking how many events have occurred, or generating a steadily advancing sequence of addresses or indices — is by far the most common counting need in digital systems, from a CPU's program counter to a loop index in a hardware state machine.

Core concept: next state = current state + 1 (mod 2^n)

Formally, an up counter's next-state function is next_state = (current_state + 1) mod 2^n for an n-bit natural binary counter. This single rule is what both the ripple counter (Topic 10.2, implemented by cascading toggle flip-flops) and the synchronous counter (Topic 10.3, implemented with T_k = AND of all lower bits) realize in hardware — 'up counter' describes the sequence/direction, while 'ripple' vs. 'synchronous' describes how the clocking is organized to produce that sequence.

Bit by bit, the up-counting rule directly mirrors binary addition's carry chain: the LSB toggles on every clock (it is always being 'added 1' to); each higher bit toggles exactly when every bit below it is currently 1, since that is precisely the condition under which incrementing produces a carry into that bit position — this is why the excitation equations shown in Topic 10.3 look identical to a ripple-carry adder's carry logic.

• Next state = (current state + 1) mod 2^n — counts strictly upward, wrapping at the top. • LSB always toggles every clock; each higher bit toggles exactly on the carry-out condition from the bits below it. • 'Up counter' specifies the direction/sequence; whether it's built as ripple or synchronous is a separate implementation choice.

Step-by-step working

To trace any up counter, simply add 1 (in binary) to the current state on each clock edge, discarding any overflow carry out of the top bit. Starting from 000 on a 3-bit up counter: 000, 001, 010, 011, 100, 101, 110, 111, and then back to 000, since 111 + 1 = 1000 and the leading 1 has nowhere to go (it is discarded), leaving 000. This wraparound is automatic and requires no extra decode/reset hardware for a natural (all-states-used) binary up counter — it falls directly out of the arithmetic.

Practical application, real-world use, and common mistake

Up counters are the natural fit for address generators (stepping through consecutive memory locations), loop counters inside hardware state machines (counting iterations up to a target value before signaling 'done'), and, as introduced earlier in this module, a CPU's program counter, which increments by the size of one instruction after every fetch so execution proceeds through memory in sequence by default.

The common mistake is forgetting that the wraparound is not an error condition to guard against, but the counter's normal, designed behavior — after the maximum value, an unsigned n-bit up counter always returns to 0 rather than 'stopping' or producing some invalid state. This is frequently exactly what's wanted (for instance, a circular buffer index that should wrap back to the start once it reaches the end), but it must be deliberately accounted for in any design that needs to detect 'the count reached its target' rather than relying on the counter to naturally halt.

Up counter next-state rule

This next-state rule is direction-only — it says nothing about whether the counter is implemented as ripple or synchronous. Wraparound after the maximum value is automatic and intentional, not an error.

Up counter, n bits:

  next_state = (current_state + 1) mod 2^n

Carry-toggle view (bit k, 0-indexed):
  bit k toggles on a given clock edge iff bits 0..(k-1) are ALL currently 1

Sequence: 0, 1, 2, 3, ..., (2^n - 1), 0, 1, 2, ...  (repeats indefinitely)

Code Examples

Because the buffer has exactly 16 slots and the counter is a natural 4-bit up counter (2^4 = 16 states), the wraparound from 15 back to 0 is not a bug to avoid — it is precisely the circular-buffer behavior the design wants, achieved for free by the counter's natural modulo-16 arithmetic with no extra logic. Expected result: Write index sequence: ..., 13, 14, 15, 0, 1, ... — cycles through all 16 buffer slots indefinitely.

next_state = (current_state + 1) mod 16 — the counter's wraparound directly implements the circular buffer's wrap-to-start behavior.

Buffer size: 16 slots (indices 0-15), 4-bit up counter as the write index

Clock#   Index (Q3..Q0)   Action
  13         1101 (13)     write to slot 13
  14         1110 (14)     write to slot 14
  15         1111 (15)     write to slot 15  (last slot)
  16         0000 (0)      write to slot 0   <- wrapped automatically, exactly as intended

Important Rules

An up counter's next state is always (current state + 1) mod (number of available states) — a simple, direction-defining rule independent of how it's clocked.

The LSB toggles on every clock edge of an up counter; every higher bit toggles exactly when all lower bits are currently 1 (the carry-out condition).

Wraparound after the maximum value is normal, designed behavior, not an error — whether it should be treated as significant (e.g., to raise a 'done' or 'overflow' flag) is a separate design decision on top of the base counting behavior.

Address generators and loop counters

Up counters generate the sequential addresses used to step through memory during a block read or write, drive the iteration count in hardware finite-state-machine loops (e.g., 'repeat this operation 8 times'), and, as the program counter, keep a CPU's instruction fetch pointer automatically advancing through a program in the default sequential-execution case.

Treating a counter's wraparound from maximum value back to 0 as an unexpected fault condition that needs to be prevented.

Wraparound is the counter's normal, arithmetic-defined behavior (max value + 1 = 0, mod 2^n) — if a design needs to stop, reload, or flag when a specific count is reached rather than silently wrapping, that requires explicit additional comparator/decode logic on top of the base up-counting behavior.

An unsigned binary up counter has no built-in notion of 'this is an error' at its maximum value; it simply keeps counting modulo its state count, which is exactly the behavior circular buffers and free-running timers rely on, but is the wrong behavior for, say, a loop that must stop after exactly N iterations without extra logic.

[conceptual] What single next-state rule defines an up counter, independent of whether it's implemented as ripple or synchronous? A. next_state = current_state - 1 (mod 2^n) B. next_state = (current_state + 1) mod 2^n C. next_state = current_state XOR 1 D. next_state is always reset to 0 on every clock

B. next_state = (current_state + 1) mod 2^n — 'Up counter' names the counting direction/sequence, defined purely by next_state = (current_state + 1) mod 2^n. Whether that sequence is produced via a ripple chain of toggle flip-flops (Topic 10.2) or via synchronous excitation logic (Topic 10.3) is an entirely separate implementation choice layered on top of this same direction rule.

[interview] A free-running 8-bit up counter is at its maximum value, 255. What happens on the next clock edge? A. The counter stops and holds at 255 permanently B. The counter produces an error signal and must be manually reset C. The counter wraps around to 0, exactly as normal binary addition with the overflow carry discarded would predict D. The counter switches to counting downward automatically

C. The counter wraps around to 0, exactly as normal binary addition with the overflow carry discarded would predict — 255 + 1 = 256 = binary 100000000, which needs 9 bits; since the counter only has 8 bits, the overflow carry out of the top bit is simply discarded, leaving 00000000 — the counter wraps to 0 as its normal, designed next state, with no error condition or special handling required unless the design explicitly adds logic to detect and act on that wraparound.

A hardware loop needs to execute an operation exactly 10 times and then assert a DONE signal. Using a 4-bit up counter (which naturally wraps at 16, not 10), describe the extra logic needed to make DONE assert after exactly the 10th iteration.

Add a 4-bit equality comparator that compares the counter's current value Q3..Q0 against the constant 9 (the 10th count, 0-indexed 0 through 9). When the counter reaches 9 (binary 1001) after the 10th clock edge, the comparator output goes high, and that signal is used as DONE (and optionally to reset the counter back to 0 for the next loop, rather than letting it continue counting up to 15). This is exactly the reset/decode technique generalized in the Mod-N counter topic (10.7).

You cannot rely on the counter's natural wraparound (which happens at 16, not 10) — you need a comparator watching the count value.