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. Clocks and Generated Clocks
On this page

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

    Clocks and Generated Clocks

    Master and generated clocks as EXAMPLE periods, and what each tells the tool.

    A generated clock with the wrong source or the wrong pin names a clock that does not exist, and it may only warn: check_timing reports unexpandable or unreachable generated clocks. One divider, one correct pair of lines, and the distinction stops being abstract.

    After this lesson you can: write a correct create_clock and create_generated_clock pair, explain ideal against propagated clocks, and say why a clock net is never the buffering example.

    The question

    Every timing path is measured against a clock, so the first constraint names the clocks and states each EXAMPLE period. Without one the tool has no target for those paths, as the missing-constraints lesson shows. With one, the period becomes the budget, and everything else in this topic refines it: margins, IO shares, and named exceptions.

    Synthesis treats the clocks it is given as ideal: every flop clock pin switches at the same instant, with no skew and no insertion delay. Real skew is handled later, by the clock tree in layout and propagated-clock analysis in signoff.

    One divider, one run

    The design below is a divide-by-2 register: a flop whose output feeds back inverted, toggling on every master rising edge. The script synthesises it and asserts the one sequential cell with reset; the second half is the break-it preview, the feedback tied to a constant, which should leave no sequential cell. Both halves write their netlist, so every count below is read back from those files.

    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 div2(input clk, input rst, output reg q);
    always @(posedge clk) begin
      if (rst) q <= 1'b0;
      else q <= ~q;
    end
    endmodule
    EOV
    synth -top div2
    tee -o stat_toggle.txt stat
    write_json net_toggle.json
    select -assert-count 1 t:$_DFF_P_ t:$_SDFF_PP0_ %u
    check
    design -reset
    read_verilog <<EOV
    module div2stuck(input clk, output reg q);
    always @(posedge clk) q <= 1'b0;
    endmodule
    EOV
    synth -top div2stuck
    tee -o stat_stuck.txt stat
    write_json net_stuck.json
    select -assert-none t:$_DFF_P_ t:$_SDFF_PP0_
    check
    log PASS: a divider needs its inverted feedback and a stuck driver loses the flop

    The period comes from the SDC clock and the toggle from this RTL: Yosys proves the structure, the SDC names it. The netlist picture is a recording; the clock text is illustrative, because the open tools have no SDC reader.

    What the run recorded

    Predict first The toggle version feeds its output back inverted; the stuck version drives a constant into the flop. Which one keeps a sequential cell?

    The toggle version: 2 cells, 1 flop. The stuck version optimises to 0 cells and no flop: a flop that always loads a constant is wiring, not state.

    Version (recorded)

    Cells (recorded)

    Flops (recorded)

    Toggle

    2

    1 flop

    Stuck at constant

    0

    no flop

    The toggle netlist holds 2 cells: one inverter for the feedback and one resettable flop for the state, drawn below. The stuck netlist holds 0 cells with no flop: constant in, constant out, so the tool deleted the state and the divider with it.

    Recorded divider: 2 cells, the inverter feeding the flop back.

    The SDC that says the same thing

    The constraint below names both clocks for the same divider. The master line states a name and an EXAMPLE period on the clock port. The generated line carries three fields: -source takes the master source pin or port, never the clock name; the created object is the divider flop's Q pin; -divide_by 2 with -name states the relationship.

    Diagram
    # not-run: no SDC reader in the open tools
    create_clock -name CLK -period 10.0 [get_ports clk]
    create_generated_clock -name DIV2 -source [get_ports clk] -divide_by 2 [get_pins div_reg/Q]

    Two clock models share this text. The ideal model, which synthesis uses, treats both clocks as perfect: zero skew, zero latency. The propagated model, which signoff uses, traces each edge through the real clock network, so skew and insertion delay appear. The synthesis numbers in this topic are all ideal-clock numbers; the next lesson prices what the ideal model leaves out as uncertainty and latency.

    Periods and frequencies

    Frequency is one divided by the period. The EXAMPLE parameters below are a 10.0 ns master, 100 MHz, and its divide-by-2 child. The program checks both frequencies, both periods, the six-edge toggle trace, and the divided rising edges on every second master edge: five self-checks, so the doubling is proven, not quoted.

    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
    
    # Divide-by-2 clock arithmetic: EXAMPLE parameters, hand-derived.
    PERIOD_NS = 10.0
    DIVIDE_BY = 2
    
    freq_mhz = 1000.0 / PERIOD_NS
    div_period_ns = PERIOD_NS * DIVIDE_BY
    div_freq_mhz = 1000.0 / div_period_ns
    
    # Toggle model: q starts at reset 0, then inverts on every master rising edge.
    q = 0
    trace = []
    for _ in range(6):
        q = 1 - q
        trace.append(q)
    
    if freq_mhz != 100.0:
        print("FAIL: master frequency got " + str(freq_mhz) + " want 100.0")
        sys.exit(1)
    if div_period_ns != 20.0:
        print("FAIL: divided period got " + str(div_period_ns) + " want 20.0")
        sys.exit(1)
    if div_freq_mhz != 50.0:
        print("FAIL: divided frequency got " + str(div_freq_mhz) + " want 50.0")
        sys.exit(1)
    if trace != [1, 0, 1, 0, 1, 0]:
        print("FAIL: toggle trace got " + str(trace))
        sys.exit(1)
    # Rising edges of the divided clock land on every second master edge.
    rising = [i for i in range(1, len(trace)) if trace[i - 1] == 0 and trace[i] == 1]
    if rising != [2, 4]:
        print("FAIL: divided rising edges got " + str(rising) + " want [2, 4]")
        sys.exit(1)
    
    print("PASS: divide-by-2 stretches 10.0 ns to 20.0 ns and 100 MHz to 50 MHz")

    The trace is the divider working: from reset the output alternates on every master edge, and the divided rising edges sit two master periods apart. That spacing is the divided period of 20.0 ns, which is 50 MHz.

    Doubling: two master periods end to end meet the divided requirement exactly.

    A clock net is not a fanout example

    A divider output can feed thousands of flops, which tempts the textbook into using it as the buffering example. Resist that: under the ideal clock model the tool assumes zero skew however many pins the net reaches, so it never buffers the net. Real clock networks are buffered in clock-tree synthesis during layout, long after logic synthesis; the buffering lessons draw their fanout examples from data nets instead.

    Break it: tie the feedback to a constant

    The second run in the script is the break-it: the same clock, the same output port, but the flop input tied to a constant. The cell count moves from 2 to 0 and the flop count from 1 flop to no flop at all. Without toggling it is not a slow divider; it is no divider, and the tool says so by deleting the state.

    Two slips share one root cause: confusing the clock with its pins. Giving -source a clock name instead of the source pin or port constrains nothing real, and pointing the generated clock at the wrong pin names a clock that does not exist. Tools usually warn rather than fail: check_timing reports unexpandable or unreachable generated clocks, so it may only warn, and reading check_timing after every clock edit is the defence. State the source pin, the new pin, and the ratio every time.

    What does create_clock state, and what does the generated line add?

    • Weak answer: the clock name, and the generated clock just renames it for the new domain.

    • Strong answer: create_clock states a name and an EXAMPLE period, here 10.0 ns for 100 MHz. The generated line adds the source pin with -source, the new pin, and the ratio: divide-by-2 stretches the period to 20.0 ns at 50 MHz, proven by the toggle trace.

    • Follow-up: where does real skew go? Into the uncertainty margin for synthesis and the propagated clock network in layout and signoff.

    Check yourself A master clock has an EXAMPLE period of 10.0 ns. What are its frequency and its divide-by-2 period and frequency?

    100 MHz for the master. The divided clock doubles the period to 20.0 ns and halves the frequency to 50 MHz.

    Check yourself The toggle netlist keeps a flop and the stuck one keeps none. What does the difference prove?

    The toggle netlist holds 2 cells with 1 flop: feedback plus state, a real divider. The stuck version has no flop because constant in means constant out. Toggling is the divider.

    • -source takes the master source pin or port; the created object is the divider register output pin with -divide_by and -name.

    • Synthesis assumes ideal clocks; skew and insertion delay belong to layout and signoff, with uncertainty as the synthesis stand-in.

    • A flop without toggling is wiring: the stuck variant loses its sequential cell.

    Rule of thumb: state the source pin, the new pin, and the ratio on every generated clock, then check the toggle exists.

    How this was checked

    Cell and flop counts 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): a divide-by-2 register and a constant-driven variant are synthesised, with write_json netlists and flop-count assertions. Period, frequency, and toggle-trace figures come from the stdlib-only Python program shown, which asserts every figure it prints, and are labelled hand-derived. The SDC listing is illustrative: the open tools have no SDC reader.

    • Interview: run a mock interview on this topic

    Related topics

    • Uncertainty, Latency and IO Delays

    • Delay Models and Slack

    • See also: STA Foundations

    Previous

    37 / 139

    Next: Uncertainty, Latency and IO Delays

    Up next

    Up nextUncertainty, Latency and IO Delays

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Driving Cells, Loads and Units
    • False, Multicycle and Max-Delay Paths
    • Missing and Over-Tight Constraints