RTL feature | DFT risk | Preferred pattern |
|---|---|---|
Fabric-generated clock | Uncontrollable shift clock | Clock enable or approved clock cell |
Combinational reset logic | Uncontrolled reset during shift | Reset controller with test override |
Latch/custom storage | May not have scan equivalent | Approved library pattern and waiver |
Black-box state | Unobservable or uncontrollable | Test model or wrapper |
X-producing analog/status input | Compactor pollution | Test clamp/mask with reviewed behavior |
The sensor peripheral replaces its fabric divider with an approved clock wrapper, gives test control explicit reset ownership, and clamps the analog status only in authorized test mode. These changes preserve functional behavior while making scan insertion predictable.
The fabric divider below clocks a flop from logic. In shift the tester cannot drive that clock, and the divider's own state decides when it ticks.
// Bad for scan: q is clocked by a divider flop, not by a controllable clock
module div_clk_bad (
input logic clk, rst_n, d,
output logic q
);
logic clk_div2;
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) clk_div2 <= 1'b0;
else clk_div2 <= ~clk_div2;
always_ff @(posedge clk_div2) q <= d; // clock from fabric logic
endmoduleThe fix keeps one clock and turns the divide into an enable. Every flop now sees the tester's shift pulses; only the functional update rate changes.
// Scan-friendly: one clock, divide-by-two as a clock enable
module div_en_good (
input logic clk, rst_n, d,
output logic q
);
logic en_div2;
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) en_div2 <= 1'b0;
else en_div2 <= ~en_div2;
always_ff @(posedge clk)
if (en_div2) q <= d; // updates every second edge
endmoduleWhere a real divided clock is required, use the approved clock wrapper with a test bypass, as the sensor peripheral does.
Read the cell left to right. The accent wires are what scan adds; everything else is the functional flop.
The flop must be recognisable and clocked by a controllable clock, or the tool cannot replace it.
SE is a global test control, so it comes from the AON test controller, not functional software.
SO feeds the next cell, which is why every cell in a chain must shift on the same legal clock.
Instance / boundary | Functional domain and relation | Test/reset owner and hook |
|---|---|---|
u_sensor/u_sample_regs | sample_clk from sensor PLL; asynchronous to bus_clk | u_aon/u_test_ctrl owns sample clock wrapper/OCC and test reset; separate sample scan chain |
u_sensor/u_bus_regs | bus_clk; no assumed phase relation to sample_clk | Same AON owner, independent bus wrapper/OCC and reset; separate bus scan chain |
u_sensor/u_sample_sram | sample_clk, 256x16 single-port macro | u_sample_mbist owns wrapper test select, address/data/write control and done/fail status |
u_sensor/u_cfg_sram | bus_clk, 64x32 single-port macro | u_cfg_mbist owns distinct wrapper and status; not scanned as ordinary flops |
analog_status -> sample control | External asynchronous/X-capable input | Functional synchronizer retained; authorized scan/capture clamp=0 before compaction |
sensor_pins / bus_pins | External interfaces | AON pin mux parks outputs; u_tap boundary access per pin policy |
Each functional reset asserts asynchronously and releases synchronously to its domain. Test control takes ownership only with clocks stopped and reset asserted, then releases reset with the selected legal test clocks before loading vectors. Enumerate excluded AON/OCC state separately with DFT-owned reasons. Separate chains avoid assuming a lockup latch can make arbitrary asynchronous capture relationships safe.
Run DFT lint before integration.
Identify every non-scan register and why it is safe.
Expose test enables through stable top-level ownership.
Do not let functional software configuration be the only path to test mode.
Keep test behavior out of normal functional timing paths where possible.
Shift requires controllable repeated pulses. A functional divider depends on internal state and may not deliver the required test-clock sequence unless bypassed or replaced.
The instance names and mode artifacts form an illustrative integration contract, not an inserted netlist or an executed DFT signoff.