DFT · Chapter 4 · Scan Insertion & DRC
Working Example: Scan Insertion on an FSM
This capstone applies the whole chapter to the project's next design, a small finite state machine. First the FSM is made scan-ready, synchronous with a controllable reset and no inferred latches, avoiding the classic trap where an incomplete case in the next-state or output logic infers a latch. Then scan is inserted, swapping the state-register flops into scan cells stitched into a chain, and scan DRC catches a real violation, an asynchronous reset on the state register, fixed by gating the reset inactive in test. The payoff is decisive: the state register becomes directly loadable, so you can place the machine into any state, including illegal or hard-to-reach ones, and directly observable. Loading a state, capturing one clock, and shifting out the result detects a next-state fault that functional test could never reach.
Intermediate15 min readDFTScan InsertionFSMScan DRCCoverage
Chapter 4 · Section 4.5 · Scan Insertion & DRC — chapter capstone
Project thread — after the scannable counter (3.6), the project grows an FSM. This lesson makes it scan-ready (4.1), inserts scan (4.2), passes DRC (4.3) with a reset fix (4.4) — and hands the clean, scannable FSM to ATPG in Chapter 5 (5.6).
1. Why Should I Learn This?
This lesson runs the whole Chapter 4 flow end-to-end on a realistic block — and shows the FSM's unreachable states becoming directly testable.
- Scan-ready the FSM (4.1): synchronous, controllable reset, no inferred latch (the FSM trap).
- Insert scan (4.2): state flops → scan cells, stitched into a chain.
- Scan DRC (4.3) catches an async-reset violation → fix it (4.4) → DRC clean.
- Load any state (even illegal/unreachable), capture one transition, observe → next-state faults detected.
2. Real Silicon Story — the illegal state you could never reach
An FSM had a next-state fault on a transition into a rarely-used error state. Functional tests essentially never exercised that transition — reaching it required a specific, obscure input sequence over many cycles — so the fault sat undetected, a latent escape risk.
After scan insertion, the fault became trivial to catch. The test loaded the exact predecessor state directly into the state register's scan chain — no need to navigate there functionally — applied one capture clock so the FSM made the single transition under test, and shifted out the resulting state to compare against the golden next-state. A die with the stuck next-state term produced the wrong next-state → scan-out mismatch → detected.
Along the way, scan DRC caught an async reset on the state register (which would have corrupted loaded states), fixed by gating it inactive in test (4.4). Lesson: scan lets you load any FSM state directly — including ones functional test can't reach — turning unreachable-state faults into simple, detectable ones.
3. Factory Perspective — the scannable FSM through each lens
- What the test engineer sees: an FSM they can place into any state and read — patterns become load-state → capture → compare-next-state, with DRC clean and chain integrity (3.3) first.
- What the yield engineer sees: FSM next-state/output defects now fail the tester (binnable/diagnosable) instead of escaping via unreachable states.
- What the RTL/DV engineer sees: the scan-ready requirements on their FSM — full
case/default (no inferred latch), controllable reset — and that illegal states must be handled (they're now loadable). - What management cares about: the coverage jump on control logic (FSMs are everywhere) — a concrete DPPM benefit (1.5) from a clean insertion, with no functional change.
4. Concept — the FSM through the insertion flow
Step 1 — Scan-ready the FSM (4.1):
- Synchronous state register; controllable reset; outputs/next-state fully specified.
- Avoid the classic FSM latch: an incomplete
case(missingdefaultor unassigned outputs) infers a latch → a scan DRC latch violation → fix with full case / default or explicit assignment.
Step 2 — Insert scan (4.2):
- Swap the state-register flops → scan cells; stitch them into a state scan chain (scan_in → state[0..n] → scan_out).
- The next-state and output logic become the combinational block under test between scan loads and captures.
Step 3 — Scan DRC (4.3) + fix (4.4):
- DRC flags an async reset on the state register (would corrupt loaded states) → gate it inactive in test (
rst_eff = arst_n | scan_mode, 4.4) → DRC clean.
Step 4 — The payoff — load any state, capture one transition, observe:
- Load any state directly via the chain (controllability) — including illegal/unreachable states functional test can't reach.
- Capture one clock (SE=0): the FSM makes exactly one transition, exercising the next-state logic.
- Shift out the resulting state (observability) and compare to golden next-state.
- A stuck next-state term → wrong captured state → scan-out ≠ golden → detected.
A caution unique to FSMs — illegal/unreachable states:
- Scan can load states the FSM would never functionally enter. That's powerful (reaches faults) but means illegal states must be handled (a default transition), or they can produce unexpected/X behavior that mismatches golden.
The state register becomes a scan chain; next-state/output logic is the block under test:
5. Mental Model — a board game with a 'set the board' rule
An FSM is like a board game whose interesting positions take many turns to reach.
- Without scan: to test 'what happens from the rare error position?' you must play many precise turns to get there — and some positions are effectively unreachable in normal play.
- With scan: you get a 'set the board' rule — place every piece exactly where you want (load any state, even an illegal one), take one turn (capture — the next-state logic moves), and read the new board (shift out).
- Now any transition is testable in one turn, regardless of how hard it is to reach by playing.
- A caution: because you can set illegal boards, you must have a rule for illegal positions (a default transition), or the game does something undefined (X) that won't match the expected result.
Set the board, take one turn, read it — scan makes every FSM transition a one-move test.
6. Working Example — the FSM in tri-HDL, made scannable
The FSM (state register + next-state + output), written scan-ready (full case, no inferred latch):
// SystemVerilog — scan-ready FSM (synchronous, FULL case -> no inferred latch)
module fsm (input logic clk, rst_n, start, fin, ack, clr,
output logic busy);
typedef enum logic [1:0] {IDLE, RUN, DONE, ERR} state_t;
state_t state, nxt;
always_comb begin
nxt = state; // default assignment -> NO inferred latch
unique case (state)
IDLE: if (start) nxt = RUN;
RUN: if (fin) nxt = DONE; else if (!fin & clr) nxt = ERR;
DONE: if (ack) nxt = IDLE;
ERR: if (clr) nxt = IDLE;
default: nxt = IDLE; // handle illegal/unreachable states (loadable via scan!)
endcase
end
always_ff @(posedge clk)
if (!rst_n) state <= IDLE; // SYNCHRONOUS reset (scan-friendly)
else state <= nxt;
assign busy = (state == RUN);
endmodule// Verilog-2001 — same scan-ready FSM (full case + default -> no latch)
module fsm (clk, rst_n, start, fin, ack, clr, busy);
input clk, rst_n, start, fin, ack, clr; output busy;
localparam IDLE=2'd0, RUN=2'd1, DONE=2'd2, ERR=2'd3;
reg [1:0] state, nxt;
always @(*) begin
nxt = state;
case (state)
IDLE: if (start) nxt = RUN;
RUN: if (fin) nxt = DONE; else if (clr) nxt = ERR;
DONE: if (ack) nxt = IDLE;
ERR: if (clr) nxt = IDLE;
default: nxt = IDLE; // illegal-state handling
endcase
end
always @(posedge clk) if (!rst_n) state <= IDLE; else state <= nxt;
assign busy = (state == RUN);
endmodule-- VHDL — same scan-ready FSM (others => covers illegal states)
library ieee; use ieee.std_logic_1164.all;
entity fsm is port (clk, rst_n, start, fin, ack, clr : in std_logic; busy : out std_logic); end entity;
architecture rtl of fsm is type state_t is (IDLE, RUN, DONE, ERR); signal state, nxt : state_t; begin
process (state, start, fin, ack, clr) begin
nxt <= state; -- default -> no latch
case state is
when IDLE => if start='1' then nxt <= RUN; end if;
when RUN => if fin='1' then nxt <= DONE; elsif clr='1' then nxt <= ERR; end if;
when DONE => if ack='1' then nxt <= IDLE; end if;
when ERR => if clr='1' then nxt <= IDLE; end if;
when others => nxt <= IDLE; -- illegal-state handling
end case;
end process;
process (clk) begin
if rising_edge(clk) then if rst_n='0' then state <= IDLE; else state <= nxt; end if; end if;
end process;
busy <= '1' when state = RUN else '0';
end architecture;The insertion + DRC + a detected fault:
# Scan insertion + DRC + detection on the FSM — REPRESENTATIVE, SIMPLIFIED, tool-neutral:
INSERT : state[1:0] flops -> scan cells ; chain: scan_in -> state[0] -> state[1] -> scan_out (length 2)
DRC : VIOLATION async_reset on state reg -> FIX (4.4): rst_eff = rst_n | scan_mode -> re-run -> DRC CLEAN
DETECT : target a stuck next-state term on RUN->DONE
LOAD (SE=1): shift in state = RUN (directly -- no functional navigation)
CAPTURE (SE=0, 1 clk, fin=1): good FSM -> DONE ; faulty (next-state stuck) -> stays RUN (or wrong)
SHIFT OUT(SE=1): read state ; COMPARE golden = DONE
GOOD -> DONE -> match -> pass
FAULTY-> RUN -> scan_out != golden -> DETECTED
# Same fault was ~unreachable functionally; scan loads RUN directly + observes DONE -> detected.The waveform shows load-state → capture-transition → observe:
FSM scan test: load RUN → capture (good=DONE, faulty=RUN) → shift out & compare
8 cycles7. Industry Flow — the FSM is Chapter 5's ATPG target
This clean, scannable FSM is exactly what ATPG will target next:
8. Debugging Session — an inferred latch breaks the FSM's scan
After scan insertion the FSM has a scan DRC latch violation and coverage on its output/next-state logic is low, and the team blames the insertion tool; the real cause is an inferred latch from an incomplete case (a missing default or unassigned signal) in the FSM's combinational logic -- a scan-readiness (RTL) bug fixed by completing the case, not a tool problem
INCOMPLETE CASE → INFERRED LATCH → SCAN DRC LATCH VIOLATION (FIX IN RTL)After scan insertion, the FSM has a scan DRC latch violation and low coverage on its next-state/output logic. The team suspects the insertion tool created a latch or mishandled the FSM.
An incomplete case statement in the FSM's combinational logic inferred a latch, which is not a scan cell — so that logic is uncontrollable/unobservable and fails scan DRC — and the tool didn't create it, the RTL did. The classic FSM pitfall is a case (or if/else) that doesn't assign every output/next-state signal on every path — a missing default, or an output left unassigned in some state. Synthesis, needing to hold the old value on the unassigned path, infers a level-sensitive latch. That latch is not a scan cell (4.4): it's uncontrollable/unobservable and can pass X, so scan DRC (4.3) flags a latch violation, and ATPG can't test the logic behind it → the coverage hole. This is a scan-readiness (RTL) bug — exactly the kind DFT lint (4.1) is meant to catch early — not an insertion-tool error. The tell is that the latch corresponds to a signal/state not fully specified in the FSM's always_comb/case.
Complete the case in RTL so no latch is inferred — assign every next-state/output on every path (default assignment + a default case) — then re-insert and re-run DRC clean. Give the combinational block a default assignment at the top (nxt = state; and default every output) and a default: case arm that handles illegal/unreachable states (which, note, scan can now load), so every signal is assigned on every path and no latch is inferred. Re-run scan insertion and scan DRC → the latch violation clears and the FSM's next-state/output logic becomes fully controllable/observable, restoring coverage. Best of all, add the check to DFT lint (4.1) so the incomplete case is caught in RTL review next time. The principle to lock in: making an FSM scannable is the Chapter 4 flow applied — scan-ready RTL (synchronous, controllable reset, and crucially a fully-specified case so no latch is inferred), scan insertion (state register into a scan chain), and DRC-clean (fixing the async reset by gating it inactive in test) — after which the FSM's state register is directly loadable and observable, so next-state and output faults (even on functionally unreachable transitions) become detectable; a latch DRC violation on an FSM almost always means an incomplete case in your RTL, fixed by completing it, not by blaming the insertion tool. (Scan-ready rules are 4.1; the reset/latch test-mode fixes are 4.4; ATPG on this FSM is Chapter 5.6.)
9. Common Mistakes
- Incomplete case → inferred latch. The classic FSM scan bug — assign every signal on every path (default +
default:). - Async reset on the state register left active in scan. Corrupts loaded states → gate inactive in test (4.4).
- Ignoring illegal/unreachable states. Scan can load them — handle with a
defaulttransition or they cause X/mismatch. - Blaming the insertion tool for coverage/DRC issues. They're usually scan-readiness (RTL) bugs (4.1).
- Skipping chain integrity / DRC before trusting coverage. Do both (3.3, 4.3) first.
10. Industry Best Practices
- Write FSMs with full case + default — no inferred latches (DFT lint, 4.1).
- Use synchronous or test-controllable resets on the state register (4.4).
- Handle illegal/unreachable states (
defaulttransition) — scan can load them. - Run scan DRC clean and chain integrity before ATPG (4.3, 3.3).
- Treat the scannable FSM as the ATPG target (Ch5) — clean insertion → clean ATPG.
11. Senior Engineer Thinking
- Beginner: "Scan insertion made a latch and low coverage on my FSM — the tool is broken."
- Senior: "A latch DRC violation on an FSM is almost always an incomplete case in my RTL — a missing default infers a latch, which isn't a scan cell. I complete the case, handle illegal states, fix the async reset (gate inactive in test), and re-run DRC clean. Then I can load any state — even unreachable ones — and test the next-state logic. It's the Chapter 4 flow, not a tool bug."
The senior traces FSM scan issues to scan-readiness (RTL) and runs the insertion→DRC→fix flow, not tool-blaming.
12. Silicon Impact
Scan insertion on an FSM is the capstone that generalizes the counter (3.6) to real control logic — and control logic (FSMs) is everywhere in a chip, so this is the common case, not a toy. The decisive gain is reachability: an FSM's interesting and dangerous states (error states, rare corners) are often functionally hard or impossible to reach, so functional test leaves their faults undetected — a classic escape source. Scan dissolves this by making the state register directly loadable, so you can place the FSM into any state — even illegal/unreachable ones — apply one capture to exercise exactly one transition of the next-state/output logic, and observe the result: unreachable-state faults become one-move tests. This is the coverage low → high jump on control logic, a direct DPPM benefit (1.5). The lesson also surfaces the two most common FSM-specific gotchas, both scan-readiness (RTL) issues you now know to prevent: the inferred latch from an incomplete case (fixed by a full case + default, 4.1) and the async reset on the state register (fixed by gating it inactive in test, 4.4) — plus the new responsibility that, because scan can load illegal states, your FSM must handle them (a default transition) or risk X/mismatch. Finally, this clean, scannable, DRC-passing FSM is the exact input to Chapter 5's ATPG (5.6): do the insertion well here and pattern generation and coverage closure on it are straightforward. For the RTL/DV engineer, the takeaway is that a fully-specified, synchronous, reset-controllable FSM flows cleanly through the entire structural-test apparatus — turning the fault models of Chapter 2 into real protection for the customer.
13. Engineering Checklist
- FSM is scan-ready — full case + default (no inferred latch), synchronous/controllable reset.
- Scan inserted — state register → scan chain; chain integrity verified (3.3).
- Scan DRC clean — async reset gated inactive in test (4.4); no latch/loop/bus violations.
- Illegal/unreachable states handled (
defaulttransition) — safe to load via scan. - Confirmed the FSM's next-state/output faults are detectable (coverage low → high); ready for ATPG (Ch5).
14. Try Yourself
- Write the FSM scan-ready: full
casewith default (no latch), synchronous reset. - Insert scan: state register → chain (scan_in → state[0] → state[1] → scan_out).
- Run scan DRC in your head: flag the async reset (if present) and fix it (
rst_n | scan_mode, 4.4). - Detect a fault: load state RUN, capture one clock with
fin=1; good → DONE, faulty next-state → wrong → detected. - Remove the default and show a latch is inferred → scan DRC latch violation → then restore it.
The FSM and flow are tool-neutral — a free simulator runs the scan FSM. Real insertion/DRC/ATPG come from Chapters 4–6 tools. No paid tool required.
15. Interview Perspective
- Weak: "You add scan to the FSM's flip-flops so you can test it."
- Good: "Make the FSM scan-ready, insert scan on the state register, pass DRC, then load states and capture transitions."
- Senior: "I run the Chapter 4 flow on the FSM. Scan-ready it (4.1): synchronous, controllable reset, and a full case with default so no latch is inferred — the classic FSM trap. Insert scan (4.2): the state register becomes a scan chain, and the next-state/output logic is the combinational block under test. Scan DRC (4.3) catches an async reset on the state register, which I fix by gating it inactive in test (4.4) → DRC clean. Now I can load any state directly — even illegal/unreachable ones functional test can't reach — capture one clock to make one transition, and shift out to compare the next-state. A stuck next-state term → wrong captured state → detected. Because scan can load illegal states, I also make sure the FSM handles them (default). This clean FSM is exactly what ATPG targets next (5.6)."
16. Interview / Review Questions
17. Key Takeaways
- Making an FSM scannable is the Chapter 4 flow applied: scan-ready (4.1) → insert scan (4.2) → scan DRC clean (4.3) with the async-reset fix (4.4).
- Scan-ready an FSM means synchronous, controllable reset, and — the FSM-specific trap — a fully-specified case (default assignment +
default:) so no latch is inferred. - After insertion the state register is a scan chain: you can load any state directly — including illegal/unreachable states functional test can't reach — capture one transition, and observe it, making next-state/output faults detectable (coverage low → high).
- Scan DRC catches the async reset on the state register → gate it inactive in test (4.4) → DRC clean; and because scan can load illegal states, the FSM must handle them (a
defaulttransition) to avoid X/mismatch. - The clean, scannable FSM is the direct ATPG target of Chapter 5 (5.6) — a latch DRC violation on an FSM almost always means an incomplete case in your RTL, fixed by completing it, not by blaming the tool. Next: Chapter 5 — ATPG (generating the patterns for exactly this kind of scannable logic).
18. Quick Revision
Scan insertion on an FSM (Ch4 capstone). Apply the Ch4 flow: scan-ready (4.1 — synchronous, controllable reset, FULL case + default → no inferred latch, the classic FSM trap) → insert scan (4.2 — state register → scan chain; next-state/output logic = combinational block under test) → scan DRC (4.3) catches an async reset → fix (4.4 —
rst_n | scan_mode) → DRC clean. Payoff: load ANY state directly (even illegal/unreachable ones functional test can't reach), capture one transition, observe → next-state faults detected (coverage low → high). Handle illegal states (default) since scan can load them. This clean FSM = ATPG target for Ch5 (5.6). Next: Chapter 5 — ATPG.