Showing results for 
Show  only  | Search instead for 
Did you mean: 
Registered: ‎05-04-2016

Time Constraining design to interface with an ADC, design uses three cloks: AXI_CLK, ADC_CLK and DCO_CLK

I am working on a project that interfaces an AD7626 Evaluation board to a Xilinx ARTIX FPGA (the FPGA is in a NEXYS VIDEO board from Digilent).  I am having problems meeting the timing requirements of my design.


I am working in the Vivado Webpack development environment. My design is built around the Microblaze softcore processor and my interfacing between modules is done via the AXI buses and protocol.


The AD7626 is an ADC and it interfaces with the host via 3 sets of LVDS lines:  CLK, DCO and D(ata).  The image below shows the block diagram with the module I created in Verilog interfacing with the AD7626Interfacing with the AD7626.JPG

 Note that MY_INTERFACE receives 3 clocks:  The AXI_CLK (to interface with the rest of the modules in the  microblaze based design,  the ADC_CLK (in the diagram I call it CLK_FOR_ADC) and the DCO_CLK, (the last two are related as indicated below) The AXI_CLK and the ADC_CLK may have different frequencies, but in general they should be about the same order of magnitude.   My biggest problem right now is how can I safely constrain the DCO_CLK and how to ensure my clock domains crossing are safe too.


The adc_sr_clk is a train of 16 pulses at the same frequency and in phase with ADC_CLK.  This is used to extract the digitized data in serial form from the AD7626 shortly after it received the CNV  (convert or digitize) pulse.  The buffers BUFG, IBUFDS etc.are used to convert from LVDS to the levels used inside the FPGA.


Below is the timing diagram of the AD7626 signals. Note that the DCO_CLK signal is delayed from the CLK signal by 1/4 of a period, and that the middle of the data "eyes" is aligned with the rising edge of DCO_CLK


 AD7626 Timings.JPG


I used a Clock_wizard to generate the AXI_CLK (100MHz) and the ADC_CLK (100MHz).  I understand that Vivado will create automatically determine that these two will be generated clocks (derived from the board'clock: 100MHz).  To constrain the DCO I first created a clock with the timing wizard


create_clock -period 10.000 -name dco_clk -waveform {0.000 5.000} [get_ports dco_clk_p]


Then to indicate that DCO_CLK was delayed from ADC_CLK by about 1/4 of a period (2.5ns) I used the set_clock_latency constraint


set_clock_latency -clock [get_clocks dco_clk] -source -early 2.300 [get_ports dco_clk_p]
set_clock_latency -clock [get_clocks dco_clk] -source -late   2.700 [get_ports dco_clk_p]






Could someone please tell me if I am doing this constrining correct?  The timing analyzer fails:there is a Hold timing problem between the ADC_CLK and the AXI_CLK, but both clocks run at the same frequency and since they originate from the same CLK_WIZARD block they should have teh same phase.


I also have timing problems with teh oserdes_clk   to   oserdes_clkdiv   I do not have an idea of what this error means, I am not familiar with the oserdes...




Below is a rough block diagram of my overall system


Overall Diagram.JPG





0 Kudos
1 Reply
Registered: ‎01-23-2009

First, it would be helpful if you showed the tables from the ADC datasheet that showed the values for the timing paramaters (tDCO, tCLKD, tD).


Next we need to understand what you plan to do with this. For many ADC interfaces, we ignore any possible timing relationship between CLK and DCO; we do the interface capture with DCO, and if we need to move the data back to a global domain, we use clock crossing techniques (a mesochronous clock crossing FIFO).


To do this, you simply create a clock on dco_clk_p, and use that clock for your set_input_delays. You also independently constrain the other clocks, and ensure that you put proper clock crossing FIFOs between them.


However, at 100MHz SDR (which is quite slow) we may be able to do things differently (but also maybe not).


I don't know which other clock you are planning to use for the capture clock; presumably you are capturing the data on dco_clk (after the BUFG), but what are you doing with it from there? Transferring it to CLK_FOR_ADC or directly to AXI_CLK?


If it is going to AXI_CLK, then you must use clock crossing.


If it is going to CLK_FOR_ADC, then you need to specify the (fairly complex) relationship between CLK_FOR_ADC, adc_sr_clk, and dco_clk_p.


To be honest, I am not sure how to do this. Creating the clock the ADC is easy - it is a generated clock from the ODDR.


create_generated_clock -name ADC_CLK -divide_by 1 -source [get_pins <ODDR_instance_name>/C] [ get_ports ADC_CLK]


[edit: This used to read -combinational instead of -divide_by 1. See this post as for why the -combinational is incorrect]


But now you need to create a combinatorial connection from ADC_CLK to DCO_CLK, and I am not certain how to do this... Maybe with a set_output_delay or set_input_delay or set_external_delay (although none of these is really correct).


Assuming this connection can be made, then you can use the set_clock_latency command to describe the propagation delay along the path you created - but to do this, you first need to create the path; the set_clock_latency command just says that a clock passing through a point (net, pin or port) experiences a delay - you first have to get the clock to pass through that point.



0 Kudos