🔧 DFT Blog

Part 3 of 11

Verilog for DFT Engineers

Write clean RTL that's easy to test

By Praveen Kumar Vagala

1,234 views

Module Structure

Every Verilog design is built from modules.

module module_name (
    // Port declarations
    input        clk,           // Single bit input
    input        rst_n,         // Active low reset (n = negative)
    input  [7:0] data_in,       // 8-bit input bus
    output       valid,         // Single bit output
    output [7:0] data_out,      // 8-bit output bus
    inout  [7:0] bidir          // Bidirectional (avoid if possible!)
);

    // Internal signals
    wire [7:0] internal_wire;
    reg  [7:0] internal_reg;
    
    // Your logic here
    
endmodule
Avoid inout ports - they create test complications.

Always Blocks - The Core of Verilog

Combinational Logic - Use = (Blocking)

always @(*) begin              // Sensitive to ALL inputs
    case (sel)
        2'b00: out = a;
        2'b01: out = b;
        2'b10: out = c;
        default: out = d;      // Always have default!
    endcase
end

Sequential Logic - Use <= (Non-Blocking)

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        q1 <= 1'b0;
        q2 <= 1'b0;
    end else begin
        q1 <= d;
        q2 <= q1;             // Creates shift register
    end
end

Blocking vs Non-Blocking

This is the #1 source of bugs for beginners!

Blocking (=) - Executes Sequentially

always @(posedge clk) begin
    q1 = d;      // q1 gets NEW value immediately
    q2 = q1;     // q2 gets NEW q1 (same as d!)
end
// Result: q1 = q2 = d (NOT a shift register!)

Non-Blocking (<=) - Executes in Parallel

always @(posedge clk) begin
    q1 <= d;     // Both read OLD values first
    q2 <= q1;    // Then both update together
end
// Result: Proper shift register!

The Rule

Logic TypeUseWhy
Combinational= (blocking)Sequential evaluation needed
Sequential<= (non-blocking)Parallel FF behavior

D Flip-Flop - The Building Block

module dff (
    input      clk,
    input      rst_n,      // Active low async reset
    input      d,
    output reg q
);
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n)
            q <= 1'b0;     // Reset value
        else
            q <= d;        // Normal operation
    end
endmodule

Note: This is what gets converted to a scan flip-flop during DFT insertion!

Common Mistakes to Avoid

1. Latch Inference (Missing Else)

// WRONG - Creates unwanted latch!
always @(*) begin
    if (sel)
        out = a;
    // Missing else! Tool infers latch to hold 'out'
end

// CORRECT - Complete assignment
always @(*) begin
    if (sel)
        out = a;
    else
        out = b;   // Or use default at beginning
end

2. Incomplete Sensitivity List

// WRONG - Simulation/synthesis mismatch
always @(a) begin      // Missing 'b'!
    out = a & b;
end

// CORRECT - Use @(*)
always @(*) begin      // Auto-includes all
    out = a & b;
end

3. Multiple Drivers

// WRONG - Two always blocks driving same signal
always @(posedge clk) q <= a;
always @(posedge clk) q <= b;  // Conflict!

// CORRECT - Single driver
always @(posedge clk) 
    q <= sel ? a : b;

Useful Constructs

Continuous Assignment

assign y = a & b;              // AND gate
assign mux_out = sel ? a : b;  // 2:1 MUX
assign {cout, sum} = a + b;    // Adder with concatenation

Reduction Operators

assign all_ones = &data;   // AND all bits (1 if all 1s)
assign any_one  = |data;   // OR all bits (1 if any 1)
assign parity   = ^data;   // XOR all bits (odd parity)

Scan Flip-Flop in Verilog

After DFT insertion, your DFF becomes:

module scan_dff (
    input      clk,
    input      rst_n,
    input      d,           // Functional data
    input      si,          // Scan input
    input      se,          // Scan enable
    output reg q
);
    wire mux_out;
    
    // Scan MUX
    assign mux_out = se ? si : d;
    
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n)
            q <= 1'b0;
        else
            q <= mux_out;
    end
endmodule
┌───────┐ D ───►│ │ │ MUX │───► FF ───► Q SI ───►│ │ └───┬───┘ │ SE

Summary

TopicKey Point
Always blocks@(*) for combo, @(posedge clk) for seq
Blocking =Use for combinational logic
Non-blocking <=Use for sequential logic
LatchesAvoid! Always have complete if-else
SensitivityUse @(*) to avoid mistakes