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%;
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;
david tweed
david tweed
multinivel