A scan flop is a D flop with a 2:1 mux on its input. When scan_en is high the flop shifts; when low it captures functional data.
The scan-out so follows q combinationally so the next flop in the chain sees it within the same cycle.
`timescale 1ns/1ps
module scan_ff (
input logic clk,
input logic rst_n,
input logic scan_en,
input logic d,
input logic si,
output logic q,
output logic so
);
logic d_mux;
assign d_mux = scan_en ? si : d;
assign so = q;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n)
q <= 1'b0;
else
q <= d_mux;
end
endmoduleFour flops stitch so to si down the row. The first flop shifts in from the pin; the last shifts out to the pin.
Watch so: it stays 0 while the chain fills, then shows the first bit shifted in.
Slot 1: rst_n is 0, so the chain is in reset and so is 0.
Slot 2: reset is released and the first bit 1 shifts into bit 0; so is still 0.
Slot 3: the second bit 0 shifts in; so is still 0.
Slot 4: the third bit 1 shifts in; so is still 0.
Slot 5: the fourth bit 1 shifts in, the chain holds 1011, and the first bit reaches so.
Slot 6: scan_en is 0, so functional data 0100 is captured and so is 0.
Slot 7: scan_en is 1 again, the captured word shifts out, and so is 1.
A full round on the four-flop chain: shift in 0,0,1,1, capture the logic once, then shift the answer out. The capture cone is n = q1 & q0, wired into q3, so the fault-free answer is 1000.
Each slot is one clock cycle, numbered from 0, sampled just after the rising edge; q is shown as q3 q2 q1 q0 in hex.
Slots 1 to 4 (shift in): scan_en is 1 and each edge moves si one place up the chain. After slot 4, q is 3 (0011): the first bit shifted in has reached q3.
Slot 5 (capture): scan_en is 0 for one edge, so every flop loads its functional input. q1 & q0 = 1 lands in q3, so q is 8 (1000) and so shows the first answer bit, 1.
Slots 6 to 8 (shift out): scan_en is 1 again and so reads 0, 0, 0. The serial answer is 1,0,0,0, q3 first.
The fault: with n stuck at 0, the capture in slot 5 would load 0000 and so would stay 0 in slot 5. That first bit is where the tester sees the defect.
Fault experiment (illustrative) | Good circuit | n stuck at 0 |
|---|---|---|
Shift 0,0,1,1 into q0-to-q3 chain | q=0011 | q=0011 |
Activate: n=q[1]&q[0] | n=1 | n=0 |
Propagate: d={n,3'b000} | d=1000 | d=0000 |
Capture with scan_en=0 | q=1000 | q=0000 |
Sample so before each of four shift edges | 1,0,0,0 | 0,0,0,0: first serial bit mismatches |
The bench injects this one stuck-at defect at the capture input. A zero activation pattern would not distinguish these circuits.
Every scan operation is the same three steps. The testbench below performs one full round.
Step |
| What happens | Cycles for 4 flops |
|---|---|---|---|
Shift in | 1 | Each edge moves one bit down the chain | 4 |
Capture | 0 | One edge loads functional data into every flop | 1 |
Shift out | 1 | Each edge presents the next answer bit on | 4 |
The stepper starts on the first waveform's pattern: shift in 1,0,1,1, capture once with every flop's functional input set to NOT q, then shift the answer out while zeros shift in.
Loading scan chain stepper…
Step four times: the chain holds 1011 (q3 q2 q1 q0) and so is already 1. One more step captures 0100, the bitwise NOT.
Run to the end: sampled before each unload edge, so reads 0, 1, 0, 0, which is the captured word with q3 first.
Set the fault to q2's d stuck at 0: the capture loads 0000 and the second bit out mismatches. Switch the logic to and-pair and the same fault goes unseen, because q2 AND q3 is 0 for this pattern.
Production stitching order comes from scan insertion; the explicit RTL chain below fixes q0 to q3. The first serial bit in reaches q3 first and is therefore first out when a loaded vector is shifted out without capture. Sample so before each shift edge, or immediately before that edge's register updates; sampling after the shift sees the next bit. Functional capture replaces the loaded vector, so its response has its own ordering.
Four, one per flop. The first bit shifted in lands in the last flop just as capture arrives.
so stays 0 through slots 2 to 4 and rises in slot 5. Why?The chain is four deep, so the first bit shifted in needs four edges to reach the last flop. The waveform shows that delay directly.
The chain of reused scan flops plus a testbench that shifts a vector in, captures, and shifts the answer out.
`timescale 1ns/1ps
module scan_ff (
input logic clk,
input logic rst_n,
input logic scan_en,
input logic d,
input logic si,
output logic q,
output logic so
);
logic d_mux;
assign d_mux = scan_en ? si : d;
assign so = q;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n)
q <= 1'b0;
else
q <= d_mux;
end
endmodule
module scan_chain4 (
input logic clk,
input logic rst_n,
input logic scan_en,
input logic [3:0] d,
input logic si,
output logic [3:0] q,
output logic so
);
logic [3:0] qq;
scan_ff f0 (.clk(clk), .rst_n(rst_n), .scan_en(scan_en), .d(d[0]), .si(si), .q(qq[0]), .so());
scan_ff f1 (.clk(clk), .rst_n(rst_n), .scan_en(scan_en), .d(d[1]), .si(qq[0]), .q(qq[1]), .so());
scan_ff f2 (.clk(clk), .rst_n(rst_n), .scan_en(scan_en), .d(d[2]), .si(qq[1]), .q(qq[2]), .so());
scan_ff f3 (.clk(clk), .rst_n(rst_n), .scan_en(scan_en), .d(d[3]), .si(qq[2]), .q(qq[3]), .so());
assign q = qq;
assign so = qq[3];
endmodule
The bench injects one modelled combinational stuck-at defect at the capture input. It checks detection, not ATPG coverage, physical defect behaviour or at-speed timing.