Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • Logic Synthesis Glossary
  • Logic Synthesis Cheatsheet
  • Synthesis Foundations14
  • Logic Optimisation and Mapping20
  • Constraints and Timing15
  • Sequential, FSM and Memory19
  • Datapath Synthesis14
  • Area, Power and Test14
  • Verification, ECO and Handoff15
  • Flows and Debugging15
  • Interview and Judgment11
    • Synthesis Interview Questions
    • Synthesis Design Scenarios
      • Timing Fails After an RTL Change
      • Area Blows Up After Enabling a Feature
      • A Latch Appears and a Hold Surprise After Scan
      • A Netlist Fails Equivalence
      • Power Too High at the Same Timing
Loading lesson

‹Synthesis Design Scenarios
  1. Topics
  2. Logic Synthesis
  3. Interview and Judgment
  4. Synthesis Design Scenarios
  5. A Latch Appears and a Hold Surprise After Scan

Part 9 · Interview and Judgment · Intermediate

A Latch Appears and a Hold Surprise After Scan

An inferred latch and a scan hold violation, each found, fixed, and priced.

On this page

    The symptoms

    The netlist contains a latch nobody drew, and a short path fails hold only after scan insertion. Both are sequential surprises found late.

    The latch shows up as storage on a combinational output. The hold failure shows up on a path that passed before the scan muxes landed.

    Surprise

    Symptom

    First suspicion

    Inferred latch

    Storage on a combinational output

    Incomplete assignment in a combinational block.

    Hold failure after scan

    Short path fails hold only in scan mode

    Scan skew and routing with arrival fixed in the EXAMPLE.

    Finding the latch

    A combinational block that leaves an output unassigned on some path must hold the old value. The tool builds a latch for that memory.

    The Yosys block below proves it on one small design. The buggy variant holds one latch cell; the fixed variant holds none.

    yosys
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    read_verilog <<EOV
    module latcher(input wire en, input wire [7:0] a, output reg [7:0] y);
      always @* begin
        if (en) y = a;
      end
    endmodule
    EOV
    hierarchy -top latcher
    proc
    select -assert-count 1 t:$dlatch
    design -reset
    read_verilog <<EOV
    module latcher(input wire en, input wire [7:0] a, output reg [7:0] y);
      always @* begin
        if (en) y = a;
        else y = 8'h00;
      end
    endmodule
    EOV
    hierarchy -top latcher
    proc
    select -assert-none t:$dlatch
    log PASS: latch present in buggy variant and absent in fixed variant

    Finding the hold violation

    Hold slack is arrival minus required, where required covers hold time plus skew plus uncertainty. Scan insertion moves both sides: the added mux delay helps hold on arrival, while skew and routing hurt it.

    The EXAMPLE fixes arrival at 0.16 ns to isolate a +0.10 ns skew growth. The calc block substitutes those parameters; the program below rechecks both slacks.

    Diagram
    EXAMPLE parameters (not real silicon): data arrival fixed at 0.16 ns, hold time 0.02 ns, uncertainty 0.04 ns
    scan changes arrival and skew both; arrival is fixed here to isolate the skew growth of 0.12 - 0.02 = +0.10 ns
    required before = 0.02 + 0.02 + 0.04 = 0.08 ns (skew 0.02 ns)
    hold slack before = 0.16 - 0.08 = +0.08 ns (passes)
    required after scan = 0.02 + 0.12 + 0.04 = 0.18 ns (skew 0.12 ns)
    hold slack after scan = 0.16 - 0.18 = -0.02 ns (fails by 0.02 ns)
    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    import sys
    
    ARR = 0.16
    HOLD = 0.02
    UNC = 0.04
    SKEW_BEFORE = 0.02
    SKEW_AFTER = 0.12
    
    def close(got, want):
        return abs(got - want) < 1e-9
    
    req_before = HOLD + SKEW_BEFORE + UNC
    slack_before = ARR - req_before
    req_after = HOLD + SKEW_AFTER + UNC
    slack_after = ARR - req_after
    
    bad = 0
    if not close(req_before, 0.08):
        bad = bad + 1
    if not close(slack_before, 0.08):
        bad = bad + 1
    if not close(req_after, 0.18):
        bad = bad + 1
    if not close(slack_after, -0.02):
        bad = bad + 1
    if bad != 0:
        print("FAIL: hold arithmetic broke on " + str(bad) + " checks")
        sys.exit(1)
    print("PASS: hold slack +0.08 ns before scan and -0.02 ns after")

    Fixes and trade-offs

    Fix the latch by assigning every output on every path, with an else branch or a default before the branch. The cost is stating the intended value explicitly.

    Fix the hold violation with delay padding on the short path or a rebalanced scan clock. Padding costs area and power on a path that was fine before scan.

    Common pitfall

    Padding every short path by hand scales badly. Fix the skew source first, then pad only the paths that still fail.

    Interview

    Likely probes: telling the two surprises apart.

    • A latch comes from incomplete assignment; the proof is one latch cell before the fix and none after.

    • A scan hold failure nets both sides at fixed arrival; the numbers are +0.08 ns before and -0.02 ns after.

    • Each fix has a price: explicit defaults for the latch, padding or clock work for hold.

    Check yourself The buggy block assigns y only when en is high. What hardware results, and what removes it?

    A latch holding y when en is low. An else branch assigning y removes it, proven by zero latch cells after the fix.

    Check yourself Arrival stays fixed at 0.16 ns and required grows from 0.08 ns to 0.18 ns. What are the hold slacks?

    Before: 0.16 minus 0.08 is +0.08 ns. After: 0.16 minus 0.18 is -0.02 ns.

    Related topics

    • Next: A netlist fails equivalence

    • Flops, resets, and enables

    • DFT and scan insertion

    Previous

    137 / 139

    Next: A Netlist Fails Equivalence

    Up next

    Up nextA Netlist Fails Equivalence

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Timing Fails After an RTL Change
    • Power Too High at the Same Timing