Combinational output glitch in a six-state locker controller on a 74HC CPLD
A locker controller is a six-state Moore machine built in a 74HC-series CPLD with three state flip-flops. All outputs are decoded combinationally from the state vector; for example ALARM_EN = Q2·Q1′. The relevant codes are UNLOCK = 110 and TIMEOUT = 000. Measured clock-to-Q delays are 9 ns for Q1, 11 ns for Q0 and 16 ns for Q2. ALARM_EN drives a piezo sounder and is also sampled by a synchronous input of the same CPLD once every 1 µs clock period. The unit works, but roughly every few hundred lock cycles the piezo emits a short chirp; a logic analyser with 1 ns resolution, triggered on the 110 → 000 transition, captures a 7 ns positive pulse on ALARM_EN together with the transient state codes 100 and 010 on the state bus. The state diagram, the state coding and the 1 µs clock are fixed by the specification and simulation of the RTL shows no error.
1. Derive the 7 ns pulse from the timing data, and estimate how often the synchronous sampler will capture it.
Read the worked answer
The race. ALARM_EN = Q2·Q1′ must be 0 in 110 (Q1 = 1 so Q1′ = 0) and 0 in 000 (Q2 = 0). On the 110 → 000 transition both Q1 and Q2 fall, but at different times: Q1 falls at t = 9 ns, so Q1′ goes high at 9 ns, while Q2 does not fall until t = 16 ns. Between 9 ns and 16 ns the AND gate sees Q2 = 1 and Q1′ = 1, so ALARM_EN is high for 7 ns. The measured 7 ns is the delay difference, not a gate delay artefact.
Why it is not a state-diagram bug. Every stable state produces the correct output. The function is correct for all valid inputs; the error exists only during the transient, so RTL simulation with zero-delay models cannot show it. This is a multi-bit transition race, not a static hazard: two state bits change at once and the output is defined by which one wins.
Capture probability. The sampler samples once per 1 µs and the pulse is 7 ns wide, so the chance that a given transition is captured is 7 ns / 1000 ns = 0.7%, i.e. one capture per ~143 transitions. That matches the observed rate and explains why the fault looks random rather than systematic. The transient codes 100 and 010 appear on the bus for the same reason and must not be decoded as valid states.
2. Compare one-hot coding, registered (Moore) outputs and Gray coding as fixes. Recommend one and state its cost.
Read the worked answer
One-hot coding. Six states become six flip-flops. Each output is then a single state literal (ALARM_EN = S_alarm), so no combinational decode exists and no decode race is possible. Cost: 6 macrocells for state instead of 3, plus the outputs. In a small 74HC CPLD this may not fit with the other logic; check the fitter report.
Registered outputs. Keep the 3-bit state, decode as now, but clock the decoded result through an output flip-flop. The glitch still occurs at the decode gate input, but it is sampled by a flip-flop on the same edge as the state change, so it never reaches the pin: the output is the previous state's decode, delayed by one clock. Cost: 3 extra macrocells and 1 µs of latency on every output.
Gray coding. A Gray code prevents races only for transitions that differ in one bit. A six-state machine with branching cannot have all its taken transitions single-bit in 3 bits, and 110 → 000 needs at least two; the race would simply move to another transition. Gray coding also over-constrains the design and gives no guarantee for the unused codes. It does not solve this problem.
Recommendation. Registered outputs: 1 µs of latency is irrelevant against the tens of milliseconds of the lock and solenoid timing, it costs only 3 macrocells, it keeps the coding and the state diagram unchanged, and it removes the glitch on every output at once, not just ALARM_EN. One-hot is the better choice only if macrocells are available and the decode is large.
3. The ALARM_EN net also leaves the board to a monitoring unit. Explain why the 7 ns pulse is still a real system fault and what verification step would have caught it before production.
Read the worked answer
Downstream, a 7 ns pulse is not automatically harmless. Any edge-triggered input on the monitoring unit (interrupt pin, counter clock, latch enable) responds to the edge, not to the width, so the pulse is captured with the same probability argument as before - and in an asynchronous receiver it may also cause metastability if it lands on a clock edge. Even where the energy is negligible for a solenoid, a logic input has no such inertia, so the fault is functional.
Verification that would have caught it:
- Gate-level simulation with back-annotated (SDF) delays after place-and-route, forcing the state bits to arrive skewed. Zero-delay RTL cannot show a race.
- A static timing check on combinational outputs, or simply a timing constraint that flags outputs decoded from more than one state bit.
- A testbench that sweeps the skew between state bits from 0 to the worst-case delay difference, rather than assuming they change together.
- Bench check with a logic analyser in timing mode (not state mode) triggered on the transition, which is what exposed the 7 ns pulse. State-mode analysis would have hidden it because it samples only on the clock.