Authoring SDC Constraints
Timing Verification and STA already covered SDC from the checking side — "written once, as an SDC file, and used by both synthesis and STA... the same file, not two independently-maintained descriptions." This page is that other side: what actually goes into an SDC file, and how a synthesis tool reads it.
The three basic requirements
A design's SDC file needs, at minimum, its clocks and its I/O timing relationships defined — without them, a synthesis tool has no concept of "fast enough" at all.
create_clock -period 3 -name clk [get_ports clk]
set_input_delay -clock clk -max 0.5 [get_ports {in1 in2 in3}]
set_output_delay -clock clk -max 0.8 [get_ports {out1 out2}]
create_clockdeclares a clock:-period(in nanoseconds), an optional-waveformfor a non-50%-duty-cycle clock, and the actual port or pin the clock originates from. A virtual clock — declared with-namebut no real netlist source — exists specifically to constrain I/O against a clock that's genuinely external to this block, with nothing in this netlist to pointcreate_clockat directly.set_input_delaytells the tool how much delay already exists before a signal reaches this input port, relative to the named clock edge — modeling whatever external logic drives that port, which this synthesis run has no visibility into otherwise.set_output_delaytells the tool how much delay budget is available after this output port, before the signal has to be valid at whatever it's driving next.
What these constraints actually describe, visually
clk runs at its declared 3ns period. in1 arrives -max 0.5ns after the previous clock edge — modeling delay from external logic this run can't see. out1 must be valid -max 0.8ns before the next clock edge — the budget for whatever reads it next.
-max/-min (not shown above) distinguish the longest-path and shortest-path cases — a real design usually needs both, since a signal arriving too early can violate a hold requirement exactly as a signal arriving too late violates setup, the same asymmetry Timing Verification and STA already covered.
Clocks derived from other clocks: create_generated_clock
Not every clock in a design originates from a real input port — a divide-by-2 counter output, or a PLL's divided-down feedback tap, is itself a clock that other logic is timed against, but it's derived from an already-declared clock rather than being an independent source. create_generated_clock declares exactly this: a clock defined relative to a -source (the master clock it's derived from) and a -divide_by (or -multiply_by) factor, so the tool can correctly relate the generated clock's period and phase back to the master clock it actually comes from, instead of treating it as yet another unrelated, independently-declared clock.
Why authoring this correctly matters more than it might look
An SDC file with a missing clock, or an input/output delay left at its default, doesn't cause a visible error — synthesis still runs, and still produces a netlist. What it produces instead is a netlist optimized against the wrong target: paths the tool believed were unconstrained get no optimization effort at all, while genuinely critical paths might not stand out as critical if their real timing budget was never actually declared. A clean synthesis run with an incomplete SDC file is a specific, real failure mode — not a syntax error, a silently wrong optimization target.
What's next
With real constraints in place, the next page covers what a synthesis tool actually does with them — how a tighter clock period or a smaller input delay concretely reshapes the optimization decisions made throughout the flow, not just what gets reported at the end.