El objetivo es implementar en la FPGA disponible en la tarjeta Basys 2, Digilent, y utilizando el software Xilinx ISE, un conversor de Binario a BCD, que al introducir en binario un Byte, por medio de los 8 interruptores disponibles en la tarjeta de desarrollo, se pueda visualizar en tres displays de 7 segmentos de la tarjeta, el respectivo número decimal que corresponda al número binario introducido de 8 bits. Los decimales visualizados en los displays estan comprendidos desde el 000 hasta el 255.
Se tiene en cuenta el siguiente diagrama esquematico:
Elaboramos el código en VHDL del conversor de Binario a BCD de acuerdo al algoritmo de sumar 3 y desplazar cada 4 bits, para lo cual hacemos uso de una VARIABLE de 20 bits, que llamamos la variable Z, y que debe contener los 8 bits del binario a convertir, y los 12 bits del BCD: 4 bits de las centenas, 4 bits de las decenas y los 4 bits de las unidades. Cada vez que en BCD se detecte un número mayor de 4 se le suma 3 y se desplaza, lo cual equivale a sumar 6, lo cual es lo requerido para efectuar la conversión de binario a BCD para cada 4 bits. Inicialmente la variable Z se pone en ceros, y luego desplaza los tres primeros bits, antes de averiguar si el número es mayor de 4, para sumarle tres y desplazarlo en caso que lo sea.
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Conv_Bin_BCD is
Port ( Bin : in STD_LOGIC_VECTOR (7 downto 0);
Cen : out STD_LOGIC_VECTOR (3 downto 0);
Dec : out STD_LOGIC_VECTOR (3 downto 0);
Uni : out STD_LOGIC_VECTOR (3 downto 0));
end Conv_Bin_BCD;
architecture Behavioral of Conv_Bin_BCD is
begin
Process(Bin)
variable Z: STD_LOGIC_VECTOR (19 downto 0);
begin
for i in 0 to 19 loop
Z(i) := '0';
end loop;
Z(10 downto 3) := Bin;
for i in 0 to 4 loop
if Z(11 downto 8) > 4 then
Z(11 downto 8) := Z(11 downto 8) + 3;
end if;
if Z(15 downto 12) > 4 then
Z(15 downto 12) := Z(15 downto 12) + 3;
end if;
Z(17 downto 1) := Z(16 downto 0);
end loop;
Cen <= Z(19 downto 16);
Dec <= Z(15 downto 12);
Uni <= Z(11 downto 8);
end Process;
end Behavioral;
Luego seguimos con un Multiplexor de 3 entradas/ 1 salida , y como selector la salida de un contador ascendente binario del 0 al 2, cuyo reloj tiene una frecuencia de 1 khz, para poder lograr la visualización dinámica para el manejo de los displays de 7 segmentos:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Mux_31 is
Port ( C : in STD_LOGIC_VECTOR (3 downto 0);
D : in STD_LOGIC_VECTOR (3 downto 0);
U : in STD_LOGIC_VECTOR (3 downto 0);
Selectores : in STD_LOGIC_VECTOR (1 downto 0);
Salidas : out STD_LOGIC_VECTOR (3 downto 0));
end Mux_31;
architecture Behavioral of Mux_31 is
begin
process (Selectores,C,D,U)
begin
case Selectores is
when "00" => Salidas <= C;
when "01" => Salidas <= D;
when "10" => Salidas <= U;
when others => Salidas <= "0000";
end case;
end process;
end Behavioral;
De acuerdo al esquemático que nos sirve de guía seguimos con el decodificador de BCD a 7 segmentos:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Dec7seg is
port( BCD: in STD_LOGIC_VECTOR (3 downto 0);
led: out STD_LOGIC_VECTOR(6 downto 0) );
end Dec7seg;
architecture comportamiento of Dec7seg is
begin
process (BCD)
begin
case BCD is
when "0000" => LED <= "0000001"; --0
when "0001" => LED <= "1001111"; --1
when "0010" => LED <= "0010010"; --2
when "0011" => LED <= "0000110"; --3
when "0100" => LED <= "1001100"; --4
when "0101" => LED <= "0100100"; --5
when "0110" => LED <= "0100000"; --6
when "0111" => LED <= "0001111"; --7
when "1000" => LED <= "0000000"; --8
when "1001" => LED <= "0001100"; --9
when others => LED <= "0001100"; --9
end case;
end process ;
end comportamiento;
Continuamos ahora con el Divisor de frecuencia del clock de 50 Mhz a 1 Khz:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity RELOJ1KHZ is
Port ( CLK50MHZ : in STD_LOGIC;
CLK1KHZ : out STD_LOGIC);
end RELOJ1KHZ;
architecture Behavioral of RELOJ1KHZ is
signal pulso: STD_LOGIC := '0';
signal contador: integer range 0 to 24999 := 0;
begin
process (CLK50Mhz)
begin
if (CLK50Mhz'event and CLK50Mhz = '1') then
if (contador = 24999) then
pulso <= NOT(pulso);
contador <= 0;
else
contador <= contador+1;
end if;
end if;
end process;
CLK1KHZ <= pulso;
end Behavioral;
El esquemático nos muestra ahora que seguimos con el contador del 0 al 2:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Cont_0al2 is
Port ( Clk : in STD_LOGIC;
Q : inout STD_LOGIC_VECTOR (1 downto 0));
end Cont_0al2;
architecture Behavioral of Cont_0al2 is
begin
process (Clk)
begin
if Clk ='1' and Clk'event then
if Q = "11" then Q <= "00";
else
Q <= Q + 1;
end if;
end if;
end process;
end Behavioral;
Finalmente requerimos manejar los ánodos de los displays de 7 segmentos, ánodo común, para lograr el efecto de persistencia de la imágen en la retina requerido para la visualización dinámica:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Anodos_displays is
Port ( Input : in STD_LOGIC_VECTOR(1 downto 0);
Anodos : out STD_LOGIC_VECTOR (3 downto 0));
end Anodos_displays;
architecture Behavioral of Anodos_displays is
begin
process(Input)
begin
case Input is
when "00" => Anodos <= "0111";
when "01" => Anodos <= "1011";
when "10" => Anodos <= "1101";
when others => Anodos <= "1111";
end case;
Anodos(0) <= '1';
end process;
end Behavioral;
Luego procedemos a elaborar el código del circuito final que utilice los seis componentes descritos anteriormente y que cumpla con las conexiones, señales internas, entradas y salidas, descritas en el esquemático que nos ha servido de guía en el diseño:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Final is
Port ( Binario : in STD_LOGIC_VECTOR (7 downto 0);
Reloj50mhz : in STD_LOGIC;
Catodos : out STD_LOGIC_VECTOR (6 downto 0);
Anodos : out STD_LOGIC_VECTOR (3 downto 0));
end Final;
architecture Behavioral of Final is
Signal XCen, XDec, XUni, XBCD: STD_LOGIC_VECTOR (3 downto 0);
Signal X1khz : STD_LOGIC;
Signal XQ: STD_LOGIC_VECTOR (1 downto 0);
Component Conv_Bin_BCD
Port ( Bin : in STD_LOGIC_VECTOR (7 downto 0);
Cen : out STD_LOGIC_VECTOR (3 downto 0);
Dec : out STD_LOGIC_VECTOR (3 downto 0);
Uni : out STD_LOGIC_VECTOR (3 downto 0));
end Component;
Component Mux_31
Port ( C : in STD_LOGIC_VECTOR (3 downto 0);
D : in STD_LOGIC_VECTOR (3 downto 0);
U : in STD_LOGIC_VECTOR (3 downto 0);
Selectores : in STD_LOGIC_VECTOR (1 downto 0);
Salidas : out STD_LOGIC_VECTOR (3 downto 0));
end Component;
Component Dec7seg
port( BCD: in STD_LOGIC_VECTOR (3 downto 0);
led: out STD_LOGIC_VECTOR(6 downto 0) );
end Component;
Component RELOJ1KHZ
Port ( CLK50MHZ : in STD_LOGIC;
CLK1KHZ : out STD_LOGIC);
end Component;
Component Cont_0al2
Port ( Clk : in STD_LOGIC;
Q : inout STD_LOGIC_VECTOR (1 downto 0));
end Component;
Component Anodos_displays
Port ( Input : in STD_LOGIC_VECTOR(1 downto 0);
Anodos : out STD_LOGIC_VECTOR (3 downto 0));
end Component;
begin
paso1: Conv_Bin_BCD PORT MAP (Binario, XCen, XDec, XUni);
paso2: Mux_31 PORT MAP (XCen, XDec, XUni, XQ, XBCD );
paso3: Dec7seg PORT MAP (XBCD, Catodos);
paso4: RELOJ1KHZ PORT MAP (Reloj50mhz, X1khz);
paso5: Cont_0al2 PORT MAP (X1khz,XQ);
paso6: Anodos_displays PORT MAP (XQ, Anodos);
end Behavioral;
Tenemos que tener el archivo UCF que describa los pines de la FPGA que voy a utilizar como entradas y salidas:
#PACE: Start of Constraints generated by PACE
#PACE: Start of PACE I/O Pin Assignments
NET "Anodos<0>" LOC = "F12" ;
NET "Anodos<1>" LOC = "J12" ;
NET "Anodos<2>" LOC = "M13" ;
NET "Anodos<3>" LOC = "K14" ;
NET "catodos<0>" LOC = "M12" ;
NET "catodos<1>" LOC = "L13" ;
NET "catodos<2>" LOC = "P12" ;
NET "catodos<3>" LOC = "N11" ;
NET "catodos<4>" LOC = "N14" ;
NET "catodos<5>" LOC = "H12" ;
NET "catodos<6>" LOC = "L14" ;
NET "Reloj50mhz" LOC = "B8" ;
NET "Binario<7>" LOC = "N3" ;
NET "Binario<6>" LOC = "E2" ;
NET "Binario<5>" LOC = "F3" ;
NET "Binario<4>" LOC = "G3" ;
NET "Binario<3>" LOC = "B4" ;
NET "Binario<2>" LOC = "K3" ;
NET "Binario<1>" LOC = "L3" ;
NET "Binario<0>" LOC = "P11" ;
#PACE: Start of PACE Area Constraints
#PACE: Start of PACE Prohibit Constraints
#PACE: End of Constraints generated by PAC
MUY INTERESANTE, YA LO IMPLEMENTE FUE MUY BUENA SU DESCRIPCIÓN APRENDÍ MUCHO DE SU LÓGICA: ¡¡GRACIAS!!!
ResponderEliminarIngeniero le agradezco el apoyo me ah salvado !
ResponderEliminarMESSIRVE
ResponderEliminarMuchas gracias, fue muy útil su blog. Saludos desde México.
ResponderEliminarGRACIAS PROFE CHUCHO, COMO LO AMO AHORA SÍ MI PROFE HILARIO NO ME VOLVERA A HUMILLAR FRENTE A TODOS MIS COMPAÑEROS LA VERDAD DEJA MUCHA TAREA DEBERIAN SACARLO DE MI ESCUELA. SALUDOS DESDE AREQUIPA - PERÚ
ResponderEliminar