Skip to content

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 (missing default or 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 termwrong captured statescan-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.
An FSM with IDLE, RUN, DONE, and a hard-to-reach ERR state; the next-state logic computes transitions each clockstartfinackfault (rare)clrIDLERUNDONEERR
Figure 1 — the example FSM (representative): states IDLE, RUN, DONE, and an ERR (error) state reached only by an obscure sequence. Transitions are driven by inputs; the NEXT-STATE logic computes the move each clock. Functionally, ERR is hard to reach -- so a fault on the transition INTO ERR escapes functional test. With scan, you LOAD the predecessor state directly and CAPTURE one clock to exercise that exact transition, making the fault testable regardless of functional reachability.

The state register becomes a scan chain; next-state/output logic is the block under test:

The FSM state register becomes a scan chain; the next-state and output logic is the combinational block tested each capturecurrent statenext statescan_inload any state (SE=1)State register (scanchain)state[0..n] as scan cellsscan_outread captured state (SE=1)Next-state + outputlogiccombinational block UNDERTESTCapture (SE=0, 1clock)one transition → capturedinto state reg12
Figure 2 — the FSM after scan insertion (representative). The STATE REGISTER flops are swapped to scan cells and stitched: scan_in -> state[0] -> state[1] -> ... -> scan_out. In shift mode you LOAD any state (controllability) and READ the captured state (observability). In capture mode (one clock) the NEXT-STATE + OUTPUT logic (the combinational block under test) computes the transition from the loaded state + inputs. A fault in that logic makes the captured next-state wrong -> detected at shift-out compare. Scan turns the FSM's sequential state into directly-accessed, testable state.

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' ruleplace 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):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// 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
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// 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
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
# 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 cycles
Loading state RUN and capturing one clock makes a good FSM go to DONE while a faulty next-state stays RUN, detected at shift-out compareloaded RUNloaded RUNcapture: good=DONE, faulty=RUNcapture: good=DONE, fa…shift out → compare golden DONEshift out → compare go…clkscan_enfinstate_goodloadRUNcapDONEoutoutoutoutstate_faultyloadRUNcapRUNoutoutoutoutt0t1t2t3t4t5t6t7
Figure 3 — the FSM scan test, good vs faulty (representative). SHIFT IN (SE=1): load state = RUN directly into the state scan chain. CAPTURE (SE=0, one clock, fin=1): the next-state logic computes RUN->DONE; a GOOD FSM captures DONE, a FAULTY FSM (next-state term stuck) stays RUN (or a wrong state). SHIFT OUT (SE=1): read the captured state; compare to golden DONE. Good -> match; faulty -> mismatch (DETECTED). Scan loaded RUN directly -- no need to reach it by functional play -- and observed the transition, testing next-state logic that functional test may never exercise.

7. Industry Flow — the FSM is Chapter 5's ATPG target

This clean, scannable FSM is exactly what ATPG will target next:

Scan-ready FSM goes through scan insertion, DRC with an async-reset fix, to a clean scannable FSM that ATPG targets in Chapter 5Scan-ready FSM → insertion → DRC clean → ATPG (Ch5)Scan-ready FSM → insertion → DRC clean → ATPG (Ch5)1Scan-ready FSM (4.1)full case, controllable reset2Scan insertion (4.2)state reg → scan chain3DRC + reset fix (4.3/4.4)async reset gated inactive → clean4ATPG on the FSM (Ch5, 5.6)load-state/capture/observe patterns5Coverage closure (Ch6)→ DPPM (1.5)
Figure 4 — the FSM from scan-ready to ATPG (representative). SCAN-READY FSM (4.1: full case, controllable reset) -> SCAN INSERTION (4.2: state reg -> scan chain) -> SCAN DRC (4.3) catches an async reset, FIXED (4.4) -> DRC CLEAN. The clean scannable FSM is handed to ATPG (Ch5, specifically 5.6 'ATPG on the FSM') which generates load-state/capture/observe patterns for the whole fault list, then COVERAGE closes (Ch6). This capstone is the direct input to the next chapter.

8. Debugging Session — an inferred latch breaks the FSM's scan

1

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)
Symptom

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.

Root Cause

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.

Fix

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 default transition 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 (default transition) — 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-readyfull case + default (no inferred latch), synchronous/controllable reset.
  • Scan inserted — state register → scan chain; chain integrity verified (3.3).
  • Scan DRC cleanasync reset gated inactive in test (4.4); no latch/loop/bus violations.
  • Illegal/unreachable states handled (default transition) — 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

  1. Write the FSM scan-ready: full case with default (no latch), synchronous reset.
  2. Insert scan: state register → chain (scan_in → state[0] → state[1] → scan_out).
  3. Run scan DRC in your head: flag the async reset (if present) and fix it (rst_n | scan_mode, 4.4).
  4. Detect a fault: load state RUN, capture one clock with fin=1; good → DONE, faulty next-state → wrongdetected.
  5. Remove the default and show a latch is inferredscan 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 directlyeven 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 directlyincluding 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 default transition) 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 resetfix (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.