Home Digital Electronics VLSI Tools & Labs Protocols About
Digital Electronics · Sequential Logic

Counters in Digital Electronics

Synchronous vs asynchronous, up/down, Mod-N, BCD, ring, and Johnson counters — with truth tables, timing diagrams, and working Verilog for every type.

Synchronous Counter Ripple Counter Mod-N Counter BCD Counter Ring Counter Johnson Counter Verilog
Introduction
What Is a Counter?

A counter is a sequential logic circuit that progresses through a defined sequence of binary states on each clock edge. It is built from flip-flops — typically D or T type — connected so that each clock pulse advances the count by one. After reaching its maximum state, the counter wraps back to zero and repeats the sequence indefinitely.

An n-bit counter has 2ⁿ possible states, counted from 0 to 2ⁿ−1. A 4-bit counter counts 0 through 15 (0000 to 1111 in binary), then resets to 0000. Every real digital system uses counters: your CPU's program counter increments on every fetch, your UART uses a counter to time bit periods, and the address bus of every RAM controller is driven by a counter.

Q3 (MSB)
0
Q2
0
Q1
0
Q0 (LSB)
0
Count: 0 / 15

Counters are classified by:

Asynchronous Counter
Ripple Counter — How It Works

In an asynchronous (ripple) counter, only the first flip-flop (Q0, LSB) is driven by the external clock. Every subsequent flip-flop uses the output of the previous flip-flop as its clock. The "clock pulse" ripples through the chain — hence the name.

Each T flip-flop with T=1 toggles on every rising edge of its clock input. So Q0 toggles every clock cycle. Q1 toggles every time Q0 goes from 1→0 (falling edge). Q2 toggles every time Q1 falls. Q3 toggles every time Q2 falls. The result is binary counting: Q3Q2Q1Q0 cycles 0000→0001→0010→...→1111→0000.

Propagation delay problem: Each flip-flop adds one tpd of delay before the next flip-flop can respond. For a 4-bit ripple counter, the total delay is 4 × tpd. At high clock frequencies, Q3 has not yet settled before the next clock edge arrives, causing glitches and incorrect intermediate states (e.g., the counter passes through 0111 on the way from 0111→1000). This is why ripple counters are not used above a few MHz in real designs.

4-Bit Ripple Counter — State Table

Clock PulseQ3Q2Q1Q0Decimal
0 (Reset)00000
100011
200102
300113
401004
810008
15111115
16 (wraps)00000

Advantages and Disadvantages

Advantages

Simple circuit — each FF needs no extra logic. Uses fewer gates than synchronous. Natural for low-frequency event counting where glitches don't matter (e.g., counting button presses).

Disadvantages

Cumulative propagation delay limits maximum clock speed. Produces glitches — intermediate wrong states during counting. Output cannot be used combinationally without extra settling time.

Synchronous Counter
Synchronous Counter — No Ripple, No Glitches

In a synchronous counter, all flip-flops share the same clock. They all update simultaneously at the rising clock edge. Combinational logic on the flip-flop inputs determines which FFs toggle. The result: no propagation delay accumulation — the maximum clock frequency is limited only by the slowest combinational logic, not the chain of FFs.

How the Toggle Logic Works

Using T flip-flops (toggle when T=1):

This is the carry chain: each higher bit only toggles when all lower bits are 1 — which is exactly when a carry would propagate in binary addition. Unlike ripple where the carry physically ripples one FF at a time, here the carry is computed combinationally and all FFs update on the same clock edge.

Key insight: Synchronous counters are the standard in all VLSI and FPGA designs. When you write count <= count + 1 in Verilog inside an always @(posedge clk) block, the synthesizer implements a synchronous counter — an n-bit adder whose output feeds back into a register. The adder is purely combinational; only the register is clocked.

Synchronous Up Counter — Verilog

module sync_counter_4bit (
    input  wire       clk,
    input  wire       rst,   // synchronous reset
    output reg  [3:0] count
);
    always @(posedge clk) begin
        if (rst)
            count <= 4'b0000;
        else
            count <= count + 1'b1;
    end
endmodule

Synchronous Down Counter — Verilog

module sync_down_counter (
    input  wire       clk,
    input  wire       rst,
    output reg  [3:0] count
);
    always @(posedge clk) begin
        if (rst)
            count <= 4'b1111;  // starts at max
        else
            count <= count - 1'b1;
    end
endmodule

Up/Down Counter — Verilog

module up_down_counter (
    input  wire       clk,
    input  wire       rst,
    input  wire       up,    // 1 = count up, 0 = count down
    output reg  [3:0] count
);
    always @(posedge clk) begin
        if (rst)
            count <= 4'b0000;
        else if (up)
            count <= count + 1'b1;
        else
            count <= count - 1'b1;
    end
endmodule
Mod-N Counter
Mod-N Counter — Custom Count Sequence

A Mod-N counter counts from 0 to N−1, then resets to 0. The modulus N defines how many states the counter visits before wrapping. A standard 4-bit binary counter is Mod-16. Clock dividers, timers, and display drivers all require specific moduli.

Common examples: Mod-10 (BCD, used in decimal digit displays), Mod-6 (seconds/minutes tens digit — 0–5), Mod-12 (12-hour clock hour display), Mod-60 (built from Mod-6 × Mod-10 cascaded).

Mod-6 Counter — Counts 0 to 5

Reset when count reaches 6 (binary 0110):

0000 0001 0010 0011 0100 0101 0110 → RESET
module mod6_counter (
    input  wire      clk,
    input  wire      rst,
    output reg [3:0] count
);
    always @(posedge clk) begin
        if (rst || count == 4'd5)
            count <= 4'b0000;
        else
            count <= count + 1'b1;
    end
endmodule

BCD Counter (Mod-10) — Counts 0 to 9

Counts 0–9, resets on 10 (1010). Used in digital clocks, calculators, and any decimal display system:

0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 → RESET
module bcd_counter (
    input  wire      clk,
    input  wire      rst,
    output reg [3:0] count,
    output wire      carry_out   // goes high when count wraps (useful for cascading)
);
    assign carry_out = (count == 4'd9);

    always @(posedge clk) begin
        if (rst || count == 4'd9)
            count <= 4'b0000;
        else
            count <= count + 1'b1;
    end
endmodule

// Cascade two BCD counters for 00-99:
// bcd_counter units(.clk(clk), .rst(rst), .count(units_val), .carry_out(tens_clk));
// bcd_counter tens (.clk(tens_clk), .rst(rst), .count(tens_val), .carry_out());

Mod-N Counter (Generic)

module mod_n_counter #(
    parameter N = 10,               // modulus
    parameter W = $clog2(N)         // auto-size bit width
)(
    input  wire          clk,
    input  wire          rst,
    output reg  [W-1:0]  count
);
    always @(posedge clk) begin
        if (rst || count == N - 1)
            count <= '0;
        else
            count <= count + 1'b1;
    end
endmodule
Special Counters
Ring Counter and Johnson Counter

Ring Counter

A ring counter is a circular shift register. A single 1 bit rotates through n flip-flops. Only one output is HIGH at any time — a one-hot encoding. An n-bit ring counter has only n valid states (not 2ⁿ). It is initialized with exactly one FF at 1 and all others at 0.

4-bit ring counter sequence (initialized to 1000):

1000 0100 0010 0001 1000 → repeats
module ring_counter (
    input  wire      clk,
    input  wire      rst,
    output reg [3:0] q
);
    always @(posedge clk) begin
        if (rst)
            q <= 4'b1000;           // initialize with single 1
        else
            q <= {q[0], q[3:1]};   // rotate right
    end
endmodule

Use case: Sequencing multiple peripherals — asserting exactly one enable signal per cycle without priority encoder logic. Simpler decode than a binary counter.

Johnson Counter (Twisted Ring Counter)

A Johnson counter feeds the complement of the last FF back to the first. An n-bit Johnson counter produces 2n states — double a ring counter. The sequence for a 4-bit Johnson counter:

0000 1000 1100 1110 1111 0111 0011 0001 → 0000
module johnson_counter (
    input  wire      clk,
    input  wire      rst,
    output reg [3:0] q
);
    always @(posedge clk) begin
        if (rst)
            q <= 4'b0000;
        else
            q <= {~q[0], q[3:1]};  // invert last bit, shift right
    end
endmodule

Use case: Generating overlapping two-phase clock signals. Each adjacent pair of outputs overlaps by one cycle, useful for controlling two-phase CMOS logic and stepper motor drives.

Ring vs Johnson — Comparison

Ring: n states, one-hot encoding, easy decode — one FF is output directly.
Johnson: 2n states, two-hot→one-hot transition, slightly more complex decode — AND of adjacent pairs.

Gray Code Counter

A Gray code counter changes only one bit per transition. Critical in CDC (clock domain crossing) — a multi-bit pointer changing only 1 bit avoids metastability ambiguity. Used in async FIFO read/write pointer design.

Real-World Applications
Where Counters Are Used in Real Systems

Frequency Division

A counter's MSB output has half the frequency of the input clock. An n-bit counter divides the clock by 2ⁿ. A single D flip-flop divides by 2. Three flip-flops in a ripple chain divide by 8. This is how PLLs generate sub-clocks from a high-frequency reference, and how UART baud rate generators work — a counter overflows at the desired bit period, generating a baud-rate enable pulse.

Program Counter (PC) in CPUs

The program counter is a register that counts the address of the next instruction to fetch. On every clock cycle (absent branches), it increments by the instruction size (4 bytes for a 32-bit ISA). On a branch, the PC is loaded with the target address. On a function call, the old PC is saved to the stack, then PC is loaded with the function entry. The PC is the most frequently updated register in any CPU — it advances 10⁹ times per second on a 1 GHz processor.

Digital Clock (Seconds → Minutes → Hours)

A complete digital clock chains counters: a 32768 Hz crystal oscillator feeds a 15-bit counter (divides by 32768) to produce a 1 Hz tick. This drives a Mod-10 counter (units seconds, 0–9), whose carry drives a Mod-6 counter (tens seconds, 0–5). Their combined output (00–59) drives the minutes chain (Mod-10 + Mod-6). The hours chain uses Mod-12 or Mod-24. Total flip-flop count for a complete clock: under 30.

Address Generator in Memory Controllers

Burst read/write operations in DDR memory controllers use a counter to auto-increment the column address within a row. The burst length counter (typically 4–16 beats) fires a "burst done" signal when it reaches the programmed burst length. AXI4 burst transactions use a beat counter that counts from 0 to AWLEN, generating ARVALID/RVALID signals for each data beat.

PWM (Pulse Width Modulation) Generator

A PWM generator compares a free-running counter against a programmable threshold register. When counter < threshold, output is HIGH; otherwise LOW. Changing the threshold changes the duty cycle without stopping the counter. This is how motor speed controllers, LED dimmers, and servo controllers work at the hardware level — all built from one counter and one comparator.

ApplicationCounter TypeBitsKey Parameter
UART Baud RateSynchronous Up8–16Overflow period = 1/baud rate
Digital ClockBCD (Mod-10 + Mod-6)4 eachCascaded for seconds/min/hr
CPU Program CounterSynchronous Up + Load32 or 64Increments by instruction size
PWM GeneratorFree-running Up8–16Compare with duty cycle register
Async FIFO PointerGray code Uplog₂(depth)+1One-bit change per increment
Frequency DividerRipple or Sync UpNMSB output = clk / 2ⁿ
Design Comparison
Synchronous vs Asynchronous — When to Use Each
FeatureSynchronousAsynchronous (Ripple)
Clock connectionAll FFs share one clockFFs chain-clock each other
Propagation delayNo accumulation — fixed tpdAdds n × tpd (n = number of FFs)
GlitchesNone — all FFs update togetherYes — incorrect intermediate states
Max clock speedHigh — limited by logic, not chainLow — limited by ripple delay
PowerHigher (all FFs toggle on same edge)Lower (FFs toggle less often)
Gate countMore (needs carry logic)Less (no carry logic needed)
Used in VLSIAlways — standard practiceRarely — only for slow counting

Rule in VLSI design: Always use synchronous counters. Asynchronous counters create multi-bit transitions that violate timing analysis assumptions and can cause metastability when their outputs cross clock domains. In all RTL designs targeting synthesis, count <= count + 1 with a single clock edge is the correct implementation — the synthesizer handles the carry logic optimally.

Frequently Asked Questions
What is a counter in digital electronics?
A counter is a sequential logic circuit built from flip-flops that progresses through a binary sequence on each clock edge. An n-bit counter has 2ⁿ states and counts from 0 to 2ⁿ−1 before wrapping. Counters are used in CPUs (program counter), timers, UART baud rate generators, address generators, PWM controllers, and frequency dividers.
What is the difference between synchronous and asynchronous counters?
In a synchronous counter, all flip-flops share the same clock and update simultaneously — no propagation delay accumulation, no glitches. In an asynchronous (ripple) counter, each flip-flop is clocked by the output of the previous one. The delay accumulates: n flip-flops add n × tpd of delay, causing incorrect intermediate states (glitches) at high frequencies. Synchronous counters are used in all modern VLSI design.
What is a Mod-N counter and how do I design one?
A Mod-N counter counts from 0 to N−1, then resets. Design: add combinational reset logic that asserts when the count reaches N. In Verilog: if (count == N-1) count <= 0; else count <= count + 1. For asynchronous counters, a NAND gate detects the terminal count and drives the CLR pin. Mod-10 (BCD), Mod-6 (seconds/minutes tens digit), and Mod-12 (hours) are the most common in practice.
What is a BCD counter and where is it used?
A BCD (Binary Coded Decimal) counter is a Mod-10 counter counting 0000–1001 (0–9) in binary. It is used wherever decimal digits need to be displayed: digital clocks, calculators, scoreboards, and 7-segment display drivers. Two cascaded BCD counters (units + tens) count 00–99. The carry output of the units counter clocks the tens counter. Reset occurs when units reaches 9 — the next pulse resets to 0 and sends a carry to the tens stage.
What is a ring counter?
A ring counter is a circular shift register where the output of the last flip-flop feeds back to the first. It starts with exactly one 1 in the chain; that 1 rotates one position per clock cycle. An n-bit ring counter has n states (not 2ⁿ). It produces one-hot encoded outputs — exactly one output is HIGH at any time — making it useful for sequencing peripherals without a decoder. No decode logic needed: each flip-flop output directly enables one device.
What is a Johnson counter?
A Johnson counter feeds the complement of the last flip-flop back to the first. An n-bit Johnson counter produces 2n states — double a ring counter. It starts at all-zeros, shifts in 1s until all-ones, then shifts in 0s until all-zeros again. The 4-bit sequence is: 0000→1000→1100→1110→1111→0111→0011→0001→0000. Used to generate overlapping two-phase signals and as a Mod-2n frequency divider.
How do I implement a 4-bit synchronous counter in Verilog?
module counter_4bit(input clk, input rst, output reg [3:0] count); always @(posedge clk) begin if (rst) count <= 4'b0000; else count <= count + 1; end endmodule. For BCD: replace count + 1 with (count == 9) ? 0 : count + 1. For up/down: use an extra input and branch on it. The synthesizer converts count + 1 into an optimized 4-bit incrementer automatically.