top of page

Ring Counter (One-Hot): Concept to Code

What is a ring counter (one-hot)?

A ring counter is a shift-register style counter where a single ‘1’ bit “circulates” through a bank of flip-flops. Because exactly one flip-flop is high at a time (i.e., one-hot), the current state is easy to decode—no combinational next-state logic is required beyond the rotation.

Why designers like it

  • Glitch-free decode: Each state is a single bit; just tap Q[i].
     

  • Fast & simple next-state: Rotate the vector; no adder/carry chain.
     

  • Timing-friendly: All flops sample the same clock; no ripples.

Trade-offs

  • Area: Needs N flip-flops for N states (vs. log2(N) for binary).
     

  • Reset discipline: Must start one-hot; if all bits become 0, it can “die.”

Problem Statement (your spec)

  • 6-bit ring; one ‘1’ rotates each clock.
     

  • Async reset to the one-hot seed 000001.
     

  • Ports: clk, arst, Q[5:0].
     

  • Expected sequence:
    000001 → 000010 → 000100 → 001000 → 010000 → 100000 → 000001 → …

     

RTL: 6-bit Ring Counter

 Verilog

module ring6 (

  input  wire clk,

  input  wire arst,

  output reg  [5:0] Q

);

  always @(posedge clk or posedge arst) begin

    if (arst)

      Q <= 6'b000001;             // seed state (one-hot)

    else

      Q <= {Q[4:0], Q[5]};        // rotate-left by 1

  end

endmodule

Code, line by line

  • Async reset (posedge arst)
    Including arst in the sensitivity list makes reset immediate. As soon as arst=1, Q becomes 000001 regardless of the clock. That guarantees a valid one-hot seed.

     

  • Rotation logic: Q <= {Q[4:0], Q[5]};
    This is a rotate-left by 1:

     

    • The high-order bit (Q[5]) moves to the least-significant position.
       

    • All other bits shift up by one.
      With an initial 000001, successive clocks produce the one-hot cycle above.

       

  • No combinational next-state
    The “next state” is the old state, just rotated. That’s the hallmark of a ring counter: simple, synchronous, predictable.

     

⚠️ Note: If Q ever becomes 000000 (e.g., due to a glitch or an uninitialized power-on), rotation keeps it at zero forever. That’s why the reset is required (or you add self-healing—see tips below).

Testbench: Drive & Observe

 Verilog

module tb_ring6;

  reg clk = 0;

  reg arst = 1;

  wire [5:0] Q;

 

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

 

  // 10-time-unit clock

  always #5 clk = ~clk;

 

  initial begin

    arst = 1;        // hold in reset

    #12;             // release reset before a posedge

    arst = 0;

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

    $finish;

  end

 

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

endmodule

What the TB proves

  • Reset seeding: With arst=1, Q is 000001.
    Reset is released at t=12, so the first active posedge after release (at t=15) starts rotation from the seeded state.

     

  • Rotation timing: Every rising clock edge changes Q to the next one-hot position. With a 10-unit period, you’ll see the full 6-state cycle in 60 time units.
     

  • Monitoring: $monitor prints time, reset, and Q continuously so you can correlate reset and state changes.
     

Expected waveform behavior (mental picture)

​​

​​

​​​​

​​​​​​​

  • Exactly one bit high at a time.

  • No intermediate glitches (purely sequential update).​​​​​​

​​

 Practical notes & pro tips

  • Reset deassertion: In real silicon, deassert async resets cleanly (meet recovery/removal to the clock). A common pattern is async assert, sync deassert.

  • Self-healing (optional but nice): If you want resilience against “all-zero” lock-up (e.g., after scan or power-up without reset), add a guard:

  • ​​​​​​ Or move this into a synthesis-guarded block if it’s only for sim safety.

Enable input (pause):

  • Keeps state when en=0.​​​

Parameterize N (easy upgrade):

SystemVerilog assertion (sanity):

In SV, assert the one-hot property on every cycle:

​​

  •  Great for catching any accidental multi-hot or zero-hot states during verification.
     

  • Johnson counter (twisted ring) variant:  If you invert the feedback before feeding it back, you get a Johnson (Möbius) counter, which yields 2N states with a similar “shift” simplicity. Handy when you want more states with little extra logic.​​​​​​

swift

clk:  _/‾\_/‾\_/‾\_/‾\_/‾\_/‾\_/‾\_

Q:    000001 000010 000100 001000 010000 100000 000001 ...

 Verilog

else if (Q == 6'b000000)

  Q <= 6'b000001;       // re-seed if ever all-zero

else

  Q <= {Q[4:0], Q[5]};

 Verilog

module ring #(parameter N=6) (...);

  reg [N-1:0] Q;

  if (arst) Q <= {{(N-1){1'b0}},1'b1};

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

endmodule

 Verilog

module ring #(parameter N=6) (...);

  reg [N-1:0] Q;

  if (arst) Q <= {{(N-1){1'b0}},1'b1};

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

endmodule

 Verilog

assert property (@(posedge clk) disable iff (arst) $onehot(Q));

Where one-hot rings shine

  • Fast state machines (no dense decode, easy timing).
     

  • Scanning/LED chasers, simple sequencers.
     

  • Clock division / phase stepping (tap different one-hot bits).
     

  • Arbiter tokens (token passing per cycle).
     

TL;DR

  • A 6-bit one-hot ring is a rotate-left of a single ‘1’ through six flip-flops.
     

  • Async reset seeds Q=000001; every posedge rotates the ‘1’.
     

  • Simple, decode-friendly, timing-friendly—at the cost of extra flops.

Ring Counter (One-Hot) — 15 Interview Q&As (Refined & Explained)

Q1) Why is one-hot encoding often faster in FPGAs?

Refined answer:
Only one flip-flop is asserted per state, so next-state logic becomes trivial (often just wiring/rotation). That means:

  • Shallow LUT depth (sometimes 0 LUTs for straight rotate).
     

  • No carry chains or large decoders.
     

  • Higher fMAX at the cost of more flip-flops (area trade-off).
     

Rule of thumb: in LUT-rich, FF-plentiful FPGAs, one-hot often beats dense encodings for speed.

​​

Q2) What are the downsides of ring counters?

Refined answer:

  • Area: Needs N FFs for N states (vs. ⌈log₂N⌉).
     

  • Initialization sensitivity: Must start one-hot; otherwise it can “die” in all-zero or multi-hot states.
     

  • Fault tolerance: Requires checks or self-healing to recover from upset/faults.

​​

Q3) How can state errors be detected in ring counters?

Refined answer:
Detect not-one-hot states:

  • In SystemVerilog: assert property (@(posedge clk) disable iff (rst) $onehot(Q));
     

  • In plain RTL: (Q==0) → zero-hot; (Q & (Q-1))!=0 → multi-hot.
    You can raise an error flag or force a re-seed on detection.​​

Q4) How does a Johnson counter provide more states than a ring counter?

Refined answer:
A Johnson (twisted-ring) counter feeds back inverted MSB to LSB, producing 2N unique states with N FFs.

  • Ring: N states (one-hot token rotates).
     

  • Johnson: 2N states (a walking 1s/0s pattern).
    Good when you need more states with similar simplicity.

     

Q5) How can ring counters be used for sequence generation?

Refined answer:
Map each one-hot bit to an enable/trigger:

  • Q[0] → action A, Q[1] → action B, etc.

Because only one bit is high, the control is glitch-free and decode is a single tap per step—great for stepper sequences, phased enables, and time-slot scheduling.

 

​​​

Q6) How to recover from multiple-ones caused by faults?

Refined answer:

  • Detect (see Q3) then re-seed synchronously or via async reset.
     

  • Add self-healing: if Q==0 or !$onehot(Q), force Q<=SEED on the next cycle.
     

  • In radiation-prone designs, consider TMR (triple modular redundancy) on state bits.
     

Q7) Why do ring counters avoid carry logic?

Refined answer:
Next state is just a rotation ({Q[N-2:0],Q[N-1]}), not arithmetic. This:

  • Avoids adder/carry chains entirely.
     

  • Keeps critical paths short and predictable.
     

​​

Q8) How to expand the length of a ring counter?

Refined answer:
Increase FF count and keep the rotate feedback:

verilog

Q <= {Q[N-2:0], Q[N-1]}; // rotate-left

 

Seed to ...0001. The method scales linearly; just ensure proper reset and one-hot checks.

Q9) How to implement a ring counter using shift-register primitives?

Refined answer:
Chain FFs (or FPGA SRL/shift primitives), and loop last bit to the input:

verilog

Q <= {Q[N-2:0], Q[N-1]}; // serial shift + feedback

 

With FPGA SRLs, verify reset/initialization behavior (some SRLs don’t have async reset—seed via load or small wrapper FFs).

​​​​

Q10) What are common interview pitfalls?

Refined answer:

  • Not explaining initialization (how you guarantee one-hot on power-up).
     

  • Ignoring fault recovery (multi-hot/zero-hot detection).
     

  • Missing trade-offs vs. binary/Gray/Johnson encodings (speed vs. FF cost).
     

  • Forgetting assertions or self-checks in verification.

​​

Q11) Can a ring counter be used as a Johnson counter?

Refined answer:
No—different feedback.

  • Ring: rotate stored bit.
     

  • Johnson: feed back inverted MSB → Q <= {Q[N-2:0], ~Q[N-1]}.
    Choose by state count needs and decode convenience.

     

Q12) How to create a variable-step ring counter?

Refined answer:
Insert a selectable rotate:

verilog

case (step)

  1: Q_next = {Q[N-2:0], Q[N-1]};

  2: Q_next = {Q[N-3:0], Q[N-1:N-2]};

  // ...

endcase

 

Or use a barrel shifter to rotate by k. Useful for skipping phases or non-uniform schedules. Mind timing if step is dynamic (adds LUT depth).

Q13) How to write ring counters in Verilog for synthesis portability?

Refined answer:

  • Use a pos-edge clocked always with explicit async/sync reset.
     

  • Express rotation with concatenation, not tool-specific primitives.
     

  • Optionally parameterize N and seed; avoid vendor-only SRL inference unless guarded for portability.
     

Q14) How to test a ring counter thoroughly?

Refined answer:

  • Reset test: confirm seed (000…1).
     

  • Cycle test: observe all N states in order, then wrap.
     

  • Fault tests: force multi-hot/zero-hot; confirm detection and recovery.
     

  • Assertions: $onehot(Q); optional functional coverage on each state index.
     

  • Corner: toggle reset near clock edge; verify clean recovery (consider async-assert, sync-deassert).
     

Q15) How to reduce power consumption in ring counters?

Refined answer:

  • Add enable: only rotate when needed (tools may infer CE on FFs).
     

  • Clock gating via vendor ICG cells (ASIC) or dedicated primitives (FPGA), used carefully.
     

  • Lower frequency for the ring or grouped enables if multiple rings exist.
     

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

Tiny, Practical RTL Patterns

One-hot ring (parameterized, with enable & self-healing):

 Verilog

module ring #(parameter N=6, parameter [N-1:0] SEED={{(N-1){1'b0}},1'b1})(

  input  wire       clk, arst, en,

  output reg [N-1:0] Q

);

  wire onehot = (Q!=0) && ((Q & (Q-1))==0); // plain-RTL onehot check

  always @(posedge clk or posedge arst) begin

    if (arst)      Q <= SEED;

    else if (en)   Q <= onehot ? {Q[N-2:0], Q[N-1]} : SEED; // self-heal

  end

endmodule

Johnson counter (2N states):

 Verilog

always @(posedge clk or posedge arst)

  if (arst) Q <= '0;

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

SVA one-hot property (SystemVerilog):

 Verilog

assert property (@(posedge clk) disable iff (arst) $onehot(Q));

Verilog LAB - >Mod-N Counter 

Verilog LAB - Johnson Counter 

© Copyright 2025 VLSI Mentor. All Rights Reserved.©

Connect with us

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