Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
Need Forum Guidance? Click here

Search our FPGA Knowledge Articles here.
19206 Discussions

Unable to meet timing requirements for 180 MHz Source-Synch. DDR Interface due to PLL uncertainty


Dear all,

My current project involves an interfacing between an ADC, clocked at 180 MHz with source-synchronous DDR LVDS outputs, and a Cyclone V FPGA (5CSXFC6).

To start, I instantiated a ALTDDIO receiver with the required number of channels and a PLL to create a 90 degree phase shifted version of the ADC clockout signal as its input clock.

With this setup, my timing fails for both the setup and hold analysis by approximately 500 ps each. The reason is that the length of the clock path differs by about 2.5 ns between the setup and hold analysis which shrinks down the data required window to almost zero, making it too small for the uncertainties in the data path and the input delays given by the ADC datasheet.

Changing the compensation mode of the PLL did not seem to have a significant effect. The chip planner showed that the clock signal was routed all over the chip. I was able to reduce the clock path length and improve the timing by assigning a specific regional clock buffer to the PLL output. (Is there any settings I could have changed for the fitter in order for it to try this automatically?). But even with this optimization, the timing fails at the "slow device corners".

When directly clocking the ALTDDIO with the ADC clockout signal, timing analysis goes well with around 0.5 ns slack for both and hold. The relatively large IC delay from the clock buffer to the DDIOs creates exactly the phase shift required.

The ADC can be configured to include a phase shift in the clock signal using an SPI interface but the datasheet recommends doing this within the FPGA. Although not using the PLL and relying on the clock delay seems to work, it is not satisfying. I am wondering if I am doing something wrong or whether a 180 MHz DDR interface is at the edge of the capabilities of the chosen device (5CSXFC6). 

Best regards

0 Kudos
10 Replies

Hi Dijkstra

Thanks for your inquiry. Allow me some time to check on your request and get back to you.



Eng Wei




Could you share the design for investigation?


Best regards,



Hi all,

A MWE QPF is attached. It features two ADCs (one single channel, one dual channel) with a total of 20 DDR LVDS outputs + 2 LVDS clocks. Three clocks enter the FPGA: the two clockouts from the ADC as well as the encode clock that is will (externally) drive the ADCs. 

Originally I planned on using the 5CSXFC6C6U23C7 chip until I found out that some of the differential receiver pairs introduce additional delay due to the HMC and should not be used for fast signals. Therefore I will propably change to the 5CSEBA4U23I7 chip which resulted in additional phaenomena:

- Initially, the ADC clocks were connected to the CLK0 / CLK3 and the encode clock to CLK2. With these assignments, the fitter fails for the SE chip (but not the SX chip) because it cannot place one of the PLLs. When changing the input of the encode clock to CLK6, both chips compile fine (and the timing for the SX is improved compared to using CLK2 as input).

- With the 5CSEBA4U23I7 chip I can just meet the timing requirements with the PLL in place, with the 5CSXFC6C6U23C7 chip I still cannot because the "data valid window" becomes negative. Could this be due to the HMC resources which are present in the SX but not in the SE chip?


For both chips however,  omitting the PLL leads to significantly improved margings which brings me back to the original question: Is there a mistake in my configuration or is it true that the PLLs add so much uncertainty that a shift (if necessary) in my case should be done at the ADC?


Thank you in advance for any help!

Honored Contributor III

Can you post your .sdc file?




There are missing files in the attachment. You may provide the design.qar by clicking on Project > Archive Project > Archive

Error (12006): Node instance "systempll_inst" instantiates undefined entity "systemPll_0002"

Error (12006): Node instance "adcpll_inst" instantiates undefined entity "adcPll_0002"

Error (12006): Node instance "adcpll_inst" instantiates undefined entity "adcPll_0002"


Best regards,



Hi all,

I didn't know about the archive function, sorry. Hopefully it works this time.

Currently the PLL output clocks are used as the clock inputs to the receivers, this can be changed here:


inclock => adc2ChClkout_90deg,
--inclock => ADC_2CH_CLKOUT,


Thank you!



You have to use create_clock on the input clock port (ADC_1CH_CLKOUT, ADC_2CH_CLKOUT and ENCODE_CLOCK) of your interface that describes the characteristics of the source clock. If the clock and data arrive at FPGA edge-aligned, you can use a PLL to shift the clock used to latch the data. If the clock and data arrive at FPGA center-aligned, you have to specify the clock phase adjustment on the input clock with the waveform options. According to AN 433, the false path and multicycle path exceptions are applied between the virtual clock and data clock. In the sdc, you are constraining the false path and multicycle path between the virtual clock itself (adc1ChClockout and adc2ChClockout). 


Best regards,



Hi Khai,


thank you for your response. There were no virtual clocks in my SDC file because I specified my input delays relative to the ADC clockout with the timings specified in the datasheet. I did this because I also wanted to analyze the timings from data launched by the input receivers and latched by the ENCODE_CLOCK. I don't think that this deviation from the AN433 affects my timing issue. To make sure, I changed the SDC file accordingly:


- Add virtual clocks (data is delayed to clock by typically 0.4 ns)

create_generated_clock -name adc2ChDataClock_virt -source [get_ports {ADC_2CH_CLKOUT}] -offset 0.4
create_generated_clock -name adc1ChDataClock_virt -source [get_ports {ADC_1CH_CLKOUT}] -offset 0.4


- Set the input delays, false paths and multicycle paths relative to the virtual clocks:

set_input_delay -min -clock [get_clocks {adc2ChDataClock_virt}] -0.1 [get_ports ADC_2CH_DATA*] -add_delay
set_input_delay -min -clock [get_clocks {adc2ChDataClock_virt}] -0.1 [get_ports ADC_2CH_DATA*] -clock_fall -add_delay
set_input_delay -max -clock [get_clocks {adc2ChDataClock_virt}] 0.15 [get_ports ADC_2CH_DATA*] -add_delay
set_input_delay -max -clock [get_clocks {adc2ChDataClock_virt}] 0.15 [get_ports ADC_2CH_DATA*] -clock_fall -add_delay

set_input_delay -min -clock [get_clocks {adc1ChDataClock_virt}] -0.1 [get_ports ADC_1CH_DATA*] -add_delay
set_input_delay -min -clock [get_clocks {adc1ChDataClock_virt}] -0.1 [get_ports ADC_1CH_DATA*] -clock_fall -add_delay
set_input_delay -max -clock [get_clocks {adc1ChDataClock_virt}] 0.15 [get_ports ADC_1CH_DATA*] -add_delay
set_input_delay -max -clock [get_clocks {adc1ChDataClock_virt}] 0.15 [get_ports ADC_1CH_DATA*] -clock_fall -add_delay

set_false_path -setup -fall_from [get_clocks {adc2ChDataClock_virt}] -rise_to [get_clocks {adc2ChClockout}]
set_false_path -setup -rise_from [get_clocks {adc2ChDataClock_virt}] -fall_to [get_clocks {adc2ChClockout}]
set_false_path -hold -fall_from [get_clocks {adc2ChDataClock_virt}] -fall_to [get_clocks {adc2ChClockout}]
set_false_path -hold -rise_from [get_clocks {adc2ChDataClock_virt}] -rise_to [get_clocks {adc2ChClockout}]

set_false_path -setup -fall_from [get_clocks {adc1ChDataClock_virt}] -rise_to [get_clocks {adc1ChClockout}]
set_false_path -setup -rise_from [get_clocks {adc1ChDataClock_virt}] -fall_to [get_clocks {adc1ChClockout}]
set_false_path -hold -fall_from [get_clocks {adc1ChDataClock_virt}] -fall_to [get_clocks {adc1ChClockout}]
set_false_path -hold -rise_from [get_clocks {adc1ChDataClock_virt}] -rise_to [get_clocks {adc1ChClockout}]

set_multicycle_path -setup -rise_from [get_clocks {adc1ChDataClock_virt}] -rise_to [get_clocks {adc1ChClockout}] 0
set_multicycle_path -setup -fall_from [get_clocks {adc1ChDataClock_virt}] -fall_to [get_clocks {adc1ChClockout}] 0

set_multicycle_path -setup -rise_from [get_clocks {adc1ChDataClock_virt}] -rise_to [get_clocks {adc2ChClockout}] 0
set_multicycle_path -setup -fall_from [get_clocks {adc1ChDataClock_virt}] -fall_to [get_clocks {adc2ChClockout}] 0


- I also had to remove the clock latency because it is not recognized anymore as common clock path pessimism). This is OK for the MWE

#set_clock_latency -source -early -0.3 [get_clocks {adc2ChClockout}]
#set_clock_latency -source -late 0.2 [get_clocks {adc2ChClockout}]
#set_clock_latency -source -early -0.3 [get_clocks {adc1ChClockout}]
#set_clock_latency -source -late 0.2 [get_clocks {adc1ChClockout}]



With these changes, the timing analysis for the capture paths is exactly the same.



Correct me if I understand wrongly. ADC_2CH_CLKOUT and ADC_1CH_CLKOUT are the output clock from the ADC and these two clocks will be shifted by 90 degree using the PLL. If this is the case, you have to use create_clock to constrain ADC_2CH_CLKOUT and ADC_1CH_CLKOUT but not create_generated_clock because you have an input port assigned to it. Besides this, the false path and multicycle constraints are applied between the virtual clock and data clock. In your latest sdc, you have applied the constraint between adc1ChDataClock_virt and adc1ChClockout. This is correct only if you are using adc1ChClockout to latch the data. You have to use the generated clock from the PLL in the false path and multicycle assignment if you are using the PLL shifted clock to latch the data.


Best regards,




We do not receive any response from you to the previous question/reply/answer that I have provided. This thread will be transitioned to community support. If you have a new question, feel free to open a new thread to get the support from Intel experts. Otherwise, the community users will continue to help you on this thread. Thank you

Best regards,