By the end of this chapter you should be able to:
- Explain how two paths of unequal delay from one input to one output produce a glitch, and calculate the width of the glitch from the gate delays.
- Distinguish static-1, static-0 and dynamic hazards, and state which can occur in a two-level AND–OR circuit and which in a two-level OR–AND circuit.
- Detect a static-1 hazard on a Karnaugh map as a pair of adjacent 1-cells covered by no single group.
- Remove a static hazard by adding a redundant prime implicant, and state what it costs in gates and in testability.
- Distinguish a logic hazard from a function hazard, and explain why no gate network can remove the latter.
- Identify the circuit nodes — asynchronous inputs, clocks, latch enables — where a glitch is dangerous rather than merely untidy.
Chapters 8, 9 and 10 treated a combinational circuit as an algebraic object. Given the same inputs it produces the same output, and two expressions that agree on every row of the truth table describe the same circuit. Every result in those chapters depends on that assumption, and on a real board it is not quite true.
Gates take time, different paths through a circuit take different times, and while the signals are sorting themselves out the output can take a value that the truth table does not contain. The result is a narrow pulse — a glitch — on an output that the algebra says should have been steady. This chapter explains where such pulses come from, how to find them on a Karnaugh map before building anything, how to remove the ones that can be removed, and what to do about the ones that cannot.
1 Where a Glitch Comes From
Boolean algebra has no time in it. When Chapter 8 wrote \(A + A' = 1\) it meant that the expression is 1 for either value of \(A\), and it said nothing about what happens in the microsecond while \(A\) is changing from one value to the other. A circuit has to live in that microsecond, and if the two copies of \(A\) that the algebra treats as one signal arrive at the output gate at different times, the circuit will briefly compute something the algebra never allowed.
Take the function \(F = AB + A'C\), implemented in the obvious two-level way. The variable \(A\) reaches the upper AND gate directly and the lower AND gate through an inverter, so there are two paths from the same input to the same output and they are not the same length.
Hold \(B = C = 1\). The function reduces to \(F = A + A' = 1\), so the output should be a steady 1 whatever \(A\) does. Now let \(A\) fall from 1 to 0 at \(t = 0\), with an inverter delay of 4 ns and gate delays of 6 ns:
- The product \(AB\) was holding the output high. It falls 6 ns after \(A\) does, at \(t = 6\) ns.
- The product \(A'C\) is the one that should take over, but \(A'\) does not appear until \(t = 4\) ns, so \(A'C\) does not rise until \(t = 10\) ns.
- Between \(t = 6\) and \(t = 10\) ns both inputs of the OR gate are 0. The OR gate faithfully reports that, one gate delay later.
A 4 ns pulse to 0 on an output that should have stayed at 1. The width of the glitch is the difference between the two path delays — here the inverter delay — and not the gate delay itself.
That momentary 0 is a glitch, and the property of the circuit that allows it is a hazard. The distinction matters: a hazard is a possibility built into the structure, while a glitch is what appears at the output on a particular occasion, with particular delays and a particular input change. A circuit with a hazard may produce no glitch at all if the delays happen to fall the right way — which is exactly why hazards are found on paper rather than on an oscilloscope.
2 Static-1, Static-0 and Dynamic Hazards
Hazards are classified by what the output was supposed to do while it was misbehaving.
- A static-1 hazard is the case just seen: the output should stay at 1 for the whole of a single-input change, and it dips momentarily to 0.
- A static-0 hazard is the mirror image: the output should stay at 0 and pulses momentarily to 1.
- A dynamic hazard occurs when the output is supposed to change once, from 0 to 1 or from 1 to 0, and instead changes three times — 1, 0, 1, 0 — before settling on the correct value.
Figure 11.2 is the static-1 hazard of the previous section drawn out in time. Read it downwards: the cause is at the top and the symptom at the bottom, and the gap between the falling edge of \(AB\) and the rising edge of \(A'C\) is the whole of the problem.
Take \(F = (A+B)(A'+C)\), built as two OR gates feeding an AND gate, and hold \(B = C = 0\). The function is then \(F = A \cdot A' = 0\), so the output should be a steady 0. Let \(A\) rise at \(t = 0\), with the same delays as before.
| Time | Event |
|---|---|
| 0 ns | \(A\) rises |
| 4 ns | \(A'\) falls |
| 6 ns | \((A+B)\) rises — it was 0 because \(A = B = 0\) |
| 10 ns | \((A'+C)\) falls — it was 1 because \(A' = 1\) |
| 12 ns | the AND gate sees two 1s from \(t = 6\) and drives its output high |
| 16 ns | the AND gate responds to \((A'+C)\) going low and returns to 0 |
A 4 ns pulse to 1 on an output that should have stayed at 0. Note where each kind of hazard lives: a two-level sum-of-products circuit can suffer a static-1 hazard but never a static-0 hazard, and a two-level product-of-sums circuit is the other way round. The reason is structural. In an AND–OR circuit the output can only glitch to 1 if some product term glitches to 1, and a product term contains at most one literal of the single changing variable while all its other literals are constant — so a term that is 0 before the change and 0 after it stays 0 throughout.
Dynamic hazards need at least three paths of different delay from one input to the output, so they cannot occur in a two-level circuit at all. In a multi-level circuit they are usually a static hazard at some internal node propagating outwards: the internal glitch arrives at a later gate that is in the middle of switching, and the extra edges reach the output. The useful consequence is that a multi-level circuit whose every internal node is free of static hazards is also free of dynamic hazards, so there is only ever one thing to look for.
3 Spotting a Static Hazard on the Map
The timing analysis of Section 1 is convincing but slow, and no designer wants to do it for every input of every gate. The Karnaugh map gives the answer by inspection, and the rule follows directly from what a glitch is.
A single-input change moves the circuit from one cell of the map to an adjacent cell. If both cells hold 1, the output should stay at 1 for the whole move. It will do so without any assumption about delays if there is a product term that covers both cells, because that term is 1 before, during and after the change — no gate anywhere in the circuit has to switch for it to remain 1. If instead the move leaves one group and enters another, the output depends on one term turning off while a different term turns on, and whether the output survives the handover is a matter of which gate is faster.
Take every pair of adjacent 1s on the map — every pair of cells that differ in one variable, including pairs that are adjacent only round the edge. If some product term of the implemented expression contains both cells, that transition is safe. If no term contains both, the circuit has a static-1 hazard on that transition. The dual rule detects static-0 hazards on a POS circuit: look for pairs of adjacent 0-cells that no single sum term covers.
Figure 11.3 shows the map of \(F = A'C + AB\), which Chapter 8 would call minimal and correct. Its two groups are both essential prime implicants and between them they cover all four 1s. But cells 3 (\(011\)) and 7 (\(111\)) differ only in \(A\), so they are adjacent, and no single group holds both: cell 3 belongs to \(A'C\) and cell 7 to \(AB\). That pair is the hazard, and the input change it corresponds to — \(B = C = 1\), \(A\) changing — is exactly the one that produced the glitch in Figure 11.2.
Working the other way is just as useful. The minimal expression from Chapter 8 for \(\Sigma m(0,1,2,5,8,9,10)\) was \(B'D' + B'C' + A'C'D\); checking every adjacent pair of its seven 1s shows that each pair is covered by one of the three terms, so that circuit has no static hazard and needs no attention at all. Minimality and hazard-freedom are independent properties, and a given minimal expression may happen to have both.
4 Removing a Hazard with a Redundant Prime Implicant
The cure follows from the diagnosis. If the trouble is a pair of adjacent 1s that no term covers, add a term that covers them. On the map that is a group spanning the boundary between the two existing groups, and it is always available: two adjacent 1-cells can always be grouped, and enlarging that group as far as it will go gives a prime implicant.
For \(F = A'C + AB\) the bridging group is cells 3 and 7, which is \(BC\). Adding it gives
This is the consensus theorem of Chapter 6, \(AB + A'C + BC = AB + A'C\), read backwards. The added term is logically redundant — the two expressions agree on all eight input combinations — but it is not electrically redundant.
Why it works is worth stating plainly. With \(B = C = 1\), the term \(BC\) is 1 and does not contain \(A\) at all, so nothing that \(A\) does can disturb it. Its AND gate holds the OR gate's input high right through the handover between the other two terms, and the output cannot dip. The cost is one three-input AND gate, one more input on the OR gate and two literals; the delay is unchanged, since the circuit is still two levels.
Chapter 9 minimised \(F(A,B,C,D) = \Sigma m(0,1,2,5,6,7,8,9,10,14)\) to \(B'C' + CD' + A'BD\), seven literals and four gates. Check it for hazards by listing the adjacent pairs of 1s that no term covers:
| Adjacent pair | Cells | Changing variable | Covered by a common term? |
|---|---|---|---|
| \(m_0, m_2\) | 0000, 0010 | \(C\) | no |
| \(m_1, m_5\) | 0001, 0101 | \(B\) | no |
| \(m_6, m_7\) | 0110, 0111 | \(D\) | no |
| \(m_8, m_{10}\) | 1000, 1010 | \(C\) | no |
Four hazards. The bridging prime implicants are \(B'D'\) for the pairs \((0,2)\) and \((8,10)\), \(A'C'D\) for \((1,5)\) and \(A'BC\) for \((6,7)\) — and those are precisely the three prime implicants that the prime implicant chart discarded as unnecessary. The hazard-free expression is therefore the sum of all six prime implicants:
Fifteen literals and seven gates against seven literals and four gates: more than twice the logic, for a function whose behaviour has not changed by a single row of the truth table. That is the honest price of hazard-freedom, and it is why the technique is applied where it is needed and nowhere else.
The static-0 case is the exact dual. On the map, find pairs of adjacent 0s that no sum term of the POS expression covers, and add the redundant sum term that bridges them. For \(F = (A+B)(A'+C)\) the offending pair is the zeros at \(000\) and \(100\), and the bridging term is \((B+C)\), giving the hazard-free form \(F = (A+B)(A'+C)(B+C)\) — again an identity, again an extra gate.
A redundant term is exactly what a logic optimiser exists to remove, and it will remove it unless told not to. In VHDL or Verilog the usual instruments are a keep or dont_touch attribute on the redundant signal, or a physical constraint that fixes the structure. It is also worth knowing that the redundancy defeats stuck-at fault testing: a fault on the added gate cannot be detected at the output, because the term is logically unnecessary. Hazard-free redundancy and full testability pull against each other, and production test engineers know it.
5 Function Hazards, and Why Gates Cannot Cure Them
Everything so far assumed that exactly one input changes at a time. Such a hazard is called a logic hazard, because it is a property of the particular gate network and can be removed by changing the network. When two or more inputs change at once, a different and worse problem appears.
Real inputs never change simultaneously. Two signals nominally changing together arrive skewed by wiring delay, by differing drive strengths, by the difference between one flip-flop's clock-to-output time and another's. The circuit therefore passes through an intermediate input state, and which one depends on which signal won the race. If the function is 0 in that intermediate state, the output is entitled to go to 0, and no arrangement of gates can prevent it, because the circuit is doing precisely what it was asked to do for the inputs it was actually given.
Consider the input change from \(ABC = 011\) to \(ABC = 110\). Both are 1-cells of the function, so the output should stay high. Two inputs change: \(A\) from 0 to 1 and \(C\) from 1 to 0.
| Which input wins the race | Intermediate state | \(F\) there |
|---|---|---|
| \(A\) changes first | \(111\) | 1 — output stays high |
| \(C\) changes first | \(010\) | 0 — output goes low |
If \(C\) arrives first the circuit sits at \(010\), where the function genuinely is 0, and the output falls. Adding \(BC\), or any other redundant term, changes nothing: with \(A = 0\), \(B = 1\), \(C = 0\) every product term of the function is 0, so there is nothing to hold the output up. The expression is not at fault and neither is the implementation.
A function hazard exists whenever a multiple-input change starts and ends on the same output value but passes through an input state where the function takes the other value. Every implementation of that function has it. The remedies are therefore all outside the gate network: allow only one input to change at a time (the reason asynchronous state machines are given Gray-coded state assignments in Chapter 26), or ignore the output until it has settled, which is what a clocked system does automatically.
Distinguishing the two is the first question to ask about any suspected glitch. If only one input changed, it is a logic hazard and a redundant term will fix it. If more than one changed, no amount of redrawing will help and the answer lies in the timing discipline of the system around the circuit.
6 When It Matters and When It Does Not
Given the cost of hazard-free design, it is important to know that most combinational logic in most circuits needs none of it. In a synchronous system the combinational block sits between two ranks of flip-flops, its output is sampled only at a clock edge, and the timing rule of Chapter 1 already requires the output to be stable for \(t_{su}\) before that edge. A glitch of a few nanoseconds that disappears long before the clock arrives is not merely harmless, it is invisible — it costs a little extra switching power and nothing else.
Hazards matter in exactly the places where a level is not sampled but an edge is caught, or where the receiving circuit has no clock of its own:
- Asynchronous inputs of a flip-flop. A glitch on an asynchronous \(\overline{CLR}\) or \(\overline{PRE}\) is obeyed the moment it arrives, however narrow, because those inputs do not wait for a clock. Combinational logic should never drive them directly.
- Anything used as a clock. An edge-triggered flip-flop counts edges, and a 4 ns glitch has two of them. Gating a clock with combinational logic is the classic way to produce a counter that occasionally advances twice.
- Latch enables and write strobes. A transparent latch follows its input while enabled, so a glitch on the enable captures whatever happened to be on the data input at that instant. A memory write strobe does the same to a memory location (Chapter 27).
- Signals crossing into another clock domain, where an edge may be caught by a clock that has no relationship to the one that produced it.
A 4-bit ripple counter (Chapter 23) clocks each stage from the previous stage's output, so its outputs do not change together: on the step from 0111 to 1000 the four bits change one after another, separated by a flip-flop delay each. If \(t_{pd} = 12\) ns per stage, the counter passes through 0110, 0100 and 0000 on its way, spending about 12 ns in each.
A decoder watching those outputs will assert its \(0110\), \(0100\) and \(0000\) lines in turn, each for around 12 ns, before settling on \(1000\). These are function hazards of the decoder — several inputs changing at once — so no redundant gate inside the decoder can remove them. If one of those decoded lines is used as a chip select or a clock, the circuit will misbehave.
The standard remedies are all outside the decoder: strobe its enable with the clock so that its outputs are only valid after the counter has settled; use a synchronous counter (Chapter 24), whose outputs change together and reduce the problem to a single skew rather than a cascade; or re-register the decoded output in a flip-flop clocked by the system clock, which samples a level rather than catching an edge.
The general design rule that follows is worth carrying into Part 5. Keep combinational outputs away from anything that reacts to an edge; sample levels with a clock; and reserve redundant-term hazard removal for the few signals — an asynchronous reset, a bus arbitration line, an output leaving the board — where a glitch would be acted on rather than waited out.
7 Summary and Key Results
| Type | What happens | Detection | Cure |
|---|---|---|---|
| Static-1 | Output should stay 1, dips to 0 | Adjacent 1-cells in no common product term | Add the bridging (redundant) prime implicant |
| Static-0 | Output should stay 0, pulses to 1 | Adjacent 0-cells in no common sum term | Add the bridging redundant sum term |
| Dynamic | Output changes three times instead of once | Three or more paths of unequal delay; needs a multi-level circuit | Remove the static hazards at every internal node |
| Function hazard | Output dips during a multiple-input change | The change passes through an input state where \(F\) differs | Cannot be fixed by gates — change one input at a time, or sample after settling |
| Glitch width | Difference between the two path delays | Timing analysis of the two paths | Not the gate delay itself |
| Cost of a cure | One extra gate per hazardous adjacency | Expression is no longer minimal | Also blocks stuck-at fault detection on that gate |
8 Common Mistakes
Minimisation and hazard-freedom are unrelated. The minimal cover of \(\Sigma m(0,1,2,5,6,7,8,9,10,14)\) has four static-1 hazards, and removing them means putting back all three prime implicants that the prime implicant chart had just discarded. The rule from Chapters 8 and 9 — never include a redundant term — is a rule about cost, and it is suspended whenever glitch-free behaviour is required.
If two inputs changed, the circuit visited an intermediate input state and computed the function correctly for it. Adding terms cannot help, because in that state every product term of the function is 0. Time spent redrawing the map is wasted; the fix is to control the input timing or to sample the output only when it has settled.
A decoded count, an address match or an enable that is ANDed with the clock will glitch, and a flip-flop counts edges rather than measuring widths. The correct construction is a synchronous enable — the clock goes to every flip-flop untouched and the decoded signal controls a multiplexer or an enable input — which is developed in Chapters 24 and 25.
9 Chapter Review
1. In the circuit of Figure 11.1 the inverter delay is 3 ns and every AND and OR gate has a delay of 7 ns. With \(B = C = 1\) and \(A\) falling at \(t = 0\), when does the glitch start and how wide is it?
The product \(AB\) falls at 7 ns, so the OR output falls at \(7 + 7 = 14\) ns. \(A'\) rises at 3 ns, \(A'C\) rises at \(3 + 7 = 10\) ns, and the OR output rises again at \(10 + 7 = 17\) ns. The glitch starts at 14 ns and is 3 ns wide — equal to the inverter delay, which is the difference between the two path delays, and independent of the AND and OR delays.
2. \(F(A,B,C,D) = \Sigma m(0,1,2,3,5,7,13,14,15)\) was minimised in Chapter 8 to \(A'B' + BD + ABC\). Is that implementation hazard-free? If not, repair it.
No. Cells 1 and 5 are adjacent (they differ in \(B\)): cell 1 is in \(A'B'\), cell 5 is in \(BD\), and no term holds both. Cells 3 and 7 are adjacent in the same way. Both pairs are bridged by the prime implicant \(A'D\), which covers 1, 3, 5 and 7 — the very term Chapter 8 rejected as redundant. The hazard-free expression is \(F = A'B' + BD + ABC + A'D\), which agrees with the original on all sixteen input combinations and costs one extra two-input AND gate and one more input on the OR.
3. Why can a two-level AND–OR circuit never show a static-0 hazard for a single-input change?
For the output to pulse to 1, some product term must momentarily go to 1. During a single-input change every literal except those of the changing variable is constant, and a product term contains that variable at most once. If the term evaluates to 0 both before and after the change, one of its constant literals must be 0, and that literal is 0 throughout — so the term cannot rise at any instant. The dual argument shows that a two-level OR–AND circuit cannot show a static-1 hazard.
4. A 3-to-8 decoder is driven by a 3-bit ripple counter, and one decoder output is used to clock a second counter. Explain what goes wrong and give two fixes.
The ripple counter's three outputs change one after another, so the decoder sees intermediate codes and asserts the wrong output lines for one flip-flop delay each — a function hazard, since several decoder inputs change at once, so no redundant gate inside the decoder can help. The second counter, which responds to edges, counts those spikes. Two fixes: strobe the decoder's enable with the clock so that its outputs are only asserted after the counter has settled; or replace the ripple counter with a synchronous one and re-register the decoded output, driving the second counter from the system clock with that signal as a synchronous enable rather than as a clock.
5. A designer removes a static hazard by adding a redundant term, and the test engineer reports that a stuck-at-0 fault on the added gate's output cannot be detected. Explain, and say whether the design should be changed.
The added term is logically redundant: the function is identical with or without it, so no static input pattern exists for which the output differs, and a stuck-at-0 fault on that gate changes nothing that a functional test can observe — it only restores the hazard. Nothing is wrong with the design. The usual practice is to keep the redundant gate, mark it as untestable in the fault-coverage report, and rely on the timing analysis rather than the functional test to justify it. Where full testability is mandatory, the alternative is to remove the redundancy and prevent the glitch from doing harm by sampling the output synchronously instead.