To understand how the constraints are added, it is important to understand the logic structure around the clock and data in AXI Quad SPI flash memory.
The following figure gives an idea of the logic structure:
The STARTUP primitive adds delay on the USRCCLKO to the CCLK pin. This delay is unaccounted for in the tool and is not considered in the timing calculation. For the tool, the timing path ends at USRCCLKO.
To obtain the required constraints you must account for the STARTUP primitive delay. As the timing path ends at USRCCLKO, you cannot create a clock on the CCLK pin.
To emulate the SCK clock, you must create a generated clock such that the STARTUP primitive delay is taken into account. This can be achieved by creating a generated clock on the USRCCLKO pin.
This takes into account the delay of the
flip-flop that generates the SCK, the routing delay from that flip-flop to USRCCLKO pin, and
the STARTUP primitive delay. Further, to reduce the delay on SCK you must ensure that the
delay from the flip-flop to USRCCLKO is as low as possible. This can be constrained by using
set_max_delay.
The datapaths can then be constrained using
set_output_delay and set_input_delay along with set_multicyle_path constraints. All the following
constraints are provided for SCK_ratio = 2.
- STARTUPE3 (UltraScale) primitive included
inside
IP:
# You must provide all the delay numbers # CCLK delay is 0.1, 6.7 ns min/max for ultra-scale devices; refer Data sheet # Consider the max delay for worst case analysis set cclk_delay 6.7 create_generated_clock -name clk_sck -source [get_pins -filter {REF_PIN_NAME==ext_spi_clk} -of [get_cells -hier -filter {x_core_info=~axi_quad_spi,*}]] -edges {3 5 7} -edge_shift [list $cclk_delay $cclk_delay $cclk_delay] [get_pins -hierarchical *USRCCLKO] set_multicycle_path -setup -from clk_sck -to [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] 2 set_multicycle_path -hold -end -from clk_sck -to [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] 1 set_multicycle_path -setup -start -from [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] -to clk_sck 2 set_multicycle_path -hold -from [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] -to clk_sck 1 set_max_delay -datapath_only -from [get_pins -hier {*STARTUP*_inst/DI[*]}] 1.000 set_max_delay -datapath_only -from [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] -to [get_pins -hier *STARTUP*_inst/USRCCLKO] 1.000 set_max_delay -datapath_only -from [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] -to [get_pins -hier *STARTUP*_inst/DO[*]] 1.000 set_max_delay -datapath_only -from [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] -to [get_pins -hier *STARTUP*_inst/DTS[*]] 1.000 - STARTUPE3 (UltraScale+) primitive included inside IP: Vivado times the STARTUPE3 differently for UltraScale+ devices. For the purpose of timing the
STARTUPE3, certain internal pins were modeled which can be used to time the primitive. Below lines
show the set of constraints that can be used with UltraScale+ devices.
set tdata_trace_delay_max 0.25 set tdata_trace_delay_min 0.25 set tclk_trace_delay_max 0.2 set tclk_trace_delay_min 0.2 create_generated_clock -name clk_sck -source [get_pins -filter {REF_PIN_NAME==ext_spi_clk} -of [get_cells -hier -filter {x_core_info=~axi_quad_spi,*}]] [get_pins -hierarchical */CCLK] -edges {3 5 7} set_input_delay -clock clk_sck -max [expr $tco_max + $tdata_trace_delay_max + $tclk_trace_delay_max] [get_pins -hierarchical *STARTUP*/DATA_IN[*]] -clock_fall; set_input_delay -clock clk_sck -min [expr $tco_min + $tdata_trace_delay_min + $tclk_trace_delay_min] [get_pins -hierarchical *STARTUP*/DATA_IN[*]] -clock_fall; set_multicycle_path 2 -setup -from clk_sck -to [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] set_multicycle_path 1 -hold -end -from clk_sck -to [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] set_output_delay -clock clk_sck -max [expr $tsu + $tdata_trace_delay_max - $tclk_trace_delay_min] [get_pins -hierarchical *STARTUP*/DATA_OUT[*]]; set_output_delay -clock clk_sck -min [expr $tdata_trace_delay_min -$th - $tclk_trace_delay_max] [get_pins -hierarchical *STARTUP*/DATA_OUT[*]]; set_multicycle_path 2 -setup -start -from [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] -to clk_sck set_multicycle_path 1 -hold -from [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] -to clk_sck set_max_delay -datapath_only -from [get_pins -hier {*STARTUP*_inst/DI[*]}] 1.000 set_max_delay -datapath_only -from [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] -to [get_pins -hier *STARTUP*_inst/USRCCLKO] 1.000 set_max_delay -datapath_only -from [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] -to [get_pins -hier *STARTUP*_inst/DO[*]] 1.000 set_max_delay -datapath_only -from [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] -to [get_pins -hier *STARTUP*_inst/DTS[*]] 1.000Note: [1] Multi Cycle Path constraints can be removed or updated on getting any timing violations.Note: [2] Regarding set_max_delay constraints, recent Vivado tool (From 2020.1 onwards) flow takes care of adding set_max_delay constraints for UltraScale/UltraScale+. In this case, do not add explicit constraints mentioned above and make sure to comment theset_max/min_delayconstraints. - STARTUPE2 Enabled:
Use the set of constraints for STARTUPE2.
# You must provide all the delay numbers # CCLK delay is 0.5, 6.7 ns min/max for K7-2; refer Data sheet # Consider the max delay for worst case analysis set cclk_delay 6.7 #Following are the SPI device parameters according to the data sheet # Maximum Clock-to-output delay set tco_max 7 # Minimum Clock-to-output delay set tco_min 1 # Data in Setup time requirement set tsu 2 # Data in Hold time requirement set th 3 # Following are the board/trace delay numbers # Assumption is that all Data lines are matched set tdata_trace_delay_max 0.25 set tdata_trace_delay_min 0.25 set tclk_trace_delay_max 0.2 set tclk_trace_delay_min 0.2 ### End of user provided delay numbers # this is to ensure min routing delay from SCK generation to STARTUP input # User should change this value based on the results # having more delay on this net reduces the Fmax set_max_delay 1.5 -from [get_pins -hier *SCK_O_reg_reg/C] -to [get_pins -hier *USRCCLKO] -datapath_only set_min_delay 0.1 -from [get_pins -hier *SCK_O_reg_reg/C] -to [get_pins -hier *USRCCLKO] # Following command creates a divide by 2 clock # It also takes into account the delay added by STARTUP block to route the CCLK create_generated_clock -name clk_sck -source [get_pins -filter {REF_PIN_NAME==ext_spi_clk} -of [get_cells -hier -filter {x_core_info=~axi_quad_spi,*}]] [get_pins -hierarchical *USRCCLKO] -edges {3 5 7} -edge_shift [list $cclk_delay $cclk_delay $cclk_delay] # Data is captured into FPGA on the second rising edge of ext_spi_clk after the SCK falling edge # Data is driven by the FPGA on every alternate rising_edge of ext_spi_clk set_input_delay -clock clk_sck -max [expr $tco_max + $tdata_trace_delay_max + $tclk_trace_delay_max] [get_ports IO*_IO] -clock_fall; set_input_delay -clock clk_sck -min [expr $tco_min + $tdata_trace_delay_min + $tclk_trace_delay_min] [get_ports IO*_IO] -clock_fall; set_multicycle_path 2 -setup -from clk_sck -to [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] set_multicycle_path 1 -hold -end -from clk_sck -to [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] # Data is captured into SPI on the following rising edge of SCK # Data is driven by the IP on alternate rising_edge of the ext_spi_clk set_output_delay -clock clk_sck -max [expr $tsu + $tdata_trace_delay_max - $tclk_trace_delay_min] [get_ports IO*_IO]; set_output_delay -clock clk_sck -min [expr $tdata_trace_delay_min -$th - $tclk_trace_delay_max] [get_ports IO*_IO]; set_multicycle_path 2 -setup -start -from [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] -to clk_sck set_multicycle_path 1 -hold -from [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] -to clk_sckSTARTUP is Disabled:#Following are the SPI device parameters according to the data sheet # Maximum Clock-to-output delay set tco_max 7 # Minimum Clock-to-output delay set tco_min 1 # Data in Setup time requirement set tsu 2 # Data in Hold time requirement set th 3 # Following are the board/trace delay numbers # Assumption is that all Data lines are matched set tdata_trace_delay_max 0.25 set tdata_trace_delay_min 0.25 set tclk_trace_delay_max 0.2 set tclk_trace_delay_min 0.2 ### End of user provided delay numbers create_generated_clock -name clk_sck -source [get_pins -filter {REF_PIN_NAME==ext_spi_clk} -of [get_cells -hier -filter {x_core_info=~axi_quad_spi,*}]] [get_ports <SCK_IO>] -edges {3 5 7} # Data is captured into FPGA on the second rising edge of ext_spi_clk after the SCK falling edge # Data is driven by the FPGA on every alternate rising_edge of ext_spi_clk set_input_delay -clock clk_sck -max [expr $tco_max + $tdata_trace_delay_max + $tclk_trace_delay_max] [get_ports IO*_IO] -clock_fall; set_input_delay -clock clk_sck -min [expr $tco_min + $tdata_trace_delay_min + $tclk_trace_delay_min] [get_ports IO*_IO] -clock_fall; set_multicycle_path 2 -setup -from clk_sck -to [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] set_multicycle_path 1 -hold -end -from clk_sck -to [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] # Data is captured into SPI on the following rising edge of SCK # Data is driven by the IP on alternate rising_edge of the ext_spi_clk set_output_delay -clock clk_sck -max [expr $tsu + $tdata_trace_delay_max - $tclk_trace_delay_min] [get_ports IO*_IO]; set_output_delay -clock clk_sck -min [expr $tdata_trace_delay_min -$th - $tclk_trace_delay_max] [get_ports IO*_IO]; #tCSS - chip select setup time requirement set tCSS 2 #tCSH - chip select hold time requirement set tCSH 3 #SS Setup: Must be asserted before first clock edge set_output_delay -clock clk_sck -max [expr $tCSS + $tdata_trace_delay_max - $tclk_trace_delay_min] [get_ports ss_*] #SS Hold: Must remain asserted after last clock edge set_output_delay -clock clk_sck -min [expr $tdata_trace_delay_min - $tCSH - $tclk_trace_delay_max] [get_ports ss_*] set_multicycle_path 2 -setup -start -from [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] -to clk_sck set_multicycle_path 1 -hold -from [get_clocks -of_objects [get_pins -hierarchical */ext_spi_clk]] -to clk_sck