Altifigence Academy

26 / 37 · Concept

Counter debugging and minimal counterexamples

Design short tests that distinguish reset, enable and wrap-boundary errors.

A correct final value can hide an incorrect sequence

Ending at 0 does not establish correct reset and wraparound. A circuit stuck at 0 produces the same final value. Use observation points that separately expose normal incrementing, holding, resetReset A control that returns state to a specified initial value. Define whether it is synchronous or asynchronous and whether it has priority over other controls. Learn more and boundary wraparound.

Deliberately combine conflicting controls

SituationSpecification to check
reset=1, enable=0Is reset hidden behind enable?
reset=1, enable=1Does reset outrank incrementing?
count=M-1, enable=0Does the counter incorrectly wrap while stalled?
count=M-1, enable=1Does it return precisely from M-1 to 0?
Change reset between edgesIs synchronous reset applied at the next edge?

Priority errors are hard to find when controls are tested only separately.

Each column below records a rising edgeRising edge The instant at which the clock changes from 0 to 1. Distinguish it from a level, which refers to the entire interval during which CLK=1. Learn more. Inputs are pre-edge; states labeled “after” are post-update. Alignment denotes sample order, not physical propagation delayPropagation delay The time from an input change until the output settles to the correct value. Logical equivalence and timing behavior are separate properties. Learn more. Initially count=5. The faulty circuit checks reset only inside enable and therefore holds 5 at the first edge. Although the final values agree, the first mismatch reveals the fault.

A minimal counterexample: enable masks reset
View waveform data
Wave data: each character is one interval; a dot holds the previous state; p is a clock cycle.
SignalWaveBus values
edge234E0 → E1 → E2
reset101
enable01.
correct after2340 → 1 → 0
bug after2345 → 6 → 0

Start the modulo-8 reference circuit at 101. Select enable=0 and reset=1, then advance the clock. The correct value is 000; RTL that places reset inside enable holds 101. Release reset and also distinguish holding with enable=0 from incrementing with enable=1.

Assert reset and enable in conflicting cases

Synchronous reset takes priority over enable. With enable=0, hold the stored value. q=101; q_next = (q + 1) mod 8

Find the first mismatch with a reference model

Ck+1=rk?0:(ek?((Ck+1) mod M):Ck)C_{k+1}=r_k?0:(e_k?((C_k+1)\bmod M):C_k)

This functional model assumes valid states 0–M-1. Add a separate policy for out-of-range recovery. Compute and compare the expected value at each edge. Inputs and state immediately before the first mismatch are the smallest useful starting point for diagnosis.

If failure appears after 1000 cycles, remove unnecessary input intervals to reproduce it in three to five edges. After fixing RTL, retain that minimal counterexample as a regression test. Review the revised specification and code separately so that the design and test are not both changed to the same incorrect condition.

Try it yourself

Incorrect code nests reset inside if(en) begin if(rst) ... end. What initial state and inputs expose the problem with the shortest test?

Read the explanation

Start in a nonzero state and apply one rising edge with rst=1, en=0. Reset priority requires 0, but the incorrect circuit holds the previous value. Starting at 0 would hide the error.

Your choice applies to this browser. Change it any time using the footer.