Processing math: 100%

6 votos

¿Por qué dividir un camino crítico de la FPGA funciona para mejorar el rendimiento?

Contexto

Actualmente estoy leyendo el (muy bueno) material del curso "Introduciendo el 3E FPGA espartano 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 se trata de mostrar los 8 MSbits de un contador de 30 bits en LEDs. En los códigos siguientes, el primer ejemplo tiene un tiempo de configuración de 4.053ns y el segundo de 3.537ns, logrado dividiendo el contador en dos contadores de 15 bits y una chancleta de transporte.

Pregunta

¿Por qué funciona? ¿No es el momento de ondular el transporte desde el contador de LS al de MS el mismo, y aún más alto al insertar la chancleta? Al final, el contador MS todavía necesitará su entrada del contador LS para terminar su ciclo... Puntos de bonificación para aquellos que ilustren su respuesta con diagramas del camino crítico antes/después y cómo se propagan las señales.

Código

Antes de separarse:

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 separarse:

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;

5voto

Ruben Puntos 584

¡Buena pregunta! Parece un poco impar a primera vista, pero te aseguro que tiene sentido.

En la primera versión, el contador (14:0) debe ser all-one antes de que la carga pueda propagarse hasta el bit 15. Con la división de la trayectoria, se prueba contra "111111111111110", de modo que se puede decir un ciclo de reloj antes que el siguiente va a generar una carga. Si examinas la salida de la simulación en un visor de ondas, verás que incHighNext se convierte en 1 durante el mismo ciclo de reloj que el contador (14 hasta 0) se convierte en "111111111111111". Al final de ese ciclo, ya se puede decir que el contador de bits altos va a tener que incrementarse, así que no hay que esperar a que la carga se propague todo el camino desde el lsb.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X