Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Industrial programming >> VHDL

Schritt-für-Schritt-Anleitung: Ihre erste FPGA-LED-Blink-Schaltung erstellen

Schritt-für-Schritt-Anleitung: Erste FPGA-LED-Blink-Schaltung bauen

Teil 1: VHDL- oder Verilog-Design

In diesem Tutorial lernen Sie, wie Sie VHDL- und Verilog-Code erstellen, der eine LED mit einer benutzerdefinierten Frequenz ansteuert. Wählen Sie die Sprache, die am besten zu Ihrem Workflow passt.

Beim Schreiben von HDL müssen Sie überprüfen, ob sich das Design wie beabsichtigt verhält. Fehler sind unvermeidlich, daher ist Simulation unverzichtbar. Dieses Tutorial ist in zwei kritische Phasen unterteilt:

  1. HDL-Design
  2. HDL-Simulation

Das Überspringen der Simulation kann zu kostspieligem On-Hardware-Debugging führen. Behandeln Sie die Simulation als obligatorischen Kontrollpunkt.

Projektanforderungen

Schreiben Sie HDL, das eine LED mit 100 Hz, 50 Hz, 10 Hz oder 1 Hz bei 50 % Tastverhältnis blinken lässt. Zwei Schalter wählen die gewünschte Frequenz, und ein zusätzlicher LED_EN-Schalter muss high sein, um die LED zu aktivieren. Der FPGA läuft mit einem 25-MHz-Oszillator.

Wahrheitstabelle für den Frequenzwähler:

EnableSchalter 1Schalter 2LED-Ansteuerfrequenz
0––deaktiviert
100100 Hz
10150 Hz
11010 Hz
1111 Hz

Signalübersicht:

SignalnameRichtungBeschreibung
i_clockEingang25 MHz Takt
i_enableEingangAktivierungsschalter (Logik 0 = LED aus)
i_switch_1EingangFrequenzwähler-Schalter 1
i_switch_2EingangFrequenzwähler-Schalter 2
o_led_driveAusgangLED-Ansteuersignal

Vier parallele Zählerprozesse überwachen den 25-MHz-Takt und erzeugen Toggles für jede Zielfrequenz. Selbst wenn eine bestimmte Frequenz nicht gewählt ist, läuft ihr Zähler weiter – ein Kernprinzip der Hardware-Konkurrenz.

Die Schalter bilden einen Multiplexer, der das gewählte Toggle zum LED-Ausgang routet. Multiplexer sind rein kombinatorische Logik und arbeiten ohne Takt.

Unten sehen Sie ein Blockdiagramm der Architektur:

Schritt-für-Schritt-Anleitung: Ihre erste FPGA-LED-Blink-Schaltung erstellen

VHDL-Implementierung

 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
    -- Konstanten für die benötigten Frequenzen:
    -- Formel: (25 MHz / 100 Hz * 50% Tastverhältnis)
    -- Für 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;

    -- Zähler-Signale
    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;

    -- Toggle-Signale für die Frequenzen
    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';

    -- Ein-Bit-Auswahlsignal
    signal w_LED_SELECT : std_logic;

begin
    -- Alle Prozessen toggeln ein spezifisches Signal mit einer anderen Frequenz.
    -- Sie laufen kontinuierlich, auch wenn die Schalter ihre Ausgabe nicht wählen.

    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;

    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;

    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;

    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;

    -- Multiplexer basierend auf Schalter-Eingängen
    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;

    -- o_led_drive nur treiben, wenn i_enable high ist (UND-Gatter).
    o_led_drive <= w_LED_SELECT and i_enable;

end rtl; 

Verilog-Implementierung

 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;

    // Konstanten (Parameter) für die Frequenzen:
    // Eingangstakt ist 25 kHz, willkürlich gewählt.
    // Formel: (25 kHz / 100 Hz * 50% Tastverhältnis)
    // Für 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;

    // Zähler-Signale
    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;

    // Toggle-Signale
    reg r_TOGGLE_100HZ = 1'b0;
    reg r_TOGGLE_50HZ  = 1'b0;
    reg r_TOGGLE_10HZ  = 1'b0;
    reg r_TOGGLE_1HZ   = 1'b0;

    // Ein-Bit-Auswahl
    reg r_LED_SELECT;
    wire w_LED_SELECT;

    // Alle always-Blöcke toggeln ein spezifisches Signal mit einer anderen Frequenz.
    // Sie laufen kontinuierlich, auch wenn die Schalter ihre Ausgabe nicht wählen.

    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

    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

    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

    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

    // Multiplexer basierend auf Schalter-Eingängen
    always @ (*) begin
        case ({i_switch_1, i_switch_2}) // Konkatenationsoperator
            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 Multiplexer-Design (gleich wie oben):
    // Kompakter, aber schwerer lesbar, besonders für Verilog-Einsteiger
    // 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;

endmodule 

Nächster Schritt: Simulieren Sie dieses Design in VHDL oder Verilog, um das korrekte Verhalten vor der Bereitstellung zu bestätigen.

VHDL

  1. VHDL & Verilog meistern: Saubere kombinatorische & sequentielle Logik schreiben
  2. FPGA Block RAM aus Textdateien mit VHDLs TEXTIO-Bibliothek initialisieren
  3. VUnit 101: Praktischer Leitfaden für automatisierte VHDL-Verifikation
  4. Einführung in VHDL: Ihr erstes AND-Gate bauen
  5. VHDL Procedure Beispiel: Inkrementieren eines Standard Logic Vectors
  6. Prozeduren in VHDL: Wiederverwendbaren Code für einfachere Designs
  7. Bedingte Logik in VHDL meistern: If-Then-Elsif-Else erklärt
  8. VHDL-Funktionen meistern: Praktischer Leitfaden für effizientes Design
  9. Umfassender Guide zu VHDL Typkonvertierungen mit Numeric_Std & Std_Logic_Arith
  10. While-Schleifen in VHDL meistern: Dynamische Iterationssteuerung