UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Explorer
Explorer
943 Views
Registered: ‎09-13-2011

Validating worst case skew

Jump to solution

I’m trying to find a way to validate a skew parameter on two outputs in the same bank. Looking around there doesn’t seem to be a simple way of doing this. As far as I understand skew between two pins in the same bank using IOB registers clocked with the same clock buffer depends upon a number of things:

 

  1. Package skew, differences in package flight times (static, from FPGA datasheet)
  2. Clock tree skew, difference in when the clock edge reaches the IOB-FF – but the numbers in Kintex datasheet seems rather pessimistic for this setup.
  3. PVT variation optimism or pessimism – whether the max skew is always the same as in the corners or it can vary in the full PVT spectrum. I would think that you can’t just say that if there’s a difference of 300ps in SLOW corner then the skew can never be larger. Vivado only calculates in corners but I guess the skew could in principle be larger somewhere in-between?
  4. Some say clock jitter but I don’t understand this. If clock jitter is a contributor to the skew then all sorts of things contribute (power supply ripple, noise). I would think the jittered clock edge is somewhat the same for two IOB-FFs in the same bank?
  5. Output load but I want to neglect this (mainly because it is beyond my scope).

So I presume that I can’t get Vivado to report a worst case skew?

 

I know it will be small, and I know it is not a problem in my application since my constraint is 2ns, but I need a formal way to validate it.

 

0 Kudos
1 Solution

Accepted Solutions
Historian
Historian
926 Views
Registered: ‎01-23-2009

Re: Validating worst case skew

Jump to solution

So you are right in pretty much everything you say. Including what you say about jitter - if the two IOB FFs are clocked on the same clock, then jitter is not a factor on the skew.

 

And you can (at least in some cases) get Vivado to report on this. If you declare one of them as a generated clock and then use a set_output_delay between that one and the other one, the tools will do a setup and hold check between them. This will give you some idea about skew.

 

You may also be able to put a "set_bus_skew" on the two outputs (you will need set_output_delay commands on both to complete the path), and the tool may give you a skew report on them (I have never tried this, but it might work).

 

But, I will warn you. The tools are very pessimistic about this analysis. When analyzing clock forwarded same edge output interfaces (where the skew is really the most important feature), where both outputs (the clock and data) come from an ODDR (so in the IOB), the tools report the skew as almost +/-600ps, which is quite large. This is due to the way the tool calculates on chip variation (OCV) - particularly the OCV of the pad which has a large delay (so is significantly affected by OCV). But, OCV is a "chip wide" thing - the tool doesn't use one OCV factor for cells that are "close" to each other and another one for cells that are "far" from each other. I would argue that the OCV for two adjacent OBUFs is very small, but the tools don't show it as such.

 

So the net result is that even if you do get the tools to report this, the number is going to be far higher than you might think, and possibly (I hate to disagree with Vivado timing numbers) even too pessimistic.

 

Avrum

5 Replies
Historian
Historian
927 Views
Registered: ‎01-23-2009

Re: Validating worst case skew

Jump to solution

So you are right in pretty much everything you say. Including what you say about jitter - if the two IOB FFs are clocked on the same clock, then jitter is not a factor on the skew.

 

And you can (at least in some cases) get Vivado to report on this. If you declare one of them as a generated clock and then use a set_output_delay between that one and the other one, the tools will do a setup and hold check between them. This will give you some idea about skew.

 

You may also be able to put a "set_bus_skew" on the two outputs (you will need set_output_delay commands on both to complete the path), and the tool may give you a skew report on them (I have never tried this, but it might work).

 

But, I will warn you. The tools are very pessimistic about this analysis. When analyzing clock forwarded same edge output interfaces (where the skew is really the most important feature), where both outputs (the clock and data) come from an ODDR (so in the IOB), the tools report the skew as almost +/-600ps, which is quite large. This is due to the way the tool calculates on chip variation (OCV) - particularly the OCV of the pad which has a large delay (so is significantly affected by OCV). But, OCV is a "chip wide" thing - the tool doesn't use one OCV factor for cells that are "close" to each other and another one for cells that are "far" from each other. I would argue that the OCV for two adjacent OBUFs is very small, but the tools don't show it as such.

 

So the net result is that even if you do get the tools to report this, the number is going to be far higher than you might think, and possibly (I hate to disagree with Vivado timing numbers) even too pessimistic.

 

Avrum

Adventurer
Adventurer
925 Views
Registered: ‎08-30-2018

Re: Validating worst case skew

Jump to solution

Hi @tsjorgensen,

 

I just tumbled into your post. I think looking at this Application file, you'll be able to do some actions in Vivado.

 

https://www.xilinx.com/support/documentation/application_notes/xapp259.pdf

 

 

Bests,

Daryon

Explorer
Explorer
834 Views
Registered: ‎09-13-2011

Re: Validating worst case skew

Jump to solution

Thanks to Avrumw for telling me to give up my endeavour ;-)

I quite agree but just for giving it a try I've tried setting set_bus_skew constraints.

 

Constraints came to look something like this:

set_bus_skew 2 -from [get_clocks clk_50_io*] -to [list \
  [get_pins blabla/serial_link_tx_io_inst/data_port_inst/D1] \
  [get_pins blabla/serial_link_tx_io_inst/clk_port_inst/D1] ]

 

where the data_port_inst and clk_port_inst are both ODDRs. When transmitting the D1 on the clock port inst is set to be the inverted of the CE and D2 is set same as CE. The constraint is accepted but the timing is not as expected.

 

The report_bus_skew gives this report (names of hierarchy has been changed to blabla):

Id: 3
set_bus_skew -from [get_clocks clk_50_io*] -to [list [get_pins blabla/serial_link_tx_io_inst/data_port_inst/D1] [get_pins blabla/serial_link_tx_io_inst/clk_port_inst/D1]] 2.000
Requirement: 2.000ns
Endpoints: 1

From Clock            To Clock              Endpoint Pin                    Reference Pin                   Corner  Actual(ns)  Slack(ns)
--------------------  --------------------  ------------------------------  ------------------------------  ------  ----------  ---------
clk_50_io_1           clk_50_io_1           blabla/serial_link_tx_io_inst/clk_port_inst/D1
                                                                            blabla/serial_link_tx_io_inst/data_port_inst/D1
                                                                                                            Slow         3.828     -1.828


Slack (VIOLATED) :        -1.828ns  (requirement - actual skew)
  Endpoint Source:        blabla/serial_link_tx_core_inst/io_clk_en_reg/C
                            (rising edge-triggered cell FDRE clocked by clk_50_io_1)
  Endpoint Destination:   blabla/serial_link_tx_io_inst/clk_port_inst/D1
                            (rising edge-triggered cell ODDR clocked by clk_50_io_1)
  Reference Source:       blabla/serial_link_tx_core_inst/serial_link_tx_data_output_fifo_reg[39]/C
                            (rising edge-triggered cell FDRE clocked by clk_50_io_1)
  Reference Destination:  blabla/serial_link_tx_io_inst/data_port_inst/D1
                            (rising edge-triggered cell ODDR clocked by clk_50_io_1)
  Path Type:              Bus Skew (Max at Slow Process Corner)
  Requirement:            2.000ns
  Endpoint Relative Delay:    7.888ns
  Reference Relative Delay:   4.000ns
  Relative CRPR:              0.060ns
  Actual Bus Skew:            3.828ns  (Endpoint Relative Delay - Reference Relative Delay - Relative CRPR)

Endpoint path:
    Location             Delay type                Incr(ns)  Path(ns)    Netlist Resource(s)
  -------------------------------------------------------------------    -------------------
                         (clock clk_50_io_1 rise edge)
                                                      0.000     0.000 r  
    Y18                                               0.000     0.000 r  blabla_pl_33_333mhz_clk (IN)
                         net (fo=0)                   0.000     0.000    blabla_pl_33_333mhz_clk
    Y18                  IBUF (Prop_ibuf_I_O)         1.484     1.484 r  blabla_pl_33_333mhz_clk_IBUF_inst/O
                         net (fo=1, routed)           2.205     3.689    blabla_pl_33_333mhz_clk_IBUF
    BUFGCTRL_X0Y1        BUFG (Prop_bufg_I_O)         0.101     3.790 r  blabla_pl_33_333mhz_clk_IBUF_BUFG_inst/O
                         net (fo=928, routed)         1.803     5.593    pl_sub_system_inst/system_clock_inst/blabla.sys_33_clock_gen.mmcm_prim_config_33_mmcm_inst/blabla_pl_33_333mhz_clk_IBUF_BUFG
    MMCME2_ADV_X1Y0      MMCME2_ADV (Prop_mmcme2_adv_CLKIN1_CLKOUT0)
                                                      0.088     5.681 r  pl_sub_system_inst/system_clock_inst/blabla.sys_33_clock_gen.mmcm_prim_config_33_mmcm_inst/mmcm_inst.mmcme2_adv_inst/CLKOUT0
                         net (fo=1, routed)           1.889     7.570    clk_50_io
    BUFGCTRL_X0Y0        BUFG (Prop_bufg_I_O)         0.101     7.671 r  clk_50_io_BUFG_inst/O
                         net (fo=706, routed)         1.750     9.421    blabla/serial_link_tx_core_inst/clk_50_io_BUFG
    SLICE_X8Y38          FDRE                                         r  blabla/serial_link_tx_core_inst/io_clk_en_reg/C
  -------------------------------------------------------------------    -------------------
    SLICE_X8Y38          FDRE (Prop_fdre_C_Q)         0.518     9.939 f  blabla/serial_link_tx_core_inst/io_clk_en_reg/Q
                         net (fo=24, routed)          2.781    12.719    blabla/serial_link_tx_core_inst/io_clk_en
    SLICE_X26Y76         LUT2 (Prop_lut2_I1_O)        0.124    12.843 r  blabla/serial_link_tx_core_inst/clk_port_inst_i_1/O
                         net (fo=1, routed)           3.499    16.343    blabla/serial_link_tx_io_inst/D1
    OLOGIC_X0Y18         ODDR                                         r  blabla/serial_link_tx_io_inst/clk_port_inst/D1
  -------------------------------------------------------------------    -------------------

                         (clock clk_50_io_1 rise edge)
                                                      0.000     0.000 r  
    Y18                                               0.000     0.000 r  blabla_pl_33_333mhz_clk (IN)
                         net (fo=0)                   0.000     0.000    blabla_pl_33_333mhz_clk
    Y18                  IBUF (Prop_ibuf_I_O)         1.413     1.413 r  blabla_pl_33_333mhz_clk_IBUF_inst/O
                         net (fo=1, routed)           2.006     3.419    blabla_pl_33_333mhz_clk_IBUF
    BUFGCTRL_X0Y1        BUFG (Prop_bufg_I_O)         0.091     3.510 r  blabla_pl_33_333mhz_clk_IBUF_BUFG_inst/O
                         net (fo=928, routed)         1.609     5.119    pl_sub_system_inst/system_clock_inst/blabla.sys_33_clock_gen.mmcm_prim_config_33_mmcm_inst/blabla_pl_33_333mhz_clk_IBUF_BUFG
    MMCME2_ADV_X1Y0      MMCME2_ADV (Prop_mmcme2_adv_CLKIN1_CLKOUT0)
                                                      0.083     5.202 r  pl_sub_system_inst/system_clock_inst/blabla.sys_33_clock_gen.mmcm_prim_config_33_mmcm_inst/mmcm_inst.mmcme2_adv_inst/CLKOUT0
                         net (fo=1, routed)           1.725     6.928    clk_50_io
    BUFGCTRL_X0Y0        BUFG (Prop_bufg_I_O)         0.091     7.019 r  clk_50_io_BUFG_inst/O
                         net (fo=706, routed)         1.629     8.647    blabla/serial_link_tx_io_inst/clk_50_io_BUFG
    OLOGIC_X0Y18         ODDR                                         r  blabla/serial_link_tx_io_inst/clk_port_inst/C
                         clock pessimism              0.767     9.414    
                         clock uncertainty           -0.126     9.288    
    OLOGIC_X0Y18         ODDR (Setup_oddr_C_D1)      -0.834     8.454    blabla/serial_link_tx_io_inst/clk_port_inst
  -------------------------------------------------------------------
                         data arrival                          16.343    
                         clock arrival                          8.454    
  -------------------------------------------------------------------
                         relative delay                         7.888    

Reference path:
    Location             Delay type                Incr(ns)  Path(ns)    Netlist Resource(s)
  -------------------------------------------------------------------    -------------------
                         (clock clk_50_io_1 rise edge)
                                                      0.000     0.000 r  
    Y18                                               0.000     0.000 r  blabla_pl_33_333mhz_clk (IN)
                         net (fo=0)                   0.000     0.000    blabla_pl_33_333mhz_clk
    Y18                  IBUF (Prop_ibuf_I_O)         1.413     1.413 r  blabla_pl_33_333mhz_clk_IBUF_inst/O
                         net (fo=1, routed)           2.006     3.419    blabla_pl_33_333mhz_clk_IBUF
    BUFGCTRL_X0Y1        BUFG (Prop_bufg_I_O)         0.091     3.510 r  blabla_pl_33_333mhz_clk_IBUF_BUFG_inst/O
                         net (fo=928, routed)         1.609     5.119    pl_sub_system_inst/system_clock_inst/blabla.sys_33_clock_gen.mmcm_prim_config_33_mmcm_inst/blabla_pl_33_333mhz_clk_IBUF_BUFG
    MMCME2_ADV_X1Y0      MMCME2_ADV (Prop_mmcme2_adv_CLKIN1_CLKOUT0)
                                                      0.083     5.202 r  pl_sub_system_inst/system_clock_inst/blabla.sys_33_clock_gen.mmcm_prim_config_33_mmcm_inst/mmcm_inst.mmcme2_adv_inst/CLKOUT0
                         net (fo=1, routed)           1.725     6.928    clk_50_io
    BUFGCTRL_X0Y0        BUFG (Prop_bufg_I_O)         0.091     7.019 r  clk_50_io_BUFG_inst/O
                         net (fo=706, routed)         1.479     8.497    blabla/serial_link_tx_core_inst/clk_50_io_BUFG
    SLICE_X48Y91         FDRE                                         r  blabla/serial_link_tx_core_inst/serial_link_tx_data_output_fifo_reg[39]/C
  -------------------------------------------------------------------    -------------------
    SLICE_X48Y91         FDRE (Prop_fdre_C_Q)         0.337     8.834 r  blabla/serial_link_tx_core_inst/serial_link_tx_data_output_fifo_reg[39]/Q
                         net (fo=2, routed)           3.878    12.712    blabla/serial_link_tx_io_inst/serial_data
    OLOGIC_X0Y17         ODDR                                         r  blabla/serial_link_tx_io_inst/data_port_inst/D1
  -------------------------------------------------------------------    -------------------

                         (clock clk_50_io_1 rise edge)
                                                      0.000     0.000 r  
    Y18                                               0.000     0.000 r  blabla_pl_33_333mhz_clk (IN)
                         net (fo=0)                   0.000     0.000    blabla_pl_33_333mhz_clk
    Y18                  IBUF (Prop_ibuf_I_O)         1.484     1.484 r  blabla_pl_33_333mhz_clk_IBUF_inst/O
                         net (fo=1, routed)           2.205     3.689    blabla_pl_33_333mhz_clk_IBUF
    BUFGCTRL_X0Y1        BUFG (Prop_bufg_I_O)         0.101     3.790 r  blabla_pl_33_333mhz_clk_IBUF_BUFG_inst/O
                         net (fo=928, routed)         1.803     5.593    pl_sub_system_inst/system_clock_inst/blabla.sys_33_clock_gen.mmcm_prim_config_33_mmcm_inst/blabla_pl_33_333mhz_clk_IBUF_BUFG
    MMCME2_ADV_X1Y0      MMCME2_ADV (Prop_mmcme2_adv_CLKIN1_CLKOUT0)
                                                      0.088     5.681 r  pl_sub_system_inst/system_clock_inst/blabla.sys_33_clock_gen.mmcm_prim_config_33_mmcm_inst/mmcm_inst.mmcme2_adv_inst/CLKOUT0
                         net (fo=1, routed)           1.889     7.570    clk_50_io
    BUFGCTRL_X0Y0        BUFG (Prop_bufg_I_O)         0.101     7.671 r  clk_50_io_BUFG_inst/O
                         net (fo=706, routed)         1.849     9.520    blabla/serial_link_tx_io_inst/clk_50_io_BUFG
    OLOGIC_X0Y17         ODDR                                         r  blabla/serial_link_tx_io_inst/data_port_inst/C
                         clock pessimism             -0.652     8.868    
                         clock uncertainty            0.126     8.994    
    OLOGIC_X0Y17         ODDR (Hold_oddr_C_D1)       -0.282     8.712    blabla/serial_link_tx_io_inst/data_port_inst
  -------------------------------------------------------------------
                         data arrival                          12.712    
                         clock arrival                          8.712    
  -------------------------------------------------------------------
                         relative delay                         4.000    



 

Inbetween this leads me to the question of actually using ODDR as OREG; if I feed D1 and D2 of an ODDR with the same signal to use it as a way to instantiate an OREG I will then have to be sure the timing path to the falling edge is also met otherwise I may get that the output changes on a falling edge where I only want rising edge. So the timing gets more complicated than if I do not instantiate an ODDR and just use a register constrained to be in the IOB. Anyone has any thoughts on this?

 

Regarding the report it says that my constraint is violated. But what I'm really after is the difference in skew between the outputs of the two ODDRs and not the inputs which I guess is what is reported but the set_bus_skew constraint wont accept /Q as valid endpoints. I think my conclusion is that set_bus_skew can't be used for validating the skew between two output ports and that there isn't a way to get Vivado to report the skew without it being way too pessimistic as Avrumw states.

0 Kudos
Explorer
Explorer
360 Views
Registered: ‎09-13-2011

Re: Validating worst case skew

Jump to solution

Coming back to this.

In the old XAPP259 the maximum skew between two output pins in the same bank is calculated using the datasheet value for the packet skew and adding the clock tree skew. Is this still the Xilinx preferred method? Is there a newer version of the xapp or will there be one?

I have tried setting a generated clock and setting output delays and getting a datasheet report on the outputs. This gives me all sorts of numbers, from as low as 0.000ns up to around 2 ns in the Edge Skew column. This doesn't seem correct - 0ps seems overly optimistic and 2ns seems overly pessimistic (all in IOB-regs same banks).

 

0 Kudos
Explorer
Explorer
329 Views
Registered: ‎09-13-2011

Re: Validating worst case skew

Jump to solution

It is the Worst Case Summary of the Edge Skew that can be everything from 0.000ns to 2.000ns.

When using the report_datasheet I also make sure that the clock is the first in the list.

 

0 Kudos