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: 
Highlighted
Explorer
Explorer
9,746 Views
Registered: ‎06-15-2010

ADC differential DDR interface to Spartan 6

Jump to solution

Hello!

 

I'd like to ask community for advice.

 

In our system we have Spartan 6 FPGA, namely XC6SLX100 of -2 speed grade. We have AD9643 ADC which I have to interface to. Both parts receive clocks from separate outputs of the clock distributor. ADC provides two channels in parallel. Each channel, however, operates in DDR manner, so even and odd bits are supplied at rising and falling edge of the clock. Every bit output is routed to FPGA as differential pair. Also, ADC supplies DCO signal to FPGA. At present the target is 40 MHz clock (I mean that rising and falling edges are of this 40 MHz clock), but 80 and 160 MHz are to be provided later.

 

This is a first time for me to design differential DDR interface, so I'd like community judgement, whether my self education was right.

 

PCB engineer was instructed to design DCO pair and data pairs with similar routing. So I plan to use DCO signal provided by ADC to sample data in FPGA. Since DCO comes as differential pair, I have to instantiate differential input buffer, and because that signal would clock several nets, the buffer has to be global. So having DCO inputs defined as

 

NET	"DCO_P"		LOC = U25;
NET	"DCO_N"		LOC = U26;

 I have to instantiate IBUFGDS:

 

IBUFGDS #(
      .DIFF_TERM    ("TRUE"    ), // Differential Termination
      .IOSTANDARD ("LVDS_25") // Specifies the I/O standard for this buffer
   ) IBUFGDS_ADC_DCO (
      .O  (DCO   ),  // Clock buffer output
      .I   (DCO_P),  // Diff_p clock buffer input
      .IB (DCO_N)   // Diff_n clock buffer input
   );

Next I have to input differential DDR bits. Because bit come through differential pair I have to input it using IBUFDS, I mean there is no way that tools can that for me. So, there should be something like

 

IBUFDS #(
      .DIFF_TERM    ("TRUE"     ), // Differential Termination
      .IOSTANDARD ("LVDS_25")  // Specify the input I/O standard
   ) IBUFDS_ADC_D0D1 (
      .O  (D0D1         ), // Buffer output
      .I   (IQIN_I_N[0]), // Diff_p buffer input
      .IB (IQIN_I_P[0])  // Diff_n buffer input
   );

Then output of IBUFDS have to be connected to IDDR2. If I set alignment in this component, then Q0 and Q1 outputs of IDDR2 would provide even and odd bits, which I have to latch and then resyncronize to the system clock. So it might look like

 

IDDR2 #(
      .DDR_ALIGNMENT("C1") // Sets output alignment to "NONE", "C0" or "C1"       
   ) IDDR2_D0D1 (
      .Q0 ( D0 ), // 1-bit output captured with C0 clock
      .Q1 ( D1 ), // 1-bit output captured with C1 clock
      .C0 ( DCO), // 1-bit clock input
      .C1 (~DCO), // 1-bit clock input
      .CE (1'b1), // 1-bit clock enable input
      .D  (D0D1), // 1-bit DDR data input
      .R  (1'b0), // 1-bit reset input
      .S  (1'b0)  // 1-bit set input
   );

 

My doubt is that IDDR2 primitive takes two clocks, C0 and C1, with opposite phases. I've heard, that IDDR2 has capability to make local clock inversion if I specify .C1(~DCO). But maybe I'd better use IBUFGDS_DIFF_OUT primitive and put both polarities of DCO on two global buffers? And bout presented plan, is it generally correct?

 

Comments are very appreciated.

 

Thanks in advance.

Tags (2)
0 Kudos
1 Solution

Accepted Solutions
Historian
Historian
12,649 Views
Registered: ‎01-23-2009

Re: ADC differential DDR interface to Spartan 6

Jump to solution

So, lesson 1 is that if I want to take source clocking inside FPGA, I have to use IBUFGDS-->BUFIO2-->BUFG or IBUFGDS-->BUFIO2-->CLK_IN-of-DCM chain.

 

This is structurally correct - the BUFIO2 is necessary (in most cases) to reach the BUFG and/or DCM. However I believe (and I am not an S6 expert) that the tools will infer the BUFIO2 if you connect a GCLK input to a BUFG or DCM.

 

As for source vs. synchronous interface, it is the structure of the clock connection between the source and destination device that matters. The ADC (sort of) allows either - if the ADC and FPGA have a common clock; on the ADC connected to the CLK inputs and on the FPGA connected to a GCLK input, and the DCO from the ADC is ignored, then this is a system synchronous connection. If, however, you use the DCO to clock the FPGA, then it is source synchronous (also called clock forwarded). However, looking at the ADC datasheet, it doesn't "really" support system synchronous, since it doesn't give min/max values for tPD, only typ (which is basically useless).

 

So, the proper way to clock this is to provide a "good" clock to the ADC on the CLK pins. Then, use the DCO output of the ADC as the CLK input to the FPGA (on a GCLK pair). Depending on what else is going on in your system, you might also need a different clock (on a different GCLK pin/pair), or the DCO will be the only "clock" you need.

 

Don't confuse the interface style with the mode of the DCM - they are only lightly related. In a system synchronous interface, two devices can communicate easily (in both directions) if both devices have hold times that are very small or less than 0. To enable that, Xilinx has created a mode for the DCM that adjusts the internal clock to ensure that the required hold times of the IOB FFs have near 0 hold time (this is SYSTEM_SYNCHRONOUS mode). In a source synchronous interface, the internal clock will have to be managed by the user, so you can turn off this Xilinx automatic delay by specifying the DCM to be in SOURCE_SYNCHRONOUS mode - here the hold requirement is significant, but the required setup/hold window is smaller.

 

As for the setup/hold amount provided by the ADC, ignore the tPD - its irrelevent. The only parameters that matter are the tSKEW. See the attached timing diagram - it shows the relationship of the data generated by the ADC with respect to the DCO clock. The data sheet says that there is a range to tSKEW - the actual data transition will vary from device to device, and across voltage and temperature between the range specified - i.e. between 1.1ns and 0.3ns before the edges of DCO.

 

As for the OFFSET IN - they are determined by this diagram. For the sake of argument, lets say that the PERIOD is 25ns, and the "delta" (the clock jitter and edge uncertainty) is 1ns. The data VALID time is 25/2 - 1 - 1.1 + 0.3 = 10.7

 

NET "DCO" TNM_NET = tnm_DCO;

TIMESPEC TS_DCO = PERIOD 25ns;

OFFSET = IN 0.3ns VALID 10.7ns BEFORE DCO RISING;

OFFSET = IN 0.3ns VALID 10.7ns BEFORE DCO FALLING;

 

For faster clock rates, the PERIOD will obviously change. The 0.3 will remain the same, but the VALID will change using the formula above.

 

Avrum

 

6 Replies
Historian
Historian
9,739 Views
Registered: ‎01-23-2009

Re: ADC differential DDR interface to Spartan 6

Jump to solution

Structurally, you are on the right track.

 

You have brough the DCO to a clock capable differential pair, and presumably, you have used proper differential pairs for all your data signals. You mentioned that "the buffer has to be global", but you haven't actually done anything to use a global buffer - the IBUFGDS is just an INPUT buffer - you still need to use a global clock buffer (BUFG) to distribute it globally. However, the tools will probably insert one for you, so its currently "legal".

 

However, you have not given any consideration to the timing of the data capture - and that is the most complex part of designing this interface. As a base line, I am going to refer you to another post - see the bottom half of message 4 in this thread http://forums.xilinx.com/t5/Virtex-Family-FPGAs/V4-IDDR-with-IDELAY-element-and-IOBDELAY-TYPE-DEFAULT/m-p/270792#M15320.

 

Looking at the datasheet for the AD9643 (you don't say which speed grade), tSKEW is 0.3(min) to 1.1(max), and according to the datasheet this is showing how long before the edges of DCO the data changes. Drawing this in a waveform, this means that the device provides 0.3ns of setup time, and "some" amount of hold time - the hold time is more complicated it is 1/2 clock period minus 1.1ns, but there are lots of other things to factor in

  - the worst case duty cycle of the DCO (which, I presume, is the same as the duty cycle of the input clock)

  - the jitter on the clock

 

At 40MHz, you have lots of hold time. At 120MHz, its pretty small - 3.07ns before taking out duty cycle and jitter.

 

The clocking options (and timing parameters) of a Spartan-6 are similar to the device described in the post I referenced above. Using JUST a BUFG (with no DCM/PLL) the setup/hold is Tpsfd/Tphfd = 0.39/1.28. Looking at your data window, this will (just) fail - you need 0.39ns of setup, and you only have 0.3.

 

If you use a DCM to deskew the input clock, then you have two choices (based on the DESKEW_ADJUST attribute of the DCM)

  - SYSTEM_SYNCHRONOUS Tpsdcm/Tphdcm = 1.97/0.06

  - SOURCE_SYNCHRONOUS  Tpsdcm_0/Tphdcm_0 = 0.94/0.69 - this has the smaller window, so is preferred

Neither of these timings will capture your data window as is. However, one feature of the DCM is that you can adjust the phase of the clock - in this case, you can push the internal clock forward, which will reduce the required setup time and increase the required hold time. So if you push the clock foward by at least 0.64ns, the requirements of the FPGA will now just match your data window. Of course, you would want to push it further forward to create some setup margin (particularly at 40MHz, where you have TONS of hold margin).

 

The last option - using the BUFIO only, is probably not that attractive in Spartan-6 (particularly since the IODELAY elements aren't calibrated).

 

So, it looks like using the DCM in SOURCE_SYNCHRONOUS mode with a CLKOUT_PHASE_SHIFT=FIXED, and PHASE_SHIFT of at least 7 (which results in 7/256*25ns = 0.684ns of phase shift ), is the best option.

 

Avrum

Explorer
Explorer
9,700 Views
Registered: ‎06-15-2010

Re: ADC differential DDR interface to Spartan 6

Jump to solution

Avrum,

 

Thank you very much for your detailed post. I am going to mark it as accepted answer anyway, but now I'd like to continue a little bit more.

 

The ADC in our design is AD9643-250. As I mentioned, current target is 40 MHz, which I suspect there is no magic to achieve, but 80 and 160 MHz to be next targets. So I want to learn on simpler example right now.

 

First, about IBUFGDS. In fact, I did not considered that deep and hoped output of IBUFGDS is already a global buffer. From your note I understand it is not. In ug381 I don't see enough information, wheter I can place output of IBUFGDS onto global buffer directly. I found design example by eteam00, where I see I have to use BUFIO2 to do that. So I followed to ug382 and found that "BUFIO2 takes a GCLK clock input" and that DIVCLK output of BUFIO2 can be connected to BUFG or DCM input.

So, lesson 1 is that if I want to take source clocking inside FPGA, I have to use IBUFGDS-->BUFIO2-->BUFG or IBUFGDS-->BUFIO2-->CLK_IN-of-DCM chain.

 

Next, in the referred thread I found useful considerations about system vs source synchonous interfaces. Sure, there are exception always, but lesson 2 is that source synchronous interface might have smaller uncertainties window, so that is better for faster interface. Initialy, I thought I might try to adjust phase of ADC cllock at clock distributor, so the data eye from ADC alighnes with FPGA clock, but from your explanation I see that might not work as expected. Benefit of source synchonous interface is that clock signal propahates similarly to data bits, reducing uncertainty.

 

Lesson 3 of your post is that DCO signal being input as is might not be good enough, so I have to make clock conditioning with DCM.

 

Please confirm that I got you right.

 

Timing specs still is dark side of the force to me. I've heard it hurts only first time to learn this subject, so I'd like to try better understand your calculations.

 

ADC's datasheet is not very detailed in explanations, so I'd like to have someone to verify my understanding is correct. According to AN-835, p.18

Propagation delay is the delay between the clock logic threshold (or 50% point for a differential clock input) and the time when all bits are within valid logic levels.

As per ADC datasheet this time is tPD and equals 4.8 ns behind the clock. Then DCO signal is issued after all bits in valid levels, so DCO is further behind the clock. Datasheet defines DCO-to-Data Skew (tSKEW) to be 0.3 minimum, 0.7 typical 1.1 max. So, I guess, defined just above tDCO propagation delay of 5.5 ns is 4.8 of tPD and 0.7 typical skew.

 

From here we conclude that DCO is going active no earlier, than 0.3 ns after data settle. In your post I am confused by the phase:

Looking at the datasheet for the AD9643 (you don't say which speed grade), tSKEW is 0.3(min) to 1.1(max), and according to the datasheet this is showing how long before the edges of DCO the data changes.

Did you really mean that tSKEW is amount of time the data are steady before DCO edge? If so, then samplng data with a flip-flop, the amount of time the data are steady before the clock edge would be setup time. In other words, if I had a filp-flop directly connected to DCO and data line of ADC, then that flip-flop must have setup time less than 0.3 ns. If it needs more, then sampling edge must be shifted behind, allowing more setup time to the flip-flop. Is this understanding correct?

As to hold time, we have to find out how long data remains steady after DCO. I don't clearly undestand why hold time is more complicated it is 1/2 clock period minus 1.1ns. Suppose perfect clock. Then DCO timing is defined by propagation delay and skew of ADC. With propagation delay of 4.8 ns and skew in range of 0.3~1.1 ns DCO signal goes active somewhere between 4.8+0.3=5.1 and 4.8+1.1=5.9 ns after corresponding clock edge. Assuming perfect 50% duty cycle of the clock the worst condition may happen when positive DCO had maximum delay after rising edge and negative DCO had minimum delay after faling edge of the clock. Assume 40 MHz clock, rising at 0. Then positive DCO would happen at 5.9 ns, and negative at 25/2+5.1=17.6 ns. The difference between them is VALID time and it is 11.7 ns, which is half period = 12.5 ns minus (max_skew - min_skew)=(1.1-0.3)=0.8 ns. Then for 80 MHz I would have 6.25-0.8=5.45 ns valid window and for 160 MHz that would be 3.125-0.8=2.325 ns. Isn't this calculation correct? May I use it for OFFSET IN constraint? 

 

Next as I understand I have to shift DCO edge in a way, that it allows enough setup time for FPGA and keep it withing VALID window in a way, that allows enough hold time.

 

I found numbers of setup/hold times in switching characteristics data sheet. I wonder, if I understand Table 71: Global Clock Setup and Hold Without DCM or PLL (Default Delay) of ds162 right. Tables 71, 72 and so on  just say, that if I clock input FF with globall buffer, it requires TPSFD/ TPHFD time, if I condition the clock with DCM in system synchronous mode, same flip-flop would need TPSDCM/ TPHDC times and so on. As setup+hold define minimum valid window, we find that DCM source syncronous mode provide the smallest requirement.

 

Please comment.

 

Thanks in advance.

0 Kudos
Historian
Historian
12,650 Views
Registered: ‎01-23-2009

Re: ADC differential DDR interface to Spartan 6

Jump to solution

So, lesson 1 is that if I want to take source clocking inside FPGA, I have to use IBUFGDS-->BUFIO2-->BUFG or IBUFGDS-->BUFIO2-->CLK_IN-of-DCM chain.

 

This is structurally correct - the BUFIO2 is necessary (in most cases) to reach the BUFG and/or DCM. However I believe (and I am not an S6 expert) that the tools will infer the BUFIO2 if you connect a GCLK input to a BUFG or DCM.

 

As for source vs. synchronous interface, it is the structure of the clock connection between the source and destination device that matters. The ADC (sort of) allows either - if the ADC and FPGA have a common clock; on the ADC connected to the CLK inputs and on the FPGA connected to a GCLK input, and the DCO from the ADC is ignored, then this is a system synchronous connection. If, however, you use the DCO to clock the FPGA, then it is source synchronous (also called clock forwarded). However, looking at the ADC datasheet, it doesn't "really" support system synchronous, since it doesn't give min/max values for tPD, only typ (which is basically useless).

 

So, the proper way to clock this is to provide a "good" clock to the ADC on the CLK pins. Then, use the DCO output of the ADC as the CLK input to the FPGA (on a GCLK pair). Depending on what else is going on in your system, you might also need a different clock (on a different GCLK pin/pair), or the DCO will be the only "clock" you need.

 

Don't confuse the interface style with the mode of the DCM - they are only lightly related. In a system synchronous interface, two devices can communicate easily (in both directions) if both devices have hold times that are very small or less than 0. To enable that, Xilinx has created a mode for the DCM that adjusts the internal clock to ensure that the required hold times of the IOB FFs have near 0 hold time (this is SYSTEM_SYNCHRONOUS mode). In a source synchronous interface, the internal clock will have to be managed by the user, so you can turn off this Xilinx automatic delay by specifying the DCM to be in SOURCE_SYNCHRONOUS mode - here the hold requirement is significant, but the required setup/hold window is smaller.

 

As for the setup/hold amount provided by the ADC, ignore the tPD - its irrelevent. The only parameters that matter are the tSKEW. See the attached timing diagram - it shows the relationship of the data generated by the ADC with respect to the DCO clock. The data sheet says that there is a range to tSKEW - the actual data transition will vary from device to device, and across voltage and temperature between the range specified - i.e. between 1.1ns and 0.3ns before the edges of DCO.

 

As for the OFFSET IN - they are determined by this diagram. For the sake of argument, lets say that the PERIOD is 25ns, and the "delta" (the clock jitter and edge uncertainty) is 1ns. The data VALID time is 25/2 - 1 - 1.1 + 0.3 = 10.7

 

NET "DCO" TNM_NET = tnm_DCO;

TIMESPEC TS_DCO = PERIOD 25ns;

OFFSET = IN 0.3ns VALID 10.7ns BEFORE DCO RISING;

OFFSET = IN 0.3ns VALID 10.7ns BEFORE DCO FALLING;

 

For faster clock rates, the PERIOD will obviously change. The 0.3 will remain the same, but the VALID will change using the formula above.

 

Avrum

 

Explorer
Explorer
9,674 Views
Registered: ‎06-15-2010

Re: ADC differential DDR interface to Spartan 6

Jump to solution

Avrum,

 

Thank you very much for detailed explanation again and for diagram in the attachment. Now thins begin to line up in my head. I see where valid window comes from and how to tell tools about it.

 

Especially important note was that my ADC is not well described for the system synchronous design with reasonable high speed. I did not think that way before your bright explanation.

 

So, I gues, I am almost ready to code and check. One thing which is still unclear to me is clock domain crossing.

 

From the last post there is an option to use the only clock defined by DCO input from ADC. That is simple approach but I doubt whether that is really good enough for high speed design. I know DCM is doing magic with clocks, but as we saw in ADC datasheet DCO has significant skew margins. In our system we use clock generator and clock distributor just to be able to feed FPGA, ADCs and DACs with high quality clock. And I have my own interest to try more complicated approach.

 

As I understand my current situation, though FPGA and ADC receive clock from the same source, FPGA internal clock produced with DCM and DCO signal from ADC, also conditioned with DCM, have same frequecy, but because their transitions are not aligned, these clocks constitute independet clock domains. Using IDDR2 primitive I can capture data in DCO clock domain. However, to work with sampled data in FPGA I have to transfer them to FPGA's internal clock domain. Because routing from clock distributor to FPGA clock input and from ADC to DCO input are different, mentioned two clocks might be shifted arbitrarily. Without measurements I canot tell more about their relationship.

 

So how can I resynchronize input data from DCO clock domain to FPGA's internal clock domain?

 

Thanks.

0 Kudos
Historian
Historian
9,672 Views
Registered: ‎01-23-2009

Re: ADC differential DDR interface to Spartan 6

Jump to solution

If you do need to move the data to the "main" clock domain, you will need to do clock crossing. The easiest way to do this is using a clock crossing FIFO. Since the two clocks have the same frequency, and only differing phase (hence are "mesochronous"), only a small FIFO is necessary; this can easily be implemented in distributed RAM. The Core Generator can help you build the FIFO.

 

The only minor complexity is if you want your data on the main domain to be continuous. As you mentioned, the two clocks are synchronous, only the phase differs. However, the phase can vary over time within a certain range. Therefore, if you just use !empty as the read_enable for your FIFO, there is the possibility that you may get gaps in the data as the phase of the two clock change - the number of gaps is finite; after a RESET, you can get 2 maybe 3, but never more than that. To avoid this, simply make sure your FIFO fills up "a bit" before starting to read out of the FIFO. So, on reset, start writing into the FIFO, but don't start reading until some data has been built up. Simply wait a few clocks after the first deassertion of empty before you start reading from the FIFO. Since the skew between the two clocks can't change by more than a couple of ps, it should be sufficient to build up 2 or 3 data in the FIFO before reading - if latency isn't an issue, I would wait more like 4-8 cycles...

 

Avrum

Explorer
Explorer
9,669 Views
Registered: ‎06-15-2010

Re: ADC differential DDR interface to Spartan 6

Jump to solution
Avrum,

Thanks again for the clear explanation. I've got idea, the rest is implementation challenge, I hope.

PS
Perhaps its a first time to me when I get replies on the forum and every word in those replies is relevant, clear and very useful. Thank you very much!
0 Kudos