Generación de relojes no superpuestos en FPGA usando VHDL

2

Estoy tratando de implementar circuitos de capacitores conmutados y, por lo tanto, necesito generar un reloj de dos fases sin superposición. He estado tratando de usar un FPGA para el mismo. Desafortunadamente, mi herramienta de síntesis: Quartus II está lanzando advertencias de tiempo. Además, cuando vuelco el código en el FPGA (Altera MAX7000S series FPGA), observo claramente niveles metaestables y salidas impredecibles.

El código que he escrito para implementar esto se proporciona a continuación:

arquitectura clock_gen_integrator_arch de clock_gen_integrator es     señal counter_15: STD_LOGIC_VECTOR (3 downto 0);     señal phi1_sig, phi2_sig: STD_LOGIC;     contador de señal: STD_LOGIC_VECTOR (14 downto 0);

begin
phi1     <= phi1_sig;
phi2     <= phi2_sig;

signal_gen: process (reset, clock25M) begin
    if(reset = '0') then
        counter_15    <= (others => '0');
        counter       <= (others => '0');
        phi1_sig      <= '1';
        phi2_sig      <= '0';
        reset_int     <= '1';
    elsif(clock25M = '1' and clock25M'EVENT) then
              if(counter < "000010000000000" and counter_15 < "1111") then
              phi1_sig      <= '0';
              phi2_sig      <= '0';
              counter       <= counter + 1;
              reset_int     <= '0';
          elsif (counter < "011100000000000" and counter_15 < "1111") then
              phi1_sig      <= '1';
              phi2_sig      <= '0';
              counter       <= counter + 1;
              reset_int     <= '0';
          elsif (counter < "100010000000000" and counter_15 < "1111") then
              phi1_sig      <= '0';
              phi2_sig      <= '0';
              counter       <= counter + 1;
              reset_int     <= '0';
          elsif (counter < "111100000000000" and counter_15 < "1111") then
              phi1_sig      <= '0';
              phi2_sig      <= '1';
              counter       <= counter + 1;
              reset_int     <= '0';
          elsif (counter < "111111111111111" and counter_15 < "1111") then
              phi1_sig      <= '0';
              phi2_sig      <= '0';
              counter       <= counter + 1;
              reset_int     <= '0';
          elsif (counter = "111111111111111" and counter_15 < "1111") then
              counter_15    <= counter_15 + 1;
              counter       <= counter + 1;
              reset_int     <= '0';
          else 
              phi1_sig      <= phi1_sig;
              phi2_sig      <= phi2_sig;
              reset_int     <= '0';
          end if;

        end if;
    end process;
end architecture;

Desafortunadamente, no puedo incluir todo el código aquí, tengo problemas de formato. Sin embargo, ya que es solo la desintegración de la entidad, la he dejado fuera. phi1 (out), phi2 (out), reset (in), reset_int (out), clock25M (in) están presentes en la lista de puertos.

En este código, estoy eligiendo arbitrariamente la frecuencia y los ciclos de trabajo de los relojes requeridos. Quiero específicamente 15 pulsos de phi1 y 15 pulsos de phi2 y counter_15 me ayudan a lograr esto.

QuartusII me ha dicho que tengo infracciones de tiempo de configuración.

Lo siento por la imagen en escala de grises, tuve que reducir el tamaño de la imagen de alguna manera para poder subirla. El primer canal es la salida phi1 y el segundo canal es la salida phi2. Al ser nuevo en la herramienta, así como en el análisis del tiempo, agradecería que alguien me dijera lo que estoy haciendo mal y cómo puedo solucionar la infracción del tiempo. Además, cualquier sugerencia sobre cómo evitar estos problemas en general es bienvenida.

    
pregunta Amogh

4 respuestas

1

Un método general para mejorar el tiempo es dividir la lógica en múltiples ciclos registrando resultados.

Puedes probar algo como esto ...

signal_gen: process (reset, clock25M) begin
    if(reset = '0') then
        counter_15    <= (others => '0');
        counter       <= (others => '0');
        phi1_sig      <= '1';
        phi2_sig      <= '0';
        reset_int     <= '1';
        counter_15_not_done <= true;
        count_lt_000010000000000 <= false;
        count_lt_011100000000000 <= false;
        count_lt_100010000000000 <= false;
        count_lt_111100000000000 <= false;
        count_lt_111111111111111 <= false;
        count_eq_111111111111111 <= false;
    elsif(clock25M = '1' and clock25M'EVENT) then
          --the comparisons are computed in parallel and registered
          counter_15_not_done <= counter_15 < "1111";
          count_lt_000010000000000 <= count < "000010000000000";
          count_lt_011100000000000 <= count < "011100000000000";
          count_lt_100010000000000 <= count < "100010000000000";
          count_lt_111100000000000 <= count < "111100000000000";
          count_lt_111111111111111 <= count < "111111111111111";
          count_eq_111111111111111 <= count = "111111111111111";
          --the logic now only depends on the registered results.
          --The registered results are only 7 bits rather than 19 bits
          --this should have much better timing
          if(count_lt_000010000000000 and counter_15_not_done) then
              phi1_sig      <= '0';
              phi2_sig      <= '0';
              counter       <= counter + 1;
              reset_int     <= '0';
          elsif (count_lt_011100000000000 and counter_15_not_done) then
              phi1_sig      <= '1';
              phi2_sig      <= '0';
              counter       <= counter + 1;
              reset_int     <= '0';
          elsif (count_lt_100010000000000 and counter_15_not_done) then
              phi1_sig      <= '0';
              phi2_sig      <= '0';
              counter       <= counter + 1;
              reset_int     <= '0';
          elsif (count_lt_111100000000000 and counter_15_not_done) then
              phi1_sig      <= '0';
              phi2_sig      <= '1';
              counter       <= counter + 1;
              reset_int     <= '0';
          elsif (count_lt_111111111111111 and counter_15_not_done) then
              phi1_sig      <= '0';
              phi2_sig      <= '0';
              counter       <= counter + 1;
              reset_int     <= '0';
          elsif (count_eq_111111111111111 and counter_15_not_done) then
              counter_15    <= counter_15 + 1;
              counter       <= counter + 1;
              reset_int     <= '0';
          else 
              phi1_sig      <= phi1_sig;
              phi2_sig      <= phi2_sig;
              reset_int     <= '0';
          end if;

        end if;
    end process;
end architecture;

Tenga en cuenta que los resultados registrados retrasarán las cuentas reales en 1 ciclo de reloj, por lo que es posible que deba ajustar los puntos de comparación en 1 ciclo.

    
respondido por el user4574
1

La igualdad se implementa con menos niveles de retardo 'de puerta' que la magnitud ("<"), lo que implica una resta y no se optimizará completamente si hay valores de operandos mayores que el operando de mayor magnitud estática. (El operando de comparación de contador más alto es x "7800", el conteo más alto del contador es x "7FFF".)

Utilice solo comparaciones de igualdad, por ejemplo:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;          -- ADDED

entity clock_gen_integrator is
    port (
        clock25M:   in  std_logic;
        reset:      in  std_logic;
        reset_int:  out std_logic;
        phi1:       out std_logic;
        phi2:       out std_logic
    );
end entity;

architecture foo of clock_gen_integrator is 

    signal counter_15:  unsigned (3 downto 0); -- WAS std_logic_vector
    signal phi1_sig:    std_logic;
    signal phi2_sig:    std_logic; 
    signal counter:     unsigned(14 downto 0); -- WAS std_logic_vector 
    signal notcount15:  boolean;
    signal notcount15h: boolean; 
begin

    phi1 <= phi1_sig;
    phi2 <= phi2_sig;

    notcount15 <= counter_15 /= 15;  -- 4 input NAND gate

signal_gen: 
    process (reset, clock25M) 
    begin
        if reset = '0' then
            counter_15    <= (others => '0');
            notcount15h     <= true;
            counter       <= (others => '0');
            phi1_sig      <= '1';
            phi2_sig      <= '0';
            reset_int     <= '1';
        -- elsif clock25M = '1' and clock25M'EVENT then 
        elsif rising_edge (clock25M) then
            -- the counters:
            counter <= counter + 1;
            if counter = x"3800" and notcount15 then
                counter_15 <= counter_15 + 1;
            end if;
            -- notcount15h holdover flip flop for phi2
            if counter = x"3800" and not notcount15 then
                notcount15h <= false;
            end if;
            -- reset_int flip flop:
            reset_int <= not reset;
            -- toggle phi1:
            if counter = x"400"  and notcount15 then
                phi1_sig <= '1';
            elsif counter = x"3800" and notcount15 then
                phi1_sig <= '0';
            end if;
            -- toggle phi2:
            if counter = x"4400" and notcount15h then
                phi2_sig <=  '1';
            elsif counter = x"7800" and notcount15h then
                phi2_sig <= '0';
            end if;  
            -- four equality comparators to specific 15 bits of counter
        end if;
    end process;
end architecture;


library ieee;
use ieee.std_logic_1164.all;

entity clock_gen_integrator_tb is
end entity;

architecture foo of clock_gen_integrator_tb is
    signal clock25M:   std_logic := '0';
    signal reset:      std_logic := '1';
    signal reset_int:  std_logic;
    signal phi1:       std_logic;
    signal phi2:       std_logic;
begin

CLOCK:
    process
    begin
        wait for 20 ns;
        clock25M <= not clock25m;
        if now > 21 ms then
            wait;
        end if;
    end process;
DUT:
    entity work.clock_gen_integrator
        port map (
            clock25M => clock25M,
            reset => reset,
            reset_int => reset_int,
            phi1 => phi1,
            phi2 => phi2
        );

STIMULUS:
    process
    begin
        wait for 30 ns;
        reset <= '0';
        wait for 80 ns;
        reset <= '1';
        wait;
    end process;

end architecture;

El banco de pruebas muestra 15 relojes phi1 y phi2 ("Quiero específicamente 15 pulsos de phi1 y 15 pulsos de phi2 y counter_15 me ayudan a lograr esto") en los mismos valores de contador que en la arquitectura original clock_gen_integrator_arch:

    
respondido por el user8352
1

Todos los bits inferiores en sus puntos de transición son cero (sin contar la instancia en la que borra phi2 dos veces, por lo que puede dividir el reloj unas cuantas veces y usar un contador más pequeño.

También puede dividir la generación de un tren continuo de pulsos de la longitud deseada (bits de orden inferior del contador) y enrutar a una salida (bits de orden superior), por ejemplo. 16 pulsos con un ciclo de trabajo \ $ \ frac {1} {8} \ $ y dos salidas podrían lograrse con un contador de 8 bits (ni siquiera compilarse probado, pero debería tener la idea):

pulse <= '1' WHEN counter(2 downto 0) = "000" ELSE '0';
output <= counter(3);
phi1 <= pulse AND NOT output;
phi2 <= pulse AND output;

Haz que counter corra hacia arriba y se detenga después de "11111111" .

Dependiendo de lo que ocurra en el diseño, probablemente también use un PLL para derivar un reloj lento (1 MHz) y dividir desde allí.

    
respondido por el Simon Richter
0

Desafortunadamente, esta es una implementación deficiente de un diseño que no tiene especificaciones ni tolerancias. Comience siempre con las especificaciones de diseño y las tolerancias antes de intentar diseñar una solución.

Su falta de diseño de impedancia (RdsOn o ESR del interruptor) y el hundimiento de las fugas muestran evidencia de ruido de conmutación y timbre cuantificado.

La elección de las tapas no debe ser cerámica, que tienen problemas de histéresis y microfonía en los diseños S & amp, H, a menos que sean del tipo NP0.

Dado;

  

circuitos de condensadores conmutados y, por lo tanto, necesito generar un reloj de dos fases sin superposición

¿Cuáles son los siguientes? Incluya las tolerancias esperadas para cada uno.

  • respuestas de filtro deseadas y tolerancia
  • reloj de entrada f
  • reloj de salida f
  • límite de corriente del reloj de salida
  • capacitancia de carga de salida (por lo tanto, tiempo de aumento)
  • sesgos de retardo de salida desde el peor de los casos de latencia
  • resistencia de interruptor
  • capacitancia conmutada, por lo tanto, tiempo de subida
  • tiempo muerto no superpuesto de relojes bifásicos
  • efecto en la constante de tiempo RC con tiempo muerto (RdsOn / d)
  • se requiere la sincronización del ancho de pulso para los bordes iniciales y finales en V + / 2 o "PW50"
  • sensibilidad hacia arriba con la temperatura y la tensión de alimentación.

Cuantas más especificaciones defina por adelantado que puedan causar errores, más posibilidades tendrá de hacerlo correctamente la primera vez . De lo contrario, las iteraciones sobre las especificaciones de diseño y reintento o confusión cuando falla.

Ahora, ¿qué método será el más fácil de crear estos requisitos? Análogo Como lo hicieron todos los diseños de puentes completos o digitales con límites de resolución de cuantización o?

¿Qué circuitos ha leído que están publicados en los libros de la aplicación CMOS que ya funcionan? Y si no, ¿por qué no?

p.s.
Existen muchas herramientas para cambiar el tamaño de la imagen o la relación de compresión para reducir el tamaño del archivo y conservar el color de 32 bits.

El aumento de la distancia y la mano firme con la cámara y luego el enfoque automático, directamente al monitor dará una imagen más clara, luego se recortará según sea necesario.

    
respondido por el Tony EE rocketscientist

Lea otras preguntas en las etiquetas