RTL Studio Open IDE

Wiki Sequential logic Counters

Counters

Binary, free-running, and loadable counters in RTL.

Counters are registers that advance through a numeric sequence — free-running, gated, loadable, or up/down.

Basic binary counter

always_ff @(posedge clk or negedge rst_n) begin
  if (!rst_n)      cnt <= '0;
  else if (clear)  cnt <= '0;
  else if (enable) cnt <= cnt + 1'b1;
end

Decide wrap behavior explicitly:

else if (enable) cnt <= (cnt == MAX) ? '0 : cnt + 1'b1;

Useful variants

Variant Idea
Loadable if (load) cnt <= load_val
Up/down Add ±1 from a direction flag
Prescaler Count clocks, pulse at terminal count
Gray Adjacent codes differ by 1 bit — friendlier for some CDC

Terminal count

Generate a single-cycle (or level) flag:

assign tc = enable && (cnt == MAX);

If tc must be clean for async consumers, register it.

Width & overflow

  • Size cnt for MAX ($clog2(MAX+1)).
  • cnt + 1 on an all-ones vector wraps in two’s complement — intentional for free-running timers, bugs for “stop at MAX” designs.

Test ideas

  • Reset then count N cycles; check value.
  • Enable low → hold.
  • Load mid-count.
  • Wrap boundary (MAX → 0).