Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> VHDL

Как собрать свою первую светодиодную мигалку на FPGA:пошаговое руководство

Пошаговое руководство:создание первой светодиодной мигалки на FPGA

Часть 1. Проектирование VHDL или Verilog

В этом руководстве вы узнаете, как создать код VHDL и Verilog, который управляет светодиодом с заданной пользователем частотой. Выберите язык, который лучше всего подходит для вашего рабочего процесса.

При написании HDL вы должны убедиться, что проект ведет себя так, как задумано. Ошибки неизбежны, поэтому моделирование необходимо. Это руководство разделено на два важных этапа:

  1. HDL-дизайн
  2. HDL-моделирование
  3. Пропуск моделирования может привести к дорогостоящей аппаратной отладке. Относитесь к моделированию как к обязательной контрольной точке.

    Требования к проекту

    Напишите HDL, который мигает светодиодом с частотой 100 Гц, 50 Гц, 10 Гц или 1 Гц с рабочим циклом 50%. Два переключателя выбирают нужную частоту, а дополнительный LED_EN Переключатель должен находиться в положении «высокое», чтобы включить светодиод. FPGA работает на генераторе 25 МГц.

    Таблица истинности для селектора частоты:

    Включить Переключатель1 Переключатель2 Частота управления светодиодом
    0 отключено
    1 0 0 100 Гц
    1 0 1 50 Гц
    1 1 0 10 Гц
    1 1 1 1 Гц

    Краткое описание сигнала:

    Имя сигнала Направление Описание
    i_clock Ввод Частота 25 МГц
    i_enable Ввод Включить переключатель (логический 0 =светодиод выключен)
    i_switch_1 Ввод Переключатель частоты 1
    i_switch_2 Ввод Переключатель частоты 2
    o_led_drive Вывод Сигнал управления светодиодом

    Четыре параллельных процесса счетчика контролируют тактовую частоту 25 МГц и генерируют переключатели для каждой целевой частоты. Даже если конкретная частота не выбрана, ее счетчик продолжает работать – это основной принцип аппаратного параллелизма.

    Переключатели образуют мультиплексор, который направляет выбранный переключатель на выход светодиода. Мультиплексоры представляют собой чисто комбинационную логику, поэтому они работают без тактового сигнала.

    Ниже приведена блок-схема, иллюстрирующая архитектуру:

    Как собрать свою первую светодиодную мигалку на FPGA:пошаговое руководство

    Реализация VHDL

    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
     -- Constants to create the frequencies needed:
     -- Formula is: (25 MHz / 100 Hz * 50% duty cycle)
     -- So for 100 Hz: 25,000,000 / 100 * 0.5 = 125,000
     constant c_CNT_100HZ : natural := 125000;
     constant c_CNT_50HZ : natural := 250000;
     constant c_CNT_10HZ : natural := 1250000;
     constant c_CNT_1HZ : natural := 12500000;
     -- These signals will be the counters:
     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;
     
     -- These signals will toggle at the frequencies needed:
     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';
     -- One bit select wire.
     signal w_LED_SELECT : std_logic;
     
    begin
     -- All processes toggle a specific signal at a different frequency.
     -- They all run continuously even if the switches are
     -- not selecting their particular output.
     
     p_100_HZ : process (i_clock) is
     begin
     if rising_edge(i_clock) then
     if r_CNT_100HZ = c_CNT_100HZ-1 then -- -1, since counter starts at 0
     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;
     p_50_HZ : process (i_clock) is
     begin
     if rising_edge(i_clock) then
     if r_CNT_50HZ = c_CNT_50HZ-1 then -- -1, since counter starts at 0
     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;
     
     p_10_HZ : process (i_clock) is
     begin
     if rising_edge(i_clock) then
     if r_CNT_10HZ = c_CNT_10HZ-1 then -- -1, since counter starts at 0
     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;
     
     p_1_HZ : process (i_clock) is
     begin
     if rising_edge(i_clock) then
     if r_CNT_1HZ = c_CNT_1HZ-1 then -- -1, since counter starts at 0
     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;
     
     -- Create a multiplexor based on switch inputs
     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;
     
     -- Only allow o_led_drive to drive when i_enable is high (and gate).
     o_led_drive <= w_LED_SELECT and i_enable;
    end rtl;
    

    Реализация Verilog

    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;
     
     // Constants (parameters) to create the frequencies needed:
     // Input clock is 25 kHz, chosen arbitrarily.
     // Formula is: (25 kHz / 100 Hz * 50% duty cycle)
     // So for 100 Hz: 25,000 / 100 * 0.5 = 125
     parameter c_CNT_100HZ = 125;
     parameter c_CNT_50HZ = 250;
     parameter c_CNT_10HZ = 1250;
     parameter c_CNT_1HZ = 12500;
     // These signals will be the counters:
     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;
     
     // These signals will toggle at the frequencies needed:
     reg r_TOGGLE_100HZ = 1'b0;
     reg r_TOGGLE_50HZ = 1'b0;
     reg r_TOGGLE_10HZ = 1'b0;
     reg r_TOGGLE_1HZ = 1'b0;
     
     // One bit select
     reg r_LED_SELECT;
     wire w_LED_SELECT;
     
    
    begin
     // All always blocks toggle a specific signal at a different frequency.
     // They all run continuously even if the switches are
     // not selecting their particular output.
     always @ (posedge i_clock)
     begin
     if (r_CNT_100HZ == c_CNT_100HZ-1) // -1, since counter starts at 0
     begin 
     r_TOGGLE_100HZ <= !r_TOGGLE_100HZ;
     r_CNT_100HZ <= 0;
     end
     else
     r_CNT_100HZ <= r_CNT_100HZ + 1;
     end
     
     always @ (posedge i_clock)
     begin
     if (r_CNT_50HZ == c_CNT_50HZ-1) // -1, since counter starts at 0
     begin 
     r_TOGGLE_50HZ <= !r_TOGGLE_50HZ;
     r_CNT_50HZ <= 0;
     end
     else
     r_CNT_50HZ <= r_CNT_50HZ + 1;
     end
     always @ (posedge i_clock)
     begin
     if (r_CNT_10HZ == c_CNT_10HZ-1) // -1, since counter starts at 0
     begin 
     r_TOGGLE_10HZ <= !r_TOGGLE_10HZ;
     r_CNT_10HZ <= 0;
     end
     else
     r_CNT_10HZ <= r_CNT_10HZ + 1;
     end
     
     always @ (posedge i_clock)
     begin
     if (r_CNT_1HZ == c_CNT_1HZ-1) // -1, since counter starts at 0
     begin 
     r_TOGGLE_1HZ <= !r_TOGGLE_1HZ;
     r_CNT_1HZ <= 0;
     end
     else
     r_CNT_1HZ <= r_CNT_1HZ + 1;
     end
     // Create a multiplexer based on switch inputs
     always @ (*)
     begin
     case () // Concatenation Operator 
     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
     assign o_led_drive = r_LED_SELECT & i_enable;
     // Alternative way to design multiplexer (same as above):
     // More compact, but harder to read, especially to those new to Verilog
     // assign w_LED_SELECT = i_switch_1 ? (i_switch_2 ? r_TOGGLE_1HZ : r_TOGGLE_10HZ) : 
     //(i_switch_2 ? r_TOGGLE_50HZ : r_TOGGLE_100HZ);
     // assign o_led_drive = w_LED_SELECT & i_enable;
     
    
    end 
    
    endmodule
    

    Следующий шаг:смоделируйте этот проект в VHDL или Verilog, чтобы убедиться в правильности поведения перед развертыванием.

VHDL

  1. Как использовать процедуру в VHDL
  2. RC-сервоконтроллер, использующий ШИМ от вывода FPGA
  3. Как использовать наиболее распространенный тип VHDL:std_logic
  4. Как бесплатно установить симулятор и редактор VHDL
  5. Ограниченная случайная проверка
  6. Как использовать создание экземпляра карты портов в VHDL
  7. Как использовать цикл For в VHDL
  8. Записи — пример VHDL
  9. Как использовать функцию в VHDL
  10. Как создать параллельный оператор в VHDL