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:
-
Hierarchical sequencing: a Johnson counter selects/advances among banks controlled by another counter.
-
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
