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

  • RTL Foundations36
  • Combinational Design25
  • Sequential Design27
  • FSM & Control27
  • Timing & Clocking39
  • Reset & CDC34
    • Reset Architecture
    • Metastability and Synchronisation
      • What Metastability Means in Practice
      • The Two-Flop Synchroniser
      • When to Use Three Flops
      • CDC Constraints and Implementation Hygiene
      • Do Not Synchronise Buses Bit by Bit
    • Asynchronous FIFO
    • CDC Protocols
    • Reset Domain Crossing
    • CDC Verification
  • Memory & Buses57
  • Advanced RTL28
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

‹Metastability and Synchronisation
  1. Topics
  2. RTL Design
  3. Reset & CDC
  4. Metastability and Synchronisation
  5. CDC Constraints and Implementation Hygiene

Part 6 · Reset & CDC · Intermediate

CDC Constraints and Implementation Hygiene

Tool risks to synchronisers, crossing constraints, and an implementation checklist.

On this page

    Why this matters

    Synthesis and place-and-route do not know a synchroniser is special. They can merge the flops, retime logic through them or place them far apart, and the crossing quietly loses its settling time.

    After this lesson you can: list the tool risks to a synchroniser, write the constraint a crossing needs, and review a crossing against the hygiene checklist.

    A synchroniser is only as good as its implementation

    The RTL circuit is correct on paper. Optimisation, retiming, placement, and routing can still break it.

    Unguided tools may merge the flops, retime logic through them, or place them far apart. Each of these silently destroys settling time.

    Risk

    What goes wrong

    Counter-measure

    Logic merged between the flops

    Settling time shrinks

    Keep the synchroniser in its own module; mark it do-not-touch / keep hierarchy

    Retiming moves logic across

    Same

    Exclude the synchroniser from retiming

    Flops placed far apart

    Long wire between flop 1 and 2 eats the resolution time

    Constrain placement together; use library synchroniser cells (SYNC2, or a vendor ASYNC_REG attribute)

    First flop's output used elsewhere

    Fanout of a possibly metastable signal

    Use only the second flop's output

    Timing analysed as a normal path

    Tool tries to meet setup on an inherently asynchronous input and wastes effort or reports false failures

    Constrain the crossing explicitly

    Reset on the first flop differs from the second

    Release behaviour changes

    Reset both the same way, or neither

    Constraining the crossing

    The crossing needs an explicit constraint, not an ordinary setup path.

    Diagram
    # The crossing is an asynchronous path. Do NOT leave it as an ordinary setup path, and do NOT blanket false-path it either.
    # Option 1: bound the delay of the path into the first synchroniser flop (data-only, ignore clock skew)
    set_max_delay 2.0 -datapath_only -from [get_cells src_reg*] -to [get_cells u_sync/ff1_reg*]
    
    # Option 2: ONLY when no crossing between these clocks requires a max/min-delay bound.
    # This replaces option 1; it must not be combined with it on the same clock pair.
    set_clock_groups -asynchronous -group [get_clocks clk_a] -group [get_clocks clk_b]

    Warning

    Constraint precedence is part of CDC signoff. In Vivado, clock groups override false paths and max/min delays; changing command order does not restore an overridden max delay. If this clock pair also carries a Gray pointer or held-data bus requiring a delay bound, omit the clock-group exception and use narrowly scoped exceptions for individual crossings. Other tools require the same precedence audit against their documentation.

    Diagram
    # Mixed crossings between clk_a and clk_b: no clock-group exception on this pair.
    # Bound the bus; cut only a separate, structurally checked single-bit input.
    set_max_delay 2.0 -datapath_only -from [get_cells held_data_reg*] -to [get_cells dst_data_reg*]
    set_false_path -from [get_cells status_reg] -to [get_cells u_status_sync/ff1_reg]
    # Keep synchroniser stage 1 -> stage 2 timed normally in the destination domain.
    # Signoff: report the bus paths and ignored/overridden exceptions.
    # Require an active 2.0 ns max-delay check on every bus bit, not merely an SDC line.
    The mixed-crossing example: the held-data bus keeps a 2.0 ns datapath-only bound, the single status bit is cut into its synchroniser, and no clock-group exception covers the pair

    Read each row from the source register on the left to the destination flop on the right; the label on each arrow is the constraint that path gets.

    • The bus is held stable by its protocol, but its bits must still all arrive within 2.0 ns, so it keeps a real bound.

    • The status bit enters a synchroniser, so only its first hop is cut; ff1 to ff2 stays an ordinary clk_b path.

    • A clock-group exception would cover both rows at once and silently remove the bus bound, which is why this pair uses narrow exceptions instead.

    Check yourself A 2 ns max delay is followed by asynchronous clock groups on the same clock pair. Does the bus retain its bound in Vivado?

    No. Clock groups have higher priority. Remove the broad group exception, apply selective exceptions to other crossings, and inspect the effective bus timing and overridden-exception reports.

    Warning

    A set_clock_groups -asynchronous or a false path removes timing checks only. It does not make the crossing correct. Pair every such constraint with a CDC structural check that confirms a synchroniser, handshake or FIFO is in place.

    Tip

    Wrap the synchroniser once, in a reusable module, with the flow-specific attributes inside it. Every crossing in the design then instantiates the wrapper, and the attributes, constraints and checks are all in one place.

    Hygiene checklist

    • The source of a crossing is a flop output in the source domain, directly connected.

    • The synchroniser is two (or more) flops of the destination clock with no logic between them.

    • Only the last flop feeds the destination logic.

    • The synchroniser is identified to the tools (naming, attributes, library cells).

    • A CDC tool runs on the whole design and reports every crossing and its classification.

    Check yourself A teammate adds set_false_path -from [get_clocks clk_a] -to [get_clocks clk_b] “to fix the timing report”. What is missing?

    A guarantee that every crossing between those clocks is properly synchronised. The false path silences the timing checks, but a missing synchroniser on some signal will now pass unnoticed. Run a CDC structural check and constrain specific crossings with set_max_delay where needed.

    Remember

    • A crossing needs an explicit constraint, not an ordinary setup path.

    • A false path or clock group removes timing checks. It does not make the crossing correct.

    • Wrap the synchroniser once, so its attributes, constraints and checks live in one place.

    Rule of thumb: every constraint that silences a check needs a CDC structural check beside it.

    Keep going

    • Practice: A CDC synchroniser glitch caused by clock gating

    • Practice: Design a CDC synchroniser for a memory-peripheral transfer

    • Interview: run a mock interview on this topic

    Related topics

    • Do not synchronise buses bit by bit

    Previous

    163 / 350

    Next: Do Not Synchronise Buses Bit by Bit

    Up next

    Up nextDo Not Synchronise Buses Bit by Bit

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • What Metastability Means in Practice
    • The Two-Flop Synchroniser