¿Por qué la división de una ruta crítica FPGA funciona para mejorar el rendimiento?

6

Context

Actualmente estoy leyendo el material del curso (muy bueno) sobre "Introducción al FPGA Spartan 3E y VHDL "promovido aquí (anuncios de la comunidad) y realmente no tengo la idea de dividir un camino crítico para aumentar el rendimiento:

El ejemplo trata de mostrar los 8 MSbits de un contador de 30 bits en los LED. En los códigos a continuación, el primer ejemplo tiene un tiempo de configuración de 4.053ns y el segundo 3.537ns, logrado dividiendo el contador en dos contadores de 15 bits y un flip-flop de acarreo.

Pregunta

¿Por qué funciona? ¿No es el momento de ondular el acarreo desde el LS hasta el contador de MS, e incluso más alto de insertar el flip-flop? Al final, el contador MS aún necesitará su entrada del contador LS para finalizar su ciclo ... Puntos de bonificación para aquellos que ilustran su respuesta con diagramas de la ruta crítica anterior / posterior y cómo se propagan las señales.

Código

Antes de dividir:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Switches_LEDs is
    Port (
        switches : in STD_LOGIC_VECTOR(7 downto 0);
        LEDs : out STD_LOGIC_VECTOR(7 downto 0);
        clk : in STD_LOGIC
    );
end Switches_LEDs;

architecture Behavioral of Switches_LEDs is
    signal counter : STD_LOGIC_VECTOR(29 downto 0) := (others => ’0’);
begin
    LEDs <= counter(29 downto 22);

    clk_proc: process(clk, counter)
    begin
        if rising_edge(clk) then
            counter <= counter+1;
        end if;
    end process;
end Behavioral;

Después de dividir:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Switches_LEDs is
    Port ( 
        switches : in STD_LOGIC_VECTOR(7 downto 0);
        LEDs : out STD_LOGIC_VECTOR(7 downto 0);
        clk : in STD_LOGIC
    );
end Switches_LEDs;

architecture Behavioral of Switches_LEDs is
    signal counter : STD_LOGIC_VECTOR(29 downto 0) := (others => ’0’);
    signal incHighNext : STD_LOGIC := ’0’;
begin
    LEDs <= counter(29 downto 22);

    clk_proc: process(clk, counter)
    begin
        if rising_edge(clk) then
            counter(29 downto 15) <= counter(29 downto 15)+incHighNext;
            if counter(14 downto 0) = "111111111111110" then
                incHighNext <= ’1’;
            else
                incHighNext <= ’0’;
            end if;
            counter(14 downto 0) <= counter(14 downto 0)+1;
        end if;
    end process;
end Behavioral;
    
pregunta Mister Mystère

1 respuesta

5

Buena pregunta! Parece un poco extraño a primera vista, pero te aseguro que tiene sentido.

En la primera versión, el contador (14: 0) debe ser de todos antes de que el acarreo se pueda propagar hasta el bit 15. Con la división de ruta, prueba contra "111111111111110", para poder distinguir un reloj. cicle antes que el ciclo next va a generar un carry. Si examinas la salida de simulación en un visor de ondas, verás que incHighNext se convierte en 1 durante el mismo ciclo de reloj en el que el contador (14 downto 0) se convierte en "111111111111111". Al final de ese ciclo, ya puede decir que el contador de bits altos tendrá que aumentar, por lo que no tiene que esperar a que el acarreo se propague desde la lsb.

    
respondido por el trentcl

Lea otras preguntas en las etiquetas