Pantalla multiplexada de siete segmentos lo suficientemente rápida como para hacer sólido

He estado tratando de multiplexar una pantalla de siete segmentos de 4 dígitos en mi placa FPGA, pero me he encontrado con que no podía hacerlo lo suficientemente rápido para que se viera sólido para el ojo humano.

Puedes ver un ejemplo de la velocidad aquí: http://youtu.be/geTgZcHrXTc

¿Cómo multiplexar lo suficientemente rápido para que parezca sólido para el ojo humano?

Estoy usando la placa Basys 2 .

En este momento mi VHDL se parece a:

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

entity main is
    port(
        clock       : in STD_LOGIC;
        sevenseg    : out STD_LOGIC_VECTOR(6 downto 0);
        anodes  : out STD_LOGIC_VECTOR(3 downto 0);
        switches    : in STD_LOGIC_VECTOR(6 downto 0);
        dp      : in STD_LOGIC
    );
end main;

architecture Behavioral of main is
    signal counter: STD_LOGIC_VECTOR(1 downto 0) := (others => '0');
    signal r_anodes: STD_LOGIC_VECTOR(3 downto 0);
begin

    anodes <= r_anodes;

    -- Given Binary Value print it
    multiplex: process(counter, switches)
    begin
        -- Set anode correctly
        case counter(1 downto 0) is
            when "00" => r_anodes <= "1110"; -- AN 0
            when "01" => r_anodes <= "1101"; -- AN 1
            when "10" => r_anodes <= "1011"; -- AN 2
            when "11" => r_anodes <= "0111"; -- AN 3

            when others => r_anodes <= "1111"; -- nothing
        end case;

        -- Set segments correctly
        case r_anodes is
            when "1110" => 
                if switches(0) = '1' then
                    sevenseg <= "1111001"; -- 1
                else
                    sevenseg <= "1000000"; -- 0
                end if;
            when "1101" => 
                if switches(1) = '1' then
                    sevenseg <= "1111001"; -- 1
                else
                    sevenseg <= "1000000"; -- 0
                end if;
            when "1011" => 
                if switches(2) = '1' then
                    sevenseg <= "1111001"; -- 1
                else
                    sevenseg <= "1000000"; -- 0
                end if;
            when "0111" => 
                if switches(3) = '1' then
                    sevenseg <= "1111001"; -- 1
                else
                    sevenseg <= "1000000"; -- 0
                end if;

            when others => sevenseg <= "1111111"; -- nothing
        end case;

    end process;

    countClock: process(clock, counter)
    begin
        if rising_edge(clock) then
            -- Iterate
            counter <= counter + 1;
        end if;
    end process;


end Behavioral;

Y mi archivo de restricciones se ve así:

NET "sevenseg<0>" LOC = "L14";
NET "sevenseg<1>" LOC = "H12";
NET "sevenseg<2>" LOC = "N14";
NET "sevenseg<3>" LOC = "N11";
NET "sevenseg<4>" LOC = "P12";
NET "sevenseg<5>" LOC = "L13";
NET "sevenseg<6>" LOC = "M12";
NET "dp" LOC = "N13";

NET "anodes<3>" LOC = "K14";
NET "anodes<2>" LOC = "M13";
NET "anodes<1>" LOC = "J12";
NET "anodes<0>" LOC = "F12";

NET "switches<6>" LOC = "E2";
NET "switches<5>" LOC = "F3";
NET "switches<4>" LOC = "G3";
NET "switches<3>" LOC = "B4";
NET "switches<2>" LOC = "K3";
NET "switches<1>" LOC = "L3";
NET "switches<0>" LOC = "P11";

NET "clock" TNM_NET = clock;
TIMESPEC TS_clock = PERIOD "clock" 20 ns HIGH 50%;
Parece que no está configurando un "LOC" para el pin de entrada del reloj. ¿Puedes verificar que está conectado donde crees que está?
De acuerdo con el manual, debería ser el pin B8, pero esta entrada de 50 MHz deberá dividirse a unos 500 Hz para escanear la pantalla.
@DaveTweed Gracias, he estado pasando por alto agregar el "LOC" para el reloj en todos mis proyectos ... Solo estoy haciendo una restricción de tiempo. Entonces, ¿puedo dividir el reloj en una restricción de tiempo o tengo que usar un preescalador?

Respuestas (1)

Gracias Dave Tweed por encontrar mi pequeño error.

Olvidé agregar el "LOC" en el archivo de restricciones.

NET "clock" LOC = "B8";

También tuve algunos problemas de ancho de pulso (segmentos parcialmente activados) con los 50 MHz completos, como también mencionó Dave Tweed. Así que usé un prescaler para volver a tonificarlo a 500 Hz.

Divida un reloj de 50 Mhz por 100.000 (base 10) o 11000011010100000(binario)

El código final se parece a:

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

entity main is
    port(
        clock       : in STD_LOGIC;
        sevenseg    : out STD_LOGIC_VECTOR(6 downto 0);
        anodes  : out STD_LOGIC_VECTOR(3 downto 0);
        switches    : in STD_LOGIC_VECTOR(6 downto 0);
        dp      : in STD_LOGIC
    );
end main;

architecture Behavioral of main is
    signal prescaler: STD_LOGIC_VECTOR(16 downto 0) := "11000011010100000";
    signal prescaler_counter: STD_LOGIC_VECTOR(16 downto 0) := (others => '0');
    signal counter: STD_LOGIC_VECTOR(1 downto 0) := (others => '0');
    signal r_anodes: STD_LOGIC_VECTOR(3 downto 0);
begin

    anodes <= r_anodes;

    -- Given Binary Value print it
    multiplex: process(counter, switches)
    begin
        -- Set anode correctly
        case counter(1 downto 0) is
            when "00" => r_anodes <= "1110"; -- AN 0
            when "01" => r_anodes <= "1101"; -- AN 1
            when "10" => r_anodes <= "1011"; -- AN 2
            when "11" => r_anodes <= "0111"; -- AN 3

            when others => r_anodes <= "1111"; -- nothing
        end case;

        -- Set segments correctly
        case r_anodes is
            when "1110" => 
                if switches(0) = '1' then
                    sevenseg <= "1111001"; -- 1
                else
                    sevenseg <= "1000000"; -- 0
                end if;
            when "1101" => 
                if switches(1) = '1' then
                    sevenseg <= "1111001"; -- 1
                else
                    sevenseg <= "1000000"; -- 0
                end if;
            when "1011" => 
                if switches(2) = '1' then
                    sevenseg <= "1111001"; -- 1
                else
                    sevenseg <= "1000000"; -- 0
                end if;
            when "0111" => 
                if switches(3) = '1' then
                    sevenseg <= "1111001"; -- 1
                else
                    sevenseg <= "1000000"; -- 0
                end if;

            when others => sevenseg <= "1111111"; -- nothing
        end case;

    end process;

    countClock: process(clock, counter)
    begin
        if rising_edge(clock) then
            prescaler_counter <= prescaler_counter + 1;
            if(prescaler_counter = prescaler) then
                -- Iterate
                counter <= counter + 1;

                prescaler_counter <= (others => '0');
            end if;
        end if;
    end process;


end Behavioral;