工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Industrial programming >> VHDL

初めての FPGA LED ウインカーを構築する方法:ステップバイステップのチュートリアル

ステップバイステップ ガイド:初めての FPGA LED ウィンカーの構築

パート 1:VHDL または Verilog の設計

このチュートリアルでは、ユーザー定義の周波数で LED を駆動する VHDL および Verilog コードを作成する方法を学びます。ワークフローに最適な言語を選択してください。

HDL を作成するときは、デザインが意図したとおりに動作することを確認する必要があります。間違いは避けられないので、シミュレーションは不可欠です。このチュートリアルは 2 つの重要なフェーズに分かれています:

<オル>
  • HDL デザイン
  • HDL シミュレーション
  • シミュレーションをスキップすると、ハードウェア上でのデバッグにコストがかかる可能性があります。シミュレーションを必須のチェックポイントとして扱います。

    プロジェクトの要件

    50% のデューティ サイクルで LED を 100Hz、50Hz、10Hz、または 1Hz で点滅させる HDL を作成します。 2 つのスイッチで希望の周波数を選択し、追加の LED_EN LED を有効にするには、スイッチを High にする必要があります。 FPGA は 25MHz 発振器で動作します。

    周波数セレクターの真理値表:

    シグナルの概要:

    有効にする スイッチ 1 スイッチ 2 LED 駆動周波数
    0 無効
    1 0 0 100Hz
    1 0 1 50Hz
    1 1 0 10Hz
    1 1 1 1Hz

    4 つの同時カウンタ プロセスが 25MHz クロックを監視し、ターゲット周波数ごとにトグルを生成します。特定の周波数が選択されていない場合でも、そのカウンターは実行され続けます。これは、ハードウェア同時実行の中心原則です。

    スイッチは、選択されたトグルを LED 出力にルーティングするマルチプレクサを形成します。マルチプレクサは純粋に組み合わせロジックであるため、クロックなしで動作します。

    以下は、アーキテクチャを示すブロック図です。

    初めての FPGA LED ウインカーを構築する方法:ステップバイステップのチュートリアル

    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 で時間を遅らせる方法:Wait For
    2. VHDL で関数を使用する方法
    3. VHDL でリンク リストを作成する方法
    4. プロシージャ ステートメント - VHDL の例
    5. VHDL で署名付きおよび署名なしを使用する方法
    6. 基本的な VHDL クイズ – パート 3
    7. セルフチェック テストベンチの作成方法
    8. 基本的な VHDL クイズ – パート 2
    9. 初めての VHDL プログラムの作成方法:Hello World!
    10. VUnit の概要
    11. 変数 - VHDL の例
    信号名 方向 説明
    i_クロック 入力 25MHz クロック
    i_enable 入力 スイッチを有効にする (logic0 =LED オフ)
    i_switch_1 入力 周波数選択スイッチ 1
    i_switch_2 入力 周波数選択スイッチ 2
    o_led_drive 出力 LED 駆動信号