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

Construyendo tu primer FPGA: Tutorial parpadeo LED (VHDL y Verilog)

Introducción

Bienvenido a una guía práctica que le guía through la creación de un simple parpadeo de LED en un FPGA usando VHDL o Verilog. El ejemplo demuestra conceptos centrales de FPGA: procesos concurrentes, síntesis de frecuencia y lógica de multiplexor —todo impulsado por un reloj de 25 MHz.

Visión general del proyecto

Tabla de verdad de selección de frecuencia

EnableSwitch 1Switch 2Frecuencia LED
0--(deshabilitado)
100100 Hz
10150 Hz
11010 Hz
1111 Hz

Definición de señales

Nombre SeñalDirecciónDescripción
i_clockEntradaReloj de sistema 25 MHz
i_enableEntradaInterruptor habilitación LED (lógica 0 = apagado)
i_switch_1EntradaSelector frecuencia bit 1
i_switch_2EntradaSelector frecuencia bit 0
o_led_driveSalidaSeñal de drive para el LED

Filosofía de diseño

Cuatro procesos de contador independientes se ejecutan concurrentemente, cada uno alternando una señal local en su frecuencia objetivo. Incluso cuando una frecuencia particular no está seleccionada, su contador continúa ejecutándose —esto es el sello de la concurrencia en FPGA.

Los interruptores implementan un multiplexor combinacional que enruta la señal de alternancia deseada al driver del LED. El interruptor LED_EN actúa como compuerta activa-alta, asegurando que el LED se apague cuando la habilitación es baja.

Diagrama de bloques

Construyendo tu primer FPGA: Tutorial parpadeo LED (VHDL y Verilog)

Implementación VHDL

A continuación se muestra un módulo VHDL completamente comentado que cumple la especificación. Las constantes de contador se calculan usando la fórmula:
cuenta = (frecuencia reloj / frecuencia objetivo) × 0.5 para lograr ciclo de trabajo 50%.

 library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity tutorial_led_blink is port ( i_clock : in std_logic; i_enable : in std_logic; i_switch_1 : in std_logic; i_switch_2 : in std_logic; o_led_drive : out std_logic ); end tutorial_led_blink; architecture rtl of tutorial_led_blink is -- Constantes de frecuencia (cuentas de semi-período) constant c_CNT_100HZ : natural := 125000; -- 25 MHz / 100 Hz × 0.5 constant c_CNT_50HZ : natural := 250000; -- 25 MHz / 50 Hz × 0.5 constant c_CNT_10HZ : natural := 1250000; -- 25 MHz / 10 Hz × 0.5 constant c_CNT_1HZ : natural := 12500000; -- 25 MHz / 1 Hz × 0.5 -- Señales de contador signal r_CNT_100HZ : natural range 0 to c_CNT_100HZ; signal r_CNT_50HZ : natural range 0 to c_CNT_50HZ; signal r_CNT_10HZ : natural range 0 to c_CNT_10HZ; signal r_CNT_1HZ : natural range 0 to c_CNT_1HZ; -- Salidas de alternancia signal r_TOGGLE_100HZ : std_logic := '0'; signal r_TOGGLE_50HZ : std_logic := '0'; signal r_TOGGLE_10HZ : std_logic := '0'; signal r_TOGGLE_1HZ : std_logic := '0'; -- Selección multiplexor signal w_LED_SELECT : std_logic; begin -- Proceso alternancia 100 Hz p_100_HZ : process (i_clock) is begin if rising_edge(i_clock) then if r_CNT_100HZ = c_CNT_100HZ-1 then r_TOGGLE_100HZ <= not r_TOGGLE_100HZ; r_CNT_100HZ <= 0; else r_CNT_100HZ <= r_CNT_100HZ + 1; end if; end if; end process p_100_HZ; -- Proceso alternancia 50 Hz p_50_HZ : process (i_clock) is begin if rising_edge(i_clock) then if r_CNT_50HZ = c_CNT_50HZ-1 then r_TOGGLE_50HZ <= not r_TOGGLE_50HZ; r_CNT_50HZ <= 0; else r_CNT_50HZ <= r_CNT_50HZ + 1; end if; end if; end process p_50_HZ; -- Proceso alternancia 10 Hz p_10_HZ : process (i_clock) is begin if rising_edge(i_clock) then if r_CNT_10HZ = c_CNT_10HZ-1 then r_TOGGLE_10HZ <= not r_TOGGLE_10HZ; r_CNT_10HZ <= 0; else r_CNT_10HZ <= r_CNT_10HZ + 1; end if; end if; end process p_10_HZ; -- Proceso alternancia 1 Hz p_1_HZ : process (i_clock) is begin if rising_edge(i_clock) then if r_CNT_1HZ = c_CNT_1HZ-1 then r_TOGGLE_1HZ <= not r_TOGGLE_1HZ; r_CNT_1HZ <= 0; else r_CNT_1HZ <= r_CNT_1HZ + 1; end if; end if; end process p_1_HZ; -- Multiplexor basado en entradas de interruptores w_LED_SELECT <= r_TOGGLE_100HZ when (i_switch_1 = '0' and i_switch_2 = '0') else r_TOGGLE_50HZ when (i_switch_1 = '0' and i_switch_2 = '1') else r_TOGGLE_10HZ when (i_switch_1 = '1' and i_switch_2 = '0') else r_TOGGLE_1HZ; -- Puerta el drive del LED con el interruptor de habilitación o_led_drive <= w_LED_SELECT and i_enable; end rtl; 

Implementación Verilog

A continuación se muestra un módulo Verilog equivalente. La filosofía de diseño es idéntica —cuatro bloques always independientes, cada uno alternando en una frecuencia específica, y un multiplexor combinacional impulsado por los interruptores.

 module tutorial_led_blink ( i_clock, i_enable, i_switch_1, i_switch_2, o_led_drive ); input i_clock; input i_enable; input i_switch_1; input i_switch_2; output o_led_drive; // Parámetros de frecuencia (cuentas de semi-período) parameter c_CNT_100HZ = 125000; parameter c_CNT_50HZ = 250000; parameter c_CNT_10HZ = 1250000; parameter c_CNT_1HZ = 12500000; // Registros de contador reg [31:0] r_CNT_100HZ = 0; reg [31:0] r_CNT_50HZ = 0; reg [31:0] r_CNT_10HZ = 0; reg [31:0] r_CNT_1HZ = 0; // Registros de alternancia reg r_TOGGLE_100HZ = 1'b0; reg r_TOGGLE_50HZ = 1'b0; reg r_TOGGLE_10HZ = 1'b0; reg r_TOGGLE_1HZ = 1'b0; // Selección multiplexor reg r_LED_SELECT; wire w_LED_SELECT; // Bloque alternancia 100 Hz always @(posedge i_clock) begin if (r_CNT_100HZ == c_CNT_100HZ-1) begin r_TOGGLE_100HZ <= ~r_TOGGLE_100HZ; r_CNT_100HZ <= 0; end else r_CNT_100HZ <= r_CNT_100HZ + 1; end // Bloque alternancia 50 Hz always @(posedge i_clock) begin if (r_CNT_50HZ == c_CNT_50HZ-1) begin r_TOGGLE_50HZ <= ~r_TOGGLE_50HZ; r_CNT_50HZ <= 0; end else r_CNT_50HZ <= r_CNT_50HZ + 1; end // Bloque alternancia 10 Hz always @(posedge i_clock) begin if (r_CNT_10HZ == c_CNT_10HZ-1) begin r_TOGGLE_10HZ <= ~r_TOGGLE_10HZ; r_CNT_10HZ <= 0; end else r_CNT_10HZ <= r_CNT_10HZ + 1; end // Bloque alternancia 1 Hz always @(posedge i_clock) begin if (r_CNT_1HZ == c_CNT_1HZ-1) begin r_TOGGLE_1HZ <= ~r_TOGGLE_1HZ; r_CNT_1HZ <= 0; end else r_CNT_1HZ <= r_CNT_1HZ + 1; end // Multiplexor combinacional always @(*) begin case ({i_switch_1, i_switch_2}) 2'b11: r_LED_SELECT <= r_TOGGLE_1HZ; 2'b10: r_LED_SELECT <= r_TOGGLE_10HZ; 2'b01: r_LED_SELECT <= r_TOGGLE_50HZ; 2'b00: r_LED_SELECT <= r_TOGGLE_100HZ; endcase end // Drive LED con compuerta de habilitación assign o_led_drive = r_LED_SELECT & i_enable; endmodule 

Simulación y verificación

Antes de programar el FPGA, ejecute una simulación conductual (p. ej., con ModelSim, VCS o Vivado Simulator). Verifique que cada señal de alternancia coincida con el período esperado y que el multiplexor enrute correctamente la señal según la combinación de interruptores. Simular temprano elimina costosa depuración en hardware y confirma que el ciclo de trabajo del 50% se mantiene.

Conclusión

Este tutorial demuestra cómo construir un parpadeo LED compacto y reutilizable que puede adaptarse a otras tareas de temporización. El mismo patrón de síntesis de frecuencia basado en contadores escala a máquinas de estados más complejas, convirtiéndolo en una habilidad fundamental para cualquier desarrollador FPGA.

VHDL

  1. Dominando el Mantenimiento Preventivo: Estrategias para optimizar su programa PM
  2. Mejore su programa de análisis de lubricantes para máxima confiabilidad de activos
  3. 10 Estrategias Comprobadas para Mejorar su Programa de Mantenimiento Preventivo
  4. Domine el diseño PCB rápidamente con Ultiboard: Tutorial completo
  5. Tutorial de diseño PCB con KiCad: Domine el desarrollo PCB de código abierto
  6. Diseño de un Programa Efectivo de Mantenimiento Preventivo para Equipos
  7. Iniciándose en desarrollo FPGA: Construyendo sumador 4-bit en Xilinx Artix-7
  8. Tecnología eFPGA: Revolucionando el Diseño de ASIC y SoC
  9. C# Hola Mundo – Construyendo su primera aplicación en C#
  10. Tu primer programa VHDL: Tutorial paso a paso Hello World
  11. Dominar Verilog: Tutorial completo para diseño de circuitos digitales