Forum Discussion

designEngineer's avatar
designEngineer
Icon for Occasional Contributor rankOccasional Contributor
6 years ago

Cyclone 10 GX DDR interface timing / constraint issue

I am trying to meet timing on a source synchronous edge aligned DDR interface with a Cyclone 10 GX. The interface fails timing but I think the setup relationship from the DDIO output to the first regular register may be wrong in the timing analyzer (using a half clock cycle when it has a full clock cycle).

Quick description of the interface (also see attached diagram interface_diagram.jpg):

-------------------------------------------------------------------------------------

- 8 bit wide LVDS data input "DI"

- LVDS clock input DCLK running at 338 MHz

- data changes on both rising and falling edge of the clock (DDR)

- data is edge aligned to the clock input

- there are 3 more data inputs (DID, DQ and DQD which are not drawn in the diagram, they all use the same clocking and are just a replica of DI)

The input clock goes to a PLL which is outputting a clock with the same frequency (338 MHz) and no phase shift, this PLL output clock is then used to drive the DDIO instantiation as well as the first register after the DDIO.

I am wondering if my input constraints / exceptions are wrong. I came up with them based on the AN433 and they are as follows:

Constraints:

------------

derive_pll_clocks -create_base_clocks

derive_clock_uncertainty

create_clock -name dclk_ext_virt -period 2.958

# from AN433 Example 41 and 43

set_input_delay -max .05 -clock [get_clocks dclk_ext_virt] [get_ports {DI[*] DID[*] DQ[*] DQD[*]}]

set_input_delay -max .05 -clock [get_clocks dclk_ext_virt] -clock_fall [get_ports {DI[*] DID[*] DQ[*] DQD[*]}] -add_delay

set_input_delay -min .05 -clock [get_clocks dclk_ext_virt] [get_ports {DI[*] DID[*] DQ[*] DQD[*]}] -add_delay

set_input_delay -min .05 -clock [get_clocks dclk_ext_virt] -clock_fall [get_ports {DI[*] DID[*] DQ[*] DQD[*]}] -add_delay

# from AN433 Example 50

set_multicycle_path -setup -end -rise_from [get_clocks dclk_ext_virt] -rise_to [get_clocks i_adc|i_adc_pll_c10|iopll_0|outclk338] 0

set_multicycle_path -setup -end -fall_from [get_clocks dclk_ext_virt] -fall_to [get_clocks i_adc|i_adc_pll_c10|iopll_0|outclk338] 0

# from AN433 Example 51

set_false_path -setup -fall_from [get_clocks dclk_ext_virt] -rise_to [get_clocks i_adc|i_adc_pll_c10|iopll_0|outclk338]

set_false_path -setup -rise_from [get_clocks dclk_ext_virt] -fall_to [get_clocks i_adc|i_adc_pll_c10|iopll_0|outclk338]

set_false_path -hold -rise_from [get_clocks dclk_ext_virt] -rise_to [get_clocks i_adc|i_adc_pll_c10|iopll_0|outclk338]

set_false_path -hold -fall_from [get_clocks dclk_ext_virt] -fall_to [get_clocks i_adc|i_adc_pll_c10|iopll_0|outclk338]

------------

Timing is failing from the input pin to the DDIO registers as well as from the DDIO registers to the first regular register after the DDIO. Attached is the timing report reporting setup timing to the PLL output clock for the slow corner (timing_report.txt).

One thing I don't understand in particular is why the timing analyzer is showing that it is using the clock inverted for the analysis. It uses the inverted virtual clock as the latch clock for "i_adc|i_adc_channel_top|i_ddio_c10_dqd|gpio_0|core|i_loop[x].altera_gpio_bit_i|input_path.in_path_fr.buffer_data_in_fr_ddio~ddio_in_fr__nff" and then the inverted PLL output clock as the launch clock from there to the first regular register. But the only thing that should be using the inverted clock is the DDIO register that registers data for the falling edge which should then be registered again with the rising edge of the regular clock so that both the low and the high DDIO outputs change on the rising edge of the regular PLL output clock. Meaning if "i_adc|i_adc_channel_top|i_ddio_c10_dqd|gpio_0|core|i_loop[x].altera_gpio_bit_i|input_path.in_path_fr.buffer_data_in_fr_ddio~ddio_in_fr__nff" is the falling edge register of the DDIO then from there the data should go through another register inside the DDIO (using the rising edge of the non inverted clock) before being registered by "i_adc|i_adc_channel_top|di_h_d[x]" or "i_adc|i_adc_channel_top|di_l_d[x]" but both of those show the inverted clock as the launch clock.

I am running Quartus 19.2 Pro for this project. The interesting thing is that I have that same interface with the same constraints on a Cyclone 5 (using Quartus Lite 18.0) and even though the interface is also failing timing, the setup relationship shows a full clock cycle instead of a half clock cycle from the DDIO output to the first regular register input as I would expect.

Any pointers on how to get this to meet timing and understand what is going on including just fixing my constraints if they are wrong are greatly appreciated!

15 Replies