Understanding Clock Constrains
A complete overview starting with the basic timing constraints and building it up to the more advanced categories.
Field-Programmable Gate Arrays (FPGAs) offer an unparalleled blend of hardware flexibility and reconfigurability, empowering the creation of sophisticated digital systems. However, merely translating HDL (Hardware Description Language) into a netlist is insufficient for a successful FPGA implementation. To achieve desired performance, ensure reliable operation, and enable effective utilization of the underlying silicon, precise guidance to the synthesis and place-and-route tools is indispensable. This guidance comes in the form of design constraints.
Design constraints are not merely suggestions; they are directives that define the operational environment and performance targets for your digital design within the FPGA fabric.
Omitting or incorrectly applying them is a primary source of timing violations, suboptimal resource utilization, and ultimately, non-functional hardware. While advanced FPGA designs necessitate intricate and highly specific constraints, a core set of fundamental constraints forms the bedrock for any functional and performant FPGA project.
Let's delve into the basic of clock constraints for FPGA design. Most of this information is generic and applies to generic synthesis tools as well.
Basic Clock Constraints
The first step in constraining your FPGA design is defining the primary clocks that drive your logic. These are typically the clocks that enter your FPGA from external pins.
Clock Definition (create_clock
):
- Purpose: To define a clock, specifying its period (and thus frequency), a unique name, and the physical pin or port where it enters the FPGA. This is the fundamental timing reference for all synchronous logic driven by this clock.
- Syntax:
create_clock -period <value> -name <clock_name> <objects>
-period <value>
: Clock period in nanoseconds (e.g.,10.000
for 100 MHz).-name <clock_name>
: A unique name for the clock.<objects>
: The specific input port(s) that carry this clock (e.g.,[get_ports sys_clk_p]
).
Examples:
Single Primary Clock (100 MHz)
# Define a 100 MHz clock (10 ns period) on the 'sys_clk_p' port.
create_clock -period 10.000 -name sys_clk [get_ports sys_clk_p]
Multiple Primary Clocks (from different oscillators)
# Define a 125 MHz clock (8 ns period) on 'eth_clk_p'
create_clock -period 8.000 -name eth_clk [get_ports eth_clk_p]
# Define a 50 MHz clock (20 ns period) on 'usb_clk_p'
create_clock -period 20.000 -name usb_clk [get_ports usb_clk_p]
In this scenario, sys_clk
, eth_clk
, and usb_clk
are independent primary clocks.
Non-Primary Clocks
Many FPGA designs include internal clock generation, often using specialized hard IP like Phase-Locked Loops (PLLs) or Mixed-Mode Clock Managers (MMCMs), or even simple logic like dividers.
Generated Clocks (create_generated_clock
):
- Purpose: To inform the timing analysis tools about clocks that are derived from an existing, already defined primary clock. This ensures the tools understand the phase and frequency relationship between the master clock and the derived clock, allowing for accurate timing analysis across these domains.
- When to Use It: For outputs of PLLs, MMCMs, or any clock produced by logic that modifies a primary clock's frequency or phase.
- Syntax:
create_generated_clock -name <generated_clock_name> -source <master_clock_pin> [options] <objects>
-source <master_clock_pin>
: The pin or port of the master clock from which this clock is generated (e.g.,[get_ports sys_clk_p]
or[get_pins my_pll_inst/CLKIN]
).-name <generated_clock_name>
: A unique name for the generated clock.[options]
: Can include-divide_by <factor>
,-multiply_by <factor>
,-invert
, etc., to describe the clock's relationship to its source.<objects>
: The pin or port where the generated clock appears (e.g.,[get_pins clk_wiz_0_i/inst/mmcm_adv_inst/CLKOUT0]
).
Example:
# Assuming clk_wiz_0 is an IP core for a clock wizard (PLL/MMCM)
# sys_clk (primary clock) is defined earlier
create_generated_clock -name clk_200mhz_int -source [get_ports sys_clk_p] \
[get_pins clk_wiz_0_i/inst/mmcm_adv_inst/CLKOUT0]
# Clock 'div_clk' generated by a simple flip-flop divider, half the frequency of its source
create_generated_clock -name div_clk -source [get_pins my_divider_reg/Q] \
-divide_by 2 [get_pins my_divider_reg/Q]
Input, Output Delays, Timing Exceptions and Clock Groups
In this section we will look into some of the more advanced concepts related to timing constraints in FPGA design.