Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Industrial programming >> VHDL

Controlador VHDL dual de display de 7 segmentos para Pmod SSD – Fácil integración FPGA

En este artículo, presentaré un módulo VHDL que puede mostrar un número de dos dígitos en el Pmod SSD: Display de siete segmentos de Digilent. El display dual de 7 segmentos es compatible con la interfaz Pmod, lo que significa que puede usarlo sin soldadura. Encaja en el conector Pmod, que es estándar en muchas placas de desarrollo FPGA.

Para probar la implementación VHDL, uso la Lattice iCEstick, una placa de desarrollo FPGA de bajo coste con conector Pmod. Además de la iCEstick, necesita un cable divisor Pmod de 2×6 pines a Dual 6 pines para convertir del conector Pmod paralelo en la iCEstick a la versión en serie del conector que espera el display de 7 segmentos. Finalmente, recomiendo conseguir un cable de extensión USB tipo A porque enchufar la iCEstick directamente en el puerto USB del ordenador es poco práctico.

Cómo funcionan los displays de 7 segmentos

Hay muchos displays de 7 segmentos diferentes en el mercado. El número de dígitos varía entre ellos, y también la interfaz física y pinout. Una solución genérica que cubra todos los displays de 7 segmentos posibles que pueda encontrar probablemente no sería muy amigable. Sin embargo, puede usar el código presentado en este artículo como base y modificarlo para adaptarlo a sus necesidades.

La imagen superior es del datasheet del módulo Pmod de Digilent. Muestra cómo el display de 7 segmentos conecta a los pines Pmod. Estos pines son directamente accesibles al FPGA en la iCEstick.

Siete de los pines controlan un segmento cada uno en el display. Al conducir un valor lógico alto en tal pin, el segmento correspondiente se iluminará en el display. Pero hay dos dígitos en este display, y solo podemos controlar uno a la vez. El pin P4/C en el conector J2 selecciona uno u otro dígito. Cuando el voltaje lógico en este pin es '0', el dígito derecho se ilumina, si es '1', el dígito izquierdo se activa.

El punto decimal "DP" no está conectado y no se puede acceder.

La entidad

El código inferior muestra la entidad de nuestro módulo VHDL seg7. La entidad tiene un puerto genérico con una constante llamada clk_cnt_bits. Define la longitud de un contador interno que controla la tasa de refresco del display, la frecuencia de alternancia entre los dígitos izquierdo y derecho.

La frecuencia exacta no es esencial. Seleccione una longitud de contador que esté en el rango de 50 a un par de cientos de Hertz. La fórmula que determina la tasa de refresco es refresh_hz = 2clk_cnt_bits / clk_hz.

entity seg7 is
    generic (
        -- refresh_hz = (2 ** clk_cnt_bits) / clk_hz
        clk_cnt_bits : integer
    );
    port (
        clk : in std_logic;
        rst : in std_logic;
        value : in integer range 0 to 99;
        segments : out std_logic_vector(6 downto 0);
        digit_sel : out std_logic
    );
end seg7;

Además del reloj y reset, la entidad tiene una señal de entrada: el valor a mostrar en el display de 7 segmentos. La señal value es de tipo integer restringida al rango 0 a 99 porque estos son los únicos valores numéricos que es posible mostrar usando solo dos dígitos.

Las señales de salida son los siete segmentos como vector y la señal de selección de dígito para elegir el dígito izquierdo o derecho a iluminar.

Representando un decimal codificado en binario

Para representar los dígitos mostrados en el display usaremos el formato conocido como decimal codificado en binario (BCD). Mientras que una representación binaria es la forma más eficiente de almacenar el número decimal, nos encontramos con problemas al intentar dividirlo en el dígito izquierdo y derecho para mostrar en el display. No podemos distinguir entre los dígitos decimales meramente rebanando el vector usado para almacenar el número.

subtype digit_type is integer range 0 to 9;
type digits_type is array (1 downto 0) of digit_type;
signal digit : digit_type;
signal digits : digits_type;

Como se muestra en el código superior, declaramos un subtipo de integer en el rango 0 a 9 para describir el valor que puede ser representado por un dígito decimal. Luego, declaramos un nuevo tipo array que puede contener dos valores BCD tales. La señal digit mantiene el número que se está mostrando actualmente en el lado izquierdo o derecho del display. Por otro lado, la señal digits contiene los caracteres decimales individuales para los dos dígitos, como aparecerán a una persona viendo la pantalla.

Convertir decimal a BCD

La entrada a este módulo, value, es un integer en el rango 0 a 99, una representación binaria del número. Necesitamos convertir este único integer a dos integers en el rango 0 a 9, los BCDs.

El algoritmo estándar para esto es Double Dabble, también conocido como algoritmo shift-and-add-3. Aunque está bien usarlo, optaré por una solución más corta en nuestro caso porque solo tenemos dos dígitos que separar.

digits(1) <= value / 10;
digits(0) <= value - ((value / 10) * 10);

Usando división entera como se muestra en el código superior, podemos aislar el dígito decimal más significativo y asignarlo a la señal digits(1). Para obtener el dígito menos significativo, podemos restar el dígito más significativo de la señal value, dejándonos solo el número para asignar a la señal digits(0).

Contar ciclos de reloj

Retrasar tiempo en FPGAs es simplemente cuestión de contar ciclos de reloj. El período de reloj es el único intervalo de tiempo predecible en el que puede confiar en su código VHDL. El código inferior muestra la señal clk_cnt, que usamos para contar ciclos de reloj. El genérico clk_cnt_bits determina cuántos bits reservar para esta señal unsigned.

signal clk_cnt : unsigned(clk_cnt_bits - 1 downto 0);

La tasa de refresco exacta del display es de menor importancia, por eso he optado por un tipo unsigned aquí. Nos permite utilizar el comportamiento de auto-wrap de la señal unsigned. Todo lo que tenemos que hacer es incrementar el contador en cada flanco de subida del reloj. El código inferior muestra el proceso síncrono con reset que se encarga de esto.

COUNT_PROC : process(clk)
begin
    if rising_edge(clk) then
        if rst = '1' then
            clk_cnt <= (others => '0');
        else
            clk_cnt <= clk_cnt + 1;
        end if;
    end if;
end process;

Alternar entre dígitos

Ahora que tenemos el contador libre funcionando, podemos usar el bit más significativo (MSB) de la señal de contador unsigned para cambiar entre los dos dígitos. El MSB alterna entre '0' y '1' con un ciclo de trabajo del 50%. La primera línea del código inferior establece la señal digit_sel basada en el valor del MSB. La segunda línea implementa un multiplexor con el MSB usado como selector. Reenviará el valor del dígito activo del array digits a la señal digit.

digit_sel <= clk_cnt(clk_cnt'high);
digit <= digits(0) when clk_cnt(clk_cnt'high) = '0' else digits(1);

Codificador BCD a 7 segmentos


El paso final del módulo seg7 es traducir el BCD almacenado en la señal digit a una representación visual en el display de 7 segmentos. El código inferior muestra un proceso que logra esto usando una sentencia case.

La posición en el vector de cada bit literal corresponde a un segmento en el display. Índice 0 igual a segmento A, índice 1 es B, y así sucesivamente, hasta índice 6, que controla segmento G. Los mapeos de segmentos a índices de vector se derivan del datasheet para el display de 7 segmentos de Digilent.

ENCODER_PROC : process(digit)
begin
    case digit is
        when 0 => segments <= "0111111";
        when 1 => segments <= "0000110";
        when 2 => segments <= "1011011";
        when 3 => segments <= "1001111";
        when 4 => segments <= "1100110";
        when 5 => segments <= "1101101";
        when 6 => segments <= "1111101";
        when 7 => segments <= "0000111";
        when 8 => segments <= "1111111";
        when 9 => segments <= "1101111";
    end case;
end process;

La salida

El módulo VHDL seg7 renderizará en el display lo que asigne a la señal de entrada value. En el testbench, incrementamos la señal value una vez por segundo. Luego, simulamos un poco más de 100 segundos para poder observar el punto de wrap del contador value.

La forma de onda superior es de ModelSim. Muestra la primera parte de la simulación, donde el valor ha contado de 0 a 15. Podemos ver que los números en el array digits también están contando. Las unidades (0) cuentan cada vez que la señal value cambia, mientras que las decenas (1) incrementan en cada décimo número.

Puede descargar el proyecto ModelSim, incluyendo el testbench, usando el formulario inferior.

Si implementa el módulo seg7 como módulo superior en el FPGA, el display mostrará muy probablemente un "00" estable. Eso es porque '0' es el valor por defecto más común dado a señales no inicializadas en FPGAs. Cuando la señal value se establece a todos ceros, el display mostrará justamente eso.

Para recorrer todos los números de entrada posibles, creé un módulo VHDL wrapper que incrementa la señal value diez veces por segundo. Luego instancié el módulo seg7 en el wrapper antes de implementar el diseño en la Lattice iCEstick. El video GIF en bucle inferior muestra cómo se ve el diseño implementado en el display de 7 segmentos.

Comprando el Pmod SSD: Display de siete segmentos

El display de 7 segmentos usado en esta entrada viene de Digilent. Puede comprar el módulo Pmod en la webshop de Digilent, o conseguirlo en uno de los muchos revendedores. En el listado inferior, he enlazado a la página de producto para el display en unas pocas tiendas de electrónica online que tienen el artículo.

Tenga en cuenta que si quiere usar el display de 7 segmentos de Digilent con la Lattice iCEstick, o cualquier otra placa de desarrollo FPGA que tenga un conector Pmod de 6×2 pines, también necesita un cable divisor. El cable está disponible en Digilent, Digi-key, Mouser, y RS Electronics.

Adicionalmente, todos los componentes están disponibles de varios vendedores en Amazon y eBay.

Curso VHDL usando el display de 7 segmentos de Digilent

He lanzado un nuevo curso de VHDL y FPGA para principiantes absolutos. En el curso, uso el display de 7 segmentos de Digilent y la placa de desarrollo FPGA Lattice iCEstick para enseñar VHDL. Haga clic en el enlace inferior para leer más sobre el curso.

FPGA and VHDL Fast-Track:
Hands-On for Absolute Beginners

¿Está familiarizado con programación pero es nuevo en VHDL?
¿Necesita una introducción corta a esta materia desconocida?
¿Su agenda está llena sin tiempo para estudiar?

¡Entienda los fundamentos del desarrollo FPGA usando VHDL en unas pocas tardes! Este curso es para profesionales de IT y estudiantes que necesitan un repaso rápido de la materia. Con este curso y la placa de desarrollo Lattice iCEstick de bajo coste, estará desarrollando hardware real en horas.

Haga clic aquí para leer más e inscribirse:
FPGA and VHDL Fast-Track: Hands-On for Absolute Beginners

VHDL

  1. Dominando sentencias concurrentes en VHDL: Guía práctica
  2. Cuestionario Avanzado de VHDL – Parte 3
  3. Dominando tipos Signed y Unsigned en VHDL: Guía práctica
  4. Dominando constructos Loop y Exit en VHDL: Guía práctica
  5. Guía para Principiantes: Uso de ModelSim para Simulación FPGA y ASIC
  6. Tu primer programa VHDL: Tutorial paso a paso Hello World
  7. Curso FPGA y VHDL – Construya un controlador LED matriz de puntos desde cero
  8. Diseño de un búfer circular FIFO robusto en VHDL usando RAM de bloques
  9. Domine VHDL: Introducción Completa para Diseño FPGA y ASIC
  10. Construya un temporizador fiable en VHDL: Contar ciclos de reloj hasta horas
  11. Creación de un testbench dirigido por Tcl para un módulo VHDL de cerradura por código