Design for Test: Scan and BIST
The wafers are back from the fab. On each one sit hundreds of copies of your chip — and, thanks to
the defects we will meet in the next lesson,
a good fraction of them are broken: a speck of dust shorted two wires here, a void opened a
connection there. Which ones? You cannot ship them all and let customers find out. And here is the
bind: a die has millions of internal wires and you can physically touch only its few hundred pads.
You cannot probe internal nodes. The answer is one of the great pragmatic ideas of
the industry — design for test (DFT): build the chip, from the start, so that it can
be interrogated through the pins it has.
The stuck-at fault model
First, tame the question. "Is anything wrong anywhere?" is untestable; DFT replaces it with a
concrete checklist: the stuck-at fault model. Assume any single internal node might
be permanently stuck at 0 or stuck at 1 (as if shorted to ground or
supply) — one entry per node per polarity. It is a deliberate simplification (real defects include
bridges, opens, and slow transistors — richer models exist for those), but it is enumerable:
a tool can list every fault, and for each one ask two things:
- Controllability — can I drive the circuit into a state where this node
should carry the opposite value?
- Observability — would the fault's wrong value change something I can see at an
output?
For deeply buried logic, both are hopeless through the functional pins alone. Which brings us to the
trick.
Scan: the chip becomes its own probe
The scan idea: give every flip-flop a tiny multiplexer on its data input. One leg
carries the normal functional data; the other leg connects to the previous flop's output. A
single test-enable signal flips every mux at once:
In test mode the chip's million flops become one giant shift register threading the
whole die. Now every test runs the same three-beat rhythm:
- Shift in — clock the chain n times to load any state
pattern you like into all n flops: total controllability;
- Capture — flip to functional mode for one clock: the combinational
logic computes from your planted state, and the flops capture the results;
- Shift out — back to test mode, clock n times and read
the captured snapshot at the scan-out pin (while shifting the next pattern in behind it):
total observability.
Every internal node is now two shift operations away from your tester. ATPG
(automatic test pattern generation) exploits this: for each stuck-at fault it computes a pattern that
excites the fault and steers its effect into some flop, then greedily merges patterns until a few
thousand of them cover 99%+ of all faults — the quoted fault coverage.
Run a scan test
// A 4-flop circuit: next state = simple logic of current state.
// n0 = q1 AND q2, n1 = q0 OR q3, n2 = NOT q3, n3 = q0 XOR q1
// Fault to hunt: the wire from q1 into the AND gate, stuck at 0.
type Bits = number[];
const step = (q: Bits, q1Stuck0: boolean): Bits => {
const q1 = q1Stuck0 ? 0 : q[1]; // the injected defect
return [q1 & q[2], q[0] | q[3], 1 - q[3], q[0] ^ q[1]];
};
// Scan test: shift a pattern in, capture once, shift the response out.
const scanTest = (pattern: Bits, faulty: boolean): Bits => {
let q: Bits = [0, 0, 0, 0];
for (const bit of pattern) q = [bit, q[0], q[1], q[2]]; // shift in (4 clocks)
q = step(q, faulty); // capture (1 functional clock)
return q; // (shifted out, 4 clocks)
};
// ATPG's chosen pattern: q1=1, q2=1 excites the fault (AND should see 1,1).
const pattern: Bits = [0, 1, 1, 0]; // → q = [q0,q1,q2,q3] = [0,1,1,0] after shifting
const good = scanTest(pattern, false);
const bad = scanTest(pattern, true);
console.log("pattern shifted in : " + pattern.join(""));
console.log("good die shifts out: " + good.join(""));
console.log("this die shifts out: " + bad.join(""));
const diff = good.map((b, i) => (b !== bad[i] ? "^" : " ")).join("");
console.log(" " + diff + " ← the tell-tale diff");
console.log(bad.join("") === good.join("")
? "Responses match: die passes this pattern."
: "Mismatch: q0 captured 0 where a good die captures 1 — stuck-at-0 caught. Reject the die.");
Notice how surgical it is: the pattern was designed so that a healthy AND gate outputs 1 and
a stuck-at-0 outputs 0, and that difference lands in a flop we can read. Multiply by a few thousand
patterns and every enumerable fault gets its moment in the spotlight.
Test time is money, memories test themselves, boards get scanned too
A tester (a multi-million-dollar machine) charges by the second, and a naive scan regime is slow:
each pattern costs roughly a full chain-length of shifting. With p
patterns, chain length n, and shift clock f,
test time is about p \cdot n / f. The levers follow directly:
- parallel chains — split one million-flop chain into hundreds of shorter chains
shifted simultaneously through spare pins;
- test compression — on-chip decompressors expand compact tester patterns into
full chain contents, and compactors squeeze the responses back down: 100× fewer tester bits;
- memory BIST — RAMs, with their regular structure and custom bit-cells, get
built-in self-test: a small on-chip engine marches classic patterns
(checkerboards, march algorithms) through every address at full speed and reports pass/fail —
the tester just says "go";
- boundary scan (JTAG) — the same shift-register idea wrapped around the chip's
pins, standardised (IEEE 1149.1) so that assembled boards can be tested for
soldering faults through a five-wire port.
- the stuck-at model turns "is it broken?" into an enumerable checklist of
per-node stuck-at-0/1 faults;
- scan adds a test mux to every flop; in test mode all flops form one shift
register — shift in, capture one functional clock, shift out — giving controllability and
observability of every node;
- ATPG generates the patterns and reports fault coverage;
- test time ≈ patterns × chain length ÷ shift clock — attacked with parallel chains and
test compression;
- memory BIST tests RAMs from inside; JTAG boundary scan
extends the idea to board-level;
- scan costs ~5–10% area — and every team pays it, because an untestable chip is unsellable.
A chicken-and-egg puzzle: scan finds manufacturing defects by comparing a die's responses against
the correct ones — but correct according to what? The answer is that ATPG simulates the
golden netlist to predict every expected response; the tester is really comparing silicon against
simulation. That works beautifully for fabrication defects, but notice what it can never catch: a
design bug, faithfully manufactured, passes every scan pattern with flying colours — the
silicon matches the netlist, bug included. That is why manufacturing test and functional
verification are entirely separate disciplines: verification asks "did we design the right
machine?"; test asks "did the fab build the machine we designed?". Mixing up the two questions has
embarrassed more than one project review.
To a designer squeezing timing, the scan mux on every single flop looks like pure vandalism: extra
delay on every data path, ~5–10% extra area, whole routing tracks spent threading chains. The
temptation to "skip DFT just for this block" is real — and giving in to it is how you end up with a
warehouse of chips you cannot sell. Without scan there is no way to tell good dice
from bad ones at the tester; without that, you either ship defects to customers or discard entire
wafers on suspicion. An untestable chip is unsellable regardless of how correct the design
is. Every serious team pays the scan tax gladly, plans it from day one, and treats "scan
coverage 99%+" as a tape-out gate as hard as timing closure itself.