sábado, 23 de febrero de 2013

Convertidor Binario-BCD con displays en VHDL


Si consultaste Google, seguramente encontraste la función to_bcd()del blog  VHDL Guru pero quizá te queden dudas sobre como implementarla en un código completo (Si, también tuve el mismo problema). Bien, en el caso del compilador ISE de Xilinx (se observará que estoy usando una tarjeta Basys 2) debe agregarse  un archivo de paquete que incluya esta función. Esto puede hacerse usando la plantilla VHDL Package o creando simplemente un nuevo archivo .vhd en blanco y agregarlo al proyecto (El compilador detectará automáticamente que es un paquete al terminar de escribir el código).

El siguiente código es la correcta implementación del Paquete y Cuerpo de Paquete de manera que la función pueda ser utilizada en nuestro programa:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

package bcd is

function to_bcd (bin : std_logic_vector(7 downto 0)) return std_logic_vector;
end bcd;

package body bcd is
function to_bcd (bin : std_logic_vector(7 downto 0)) return std_logic_vector is
variable i : integer:=0;
variable bcd  : std_logic_vector(11 downto 0) := (others => '0');
variable bint : std_logic_vector(7 downto 0) := bin;

begin
for i in 0 to 7 loop 
bcd(11 downto 1) := bcd(10 downto 0);
bcd(0) := bint(7);
bint(7 downto 1) := bint(6 downto 0);
bint(0) :='0';

if(i < 7 and bcd(3 downto 0) > "0100") then
bcd(3 downto 0) := bcd(3 downto 0) + "0011";
end if;

if(i < 7 and bcd(7 downto 4) > "0100") then
bcd(7 downto 4) := bcd(7 downto 4) + "0011";
end if;

if(i < 7 and bcd(11 downto 8) > "0100") then 
bcd(11 downto 8) := bcd(11 downto 8) + "0011";
end if;

end loop;
return bcd;
end to_bcd;
end bcd;


Al guardar el código agregado al proyecto, la función se agregará automáticamente a la librería "work". De manera que habrá que usarla en nuestro programa:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library work;
use work.bcd.all; -- Aquí está nuestra función

entity display is
port ( salida  : out std_logic_vector(7 downto 0);
       selector: out std_logic_vector(3 downto 0);
       binario : in  std_logic_vector(7 downto 0);
       clk     : in  std_logic );        
end entity;

architecture mostrar of display is
signal a: std_logic_vector(1 downto 0) :=(others => '0');
signal PULSO: STD_LOGIC:='0';
constant SESENTA: integer :=99999;
signal RET: integer  range 0 to SESENTA:=0;
signal BCD_out: std_logic_vector(11 downto 0);
signal bcd: std_logic_vector(3 downto 0);

begin
RETARDO: PROCESS(CLK) -- Divisor de frecuencia (de 50MHz a 50Hz)
BEGIN
 IF (RISING_EDGE(CLK)) THEN
 PULSO<='0';
 RET<=RET+1;
    IF RET=SESENTA THEN
    RET<=0;
    PULSO<='1';
    END IF;
 END IF;
 END PROCESS;


        process(pulso) begin -- Contador para selectores
       
            if (pulso'event and pulso = '1') then
                a <= a + 1;               
            end if;          
        end process;

BCD_out <= to_bcd(binario); -- Llamado a la función to_bcd

process (bcd) -- Decodificador BCD a 7 segmentos
begin      
case  bcd is
when "0000"=> salida <="00000011"-- '0'
when "0001"=> salida <="10011111"-- '1'
when "0010"=> salida <="00100101"-- '2'
when "0011"=> salida <="00001101"-- '3'
when "0100"=> salida <="10011001"-- '4'
when "0101"=> salida <="01001001"-- '5'
when "0110"=> salida <="01000001"-- '6'
when "0111"=> salida <="00011111"-- '7'
when "1000"=> salida <="00000001"-- '8'
when "1001"=> salida <="00001001";  -- '9'
when others=> salida <="11111111"-- 'x'
end case;
end process

             
        process (a) begin -- Ciclo de selectores
        case a is

    when "00" =>  bcd       <= BCD_out(3 downto 0);
                  selector  <= "0111";
               
    when "01" =>  bcd       <= BCD_out(7 downto 4);
                  selector  <= "1011";

    when "10" =>  bcd       <= BCD_out(11 downto 8);
                  selector  <= "1101";

    when others => bcd      <= "0000";
                   selector <= "1111";              
        end case;
        end process;
 end architecture;


6 comentarios:

Guerrero dijo...

Cuando veo estas publicaciones no les entiendo, pero no puedo evitar recordar cuando les entendía o por lo menos tenía una idea y me entra una nostalgia, pero por algo pasan las cosas.

Saludos!

Anónimo dijo...

what constant sesenta does?

Rodolfo Escobar dijo...

It's a frequency divider rate: Clk frequency/ Desired frequency

Unknown dijo...

¿Tendrás el arhivo .ucf para la tarjeta Spartan 3E?, ¡saludos!

Anónimo dijo...

recuerden que para realizar la correcta compilacion del paquete deben tener el programa que realize dicha compilacion en mi caso, por ejemplo, funciono bastante bien con el "modelsim-PE student edition 10.3" esto si les genera el error de que no encuentra la ruta para realizar la compilacion

Unknown dijo...

Alguien sabe si funciona en vivado ?