I am interfacing the AD7606BSTZ ADC with an XC7Z010CLG400-1 FPGA in parallel mode and encountering an issue where the ADC does not output any data on its DB[15:0] lines, even though the control signals appear correct. The CONVST_A and CONVST_B signals are correctly pulsed low, and the BUSY signal is asserted high during conversion and deasserted afterward. Once BUSY goes low, my FPGA asserts CS low and generates eight RD pulses to read the data. Additionally, the ADC provides the FRSTDATA signal, indicating that the first channel’s data should be available. However, when probing the data output lines, they remain at 0, and no valid digital output is observed.
The RESET signal is asserted and deasserted properly during initialization. The RD and CS signals toggle correctly in sync with the ADC read sequence, and I have ensured that the timing constraints in the datasheet are met, including the required pulse width for CONVST. Despite these checks, the ADC does not seem to provide valid conversion data.
I would like to understand why the ADC is not outputting data despite generating the BUSY and FRSTDATA signals as expected. Are there be additional conditions required for the ADC to begin conversion? It seems like the ADC may not be performing the conversion correctly, but I’m not certain if the issue is with the ADC itself, the FPGA logic, or the interfacing setup.
Below I have attached the screenshot of the ILA along with the design code. I’d appreciate any guidance or suggestions on troubleshooting this issue.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity ADC_read is port( clk : in std_logic; reset_in : in std_logic; reset_out : out std_logic; busy : in std_logic; start_conv : in std_logic; cs : out std_logic; rd : out std_logic; convst_a : out std_logic := '1'; convst_b : out std_logic := '1'; data_in : in std_logic_vector(15 downto 0); V1 : out std_logic_vector(15 downto 0); V2: out std_logic_vector(15 downto 0); V3 : out std_logic_vector(15 downto 0); V4 : out std_logic_vector(15 downto 0); V5 : out std_logic_vector(15 downto 0); V6 : out std_logic_vector(15 downto 0); V7 : out std_logic_vector(15 downto 0); V8 : out std_logic_vector(15 downto 0); OS : out std_logic_vector(2 downto 0); STBY : out std_logic; parallel : out std_logic; FRSTDATA : in std_logic; adc_range : out std_logic ); end ADC_read; architecture rtl of ADC_read is type state_type is (ST_ACT,RST, IDLE, CONVST,CHECK_BUSY ,BUSY_LOW, CS_LOW, RD_GEN, READ, CS_HIGH); signal state: state_type := ST_ACT; signal count_convst : integer := 0; constant convst_time : integer := 99; signal active: std_logic; signal reg_start : std_logic; signal prev_start: std_logic; signal rd_i : std_logic := '1'; signal busy_d1 : std_logic; signal count_reset : integer := 0; type data_array is array (0 to 7) of std_logic_vector(15 downto 0); signal data_channels : data_array; signal rd_count : integer range 0 to 7 := 0; signal count_rd : integer := 0; constant RD_HALF_PERIOD : integer := 39; attribute mark_debug : string; attribute mark_debug of prev_start: signal is "true"; attribute mark_debug of rd_count: signal is "true"; attribute mark_debug of data_channels: signal is "true"; attribute mark_debug of count_rd: signal is "true"; attribute mark_debug of state: signal is "true"; attribute mark_debug of active: signal is "true"; attribute mark_debug of rd_i: signal is "true"; begin parallel <= '0'; --adc_range <= '1'; STBY <= '1'; OS <= "000"; process(clk) begin if rising_edge(clk) then busy_d1 <= busy; end if; end process; process(clk) begin if rising_edge(clk) then reg_start <= start_conv; prev_start <= reg_start; if reset_in = '1' then cs <= '1'; rd_i <= '1'; convst_a <= '1'; convst_b <= '1'; data_channels <= (others => (others => '0')); count_convst <= 0; count_rd <= 0; rd_count <= 0; count_rd <= 0; else case state is when ST_ACT => if reg_start = '1' and prev_start = '0' then active <= '1'; convst_a <= '1'; convst_b <= '1'; cs <= '1'; rd_i <= '1'; convst_a <= '1'; convst_b <= '1'; data_channels <= (others => (others => '0')); count_convst <= 0; count_rd <= 0; rd_count <= 0; count_reset <= 0; reset_out <= '0'; count_rd <= 0; state <= RST; end if; when RST => reset_out <= '1'; if count_reset < RD_HALF_PERIOD*2 then count_reset <= count_reset + 1; else reset_out <= '0'; state <= IDLE; end if; when IDLE => cs <= '1'; rd_i <= '1'; state <= CONVST; count_convst <= 0; when CONVST => convst_a <= '0'; convst_b <= '0'; if count_convst = convst_time then convst_a <= '1'; convst_b <= '1'; state <= CHECK_BUSY; else count_convst <= count_convst + 1; end if; WHEN CHECK_BUSY => if busy = '0' and busy_d1 = '1' then state <= BUSY_LOW; else state <= CHECK_BUSY; end if; when BUSY_LOW => if busy = '0' then state <= CS_LOW; count_rd <= 0; rd_count <= 0; end if; when CS_LOW => cs <= '0'; state <= RD_GEN; when RD_GEN => if count_rd < RD_HALF_PERIOD then count_rd <= count_rd + 1; else count_rd <= 0; rd_i <= not rd_i; if rd_i = '0' then if rd_count < 7 then data_channels(rd_count) <= data_in; rd_count <= rd_count + 1; else data_channels(7) <= data_in; rd_i <= '1'; state <= READ; end if; end if; end if; when READ => rd_i <= '1'; state <= CS_HIGH; when CS_HIGH => cs <= '1'; active <= '0'; state <= ST_ACT; end case; end if; end if; end process; rd <= rd_i; V1 <= data_channels(0); V2 <= data_channels(1); V3 <= data_channels(2); V4 <= data_channels(3); V5 <= data_channels(4); V6 <= data_channels(5); V7 <= data_channels(6); V8 <= data_channels(7); end rtl;