cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Observer
Observer
559 Views
Registered: ‎03-14-2019

Artix 7 Source synchronous SDR interface for DAC at 500MHz

is it possible to implement source synchronous SDR LVDS interface runing at 500Mhz clock on Artix 7 device? 

 

DAC has Ts= -1.2ns and Th=2ns timing requirements and latches data on rising edge:

dac5878.PNG

 

I have implemented folowing clocking scheme:

 dac_clock.gif

And added folowing constraints: 

# Base clock 500MHz
create_clock -period 2.000 -name clk [get_ports clk_p]

# Forwarded clock for DAC (same freq. as base clock - 500MHz) create_generated_clock -name dac_clk -source [get_pins {ODDR_inst/C}] -divide_by 1 [get_ports {dac_clk_p}]
# Output delay for DAC data (Ts=-1.2, Th=2) set_output_delay -clock [get_clocks {dac_clk}] -min -add_delay -2.0 [get_ports {dac_d_p[*]}] set_output_delay -clock [get_clocks {dac_clk}] -max -add_delay -1.2 [get_ports {dac_d_p[*]}]
# Do not analyze forwarded clock as data set_false_path -to [get_ports {dac_clk_p}] 

I am getting timing violations. Is my clocking scheme or timing constraints incorrect or this impossible to achieve in Artix 7 device?

 

 

0 Kudos
9 Replies
Highlighted
Teacher
Teacher
539 Views
Registered: ‎07-09-2009

Re: Artix 7 Source synchronous SDR interface for DAC at 500MHz

500 MHz is going to be at best on the limit of the fastest artix devices,

There is an ISERDES in the IO pins, which can be used to capture data faster, its used for instance in the DDR memory interfaces,

have look here for the idea
https://www.xilinx.com/support/documentation/application_notes/xapp585-lvds-source-synch-serdes-clock-multiplication.pdf


<== If this was helpful, please feel free to give Kudos, and close if it answers your question ==>
0 Kudos
Highlighted
Observer
Observer
465 Views
Registered: ‎03-14-2019

Re: Artix 7 Source synchronous SDR interface for DAC at 500MHz

Can someone explain timing requirements for DAC? Datasheet states that Tsu=-1.2 (negative value)  and Th= 2. So the data valid vindow equals to 0.8ns as specified in MAX5878 knowledge base answer

dac_valdi_window.gif

so should i modify my timing constrints to : 

set_output_delay -clock [get_clocks {dac_clk}] -min -add_delay  0 [get_ports {dac_d_p[*]}]
set_output_delay -clock [get_clocks {dac_clk}] -max -add_delay -1.2 [get_ports {dac_d_p[*]}]

 

0 Kudos
Highlighted
Observer
Observer
423 Views
Registered: ‎03-14-2019

Re: Artix 7 Source synchronous SDR interface for DAC at 500MHz

anyone?

0 Kudos
Guide
Guide
397 Views
Registered: ‎01-23-2009

Re: Artix 7 Source synchronous SDR interface for DAC at 500MHz

OK - first, these constraints are wierd. The original ones were Tsu=-1.2 Th=2.0. So this means that the setup time is 1.2ns after the rising edge and the hold time is 2.0ns after the rising edge of the clock. If you were to actually specify it this way it would be as you wrote it in your original post:

set_output_delay -clock [get_clocks {dac_clk}] -min -2.0 [get_ports {dac_d_p[*]}]
set_output_delay -clock [get_clocks {dac_clk}] -max -1.2 [get_ports {dac_d_p[*]}]

(I know the constraints wizard puts the -add_delay option in, but it really shouldn't - so I have removed them here).

But what does this mean? It does correctly convey the need for a 0.8ns valid window, and it does tell you where it is, but it also messes up the edge relationships. For the setup check, if the launch edge is the first rising edge at time 0, the capture edge is the second rising edge at time 2ns. But the setup requirement for that edge is at -1.2ns before this edge, so starting at time 3.2 - this is "odd", but would pass (since it is much larger than it should be. Conversely the hold check launched (to make things easier) on the 2nd rising edge at time 2ns, would be captured by the hold requirement on the same edge (at time 2ns), so the data would have to arrive no earlier than the hold requirement on that edge which 2ns later so at time 4ns. This is clearly impossible...

So this needs to be fixed. It can be done with set_multicycle_path constraints, but the easier way is to "translate" these constraints to something more reasonable - basically shift the data window back one complete clock period. This results in a different set of constraints, but you got it wrong - these would be

set_output_delay -clock [get_clocks {dac_clk}] -min 0.0 [get_ports {dac_d_p[*]}]
set_output_delay -clock [get_clocks {dac_clk}] -max 0.8 [get_ports {dac_d_p[*]}]

This gives a more reasonable set of launch edges - the data launched at 0 must be valid no later than at time 1.2, and the data launched at 2.0 must not change before 2.0ns.

Ok - so now the constraints are more "reasonable". But how do you plan to meet them. Constraints simply tell the tool what you need. On "normal" paths, the tool will change "things" in order to try and meet constraints. But on these paths, where the flip-flops are in the IOB (and you don't need to use an ODDR for the data - just an SDR flip-flop with the IOB property set on the port), everything is locked in specific locations, and there are no "things" for the tool to change to make this meet timing. So it will fail. (And by the way, interfaces should always use fixed resources - namely the IOB flip-flops - so you have done it right).

When clocked like this, the data and clock will change at the same time - this will give you a data valid window centered between the two rising edges. Due to variations, there will be some skew between them - the tools are pretty pessimistic and will likely report a +/-600ps or so skew between them (you can try this yourself - but I have looked at these kinds of interfaces before, and the +/-600ps is pretty typical), so you will get a valid window that starts at 0.6ns and ends at 1.4ns. This is JUST enough for your required 800ps window, but it is in entirely the wrong place - it is early by 600ps. So you need to do something to put it in the right place.

You have two choices - delay the data in an ODELAY (if this IO bank has ODELAYs - it must be an HP bank to have them) or use a different clock to clock to drive the clock ODDR and the data IOB FF - the clock for the data must be later than the clock for the forwarded clock by 600ps.

Both solutions are possible, but both will degrade the width of the data valid window. The ODELAY adds some additional routing delay and also some data dependent jitter as well as some granularity in the delay value (so you might not be able to get exactly 600ps). The MMCM can generate the 600ps pretty precisely, but will add some static phase offset between the clock outputs (tSTATPHAOFFSET) of +/-120ps (this value comes from the datasheet and is also what the static timing engine uses).

So both solutuions will likely fail to meet these constrains - but only by a little bit. In general, this is the one and only one place where I find the tools to be overly pessimistic (clock forwarded output interfaces) - so even if it violates by a few 100ps, I would expect this interface to work...

Avrum

Highlighted
Observer
Observer
376 Views
Registered: ‎03-14-2019

Re: Artix 7 Source synchronous SDR interface for DAC at 500MHz

First of all thank you for your time  @avrumw on writing such a detailed answer. 

I came up with different clocking scheme after reading  @drjohnsmith post: 

MAX5878_clocking.gif

I have modified timing constraints as you wrote and the result with my modified design was:

 Setup time slack = 0.995 ns, Hold time slack = -0.241 ns.

In case that I have some Setup slack margin I decided to invert forwarded clock (dac_clk) by inverting D inputs of oserdese2. I think this should bring back latch edge from 2ns to 1ns time for setup and from 0ns to -1ns to hold. After inverting clock the result was: 

Setup time slack = -0.005 ns,   Hold time slack = 0.724 ns

Would this be the correct way of implementing this interface?

0 Kudos
Highlighted
Guide
Guide
310 Views
Registered: ‎01-23-2009

Re: Artix 7 Source synchronous SDR interface for DAC at 500MHz

I agree that trying to use 500MHz internally is "difficult" and in some devices impossible. I also agree that using the OSERDES is a good approach to generating a 500MHz output interface while not having 500MHz clocks internally.

But...

First, these numbers don't look right. If you are really operating at 500MHz (2ns bit period) and need a 0.8ns window, I would be VERY surprised to have almost 750ps of total slack on this interface. This would mean (working backwards) that the 2.0ns bit period minus the 0.8ns required window (specified by the set_input_delay) minus the 750ps slack reported in your timing analysis means that there is only 0.450ns of uncertainty in the edges - which corresponds to +/-225ps - I have never seen the skew this low in a clock forwarded interface. Could you post the complete path report for the setup and hold check?

Second, if you use the BUFIO/BUFR, you can only access one clock region of the device. This is often too limiting... Generally you want to use global clocks. To do this you would use the MMCM to generate your 500MHz and 250MHz clocks (instead of the BUFIO for the 500MHz and the BUFR to divide it by two). Both outputs of the MMCM would then use a BUFG.

Furthermore, if you use the MMCM, you could generate three clocks

  • The 500MHz clock for clocking the .C of the OSERDES for your data (nominally at phase 0)
  • The 250MHz clock for generating the data driving the OSERDES for your data (also nominally at phase 0)
  • Another 500MHz clock with a fine phase shift for generating your forwarded clock; even if you are using an OSERDES for the data, you can still use an ODDR for the clock (so you don't need a 250MHz clock for this).
    • With this clock, you can change the phase of the clock to be exactly where you want it - based on the required setup/hold, the "ideal" place is 600ps earlier than the 500MHz clock for the data
    • Depending on how the set_input_delays are specified (and the PHASESHIFT_MODE of the MMCM), you may need a set_multicycle_path command to "fix" the edges of the setup check

Avrum

Highlighted
Observer
Observer
289 Views
Registered: ‎03-14-2019

Re: Artix 7 Source synchronous SDR interface for DAC at 500MHz

Here is the report: 

 

---------------------------------------------------------------------------------------------------
From Clock:  clk
  To Clock:  dac_clk

Setup :            0  Failing Endpoints,  Worst Slack        0.016ns,  Total Violation        0.000ns
Hold  :            0  Failing Endpoints,  Worst Slack        0.704ns,  Total Violation        0.000ns
---------------------------------------------------------------------------------------------------

Setup: 

Max Delay Paths
--------------------------------------------------------------------------------------
Slack (MET) :             0.016ns  (required time - arrival time)
  Source:                 io_inst0/inst/pins[7].oserdese2_master/CLK
                            (rising edge-triggered cell OSERDESE2 clocked by clk  {rise@0.000ns fall@1.000ns period=2.000ns})
  Destination:            dac_d_n[7]
                            (output port clocked by dac_clk  {rise@1.000ns fall@2.000ns period=2.000ns})
  Path Group:             dac_clk
  Path Type:              Max at Slow Process Corner
  Requirement:            1.000ns  (dac_clk rise@1.000ns - clk rise@0.000ns)
  Data Path Delay:        1.930ns  (logic 1.929ns (99.948%)  route 0.001ns (0.052%))
  Logic Levels:           1  (OBUFDS=1)
  Output Delay:           0.800ns
  Clock Path Skew:        1.782ns (DCD - SCD + CPR)
    Destination Clock Delay (DCD):    4.461ns = ( 5.461 - 1.000 ) 
    Source Clock Delay      (SCD):    2.775ns
    Clock Pessimism Removal (CPR):    0.096ns
  Clock Uncertainty:      0.035ns  ((TSJ^2 + TIJ^2)^1/2 + DJ) / 2 + PE
    Total System Jitter     (TSJ):    0.071ns
    Total Input Jitter      (TIJ):    0.000ns
    Discrete Jitter          (DJ):    0.000ns
    Phase Error              (PE):    0.000ns

    Location             Delay type                Incr(ns)  Path(ns)    Netlist Resource(s)
  -------------------------------------------------------------------    -------------------
                         (clock clk rise edge)        0.000     0.000 r  
    H21                                               0.000     0.000 r  clk_p (IN)
                         net (fo=0)                   0.000     0.000    io_inst0/inst/clk_in_p
    H21                  IBUFDS (Prop_ibufds_I_O)     0.880     0.880 r  io_inst0/inst/ibufds_clk_inst/O
                         net (fo=2, routed)           0.364     1.244    io_inst0/inst/clk_in_int
    BUFIO_X0Y13          BUFIO (Prop_bufio_I_O)       1.257     2.501 r  io_inst0/inst/bufio_inst/O
                         net (fo=17, routed)          0.274     2.775    io_inst0/inst/clk_in_int_buf
    OLOGIC_X0Y162        OSERDESE2                                    r  io_inst0/inst/pins[7].oserdese2_master/CLK
  -------------------------------------------------------------------    -------------------
    OLOGIC_X0Y162        OSERDESE2 (Prop_oserdese2_CLK_OQ)
                                                      0.418     3.193 r  io_inst0/inst/pins[7].oserdese2_master/OQ
                         net (fo=1, routed)           0.001     3.194    io_inst0/inst/data_out_to_pins_int[7]
    G24                  OBUFDS (Prop_obufds_I_OB)    1.511     4.705 r  io_inst0/inst/pins[7].obufds_inst/OB
                         net (fo=0)                   0.000     4.705    dac_d_n[7]
    F24                                                               r  dac_d_n[7] (OUT)
  -------------------------------------------------------------------    -------------------

                         (clock dac_clk rise edge)    1.000     1.000 r  
    H21                                               0.000     1.000 r  clk_p (IN)
                         net (fo=0)                   0.000     1.000    io_inst0/inst/clk_in_p
    H21                  IBUFDS (Prop_ibufds_I_O)     0.840     1.840 r  io_inst0/inst/ibufds_clk_inst/O
                         net (fo=2, routed)           0.341     2.181    io_inst0/inst/clk_in_int
    BUFIO_X0Y13          BUFIO (Prop_bufio_I_O)       1.224     3.405 r  io_inst0/inst/bufio_inst/O
                         net (fo=17, routed)          0.247     3.652    io_inst0/inst/clk_in_int_buf
    OLOGIC_X0Y158        OSERDESE2 (Prop_oserdese2_CLK_OQ)
                                                      0.397     4.049 r  io_inst0/inst/clk_fwd/OQ
                         net (fo=1, routed)           0.001     4.050    io_inst0/inst/clk_fwd_out
    E26                  OBUFDS (Prop_obufds_I_O)     1.411     5.461 r  io_inst0/inst/obufds_inst/O
                         net (fo=0)                   0.000     5.461    dac_clk_p
    E26                                                               r  dac_clk_p (OUT)
                         clock pessimism              0.096     5.557    
                         clock uncertainty           -0.035     5.522    
                         output delay                -0.800     4.722    
  -------------------------------------------------------------------
                         required time                          4.722    
                         arrival time                          -4.705    
  -------------------------------------------------------------------
                         slack                                  0.016   

Hold: 

Min Delay Paths
--------------------------------------------------------------------------------------
Slack (MET) :             0.704ns  (arrival time - required time)
  Source:                 io_inst0/inst/pins[1].oserdese2_master/CLK
                            (rising edge-triggered cell OSERDESE2 clocked by clk  {rise@0.000ns fall@1.000ns period=2.000ns})
  Destination:            dac_d_p[1]
                            (output port clocked by dac_clk  {rise@1.000ns fall@2.000ns period=2.000ns})
  Path Group:             dac_clk
  Path Type:              Min at Slow Process Corner
  Requirement:            -1.000ns  (dac_clk rise@1.000ns - clk rise@2.000ns)
  Data Path Delay:        1.741ns  (logic 1.740ns (99.943%)  route 0.001ns (0.057%))
  Logic Levels:           1  (OBUFDS=1)
  Output Delay:           0.000ns
  Clock Path Skew:        2.001ns (DCD - SCD - CPR)
    Destination Clock Delay (DCD):    4.733ns = ( 5.733 - 1.000 ) 
    Source Clock Delay      (SCD):    2.636ns = ( 4.636 - 2.000 ) 
    Clock Pessimism Removal (CPR):    0.096ns
  Clock Uncertainty:      0.035ns  ((TSJ^2 + TIJ^2)^1/2 + DJ) / 2 + PE
    Total System Jitter     (TSJ):    0.071ns
    Total Input Jitter      (TIJ):    0.000ns
    Discrete Jitter          (DJ):    0.000ns
    Phase Error              (PE):    0.000ns

    Location             Delay type                Incr(ns)  Path(ns)    Netlist Resource(s)
  -------------------------------------------------------------------    -------------------
                         (clock clk rise edge)        2.000     2.000 r  
    H21                                               0.000     2.000 r  clk_p (IN)
                         net (fo=0)                   0.000     2.000    io_inst0/inst/clk_in_p
    H21                  IBUFDS (Prop_ibufds_I_O)     0.840     2.840 r  io_inst0/inst/ibufds_clk_inst/O
                         net (fo=2, routed)           0.341     3.181    io_inst0/inst/clk_in_int
    BUFIO_X0Y13          BUFIO (Prop_bufio_I_O)       1.224     4.405 r  io_inst0/inst/bufio_inst/O
                         net (fo=17, routed)          0.231     4.636    io_inst0/inst/clk_in_int_buf
    OLOGIC_X0Y176        OSERDESE2                                    r  io_inst0/inst/pins[1].oserdese2_master/CLK
  -------------------------------------------------------------------    -------------------
    OLOGIC_X0Y176        OSERDESE2 (Prop_oserdese2_CLK_OQ)
                                                      0.397     5.033 r  io_inst0/inst/pins[1].oserdese2_master/OQ
                         net (fo=1, routed)           0.001     5.034    io_inst0/inst/data_out_to_pins_int[1]
    K21                  OBUFDS (Prop_obufds_I_O)     1.343     6.377 r  io_inst0/inst/pins[1].obufds_inst/O
                         net (fo=0)                   0.000     6.377    dac_d_p[1]
    K21                                                               r  dac_d_p[1] (OUT)
  -------------------------------------------------------------------    -------------------

                         (clock dac_clk rise edge)    1.000     1.000 r  
    H21                                               0.000     1.000 r  clk_p (IN)
                         net (fo=0)                   0.000     1.000    io_inst0/inst/clk_in_p
    H21                  IBUFDS (Prop_ibufds_I_O)     0.880     1.880 r  io_inst0/inst/ibufds_clk_inst/O
                         net (fo=2, routed)           0.364     2.244    io_inst0/inst/clk_in_int
    BUFIO_X0Y13          BUFIO (Prop_bufio_I_O)       1.257     3.501 r  io_inst0/inst/bufio_inst/O
                         net (fo=17, routed)          0.277     3.778    io_inst0/inst/clk_in_int_buf
    OLOGIC_X0Y158        OSERDESE2 (Prop_oserdese2_CLK_OQ)
                                                      0.418     4.196 r  io_inst0/inst/clk_fwd/OQ
                         net (fo=1, routed)           0.001     4.197    io_inst0/inst/clk_fwd_out
    E26                  OBUFDS (Prop_obufds_I_O)     1.536     5.733 r  io_inst0/inst/obufds_inst/O
                         net (fo=0)                   0.000     5.733    dac_clk_p
    E26                                                               r  dac_clk_p (OUT)
                         clock pessimism             -0.096     5.637    
                         clock uncertainty            0.035     5.673    
                         output delay                -0.000     5.673    
  -------------------------------------------------------------------
                         required time                         -5.673    
                         arrival time                           6.377    
  -------------------------------------------------------------------
                         slack                                  0.704    

I will try your suggestion to use MMCM and oserdes and post the results.

Thank you @avrumw

 

 

 

 

0 Kudos
Highlighted
Guide
Guide
266 Views
Registered: ‎01-23-2009

Re: Artix 7 Source synchronous SDR interface for DAC at 500MHz

The only thing that looks "odd" about these timing reports is that they are at the same process corner (both are at "Slow process corner"). One would generally expect the setup and hold check to be at opposite process corners... Have you done something "odd" with the controls of the timing engine - configured it so that it is only doing timing checks at the slow process corner? This is configurable, but leads to highly optimistic results; the real performance of the device is expected to be bounded by the timing analysis done at both process corners...

Avrum

0 Kudos
Highlighted
Observer
Observer
238 Views
Registered: ‎03-14-2019

Re: Artix 7 Source synchronous SDR interface for DAC at 500MHz

On 'Timing' reports tab I can see: 

 

timer_settings.PNG

And I am running commands to generate reports: 

report_timing -setup -to [get_ports dac_clk_p]
report_timing -hold -to [get_ports dac_clk_p]  

 

0 Kudos