top of page

Johnson Counter (Twisted Ring):
Concept → RTL → Simulation


What is a Johnson Counter?

A Johnson counter (aka twisted ring) is a shift-register style counter where the inverted MSB is fed back to the LSB each clock.
For an N-bit design, it produces 2N unique states—twice as many as a one-hot ring—while keeping next-state logic extremely simple (just a shift and an invert).

​

Why designers use it

​

  • 2N states with N flip-flops (denser than a one-hot ring).
     

  • No carry chains or adders—just wiring and a single inversion.
     

  • Predictable timing (all flip-flops clocked together).
     

  • Easy decoding: patterns are runs of 1s followed by runs of 0s (or vice versa).
     

Problem Statement (Your Spec)

​

  • N = 4, 2N = 8 unique states.
     

  • Async reset → Q = 0000.
     

  • Inputs: clk, arst
     

  • Output: Q[3:0]
     

  • Expected sequence length: 8
     

For a 4-bit Johnson counter starting at 0000, the sequence is:

yaml

0000 → 0001 → 0011 → 0111 → 1111 → 1110 → 1100 → 1000 → 0000 → …

Notice each step flips one bit—this Gray-like behavior is attractive for glitch-sensitive decodes.

RTL: 4-bit Johnson Counter

 Verilog

module johnson4 (

  input  wire clk,

  input  wire arst,

  output reg  [3:0] Q

);

  always @(posedge clk or posedge arst) begin

    if (arst)

      Q <= 4'b0000;

    else

      Q <= {Q[2:0], ~Q[3]};

  end

endmodule

Code, line by line

​

  • @(posedge clk or posedge arst)
    Uses a single always block with asynchronous reset. When arst=1, the counter immediately seeds to 0000 (no clock needed).

     

  • Reset path
    Q <= 4'b0000; chooses the all-zeros starting point, which is one of the legal Johnson states.

     

  • Next-state path
    Q <= {Q[2:0], ~Q[3]}; performs:

     

    • A left shift of the existing bits (Q[2:0] move up).
       

    • Feedback of the inverted MSB (~Q[3]) into the LSB.
       

  • Walk through the first few edges:
     

    • 0000 → {000, ~0} = 0001
       

    • 0001 → {001, ~0} = 0011
       

    • 0011 → {011, ~0} = 0111
       

    • 0111 → {111, ~0} = 1111
       

    • …and then it walks the 1s back down to zeros.
       

No combinational decode/adder/carry needed—this is why it’s fast and resource-light.

Testbench: Drive & Observe

 Verilog

module tb_johnson4;

  reg clk = 0;

  reg arst = 1;

  wire [3:0] Q;

 

  johnson4 tb (.clk(clk), .arst(arst), .Q(Q));

 

  // 10 time-unit clock

  always #5 clk = ~clk;

 

  initial begin

    arst = 1;     // hold reset (Q = 0000)

    #12;          // release reset not exactly on an edge

    arst = 0;     // first active posedge at t=15 starts the sequence

    #100;         // run long enough to see multiple cycles

    $finish;

  end

 

  initial

    $monitor("Time=%0t | arst=%b | Q=%b", $time, arst, Q);

endmodule

What you’ll see in simulation

​

  • Reset phase: Q pinned to 0000.
     

  • After reset release: at the next rising edge, the counter begins the expected 8-state cycle.
     

  • $monitor prints time, reset, and Q so you can verify the exact order.

​

Where Johnson Counters Shine

​

  • Phased enables / time-slot scheduling: Each state can gate a different block.
     

  • Glitch-sensitive paths: One-bit changes per step reduce hazards.
     

  • Compact sequencers: 2N states with N flops is efficient for small N.
     

  • Simple decodes: Check short patterns like “leading/trailing 1s” with tiny logic.
     

Practical Notes & Tips

​

  • Reset discipline: Use async assert, clean de-assert (meet recovery/removal) to avoid metastability.

​

  • Parameterize easily (optional):

​

​

​

​

​

​

​

​

​

​

​​​

  • Add an enable (optional):

​

​

​

​

​

  • ​​Safety/verification (SystemVerilog):

     Assert the “one-bit change” property:​​

​​

​​

​​

​​

​

​​​

  • Decoding hint:

     States look like 0000, 0001, 0011, 0111, 1111, 1110, 1100, 1000—
     runs of 1s grow, then shrink; decoders can key off edges rather than full equality checks.

​

Summary

A 4-bit Johnson counter gives you 8 unique, glitch-light states with zero carry logic and tiny next-state hardware. The provided RTL seeds safely with an async reset and generates the classic Johnson sequence with a single line of shift-invert logic. The testbench shows the full cycle and verifies timing and reset behavior—clean, compact, and very FPGA/ASIC-friendly.​​​​​​​​​​

 Verilog

module johnson #(parameter N=4)(

  input  wire       clk, arst,

  output reg [N-1:0] Q

);

  always @(posedge clk or posedge arst)

    if (arst) Q <= '0;

    else      Q <= {Q[N-2:0], ~Q[N-1]};

endmodule

 Verilog

if (en) Q <= {Q[2:0], ~Q[3]};  // hold when en=0

 Verilog

// Only 1 bit differs between consecutive states

assert property (@(posedge clk) disable iff (arst)

  $onehot(Q ^ $past(Q)));

Johnson Counter— 15 Interview Q&As (Refined & Explained)

1) How many states are there in an N-bit Johnson counter?

​

Refined:
Exactly 2N. The next-state rule

Qnext={Q[N−2:0], ∼Q[N−1]}Q_{\text{next}} = \{Q[N-2:0],\, \sim

Q[N-1]\}Qnext​={Q[N−2:0],∼Q[N−1]}

shifts left and feeds back the inverted MSB. Starting from a legal seed (e.g., all 0s), this produces a single cycle of length 2N.
Compare: a one-hot ring uses N FFs for N states; Johnson uses the same N FFs for 2N states.

​​

​​

2) Why are Johnson counters useful for sequence generation?

​

Refined:

  • Longer sequence with fewer FFs (2N states).
     

  • Unit-distance transitions (1 bit changes each step) → fewer decode glitches.
     

  • Simple decode: states look like runs of 1s followed by runs of 0s (or mirror), so many outputs are just AND/OR of short bit runs.​​

​

​

3) How to decode Johnson states efficiently?

​

Refined:
Exploit the run pattern. For N=4 (states: 0000,0001,0011,0111,1111,1110,1100,1000):

​

verilog

​

wire s0 =  (Q == 4'b0000);

wire s1 = ~Q[3] & ~Q[2] & ~Q[1] &  Q[0];  // 0001

wire s2 = ~Q[3] & ~Q[2] &  Q[1] &  Q[0];  // 0011

wire s3 = ~Q[3] &  Q[2] &  Q[1] &  Q[0];  // 0111

wire s4 =  Q[3] &  Q[2] &  Q[1] &  Q[0];  // 1111

wire s5 =  Q[3] &  Q[2] &  Q[1] & ~Q[0];  // 1110

wire s6 =  Q[3] &  Q[2] & ~Q[1] & ~Q[0];  // 1100

wire s7 =  Q[3] & ~Q[2] & ~Q[1] & ~Q[0];  // 1000

 

No comparators or adders; just short ANDs/ORs.

​​

​

4) How to convert a Johnson counter to a ring counter?

​

Refined:
Change the feedback:

  • Johnson: Q <= {Q[N-2:0], ~Q[N-1]};
     

  • Ring: Q <= {Q[N-2:0], Q[N-1]};
    Same shift register; only feedback polarity differs.

     

​​

5) Typical applications of Johnson counters

​

Refined:

  • Phased/timed enables (time-slot scheduling).
     

  • LED chasers / pattern generators.
     

  • Clock/phase generation (tap different states).
     

Small FSMs where simple decode beats binary.

​​​​

​

6) How to ensure “maximal transition distance” / avoid glitches?

​

Refined:
Johnson is a unit-distance code: exactly one bit changes between consecutive states—this minimizes Hamming distance and switching noise. It’s inherently glitch-friendly; keep the whole design synchronous so decoders see clean edges.

​​

​

7) How to design an 8-state Johnson detector?

​

Refined:
For N=4, create 8 one-hot detects (as in Q3), or build a small decoder that maps Q to index 0..7. You can also verify sequencing with SVA:

​

systemverilog

​

// Only one bit changes per step

assert property (@(posedge clk) disable iff (arst)

  $onehot(Q ^ $past(Q)));

​​

​

8) How to initialize a Johnson counter reliably?

​

Refined:
Use asynchronous assert to a legal seed (e.g., all 0s) and clean (timed) de-assert:

verilog

​

always @(posedge clk or posedge arst)

  if (arst) Q <= '0;

  else      Q <= {Q[N-2:0], ~Q[N-1]};

 

Clean de-assert meets recovery/removal timing → no metastability.

​

​​

9) Why prefer Johnson over ring when more states are needed?

​

Refined:
With the same N flip-flops, Johnson delivers 2N states versus ring’s N. If you need more than N states but still want simple decode and 1-bit transitions, Johnson is the sweet spot.

​​​​​

​​

10) Power considerations

​

Refined:

  • Each clock toggles about one FF on average (sometimes two when entering/leaving 111…/000…), so dynamic power is moderate.
     

  • Save power by en-gating (hold state when idle) or clock gating (ASIC with ICG cells).
     

  • Short, local decode logic also keeps dynamic power low.
    ​​​

​

11) Testing for stuck-at faults

​

Refined:

  • Functional sim: force stuck bits and check if sequence deviates.
     

  • BIST idea: sequence through all 2N states and compress responses (MISR).
     

  • Assertion: guarantee every index/state appears within 2N clocks after reset.

​

​​

12) Cascading for longer sequences

​

Refined:
Two approaches:

  1. Hierarchical sequencing: a Johnson counter selects/advances among banks controlled by another counter.
     

  2. Index-over-Johnson: use a small binary counter to index through multiple Johnson banks in order.
    (Direct concatenation doesn’t create a simple 2N×M cycle; orchestrate with a controller.)

     

​

13) Encoding advantages

​

Refined:

  • Unit-distance (1-bit change) like Gray code → low hazard, low switching noise.
     

  • Small decoders: runs of 1s/0s are cheap to test.
     

  • Deterministic path: monotonic growth to all 1s, then shrink back to all 0s.
     

​

14) Synthesizing Johnson counters in HDL

​

Refined:
Write it as a sequential shift with inverted feedback—portable and tool-friendly:

verilog

​

module johnson #(parameter N=4)(

  input  wire       clk, arst,

  output reg [N-1:0] Q

);

  always @(posedge clk or posedge arst)

    if (arst) Q <= '0;

    else      Q <= {Q[N-2:0], ~Q[N-1]};

endmodule

 

Synthesis maps to FFs plus one inverter—no carry chains.

​

15) Glitch-free Johnson counters in high-speed systems

​

Refined:

  • Keep the path strictly sequential (no comb feedback loops).
     

  • Balance routing for Q[N-1] and its inversion; if timing is tight, register the feedback (one-stage pipeline) and adjust decode accordingly.
     

  • Add timing constraints (max skew, path groups) and verify with STA + post-synth/post-route sims.

​

  • Avoid unnecessary glitching (purely sequential update already helps).

Handy extras (drop-in snippets)

Enable (pause) + parameterization:

 Verilog

module johnson #(parameter N=4)(

  input  wire       clk, arst, en,

  output reg [N-1:0] Q

);

  always @(posedge clk or posedge arst)

    if (arst)      Q <= '0;

    else if (en)   Q <= {Q[N-2:0], ~Q[N-1]};

endmodule

Self-check / recovery (optional, sim-safe):

 Verilog

wire onebit_change = (Q==0) || $onehot(Q ^ $past(Q)); // SV only

// Or plain RTL: detect illegal all-zeros after reset deassert and reseed.

State index (N=4) for debug:

 Verilog

function [2:0] j_index (input [3:0] q);

  case (q)

    4'b0000: j_index = 3'd0; 4'b0001: 3'd1; 4'b0011: 3'd2; 4'b0111: 3'd3;

    4'b1111: 3'd4; 4'b1110: 3'd5; 4'b1100: 3'd6; 4'b1000: 3'd7;

    default: j_index = 3'dx;

  endcase

endfunction

Verilog LAB - Ring Counter 

Verilog LAB - Gray code Counter 

© Copyright 2025 VLSI Mentor. All Rights Reserved.©

Connect with us

  • Instagram
  • Facebook
  • Twitter
  • LinkedIn
  • YouTube
bottom of page