[SOLVED] Adc interface with FPGA

Status
Not open for further replies.

verylsi

Full Member level 2
Joined
Mar 12, 2012
Messages
123
Helped
16
Reputation
32
Reaction score
16
Trophy points
1,308
Visit site
Activity points
2,130
Hello all,

The FPGA and ADC are communicating as follows :

FPGA asserts convert_start for 14 us , ADC sends ADC_busy signal 60 ns after the rising edge of convert_start and adc_busy remains high for 3 us.
After that FPGA reads data from the data lines.

In current running code : fpga asserts convert_start and waits for 5 us and assumes that adc_busy signal must have come and gone by 5 us.

Now I need to check the ADC_busy signal for 100 ns and if the adc_busy did not go high with in 100 ns, then the adc should be reset.

It sounds simple but as soon as I check for adc_busy signal the adc_busy signal stops coming at all.
New logic works fine with simulation.

My question is that ADC checks only for convert_start signal and after that within 60 ns it sends adc_busy signal.
Adc_busy signals are coming in the previous code then what could make adc stop responding with only checking the adc_busy?

I gone through the data sheet 20 times by now ...

( I cannot post the code for specific reasons )

Thanks
 

If all you do is post a summary of what you think the ADC requires and what you think you've designed to interface with it, you're not going to get any help. Maybe you're misinterpreting the data sheet (20 times).

As you can't give us any information to help. Use something like ChipScope and/or SignalTap to see inside the FPGA or if you don't have those tools use spare pins and soldered on wires to look at the signals on a logic analyzer or DSO.
 

It sounds simple but as soon as I check for adc_busy signal the adc_busy signal stops coming at all.
No it doesn't, the ADC response is not changed by the FPGA reading the busy signal output. Rest assured that the problem is with your code, not the ADC.
New logic works fine with simulation.
Any synthesis message about incomplete sensitivity list? Do you have any processes that are not clocked?
My question is that ADC checks only for convert_start signal and after that within 60 ns it sends adc_busy signal.
Adc_busy signals are coming in the previous code then what could make adc stop responding with only checking the adc_busy?
- Maybe you're driving ADC_busy and not just using it as an input
- Maybe you stopped sending the start signal
- Maybe you clocked out only part of the previous conversion and the ADC is waiting for you to take all of that before starting another

You stated that the simulation works fine but
- Are you using a model for the ADC?
- Did that model come from the manufacturer or someplace like Free Model Foundation?

I gone through the data sheet 20 times by now
Then there is something that has eluded you 20 times. Have you matched up every input signal in the sim to verify that it exactly matches what is shown in the data sheet 20 times? More than once?

Kevin Jennings
 
Reactions: verylsi

    verylsi

    Points: 2
    Helpful Answer Positive Rating
Yes , even I believe , it has to do with FPGA.

I am not driving adc_busy. start signal is coming as I checked on DSO.

I have not using simulation model, so yes , I cannot be 100% sure about it.

Please elaborate your followning statement, I am not clear with this.
" Maybe you clocked out only part of the previous conversion and the ADC is waiting for you to take all of that before starting another"

Thanks a lot.
 

I have not using simulation model, so yes , I cannot be 100% sure about it.
Get a model.
Please elaborate your followning statement, I am not clear with this.
" Maybe you clocked out only part of the previous conversion and the ADC is waiting for you to take all of that before starting another"
I'm assuming you're using a serial output ADC. If the ADC expects 16 clocks and you give it only 15 maybe you don't get to start a new conversion... I dunno since you haven't provided any info.

What you need to do to get any sort of relevant response in this forum besides random guessing like I'm doing is
- Post a link to the ADC data sheet
- Post a screenshot of all of the ADC to FPGA signals
- If there is any special ADC setup not shown, describe it.
- Answer my earlier question about unlocked processes in your source code. Those can be a source of "...but it works fine in simulation".

Kevin Jennings
 
Last edited:

Hi,

The partnumber of adc could help.
Screenshots of your digital signals could help.

Klaus
 

No I am not having serial interface, its a 16 bit parallel interface .

following is the link for data sheet ADC 7656
HTML:
http://www.analog.com/en/analog-to-digital-converters/ad-converters/ad7656/products/product.html

currently in one condition adc_busy is coming , but I still need your help -

I am able to reset the device when I am sending convert_start and checking for 5 us and
if adc_busy is not coming then I am resetting the device hoping that the adc should recover
and start sending adc_busy again. and I am successful in doing so.

But I need to keep on resetting the ADC until adc_busy comes, When I try to do that,
ADC_BUSY stops coming from ADC. ADC_BUSY is an input port to FPGA, so FPGA cannot drive ADC_BUSY pin.

I am posting both the codes, one which is working and one which is not working. P
lease suggest me where am I wrong in the implementation.

Also even if I try to modify 1 line from the current working code, the ADC_BUSY stops coming.


---- this code is working but is capable of resetting only until all adc_busy goes high.
---- required implementation is to keep on resetting every 5 us until all adc_busy goes high.

p_Rst_frm_RCI_reg: process(int_clk_100mhz) is
begin
if(falling_edge(int_clk_100mhz))then
if (adc_reset_busy_error = '1' and adc_reset_busy_error_dly = '0') then
adc_reset_busy_error_sig <= '1' ;
elsif adc_reset_busy_error_clr = '1' then
adc_reset_busy_error_sig <= '0' ;
end if;
end if;
end process p_Rst_frm_RCI_reg;

--- state machine starts -----
case adc_state is
when idle_state =>
if(rci_start_acq_fl = '1' or adc_reset_busy_error_sig = '1') then
if(adc_rst_bsy_cnt = ADC_RESET_DURATION)then
adc_convst_sig <= (others => '0');
adc_rst_bsy_cnt <= (others => '0');
adc_reset <= '0';
adc_state <= convst_state;
adc_reset_busy_error_clr <= '1' ;
else
adc_convst_sig <= (others => '1'); -- Must be high during reset
adc_rst_bsy_cnt <= adc_rst_bsy_cnt + '1';
adc_reset <= '1';
adc_state <= idle_state;
end if;
else
adc_convst_sig <=(others => '0');
adc_state <= idle_state;
end if;

when convst_state =>
adc_reset_busy_error_clr <= '0' ;
if(frac_sec_count = 0) then -- checking for pps edge
adc_state <= adc_busy_state;
else
adc_convst_sig <= (others => '0');
adc_state <= convst_state;
end if;

when adc_busy_state =>
adc_convst_sig <= adc_convst_out; ---- sending convert_start signal to ADC
if (adc_const_int1 = '1' and adc_const_int2 = '1' ) then
if(adc_rst_bsy_cnt < BUSY_STATE_DURATION) then -- waits for 5 us
adc_rst_bsy_cnt <= adc_rst_bsy_cnt + '1';
adc_state <= adc_busy_state;
elsif (adc_busy_high = '1' ) then
adc_reset_busy_error <= '0';
adc_state <= adc_cs_state;
adc_rst_bsy_cnt <= (others => '0');
else
-- if adc_busy doesn't go high even after 5us after conver_start
-- then adc_reset_busy_error goes high.
-- but fpga will still go to next state and after completion of 1 complete
-- data cycle it will go to idle state where it will reset the ADC

adc_reset_busy_error <= '1';
adc_state <= adc_cs_state;
adc_rst_bsy_cnt <= (others => '0');
end if;
else
convst_en1 <= '1' ; -- Enable to generate convert start
convst_en2 <= '1' ;
end if;

----- continue with other states ----------



------------------ Modified code , the following code doesn't work ---------------------

p_Rst_frm_RCI_reg: process(int_clk_100mhz) is
begin
if(falling_edge(int_clk_100mhz))then
if (adc_reset_busy_error_dly = '1') then ---- checking for level
adc_reset_busy_error_sig <= '1' ; ---- rather than checking for edge.
else
adc_reset_busy_error_sig <= '0' ;
end if;
end if;

end process p_Rst_frm_RCI_reg;

--- state machine starts -----
--- state machine starts -----
case adc_state is
when idle_state =>
if(rci_start_acq_fl = '1' or adc_reset_busy_error_sig = '1') then
if(adc_rst_bsy_cnt = ADC_RESET_DURATION)then
adc_convst_sig <= (others => '0');
adc_rst_bsy_cnt <= (others => '0');
adc_reset <= '0';
adc_state <= convst_state;
else
adc_convst_sig <= (others => '1'); -- Must be high during reset
adc_rst_bsy_cnt <= adc_rst_bsy_cnt + '1';
adc_reset <= '1';
adc_state <= idle_state;
end if;
else
adc_convst_sig <=(others => '0');
adc_state <= idle_state;
end if;

when convst_state =>
if(frac_sec_count = 0) then -- checking for pps edge
adc_state <= adc_busy_state;
else
adc_convst_sig <= (others => '0');
adc_state <= convst_state;
end if;

when adc_busy_state =>
adc_convst_sig <= adc_convst_out; ---- sending convert_start signal to ADC
if (adc_const_int1 = '1' and adc_const_int2 = '1' ) then
if(adc_rst_bsy_cnt < BUSY_STATE_DURATION) then -- waits for 5 us
adc_rst_bsy_cnt <= adc_rst_bsy_cnt + '1';
adc_state <= adc_busy_state;
elsif (adc_busy_high = '1' ) then
adc_reset_busy_error <= '0';
adc_state <= adc_cs_state;
adc_rst_bsy_cnt <= (others => '0');
else
-- if adc_busy doesn't go high even after 5us after conver_start
-- then adc_reset_busy_error goes high.
-- but fpga will still go to next state and after completion of 1 complete
-- data cycle it will go to idle state where it will reset the ADC

adc_reset_busy_error <= '1';
adc_state <= adc_cs_state;
adc_rst_bsy_cnt <= (others => '0');
end if;
else
convst_en1 <= '1' ; -- Enable to generate convert start
convst_en2 <= '1' ;
end if;
----- continue with other states ----------
 

Is this state machine clocked? you dont show the clock yet it has counters in it.

(and please use the code or syntax tags please)
 

Hi Tricky,

sorry for the tag,
Yes the state machine is clocked at 100 Mhz, it was a long code so I posted the relevant part only.
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…