name: sdc-writer description: > Generate a complete, correct, and well-commented SDC (Synopsys Design Constraints) file from a natural language description of timing requirements. Covers clock definitions, generated clocks, I/O delays, clock groups, false paths, multi-cycle paths, clock uncertainty, input/output transition constraints, and operating conditions. Every constraint includes explanatory comments. category: timing-constraints level: intermediate
Purpose
Transform a timing specification into a complete SDC file that can be directly fed to synthesis (Design Compiler / Genus) and place & route (Innovus / ICC2). The SDC must be syntactically correct, logically complete, and include explanatory comments for every constraint section.
Input Specification
The user provides:
Required
- Primary clock(s): Name, port, period, duty cycle (default 50%)
- Or a text description: "I have a 100MHz system clock on port sys_clk, a 50MHz SPI clock, and a divided-by-2 clock from the system clock"
Optional
- Generated clock definitions (source, divide ratio)
- I/O delay budgets (or target technology and external chip specs)
- Clock groups (physically exclusive, logically exclusive, asynchronous)
- False path specifications
- Multi-cycle path specifications
- Clock uncertainty budget
- Input transition / output load constraints
- Operating conditions (PVT corner)
- Wire load model
- Max fanout / max transition / max capacitance limits
Core Design Rules
Rule 1: Clock Definition Order Matters
Define clocks in dependency order:
- Primary clocks (from ports/PLLs)
- Generated clocks (derived from primary)
- Virtual clocks (for I/O constraint reference)
Rule 2: Every Primary Input/Output Needs a Delay
For chip-level SDC, every input port needs set_input_delay and every output
port needs set_output_delay. If not specified, add conservative defaults:
# Default conservative I/O constraints (60% of clock period)
set_input_delay -clock [get_clocks clk] -max [expr {$period * 0.6}] [all_inputs]
set_output_delay -clock [get_clocks clk] -max [expr {$period * 0.6}] [all_outputs]Rule 3: Clock Groups Prevent False Paths
Any two clocks that are not synchronized must be declared as asynchronous or physically exclusive. Failure to do so causes tools to analyze all cross-clock paths — wasting runtime and potentially masking real violations.
# Async clocks: independent, no phase relationship
set_clock_groups -asynchronous \
-group [get_clocks clk_sys] \
-group [get_clocks clk_spi]
# Physically exclusive: only one active at a time (muxed clocks)
set_clock_groups -physically_exclusive \
-group [get_clocks clk_100m] \
-group [get_clocks clk_50m]Rule 4: No Path Should Be Unconstrained
After writing SDC, run check_timing in the target tool. Any unconstrained
endpoints (inputs without input delay, outputs without output delay) are
blind spots in timing analysis.
Rule 5: Use Meaningful Constraint Names
# BAD
set_clock_uncertainty 0.1 [get_clocks clk]
# GOOD — what kind of uncertainty? Why?
set_clock_uncertainty -setup 0.1 -hold 0.05 \
[get_clocks clk] \
-comment "PLL jitter: 50ps RMS, clock tree skew budget: 50ps"Output Specification
The generated SDC file must follow this structure:
# =============================================================================
# SDC Constraints File
# Design: [design_name]
# Generated by: ICHDL Agent (sdc-writer)
# Date: [date]
# =============================================================================
# ---- Operating Conditions ----
set_operating_conditions [condition_name]
set_wire_load_model -name [model_name]
# ---- Clock Definitions ----
# Primary clock: [name], period [value]ns, duty [value]%
create_clock -name [name] -period [value] -waveform [wave] [port]
# Generated clock: [name], derived from [source], divide by [N]
create_generated_clock -name [name] -source [source] -divide_by [N] [pin]
# ---- Clock Uncertainty ----
set_clock_uncertainty -setup [value] [clocks]
set_clock_uncertainty -hold [value] [clocks]
# ---- I/O Delays ----
# Input delays
set_input_delay -clock [clock] -max [value] [ports]
set_input_delay -clock [clock] -min [value] [ports]
# Output delays
set_output_delay -clock [clock] -max [value] [ports]
set_output_delay -clock [clock] -min [value] [ports]
# ---- Clock Groups ----
set_clock_groups -asynchronous -group [clk1] -group [clk2]
# ---- Timing Exceptions ----
# False paths
set_false_path -from [from] -to [to]
# Multi-cycle paths
set_multicycle_path [N] -from [from] -to [to]
# ---- Design Rules ----
set_max_fanout [value] [current_design]
set_max_transition [value] [current_design]
# ---- End of SDC ----Examples
Example 1: Simple Single-Clock Design
Input: "100MHz clock on port clk, 60% I/O budget, max fanout 32."
create_clock -name clk -period 10.0 -waveform {0 5} [get_ports clk]
set_clock_uncertainty -setup 0.1 [get_clocks clk]
set_clock_uncertainty -hold 0.05 [get_clocks clk]
set_input_delay -clock clk -max 6.0 [all_inputs]
set_input_delay -clock clk -min 1.0 [all_inputs]
set_output_delay -clock clk -max 6.0 [all_outputs]
set_output_delay -clock clk -min 1.0 [all_outputs]
set_max_fanout 32 [current_design]
set_max_transition 0.5 [current_design]Example 2: Multi-Clock SoC
Input: "200MHz system clock, 50MHz peripheral clock (async to system), 20MHz external memory clock, divided-by-2 clock from system clock."
# Primary clocks
create_clock -name clk_sys -period 5.0 -waveform {0 2.5} [get_ports clk_sys]
create_clock -name clk_peri -period 20.0 -waveform {0 10.0} [get_ports clk_peri]
create_clock -name clk_mem -period 50.0 -waveform {0 25.0} [get_ports clk_mem]
# Generated clock
create_generated_clock -name clk_sys_div2 -source [get_ports clk_sys] \
-divide_by 2 [get_pins clk_div_reg/Q]
# Clock groups — all are independent
set_clock_groups -asynchronous \
-group [get_clocks clk_sys clk_sys_div2] \
-group [get_clocks clk_peri] \
-group [get_clocks clk_mem]
# I/O constraints per clock domain
set_input_delay -clock clk_sys -max 3.0 [get_ports sys_*]
set_output_delay -clock clk_sys -max 3.0 [get_ports sys_*]
set_input_delay -clock clk_peri -max 12.0 [get_ports peri_*]
set_output_delay -clock clk_peri -max 12.0 [get_ports peri_*]
set_input_delay -clock clk_mem -max 30.0 [get_ports mem_*]
set_output_delay -clock clk_mem -max 30.0 [get_ports mem_*]Interaction with Other Skills
verilog-module: The module this SDC constrainscdc-synchronizer: Cross-clock paths that need false_path or max_delayrtl-reviewer: Verify SDC-to-design consistency
Disclaimer
This skill is provided "as is" for reference and educational purposes only. Code generated using this skill should be independently reviewed and verified before use in any production design, tape-out, or safety-critical application. The author(s) and ICHDL assume no liability for any errors, omissions, or damages arising from the use of this skill or any code generated with it.
Usage Rights
You are free to use, modify, and distribute this skill for personal or commercial purposes. Attribution to ICHDL (ichdl.com) is appreciated but not required. Redistribution of this skill in substantially unmodified form must retain this notice.