Showing results for 
Show  only  | Search instead for 
Did you mean: 
Registered: ‎02-26-2013

LVDS DDR input constrains


I have a trouble with constraining of FPGA input with this ADC.
I using layout posted in the attached image. I using constraints:

# timing IO
create_clock -period 2.200 -name adc_clk_i_constr [get_ports adc_CLK_I_P]
create_clock -period 2.200 -name adc_clk_q_constr [get_ports adc_CLK_Q_P]
set_input_delay -clock [get_clocks adc_clk_i_constr] -max -2.800 [get_ports {{adc_data_i_p[*]} {adc_data_id_p[*]}}]
set_input_delay -clock [get_clocks adc_clk_i_constr] -min -0.800 [get_ports {{adc_data_i_p[*]} {adc_data_id_p[*]}}]
set_input_delay -clock [get_clocks adc_clk_i_constr] -clock_fall -max -add_delay -2.800 [get_ports {{adc_data_i_p[*]} {adc_data_id_p[*]}}]
set_input_delay -clock [get_clocks adc_clk_i_constr] -clock_fall -min -add_delay -0.800 [get_ports {{adc_data_i_p[*]} {adc_data_id_p[*]}}]
set_input_delay -clock [get_clocks adc_clk_q_constr] -max -2.800 [get_ports {{adc_data_q_p[*]} {adc_data_qd_p[*]}}]
set_input_delay -clock [get_clocks adc_clk_q_constr] -min -0.800 [get_ports {{adc_data_q_p[*]} {adc_data_qd_p[*]}}]
set_input_delay -clock [get_clocks adc_clk_q_constr] -clock_fall -max -add_delay -2.800 [get_ports {{adc_data_q_p[*]} {adc_data_qd_p[*]}}]
set_input_delay -clock [get_clocks adc_clk_q_constr] -clock_fall -min -add_delay -0.800 [get_ports {{adc_data_q_p[*]} {adc_data_qd_p[*]}}]

It work properly, but I get timming problem after implementation...


Thank for advice

0 Kudos
3 Replies
Registered: ‎01-23-2009

First, you need to tell us what mode you are using the ADC in - it has many... From your constraints it looks like you are expecting a 2.2ns clock (454MHz), and DDR data (for a 1.1ns bit period [or "Unit Interval" UI]) - but your constraints don't really make any sense (the difference between your max and min values are 2ns, which is almost two complete UI.

So, assuming this is true - that you have a 1.1UI, and looking at the datasheet, tOSK is +/-50ps, this means that your data eye is 1.0ns. Before we go any further, I am going to tell you that this is too small for static capture.

But, lets look at the complete picture.

Before I get into clocking structure, I see you are using the IN_FIFO... These structures are normally used (only?) for DDRx-SDRAM interfaces and work in conjunction with the DQS recovery and PLLs - I have never seen them used anywhere outside a DDRx-SDRAM PHY... I don't know where you got this structure (i.e. is it from an answer record?) - I would be worried about using it...

The next thing we have to look at is clocking structure.

There are three (normal) ways of designing the clocking structure of an input interface (with a couple of variations). All of these assume that the capture flip-flops themselves are in the IOB (and since this is DDR, you would normally capture them with the IDDR, which is only available in the IOB). You can also use the ISERDES - the "high speed" side of the ISERDES (driven by CLK, not CLKDIV) is similar to the IOB FF or IDDR in terms of timing (they are actually the same structure).

a) Direct Capture with BUFG

(This is what you have above)

In this scheme, the clock arrives on a clock capable input (MRCC or SRCC), and (after the IBUF or IBUFDS) drive the input of a BUFG. From here the clock can drive the clock input of the IDDR as well as all fabric logic. (A BUFH can be used instead of the BUFG if the logic and I/O are all restricted to one clock region - this will be slightly faster).

Unfortunately, this has the worst timing characteristics. The BUFG is in the center of the FPGA, and the clock tree is quite deep, leaving for a long clock insertion with large process/voltage/temperature (PVT) variations; large PVT variations mean a large required data eye. Depending on device and speed grade these interfaces tend to need more than 3ns of stable data for capture (WAY more than what you are providing).

As always, the real timing of an interface needs to be determined by the tools, but the datasheets have a parameter for the required setup and hold times of interfaces like this - they are called Tpsfd/Tphfd.

b) BUFG Capture with MMCM/PLL

This is similar to a), but in this case, an MMCM/PLL is used between the IBUF and the BUFG/BUFH. The CLKFBIN of the MMCM/PLL is driven from the CLKFBOUT of the MMCM via the same type of buffer (BUFG/BUFH) as the one connected to the CLKOUT0 (or other clock of the MMCM) which drives the IDDR clock inputs.

This normally has better timing - depending on family and speed grade it can be a fair bit better, or only a little bit better. The datasheet give you information on this with the parameters Tpsmmcmcc/Tphmmcmcc or Tpspllcc/Tphpllcc (or something similar, depending on family).

c) Direct Capture with BUFIO or BUFR (ChipSync)

Here, the capture is not done with a global clock, but with an I/O clock driven by a BUFIO. This is precisely what the BUFIO and I/O clock network are for.

Here the clock capable input drives the BUFIO, and the BUFIO drives the clock inputs of the IDDR/ISERDES directly. For this to work, the clock capable I/O, BUFIO and all the IOB flip-flops/IDDRs for the interface must be in the same I/O bank.

However, the BUFIO can only drive the clock input of the IOB flip-flop, IDDR or ISERDES (and ODDR, OSERDES). Once captured there, it needs to be transferred to another clock, which can clock fabric resources. This is normally (almost always) driven by the BUFR; the clock capable I/O drives the inputs of both the BUFIO and BUFR (these two clocks are phase matched with eachother). If using an ISERDES, the BUFR can also do the required clock division.

The BUFR can only clock logic in the same clock region. If you need to bring the data to a global clock, then you need to use clock crossing techniques (usually a clock crossing FIFO).

This scheme has the best timing. Again, depending on family and speed grade, this can capture interfaces with data eyes as small as just over 1ns (like 1.1ns). This is documented as Tpscs/Tphcs in the datasheet.

If you are not using the ISERDES, then you can use the BUFR alone for capturing the interface using either an IOB flip-flop (SDR) or an IDDR (DDR). This configuration gives slightly better timing then using the BUFIO and then transferring data to the BUFR domain after the capture flip-flop/IDDR.

If the clock and data are not in the same bank (but are in adjacent banks), then you can use the BUFMR

IBUF -> BUFMR -> BUFIO (in up to three regions - the one of the BUFMR, and the one above and below)
                          |-> BUFR (in the same three regions)

But, using the BUFMR adds more delay to the clock path, and hence widens the required data eye (fairly significantly).

Clock/Data Phase Relationship

All of these clocking schemes will result in a specific setup/hold requirement at the FPGA input pins. It is highly unlikely that this will be "exactly" where your data eye is. So, you generally need to modify the clock/data phase relationship.

With clocking style b) (using the MMCM), this is most easily done by adjusting the CLKOUT0_PHASE, possibly using the inperpolated fine phase shifter. This gives you very fine control over the phase of the clock.

For other styles (a or c), you don't have the MMCM, the only option is to use the IDELAY. You can delay the clock or the data (or both), but it is preferable to not have large IDELAYs on the data (since it introduces jitter).

Unfortunately, using the IDELAY widens the required data eye.

Finally, for the constraints, I recommend you look at this forum post on constraining edge aligned source synchronous DDR interfaces. Your constraints should be very similar to the ones shown in that post - they would be something like

set_input_delay -clock <clock> 0.05            [get_ports <inputs>]
set_input_delay -clock <clock> -0.05 -min [get_ports <inputs>]
set_input_delay -clock <clock> 0.05            [get_ports <inputs>] -clock_fall -add_delay
set_input_delay -clock <clock> -0.05 -min [get_ports <inputs>] -clock_fall -add_delay

(for the tOSK of +/-0.05ns from the ADC datasheet).

For interfaces that are "tight" you also need to make sure that you are properly constraining the clock, including adding the appropriate jitter (using set_input_jitter).


Registered: ‎06-17-2016

It is very helpful to us

0 Kudos
Registered: ‎06-09-2018

Hi @avrumw

thanks for your clear explanation ...


but a question : when we use bufgmux ?

0 Kudos