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

AboutRoadmapCareersInternshipsFAQContactPrivacyTerms
Skip to lesson

Course contents

  • Logic Synthesis Glossary
  • Logic Synthesis Cheatsheet
  • Synthesis Foundations14
  • Logic Optimisation and Mapping20
  • Constraints and Timing15
    • SDC for Synthesis
      • Clocks and Generated Clocks
      • Uncertainty, Latency and IO Delays
      • Driving Cells, Loads and Units
      • False, Multicycle and Max-Delay Paths
      • Missing and Over-Tight Constraints
    • Delay Models and Slack
    • Timing-Driven Synthesis
  • Sequential, FSM and Memory19
  • Datapath Synthesis14
  • Area, Power and Test14
  • Verification, ECO and Handoff15
  • Flows and Debugging15
  • Interview and Judgment11
Loading lesson

←SDC for Synthesis
  1. Topics
  2. Logic Synthesis
  3. Constraints and Timing
  4. SDC for Synthesis
  5. False, Multicycle and Max-Delay Paths
On this page

    Part 3 of 9, lesson 4 of 15Part 3 of 9/Constraints and Timing/Lesson 4 of 15Intermediate

    False, Multicycle and Max-Delay Paths

    Exceptions that change the rules: false paths, multicycle, case analysis, max delay.

    Exceptions are trusted silently, so a wrong one is worse than none: a false path on a switching path hides the bug, and a setup-only multicycle tightens hold while relaxing setup. The standard pairing, stated exactly, is the whole defence.

    After this lesson you can: pick the fitting exception per path, state the multicycle hold pairing from the standard, and explain what each wrong exception hides.

    The question

    Most paths play by one rule: launch on one edge, capture on the next. Exceptions mark the paths that play by another rule: ones that cannot switch, ones sampled late, ones live in one mode, and ones budgeted in nanoseconds. Each exception is a claim the tool trusts silently, so a wrong exception is worse than none: a false path on a real path hides its failure.

    This lesson proves the datapath structure with a recorded run, then works the exception semantics in hand-derived arithmetic, labelled so throughout. The SDC lines are illustrative, since the open tools have no SDC reader.

    One datapath, one run

    The design below is an enable-gated datapath with a quasi-static configuration input: cfg selects between two four-bit functions, captured only when the enable agrees. It pairs the classic multicycle candidate with a static strap. The script synthesises it and asserts the enable flops; the second half is the break-it preview, the enable removed, sampling every cycle.

    yosys
    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
    read_verilog <<EOV
    module gated_dp(input clk, input en, input cfg, input [3:0] a, b, c, output reg [3:0] y);
    wire [3:0] w = cfg ? ((a & b) | (c & (a ^ b))) : (a ^ b ^ c);
    always @(posedge clk) if (en) y <= w;
    endmodule
    EOV
    synth -top gated_dp
    tee -o stat_gated.txt stat
    write_json net_gated.json
    select -assert-count 4 t:$_DFFE_PP_
    check
    design -reset
    read_verilog <<EOV
    module free_dp(input clk, input cfg, input [3:0] a, b, c, output reg [3:0] y);
    wire [3:0] w = cfg ? ((a & b) | (c & (a ^ b))) : (a ^ b ^ c);
    always @(posedge clk) y <= w;
    endmodule
    EOV
    synth -top free_dp
    tee -o stat_free.txt stat
    write_json net_free.json
    select -assert-count 4 t:$_DFF_P_
    select -assert-none t:$_DFFE_PP_
    check
    log PASS: the enable lives in the flop and dropping it changes the flop

    None of the exceptions rewrites this logic: they change which edges check the same netlist. The run proves the netlist; the arithmetic moves the edges.

    What the run recorded

    Predict first The gated version captures only when the enable agrees; the free version captures every cycle. How do the two netlists differ?

    Barely. Both hold 36 cells of the same logic; the gated run keeps 4 enable flops and the free run keeps 4 plain flops. The enable lives inside the flop cell, and no exception has touched either netlist yet.

    Version (recorded)

    Cells (recorded)

    Flop type (recorded)

    Gated

    36

    4 enable flops

    Free

    36

    4 plain flops

    The gated netlist holds 36 cells with 4 enable flops, drawn below: cfg-selected bit logic into a row of enabled flops. Dropping the enable keeps the count and swaps the flop type to plain flops. Same logic, different contract: the free version is single-cycle on every edge, while the gated version may ask for more cycles.

    Recorded gated netlist: cfg-selected bit logic feeding a row of enable flops.

    False paths, on paths that truly cannot switch

    A false-path exception tells the tool to stop timing a path because it cannot switch in the real design. The headline example is the quasi-static configuration register on this page: cfg is tied off in mission mode and changes only while the clocks are stopped, so timing it would optimise a fiction. An async crossing into its synchronizer is the second honest case: cut, with its own maximum-delay bound. Scan enable is not the headline: it is timed and high-fanout in test mode, including at-speed tests.

    Diagram
    # not-run: no SDC reader in the open tools
    set_false_path -from [get_ports cfg]

    What does not belong here is a reset posed as a false path. A reset fans out to live flops and genuinely switches during operation, so cutting it tells the tool to ignore timing on paths that really toggle. A false path on a switching path does not fix timing; it hides the violation. State the reason alongside every false path: tied off, stopped clocks, or synchronized elsewhere.

    Multicycle paths, with the hold edge stated

    A multicycle exception gives a path more than one clock period because the design samples it late: the datapath above, valid every second cycle. The condition is strict: the source must hold each value for two full cycles, here the sender holding a steady, or the extra cycle is a lie. The setup part moves the capture edge N cycles later, so setup 2 at an EXAMPLE 10.0 ns period captures at 20 ns.

    Diagram
    # not-run: no SDC reader in the open tools
    set_multicycle_path -setup 2 -from [get_ports a] -to [get_ports y]
    set_multicycle_path -hold 1 -from [get_ports a] -to [get_ports y]

    The hold half is where designs silently break: unless a -hold value is also given, the hold check moves with the setup. By default the hold edge sits N-1 cycles before the new setup edge, so with setup 2 it moves a full cycle past launch. The second line pins it back: a -hold value of N-1 restores the launch-edge hold. Always state both lines.

    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
    30
    31
    32
    33
    34
    35
    36
    import sys
    
    # Multicycle edge timeline in integer picoseconds. EXAMPLE period, hand-derived.
    # Standard SDC semantics: -setup N moves the capture edge to launch + N
    # cycles. The hold edge is launch + (N - M - 1) cycles, where M is the -hold
    # value (0 when no -hold is given), so the default hold edge sits N-1 cycles
    # before the new setup edge.
    PERIOD_PS = 10000
    
    def edges(setup_mult, hold_mult=None):
        setup_edge = setup_mult * PERIOD_PS
        m = 0 if hold_mult is None else hold_mult
        hold_edge = (setup_mult - m - 1) * PERIOD_PS
        return setup_edge, hold_edge
    
    single = edges(1)
    default_pair = edges(2)
    explicit_pair = edges(2, 1)
    
    if single != (10000, 0):
        print("FAIL: single-cycle edges got " + str(single))
        sys.exit(1)
    if default_pair != (20000, 10000):
        print("FAIL: default multicycle pair got " + str(default_pair))
        sys.exit(1)
    if explicit_pair != (20000, 0):
        print("FAIL: explicit multicycle pair got " + str(explicit_pair))
        sys.exit(1)
    if default_pair[1] != default_pair[0] - PERIOD_PS:
        print("FAIL: default hold edge is not one cycle before the setup edge")
        sys.exit(1)
    if explicit_pair[1] != single[1]:
        print("FAIL: explicit hold pairing did not restore the hold edge")
        sys.exit(1)
    
    print("PASS: setup 2 moves capture to 20 ns and the hold edge follows unless held")

    The program models the three edge pairs in integer picoseconds and asserts all of them: single-cycle, setup-2 with default hold, and setup-2 with hold-1 restoring launch-edge hold. The table and figures below read those same hand-derived edges.

    Case (hand-derived)

    Setup edge (hand-derived)

    Hold edge (hand-derived)

    Single cycle

    10 ns

    launch edge

    Setup 2, default hold

    20 ns

    10 ns after launch

    Setup 2, hold 1

    20 ns

    launch edge

    Single-cycle window: one period from launch to capture.
    Multicycle window: two periods from launch to capture, twice the room.

    Case analysis and maximum delay

    Case analysis pins a pin or port to a constant value so the tool analyses only the paths live under that value, modelling a mode tie without changing the RTL. With cfg tied to zero the tool explores the fallback function only; mission-mode STA ties scan enable the same way. A maximum-delay exception bounds named paths directly in EXAMPLE nanoseconds, independent of the clock period: the same a-to-y path with a fixed 4.0 ns budget instead of two cycles.

    Diagram
    # not-run: no SDC reader in the open tools
    set_case_analysis 0 [get_ports cfg]
    set_max_delay 4.0 -from [get_ports a] -to [get_ports y]

    Both need re-checking after every RTL change. A renamed mode signal silently narrows case analysis to paths that no longer exist. A maximum delay detached from the clock drifts whenever the period changes, and nothing in the file says so. Exceptions are dated claims; re-sign them with the RTL.

    Exception

    Effect

    Risk if wrong

    False path

    Path is not timed against the clock

    A real path escapes timing entirely.

    Multicycle path

    Setup check moves out N cycles; hold follows unless held

    A one-cycle path is given time it does not have; a setup-only pair tightens hold.

    Case analysis

    Only the tied value is analysed

    Paths live under the other value are ignored.

    Maximum delay

    Path is bounded in EXAMPLE ns

    A budget detached from the clock drifts when the period changes.

    Break it: drop the enable

    The break-it is the same logic with the enable always agreeing. The flops change from enabled to plain, and every path is now single-cycle by construction, no exception needed and none allowed. Compare that with the multicycle route, which keeps the enable flops and relaxes the check instead: one way spends samples, the other spends a constraint that must be re-checked forever.

    Exceptions are claims about the design, and the tool trusts them silently. Re-check every exception against the RTL after each change: a renamed enable turns a true multicycle into a one-cycle path with a two-cycle lie on it. The netlist never reminds you; the check must be mechanical.

    When does each exception fit, and what breaks when it is wrong?

    • Weak answer: false paths remove slow logic, multicycle hold pairing varies by tool, and resets are the standard false-path example.

    • Strong answer: false paths fit paths that cannot switch, such as the tied-off cfg strap here; multicycle fits paths sampled late, with setup 2 capturing at 20 ns on a 10.0 ns clock provided the source holds each value for two cycles, and the hold edge following out unless hold 1 pins it back. A false path on a switching path hides the bug, and a reset is a switching net, never the headline.

    • Follow-up: a setup-only multicycle passes setup but fails hold after ECO. What happened? The default hold edge moved out with the setup; add the hold line.

    Check yourself A path is marked false but can switch in mission mode. What is the result?

    The tool stops timing it, so its failure is hidden, not fixed. A false path must be truly impossible: tied off, stopped clocks, or synchronized elsewhere.

    Check yourself A multicycle setup of 2 is set without the hold part. Where does the hold edge sit, and what is missing?

    One cycle before the new setup edge, a full cycle later than launch: the hold check moved with the setup. The hold line with value 1 is missing.

    • False paths fit paths that cannot switch; resets switch, so a reset is never the headline example.

    • Setup N moves the capture edge N cycles later and the hold edge moves with it unless -hold N-1 pins it back.

    • Exceptions change which edges check the netlist; they never rewrite the logic.

    Rule of thumb: state both halves of every multicycle and a reason on every false path, then re-check both after each RTL change.

    How this was checked

    Cell counts, flop types, and the netlist picture on this page come from one Yosys 0.70 run of the script shown, recorded by the course checker (scripts/tools/run-rtl-testbenches.mjs with COURSE=synth): an enable-gated datapath and its ungated variant are synthesised, with write_json netlists and flop-type assertions. Edge pairs, the hold table, and timing bars come from the stdlib-only Python program shown, which asserts every figure it prints, and are labelled hand-derived. The SDC listings are illustrative: the open tools have no SDC reader.

    • Interview: run a mock interview on this topic

    Related topics

    • Missing and Over-Tight Constraints

    • Timing-Driven Synthesis

    • See also: Timing Exceptions

    Previous

    40 / 139

    Next: Missing and Over-Tight Constraints

    Up next

    Up nextMissing and Over-Tight Constraints

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Clocks and Generated Clocks
    • Uncertainty, Latency and IO Delays