FPGA: programa que no funciona siempre

0

Estoy haciendo un ADC (en VHDL) para Spartan-3AN. Desafortunadamente, tengo que programar mi FPGA (programa FPGA solamente) un tiempo aleatorio antes del amplificador de ganancia programable ( Spartan 3AN User Guide página 73) funciona correctamente ... Y cuando programo el flash, nunca funciona correctamente ... Pongo mi código al final de este tema para que pueda verlo, pero mi pregunta es:

¿Alguien sabe el tipo de problemas que pueden hacerme tener que programar tiempos aleatorios en mi FPGA para obtener el código correcto?

Aquí está mi código:

library     IEEE;
use         IEEE.STD_LOGIC_1164.ALL;
entity adc_dac is
Port (  CLK_50MHZ   :   in      STD_LOGIC;
            SPI_MOSI    :   out     STD_LOGIC;                                                                                      
            AMP_CS      :   out     STD_LOGIC :='1';
            SPI_SCK         :   out     STD_LOGIC :='0';
            AMP_SHDN    :   out     STD_LOGIC :='0';
            AD_CONV         :   out     STD_LOGIC;
            ADC_OUT         :   in      STD_LOGIC;
            led             :   out     STD_LOGIC_vector (7 downto 0)
        );
end adc_dac;

architecture Behavioral of adc_dac is

type state_type is (    pga_load, 
                        idle, sendBitPGA, clockHighPGA,
                        catchADC, setADC
                        );
signal state : state_type:=pga_load;
-- Extra counter
signal cnt  : integer range 0 to 34 := 8;
signal cnt_SCK  : integer range 0 to 1 := 0;

-- Programmable Gain Amplifier
signal pga_data : std_logic_vector (7 downto 0) := "00010001";
signal counter_10MHZ: integer range 0 to 10 := 0;

-- Auxiliary signals ADC
signal Data : std_logic_vector (13 downto 0);
signal ADC_path: std_logic:='0';
signal output : std_logic_vector (13 downto 0) := "10000000000000";

begin

--**********************************
--**        STATE MACHINE         **
--**********************************

process (CLK_50MHZ)
begin
if (rising_edge(CLK_50MHZ)) then                                          
     case state is

                when idle =>                                     
                    if      ADC_path = '1' then
                            ADC_path <= '0'; 
                            AD_CONV <= '0';
                            cnt <= 34;
                            state <= setADC;                         
                    else
                            SPI_SCK <= '0';
                            AD_CONV <= '1';
                            ADC_path <= '1';
                            state <= idle;
                    end if;  

    --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    --^^       PGA interface          ^^
    --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^    

                when pga_load =>
                     SPI_SCK <= '0';
                     cnt <= 8;
                     AMP_SHDN <= '0';
                     pga_data <= "00010001";
                     AMP_CS <= '0'; 
                     state <= sendBitPGA;

                when sendBitPGA =>
                        if (counter_10MHZ = 5) then
                            if (cnt_SCK = 0) then
                                SPI_SCK <= '1';
                                cnt_SCK <= 1;
                                SPI_MOSI <= pga_data(7);
                                cnt <= cnt-1;   
                                state <= clockHighPGA;
                            elsif(cnt_SCK = 1) then
                                SPI_SCK <= '0';
                                cnt_SCK <= 0;
                            end if;
                            if (cnt = 0) then
                                AMP_CS <= '1';
                                state <= idle;
                            end if;
                    counter_10MHZ <= 0;
                    else
                        counter_10MHZ <= counter_10MHZ + 1;
                        state <= sendBitPGA;
                    end if;


              when clockHighPGA =>
                    pga_data <= pga_data(6 downto 0) & '0';
                    state <= sendBitPGA;        

    --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    --^^        ADC interface         ^^
    --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                
              when setADC =>
                    if (cnt = 0) then
                        AD_CONV <= '1';
                        output <= Data (13 downto 0);
                        led <= output (13 downto 6);
                        ADC_path <= '1';
                        state <= idle;
                    else
                        SPI_SCK <= '1'; 
                        cnt <= cnt-1;
                        state <= catchADC;
                    end if;

              when catchADC =>
                        SPI_SCK <= '0';
                        if (cnt >= 18 and cnt <= 31) then
                            Data <= Data(12 downto 0) & ADC_OUT ;   
                        end if; 
                        state <= setADC;
                end case;
     end if;
   end process;
end Behavioral;

Gracias de antemano!

    
pregunta Cabs

2 respuestas

1

¿Funciona bien en la simulación? Si no, arregla eso primero. No quieres depurar los problemas lógicos y los problemas del mundo real más raros, a veces, al mismo tiempo.

Obtenga una señal de restablecimiento allí: es mucho más fácil de depurar en el mundo real cuando puede presionar un botón y restablecerlo en lugar de tener que reconfigurarlo. Confíe en mí ... He intentado en ambos sentidos :) Y asegúrese de sincronizar la señal de reinicio con el reloj antes de soltarlo. Eso puede ser una fuente de errores difíciles de rastrear a medida que su diseño crece. Consulte Figura 7 del documento de Xilinx sobre restablecimientos , que es una buena guía y le permite potencialmente reduzca la lógica requerida en su diseño haciendo uso de la inicialización en lugar de restablecer, con la advertencia de que (como se mencionó) a menudo encuentro que la depuración en el banco es más fácil con un interruptor de restablecimiento que con la reconfiguración continua.

Tendrá que escribir algún código para simular su ADC. Este es un trabajo útil que hacer, ya que asegurará que realmente entiendas la interfaz. Preste especial atención al borde del reloj SPI en el que el ADC captura y afirma los datos, por ejemplo. Y en qué orden entran los bits en las líneas de datos SPI.

Una vez que la simulación funcione, comprueba que

  • tus pines IO están correctamente asignados a los pines que crees que deberían ser
  • las restricciones de tu reloj (y otras temporizaciones) son correctas. Tedioso, pero tienes que hacerlo.
  • en realidad cumpliste con las restricciones de tiempo
  • tienes sincronizado las entradas asíncronas (como tu ADC_out ) con el reloj antes de usarlas. Solo use la versión sincronizada de la señal dentro de su lógica, como usar la salida de C1 en el ejemplo vinculado a.
  • sus fuentes de alimentación son buenas y no se hunden cuando se inicia el FPGA (por ejemplo)
respondido por el Martin Thompson
2

En primer lugar, debe asegurarse de que las restricciones de su reloj estén bien configuradas y de que su diseño pase la sincronización. Puede obtener todo tipo de comportamientos extraños de un diseño que falla en el tiempo. Idealmente, también configuraría restricciones de tiempo IO, aunque eso no es vital en sistemas realmente lentos.

En segundo lugar, debe verificar la documentación de xilnx sobre las condiciones iniciales en la versión de la herramienta de síntesis que está utilizando. Algunas herramientas de síntesis no admiten la forma estándar de VHDL / verilog de especificarlas y no permiten que se configuren en absoluto o requieren métodos específicos de herramientas para configurarlas. Este es un legado del diseño ASIC donde las condiciones iniciales no se consideraron significativas para la síntesis.

En tercer lugar, establece la línea de datos SPI y el SCLK al mismo tiempo. Esto significa que las transiciones podrían llegar al dispositivo SPI en cualquier orden. Realmente no deberías tocar ambas líneas en el mismo ciclo de reloj. Sospecho que esto es muy probable que sea su problema real.

En cuarto lugar, ¿has verificado las frecuencias SCLK aceptables para tu amplificador de ganancia programable?

Finalmente, realmente necesitas configurar algún tipo de equipo de prueba. Ya sea analizadores lógicos externos o, mejor aún, algo dentro del FPGA. Creo que xilinx tiene una herramienta llamada chipscope para esto, pero no conozco los detalles.

    
respondido por el Peter Green

Lea otras preguntas en las etiquetas