cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Visitor
Visitor
10,184 Views
Registered: ‎08-07-2013

Multiple ADC on Virtex 6

Jump to solution

Hello,

 

In my project I have to interface to 16 quad ADCs (ADS6442). In order to be able to connect an equal amount of DAC channels to a single FPGA, I am using the ADCs in 1-wire mode. The sampling rate for the A/D conversion is with 30MHz relatively low and results in a bitclock of only 240MHz.

 

For the implementation I started with the application notes XAPP866 and XAPP1071. However I found there was an issue with the 'double nibble' detection for the 1-wire mode. Therefore, I was looking into XAPP524, that contained a different mechanism for this detection.

 

I have then adopted XAPP524 and modified it to work for the Virtex 6 I am using.


I am however observing a very strange behaviour when I monitor the detected FRAME pattern that the code is providing.

 

a) Looking at all 16 ADC FRAME patterns, I can see that some are shifted by one or two bits, but never are all the expected 0xFF00. I can observe a 0xFE01 as well as 0xFD02 to give two examples.

 

b) It is not always the same channels showing the 'wrong' FRAME pattern. After a reset, different channels show the wrong pattern. It seems to be completely random.

 

c) If the solid state machine is synchrinized to the correct pattern (0xFF00 in my case), an analog, sinusoidal signal connected to the ADC is correctly converted into its digital counterpart - but the result is screwed up in all other cases.

 

My local FAE has tried to contact the author of the above application notes a couple of times but we have not received any response yet (after a month).

 

Today I am reaching out into this community to see if someone has used the XAPP524 in the past and/or has a suggestion where I could find a solution to this problem.

 

Thank you,

0 Kudos
Reply
1 Solution

Accepted Solutions
Visitor
Visitor
12,394 Views
Registered: ‎01-09-2014

Hi,

 

I am guessing this post is a bit late, but I just started trying to use XAPP524 and observed similar behavior as you describe even using the included simulation files.

 

I believe there is a bug in the bitslip state machine.  It looks to me like if the need to swap is detected, then the final bitslip should be the opposite of what is in the state machine, e.g.., if the next-to-last bitslip before a match was found was a bitslip_p, the state machine always calls for the final bitslip to be a bitslip_n but actually if the need to swap is detected, a second bitslip_p should be performed.  Similarly, if the next-to-last bitslip was a bitslip_n, then the state machine calls for a bitslip_p, but this is only true if swap is not needed.

 

I don't know if this is your exact issue, as I only see an issue when the frame logic detects the need to use the swap mux. If no swap was necessary, the frame phase would be detected properly using the state machine as-is.  Starting off with a perfectly aligned frame would also work (as you saw), since no bitslips are necessary.

 

Here is my changed bitslip state machine in AdcFrame.vhd (I added all the if-then blocks as a quick/dirty check - this may not be the most elegant solution) :

 

AdcFrame_Bitslip_PROCESS : process (IntFrmReSyncOut, FrmClkDiv)
subtype IntFrmBitSlipCase is std_logic_vector(5 downto 0);
begin
  if (IntFrmReSyncOut = High) then
    IntFrmBitSlip <= (others => '0');
  elsif (FrmClkDiv'event and FrmClkDiv = '1') then
    if (IntFrmEna = High and IntFrmEquSet_d = Low) then
      case IntFrmBitSlipCase'(IntFrmEqu_d, IntFrmEvntCntTc_d, IntFrmBitSlip(5),
                                                   IntFrmBitSlip(4), IntFrmBitSlip(3), IntFrmBitSlip(2)) is
        when "000000" => IntFrmBitSlip <= "000000"; -- B
        when "010000" => IntFrmBitSlip <= "000101"; -- C Slip_p
        when "000001" => IntFrmBitSlip <= "000100"; -- D
        when "010001" => IntFrmBitSlip <= "001010"; -- E Slip_n
        when "000010" => IntFrmBitSlip <= "001000"; -- F
        when "010010" => IntFrmBitSlip <= "000101"; -- G Slip_p and goto D
        --
        when "100000" => if IntFrmSwapMux_d = '0' then
                                            IntFrmBitSlip <= "000000";
                                          else
                                            IntFrmBitSlip <= "000100"; -- H
                                          end if;
        when "110000" => IntFrmBitSlip <= "100101"; -- K Slip_p
        when "101001" => IntFrmBitSlip <= "110000"; -- L EquSet
        when "101100" => IntFrmBitSlip <= "110000"; -- M Halt
        --
        when "100001" => if IntFrmSwapMux_d = '0' then
                                            IntFrmBitSlip <= "000100";
                                          else
                                            IntFrmBitSlip <= "001000"; -- N
                                          end if;
        when "110001" => IntFrmBitSlip <= "101010"; -- P Slip_n
        when "101010" => IntFrmBitSlip <= "110000"; -- R EquSet goto M
        --
        when "100010" => if IntFrmSwapMux_d = '0' then
                                            IntFrmBitSlip <= "001000";
                                          else
                                            IntFrmBitSlip <= "000100"; -- S
                                          end if;
        when "110010" => IntFrmBitSlip <= "100101"; -- T Slip_p goto L
        --
        when others => IntFrmBitSlip <= "110000";
      end case;
    end if;
  end if;
end process;

 

With this change, the testbench now works - I have yet to put this to the test in the lab on real HW, but will be doing so soon.

 

Hope this helps,

Mike B.

View solution in original post

10 Replies
Teacher
Teacher
10,165 Views
Registered: ‎08-14-2007

Hi,

first question that comes up?

How does your PCB look like?

 

Do you use matched delay tracks for the LVDS pairs?

Do all ADCs get the same Clock? Is it skew free?

Have all ADC data lines the same delay?

 

Do you have reflections on the "just 120 MHz" data lines

(If the signals are not already almost sinusoidal remember that a rectangular wave carries frequencies of at least 5 times higher bandwidth)

 

And inside the FPGA:

Are the input signals going to FFs inside the IOBs or is there some input delay that differs for each channel?

 

At these datarates you get in touch with the analog world, which make things a little more difficult to analyze.

 

Have a nice synthesis

 

    Eilert

 

0 Kudos
Reply
Visitor
Visitor
12,395 Views
Registered: ‎01-09-2014

Hi,

 

I am guessing this post is a bit late, but I just started trying to use XAPP524 and observed similar behavior as you describe even using the included simulation files.

 

I believe there is a bug in the bitslip state machine.  It looks to me like if the need to swap is detected, then the final bitslip should be the opposite of what is in the state machine, e.g.., if the next-to-last bitslip before a match was found was a bitslip_p, the state machine always calls for the final bitslip to be a bitslip_n but actually if the need to swap is detected, a second bitslip_p should be performed.  Similarly, if the next-to-last bitslip was a bitslip_n, then the state machine calls for a bitslip_p, but this is only true if swap is not needed.

 

I don't know if this is your exact issue, as I only see an issue when the frame logic detects the need to use the swap mux. If no swap was necessary, the frame phase would be detected properly using the state machine as-is.  Starting off with a perfectly aligned frame would also work (as you saw), since no bitslips are necessary.

 

Here is my changed bitslip state machine in AdcFrame.vhd (I added all the if-then blocks as a quick/dirty check - this may not be the most elegant solution) :

 

AdcFrame_Bitslip_PROCESS : process (IntFrmReSyncOut, FrmClkDiv)
subtype IntFrmBitSlipCase is std_logic_vector(5 downto 0);
begin
  if (IntFrmReSyncOut = High) then
    IntFrmBitSlip <= (others => '0');
  elsif (FrmClkDiv'event and FrmClkDiv = '1') then
    if (IntFrmEna = High and IntFrmEquSet_d = Low) then
      case IntFrmBitSlipCase'(IntFrmEqu_d, IntFrmEvntCntTc_d, IntFrmBitSlip(5),
                                                   IntFrmBitSlip(4), IntFrmBitSlip(3), IntFrmBitSlip(2)) is
        when "000000" => IntFrmBitSlip <= "000000"; -- B
        when "010000" => IntFrmBitSlip <= "000101"; -- C Slip_p
        when "000001" => IntFrmBitSlip <= "000100"; -- D
        when "010001" => IntFrmBitSlip <= "001010"; -- E Slip_n
        when "000010" => IntFrmBitSlip <= "001000"; -- F
        when "010010" => IntFrmBitSlip <= "000101"; -- G Slip_p and goto D
        --
        when "100000" => if IntFrmSwapMux_d = '0' then
                                            IntFrmBitSlip <= "000000";
                                          else
                                            IntFrmBitSlip <= "000100"; -- H
                                          end if;
        when "110000" => IntFrmBitSlip <= "100101"; -- K Slip_p
        when "101001" => IntFrmBitSlip <= "110000"; -- L EquSet
        when "101100" => IntFrmBitSlip <= "110000"; -- M Halt
        --
        when "100001" => if IntFrmSwapMux_d = '0' then
                                            IntFrmBitSlip <= "000100";
                                          else
                                            IntFrmBitSlip <= "001000"; -- N
                                          end if;
        when "110001" => IntFrmBitSlip <= "101010"; -- P Slip_n
        when "101010" => IntFrmBitSlip <= "110000"; -- R EquSet goto M
        --
        when "100010" => if IntFrmSwapMux_d = '0' then
                                            IntFrmBitSlip <= "001000";
                                          else
                                            IntFrmBitSlip <= "000100"; -- S
                                          end if;
        when "110010" => IntFrmBitSlip <= "100101"; -- T Slip_p goto L
        --
        when others => IntFrmBitSlip <= "110000";
      end case;
    end if;
  end if;
end process;

 

With this change, the testbench now works - I have yet to put this to the test in the lab on real HW, but will be doing so soon.

 

Hope this helps,

Mike B.

View solution in original post

Visitor
Visitor
9,905 Views
Registered: ‎08-07-2013

Hi Mike,

 

I can confirm your suggestion. After having a closer look into the sync procedure myself,  I also found that under certain circumstances there is one bitslip operation carried out too much.

 

I modified the AdcFrame_Bitslip_PROCESS in such way that the additional bitslip is ignored. - So far it works fine and I have not observed any side effects - all 64 channels work.

 

Thanks,

AF

 

0 Kudos
Reply
Visitor
Visitor
9,900 Views
Registered: ‎01-09-2014
Interesting - that doesn't sound like what I was seeing. I was seeing that the bitslip was necessary, just that it was being applied to the wrong ISERDES in the case of needing to swap.

I guess I will have to see how this works in the lab. Glad to hear you got it working for you.

MB
0 Kudos
Reply
Adventurer
Adventurer
9,604 Views
Registered: ‎11-04-2009

Hi,

 

I have the same problem with Virtex7 and 125MHz 16 channels ADCs. In my occasion (2 lanes, 16-bits) the frame pattern is either F0 (correct) or 78(wrong). The results are from real hardware design which i observe in Chipscope.

 

What is finally the case? Is an extra bitslip applied in some cases or it has to do with the need of a swap? Mike did you find a solution? 

 

Mike did your solution worked? I tested but the circuit had the same behavior.

 

Freibert what exactly did you change in the AdcFrame_Bitslip_Process and got a design that works?

 

Thank you in advance,

 

Lefteris

 

0 Kudos
Reply
Historian
Historian
9,600 Views
Registered: ‎02-25-2008

@nola94 wrote:

Hi,

 

I have the same problem with Virtex7 and 125MHz 16 channels ADCs. In my occasion (2 lanes, 16-bits) the frame pattern is either F0 (correct) or 78(wrong). The results are from real hardware design which i observe in Chipscope. 


Note that 0xF0 is just 0x78 shifted one bit to the left. So your bitslip on the channel which gives you 0x78 needs to go one more time, or maybe it did its thing one extra time. 

 

You have a bitslip state machine for each lane, yes?

----------------------------Yes, I do this for a living.
0 Kudos
Reply
Adventurer
Adventurer
9,591 Views
Registered: ‎11-04-2009

No, there is one bitslip state machine as described above by Mike.

 

I know that the pattern is shifted by one thus indicating that one more bitslip operation is occur. However is not clear from the code where this is happening. 

 

Lefteris

0 Kudos
Reply
Historian
Historian
9,585 Views
Registered: ‎02-25-2008

@nola94 wrote:

No, there is one bitslip state machine as described above by Mike.

 


You need one bitslip machine per lane! 

----------------------------Yes, I do this for a living.
0 Kudos
Reply
Visitor
Visitor
9,582 Views
Registered: ‎01-09-2014

Hi Lefteris,

 

Sorry - I should have updated my post.  I did need to update the bitslip process, but the example in my previous post was incorrect.  My latest is below, and this does work on real HW. Basically, the case statement needs to include whether or not you are swapping in order to apply the bitslip in the right directioon.

 

That said, I gave up on using this XAPP, as even though I fixed the framing logic, the function to find the right sampling point did not work correctly.  I started to investigate and then just gave up and rolled my own solution.  It may not work at the highest rates as advertised  by the XAPP, but as it turns out, I don't need it to.

 

Here is my updated code below:

 

AdcFrame_Bitslip_PROCESS : process (IntFrmReSyncOut, FrmClkDiv)
  subtype IntFrmBitSlipCase is std_logic_vector(5 downto 0);
begin
  if (IntFrmReSyncOut = High) then
    IntFrmBitSlip <= (others => '0');
  elsif (FrmClkDiv'event and FrmClkDiv = '1') then
    if (IntFrmEna = High and IntFrmEquSet_d = Low) then
      case IntFrmBitSlipCase'(IntFrmEqu_d, IntFrmEvntCntTc_d, IntFrmBitSlip(5), IntFrmBitSlip(4), IntFrmBitSlip(3), IntFrmBitSlip(2)) is
        when "000000" => IntFrmBitSlip <= "000000"; -- B
        when "010000" => IntFrmBitSlip <= "000101"; -- C Slip_p
        when "000001" => IntFrmBitSlip <= "000100"; -- D
        when "010001" => IntFrmBitSlip <= "001010"; -- E Slip_n
        when "000010" => IntFrmBitSlip <= "001000"; -- F
        when "010010" => IntFrmBitSlip <= "000101"; -- G Slip_p and goto D
        --
        when "100000" => IntFrmBitSlip <= "000000"; -- H
        when "110000" =>

          if IntFrmSwapMux_d = '0' then
            IntFrmBitSlip <= "100101"; -- K Slip_p
          else
            IntFrmBitSlip <= "100110"; -- K Slip_n
          end if;
        when "101001" => IntFrmBitSlip <= "110000"; -- L EquSet
        when "101100" => IntFrmBitSlip <= "110000"; -- M Halt
        --
        when "100001" => IntFrmBitSlip <= "000100"; -- N
        when "110001" =>

          if IntFrmSwapMux_d = '0' then
            IntFrmBitSlip <= "101001"; -- P Slip_p
          else
            IntFrmBitSlip <= "101010"; -- P Slip_n
          end if;
        when "101010" => IntFrmBitSlip <= "110000"; -- R EquSet goto M
        --
        when "100010" => IntFrmBitSlip <= "001000"; -- S
        when "110010" =>

          if IntFrmSwapMux_d = '0' then
            IntFrmBitSlip <= "100101"; -- T Slip_p goto L
          else
            IntFrmBitSlip <= "100110"; -- T Slip_n goto L
          end if;
        --
        when others => IntFrmBitSlip <= "110000";
      end case;
    end if;
  end if;
end process;

 

Hope this is useful,

Mike B.

 

0 Kudos
Reply
Adventurer
Adventurer
2,921 Views
Registered: ‎11-04-2009

Thank you Mike,

 

You rarely find someone to give part of his code online...

 

However, it was not worked for me, as sometimes (rarely) the output frame pattern is B4(hex). I observe signals on Chipscope. 

 

What board had you used?

 

Regards,

Lefteris

 

 

0 Kudos
Reply