Módulos

Siete segmentos y VHDL

Figura 2: Implementación del visualizador de siete segmentos.

En esta entrada se desarrolla un decodificador de seis bits a siete segmentos por medio de VHDL. Además se provee el archivo para implementación en la tarjeta Basys2 de Digilent.

[wpdm_file id=4]

Visualizador de siete segmentos

Un visualizador de siete segmentos se compone de siete diodos emisores de luz (LEDs) dispuestos en un patrón como se muestra en la figura 1, y algunos incluyen un octavo LED para el punto decimal. Existen dos tipos de visualizadores de acuerdo a su conexión eléctrica: ánodo común y cátodo común. Desde el punto de vista de programación (o del diseño de sistemas digitales), es necesario saber el tipo de visualizador para las condiciones de activación:

  • En ánodo común, un 0 se utiliza para encendido y un 1 para apagado (lógica negativa).
  • Caso contrario, cátodo común utiliza un uno para encender los LEDs y un cero para apagarlos (lógica positiva).
Figura 1: Visualizador de siete segmentos.

Figura 1: Visualizador de siete segmentos.

Caracteres

Al tener 7 LEDs se pueden generar un total de 128 combinaciones, aunque no todas ellas conforman caracteres. En esta entrada se hace uso de la tabla de símbolos utilizada por (Palacios, Remiro, y López, 2008) y se codifican los siguientes caracteres: 10 digitos (del 0 al 9), 26 letras (A a la Z), y los caracteres _, , y .. Para representar estos 37 símbolos se necesitan 6 bits (cinco bits pueden representar hasta 32 valores solamente). A este proceso de asignar un número a cada carácter se le conoce como codificación. Finalmente, para mostrar el digito en un visualizador de siete segmentos es necesario decodificar el valor numérico según el patrón de LEDs indicado. Esta decodificación se realiza asumiendo que el visualizador es de ánodo común (cero activa, uno apaga).

En resumen, inicialmente se tiene un carácter al cual se le asigna un valor numérico (codificación) para tratar con el digitalmente, posteriormente se transforma al patrón de LEDs correspondiente (decodificación).

Descripción de hardware

La descripción de hardware se encarga de determinar cuales LEDs estarán encendidos en base al valor de entrada de seis bits para cada uno de los 37 símbolos distintos y un caso para cubrir cualquier otro valor posible. El orden de los bits se muestra en la tabla 1.

Tabla 1: Bit correspondiente a cada segmento.
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
dp g f e d c b a

El listado 1, desarrollado en el IDE Xilinx ISE 13.4, muestra los 37 caracteres y su decodificación a siete segmentos correspondiente.

----------------------------------------------------------------------------------
-- Compañía:            Estado Finito
-- Ingeniero:           Carlos Ramos
-- 
-- Fecha de creación:   2012/07/29 12:56:33
-- Nombre del módulo:   siete_segmentos - Behavioral 
-- Descripción: 
--   Decodificador de seis bits a siete segmentos. Se incluyen los números del 0
--   al 9, las letras de la A a la Z, y otros signos de puntuación utilizados.
--
-- Revisión:
--   Revisión 0.01 - Archivo creado.
----------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
entity siete_segmentos is
    PORT (
        entrada: IN  STD_LOGIC_VECTOR(5 downto 0);
        salida : OUT STD_LOGIC_VECTOR(7 downto 0)
    );
end siete_segmentos;
 
architecture Behavioral of siete_segmentos is
begin
    visualizador: process (entrada) begin
        case entrada is
            when "000000" =>  salida <= x"C0"; -- 0
            when "000001" =>  salida <= x"F9"; -- 1
            when "000010" =>  salida <= x"A4"; -- 2
            when "000011" =>  salida <= x"B0"; -- 3
            when "000100" =>  salida <= x"99"; -- 4
            when "000101" =>  salida <= x"92"; -- 5
            when "000110" =>  salida <= x"82"; -- 6
            when "000111" =>  salida <= x"F8"; -- 7
            when "001000" =>  salida <= x"80"; -- 8
            when "001001" =>  salida <= x"98"; -- 9
            when "001010" =>  salida <= x"88"; -- A
            when "001011" =>  salida <= x"83"; -- B
            when "001100" =>  salida <= x"C6"; -- C
            when "001101" =>  salida <= x"A1"; -- D
            when "001110" =>  salida <= x"86"; -- E
            when "001111" =>  salida <= x"8E"; -- F
            when "010000" =>  salida <= x"90"; -- G
            when "010001" =>  salida <= x"89"; -- H
            when "010010" =>  salida <= x"E6"; -- I
            when "010011" =>  salida <= x"E1"; -- J
            when "010100" =>  salida <= x"85"; -- K
            when "010101" =>  salida <= x"C7"; -- L
            when "010110" =>  salida <= x"C8"; -- M
            when "010111" =>  salida <= x"AB"; -- N
            when "011000" =>  salida <= x"C0"; -- O
            when "011001" =>  salida <= x"8C"; -- P
            when "011010" =>  salida <= x"98"; -- Q
            when "011011" =>  salida <= x"AF"; -- R
            when "011100" =>  salida <= x"92"; -- S
            when "011101" =>  salida <= x"87"; -- T
            when "011110" =>  salida <= x"E3"; -- U
            when "011111" =>  salida <= x"C1"; -- V
            when "100000" =>  salida <= x"E2"; -- W
            when "100001" =>  salida <= x"8F"; -- X
            when "100010" =>  salida <= x"91"; -- Y
            when "100011" =>  salida <= x"B6"; -- Z
            when "100100" =>  salida <= x"BF"; -- -
            when "100101" =>  salida <= x"F7"; -- _
            when "100110" =>  salida <= x"7F"; -- .
            when others   =>  salida <= x"FF"; -- Nada
        end case;
    end process;
end Behavioral;

Implementación del circuito

El archivo de implementación simplemente determina a cual pin será enviada la señal de salida, como se muestra en el listado 2. El resultado se muestra en la figura 2.

# Entrada de datos. ###################
NET  "entrada<5>"  LOC = "F3";
NET  "entrada<4>"  LOC = "G3";
NET  "entrada<3>"  LOC = "B4";
NET  "entrada<2>"  LOC = "K3";
NET  "entrada<1>"  LOC = "L3";
NET  "entrada<0>"  LOC = "P11";
# Segmentos del visualizador. #########
NET  "salida<7>"   LOC = "N13"; # dp
NET  "salida<6>"   LOC = "M12"; # g
NET  "salida<5>"   LOC = "L13"; # f
NET  "salida<4>"   LOC = "P12"; # e
NET  "salida<3>"   LOC = "N11"; # d
NET  "salida<2>"   LOC = "N14"; # c
NET  "salida<1>"   LOC = "H12"; # b
NET  "salida<0>"   LOC = "L14"; # a
Figura 2: Implementación del visualizador de siete segmentos.

Figura 2: Implementación del visualizador de siete segmentos.

Como se puede apreciar en la figura 2, el carácter se despliega en los cuatro visualizadores (por el momento, este comportamiento es el esperado).

Conclusión

En este documento se plantea:

  • La codificación de 37 símbolos, es decir, asignación de caracteres a determinado número binario.
  • La decodificación de ese valor numérico hacia un visualizador de siete segmentos.
  • La descripción de hardware que crea un componente digital dedicado al visualizador.
  • La implementación del sistema en la tarjeta Basys2.

En la próxima entrega se verá como mostrar un digito diferente en cada uno de los visualizadores. En caso de alguna duda con la descripción de hardware, favor de utilizar la sección de comentarios :). Gracias por leer otro artículo más de este blog. No olvides compartir :).

Referencias

  • Haskell, Richard E. y Hanna, Darrin M. (2008). Learning by Example Using VHDL – Basic Digital Design with a Basys FPGA Board. Michigan: LBE Books.
  • Palacios, Enrique; Remiro, Fernando y López, Lucas (2004). Microcontrolador PIC16F84 – Desarrollo de proyectos. México: Alfaomega.

You Might Also Like

24 Comentarios

  • Responder
    Victor
    abril 19, 2013 at 1:25 pm

    Hola que tal buen día!!

    Quiero ver si me podrías ayudar a independizar cada uno de los displays de la tarjeta….es que estoy realizando unas practicas y pues apenas estoy empezando a conocer la plataforma….te agradecería tu ayuda….gracias

    • Responder
      Carlos Ramos
      abril 20, 2013 at 7:36 pm

      Hola, Victor. Si con independizar te refieres a mostrar un dígito distinto en cada visualizador de siete segmentos, se realiza por medio de multiplexores como se muestra en esta entrada. Espero haber resuelto tu duda. Caso contrario, no dudes en comentar. Gracias por tu participación :).

  • Responder
    nicole
    octubre 10, 2013 at 9:04 am

    Hola carlos, gusto en saludarte, quería comentarte que simulo tu programa pero cuando le doy implement design me aparece esto. FATAL_ERROR:PersonalityModule:baspmdlm.c:168:1.27 – dll library , quisiera saber cual es mi error xq no es en el único problema que corro y me aparece eso :/…..

    agradezco tu colaboracion

    • Responder
      Carlos Ramos
      octubre 15, 2013 at 5:47 pm

      Buenas tardes, Nicole. Hasta donde sé, ese problema es causado por una mala instalación del software de Xilinx por lo que una reinstalación completa debería solucionar ese error. Sería bueno contar con tu retroalimentación al respecto para futuras referencias :).

  • Responder
    Ricardo
    octubre 25, 2013 at 8:33 am

    Hola oye cuando uno todo el proyecto con los multiplexores y quienro crear el area constraints me manda un error en Implement desing y dice :

    ERROR:NgdBuild:604 – logical block ‘seg_i’ with type ‘siete_segmentos’ could not
    be resolved. A pin name misspelling can cause this, a missing edif or ngc
    file, or the misspelling of a type name. Symbol ‘siete_segmentos’ is not
    supported in target ‘spartan3e’.
    Que puedo hacer ???
    gracias

  • Responder
    Luis
    noviembre 11, 2013 at 6:43 pm

    ¿Podrías explicarme que significa los valores de salida en?
    when “000000” => salida <= x"C0"; — 0

    es que estoy implementando el proyecto en una SPARTAN 3 y esteproyecto y el del reloj me muestra solo el cero y el 8, yo le doy valores de bits a la salida y formo el número, pero esa codificación no sé si es diferente para cada tarjeta,

    ¿Podrías decirme como se llama eso o como lo busco en la datasheet?

    • Responder
      Carlos Ramos
      noviembre 13, 2013 at 6:21 pm

      Buenas tardes, Luis. Lo que esa línea hace es asignar el valor hexadecimal “C0” a la salida. Eso se traduce al siguiente valor binario: “11000000”, lo que implica que los segmentos correspondientes al punto decimal y el led g están en alto y los demás en bajo. Para la conexión en ánodo común como la que se maneja en la tarjeta Basys2, los led dp y g se encuentran apagados y los demás led están encendidos.

      En caso de utilizar una tarjeta diferente, lo que sería necesario modificar es el archivo de implementación o constraints para apuntar a los pines correspondientes.

      • Responder
        adelfo Garcia
        julio 1, 2016 at 2:01 pm

        Gran tutorial solo tengo una pregunta por que el valor binario para el display 10000000 yo veo que tu lo manejas como GFEDCBA y pues yo he visto en otros ejemplos que lo manejan asi ABCDEFG y el código que ellos manejan es casi idéntico por favor ayudame a aclarar esa duda

        • Responder
          Carlos Ramos
          julio 2, 2016 at 9:57 am

          Adelfo, la diferencia está en los pines de salida únicamente. Ambas representaciones son igual de arbitrarias (es decir, está así porque me pareció bien). Realmente, puedes hacer un desastre, como AGFBDCE si lo deseas. Mientras tú entiendas la representación, se puede utilizar. Claro, sería un dolor de cabeza, y no estándar, pero se puede. Tú como programador elijes la que consideres más oportuna.

  • Responder
    NAZARETH
    noviembre 21, 2015 at 8:09 pm

    Buenas Noches, le escribo porque estoy haciendo un proyecto pero con basys3, en donde quiero escribir en la pantalla 7 segmentos palabras como: OPEN, GUAR, ERRO. El problema es que no se como hacer que por pnatalla me salga una letra distinta. Espero me pueda ayudar y gracias!!!

  • Responder
    Mauricio Maldonado
    noviembre 24, 2015 at 2:32 pm

    Hola amigo , me gustaria saber si me podrias ayudar con el codigo del siete segmentos en VHDL para una Nexys II, es que hay algunos componentes que no existen en esta . y pues me queda complicado entender. Si no es mucho problema muchas gracias ! pdta: EXCELENTE BLOG!

  • Responder
    Raymundo
    enero 25, 2017 at 12:44 pm

    hola amigo buen tutorial, pero quisiera que esto solo se hiciera en un solo display y también poder decirle que partes del display prender, no se si me explique, espero tu pronta respuesta…..

  • Responder
    Pedro
    mayo 11, 2017 at 2:56 pm

    Buenas Carlos
    Le pido si me puede ayudar necesito hacer un código igual al de siete segmentos pero que funcione en un solo les con los selectores de la placa .no conozco la forma.Gracias

    • Responder
      Pedro
      mayo 11, 2017 at 2:58 pm

      Un solo led

  • Responder
    Francisco
    noviembre 17, 2017 at 11:02 am

    Hola, excelente tutorial, y página, he aprendido demasiado con tu ayuda, sin embargo me preguntaba ¿cómo podría colocar el valor que quiero encender en una variable en el apartado PORT? Por ejemplo:

    when “011011” => salida <= x"AF"; — R

    ¿Como podría colocar el en Port una variable que pueda asignarle a "salida" el valor que quiero?

    Espero su respuesta y gracias.

    • Responder
      Carlos Ramos
      noviembre 18, 2017 at 6:56 pm

      Francisco, gracias por tu comentario.
      He de decir que no comprendí tu pregunta.
      Tal vez busques algo como GENERIC, pero no estoy seguro :(.
      ¿Podrías elaborar un poco más en qué deseas lograr y por qué?
      Saludos.

      • Responder
        Francisco
        noviembre 18, 2017 at 7:26 pm

        Gracias por tu respuesta! Lo que pasa es que tenía que poner en los displays mi nombre y apellido en 16 estados(4 bits) por lo que la letra tendría que cambiar en cada display 16 veces. Mi programa, que ya entregué, lo realicé de manera manual es decir por cada combinación le indique la letra que tenía que poner, por ejemplo:

        When 0001 Salida<= x31;

        Y así 16 veces por display por lo que en total serían 64 declaraciones. Lo que buscaba era hacerlo mediante un subprograma en el que tuviera la letra que quiero mostrar cómo entrada y de salida diera la combinación en bcd. Por ejemplo:

        When 0001 Salida <= variable

        Y usar ese subprograma 4 veces en lugar de hacer 4 subprogramas diferentes.

        No sé si me explique, en un rato más subo mi código y me dices que opinas, esto solo es un adelanto xD.

        Gracias de nuevo por la respuesta y por la página!

        • Responder
          Carlos Ramos
          noviembre 20, 2017 at 12:17 pm

          Oh, oh. Ya entendí. Tenías que hacer que el texto se fuera moviendo, como en los letreros que colocan para informar de los vuelos, o que dicen “Bienvenido”, y que van repitiendo ese mensaje, o algo así.
          Es una buena idea para colocar aquí en el blog :).

          • Francisco
            noviembre 20, 2017 at 4:10 pm

            A si es jeje, entonces lo que no pude resolver fue como meter el código hexadecimal en una variable cómo el x”3F” por ejemplo, pensé en una variable tipo string pero no funcionó.
            Quedó pendiente por si lo subes en una nueva publicación 🙂

      • Responder
        Francisco
        noviembre 18, 2017 at 7:28 pm

        Olvide poner que me avisará, lo siento jeje.

  • Responder
    jose
    enero 9, 2018 at 1:58 pm

    Hola buenas tardes para una placa nexys 3 se hace lo mismo, espero me ayude gracias.

  • Responder
    Raul Sanchez
    febrero 26, 2019 at 2:47 pm

    Y EL CODIGO RELOJ PARA UN VHDL EN BASYS 3

  • Deja tu comentario