Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial programming >> VHDL

Stapsgewijze Handleiding: Je Eerste FPGA LED-knipperder Bouwen

Stapsgewijze Handleiding: Je Eerste FPGA LED-knipperder Bouwen

Deel 1: VHDL of Verilog Ontwerpen

In deze leer leer je hoe je VHDL- en Verilog-code schrijft die een LED aanstuurt op een door de gebruiker gedefinieerde frequentie. Kies de taal die het beste past bij je workflow.

Bij het schrijven van HDL moet je verifiëren dat het ontwerp zich gedraagt zoals bedoeld. Fouten zijn onvermijdelijk, dus simulatie is onmisbaar. Deze tutorial is verdeeld in twee cruciale fasen:

  1. HDL-ontwerp
  2. HDL-simulatie

Het overslaan van simulatie kan leiden tot dure debugging op de hardware. Behandel simulatie als een verplichte controlepunt.

Projectvereisten

Schrijf HDL dat een LED laat knipperen op 100 Hz, 50 Hz, 10 Hz of 1 Hz met een duty cycle van 50%. Twee schakelaars selecteren de gewenste frequentie, en een extra LED_EN-schakelaar moet hoog zijn om de LED in te schakelen. De FPGA draait op een 25 MHz-oscillator.

Waarheidstabel voor de frequentieselector:

EnableSchakelaar 1Schakelaar 2LED-aanstuurfrequentie
0––uitgeschakeld
100100 Hz
10150 Hz
11010 Hz
1111 Hz

Signaaloverzicht:

SignaalnaamRichtingBeschrijving
i_clockInvoer25 MHz klok
i_enableInvoerInschakelschakelaar (logica 0 = LED uit)
i_switch_1InvoerFrequentieselectorschakelaar 1
i_switch_2InvoerFrequentieselectorschakelaar 2
o_led_driveUitvoerLED-aanstuursignaal

Vier gelijktijdige tellerprocessen monitoren de 25 MHz-klok en genereren toggles voor elke doelfrequentie. Zelfs wanneer een bepaalde frequentie niet geselecteerd is, blijft de teller lopen – een kernprincipe van hardware-parallelisme.

De schakelaars vormen een multiplexer die de gekozen toggle doorstuurt naar de LED-uitgang. Multiplexers zijn puur combinatorische logica, dus ze werken zonder klok.

Hieronder is een blokdiagram dat de architectuur illustreert:

Stapsgewijze Handleiding: Je Eerste FPGA LED-knipperder Bouwen

VHDL-implementatie

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
-- Constanten om de benodigde frequenties te creëren:
-- Formule is: (25 MHz / 100 Hz * 50% duty cycle)
-- Dus voor 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;

-- Deze signalen zijn de tellers:
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;

-- Deze signalen togglen op de benodigde frequenties:
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';

-- Eén bit select-draad.
signal w_LED_SELECT : std_logic;
begin
-- Alle processen togglen een specifiek signaal op een andere frequentie.
-- Ze lopen allemaal continu, zelfs als de schakelaars
-- hun specifieke uitvoer niet selecteren.
p_100_HZ : process (i_clock) is
begin
    if rising_edge(i_clock) then
        if r_CNT_100HZ = c_CNT_100HZ-1 then
            -- -1, omdat teller begint op 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, omdat teller begint op 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, omdat teller begint op 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, omdat teller begint op 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;

-- Een multiplexer maken op basis van schakelaarinvoeren
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;

-- Alleen o_led_drive laten aansturen wanneer i_enable hoog is (en-poort).
o_led_drive <= w_LED_SELECT and i_enable;
end rtl;

Verilog-implementatie

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;

// Constanten (parameters) om de benodigde frequenties te creëren:
// Invoerkok is 25 kHz, willekeurig gekozen.
// Formule is: (25 kHz / 100 Hz * 50% duty cycle)
// Dus voor 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;

// Deze signalen zijn de tellers:
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;

// Deze signalen togglen op de benodigde frequenties:
reg r_TOGGLE_100HZ = 1'b0;
reg r_TOGGLE_50HZ = 1'b0;
reg r_TOGGLE_10HZ = 1'b0;
reg r_TOGGLE_1HZ = 1'b0;

// Een bit select
reg r_LED_SELECT;
wire w_LED_SELECT;

begin
// Alle always-blokken togglen een specifiek signaal op een andere frequentie.
// Ze lopen allemaal continu, zelfs als de schakelaars
-- hun specifieke uitvoer niet selecteren.
always @ (posedge i_clock) begin
    if (r_CNT_100HZ == c_CNT_100HZ-1) // -1, omdat teller begint op 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, omdat teller begint op 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, omdat teller begint op 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, omdat teller begint op 0
    begin
        r_TOGGLE_1HZ <= !r_TOGGLE_1HZ;
        r_CNT_1HZ <= 0;
    end else
        r_CNT_1HZ <= r_CNT_1HZ + 1;
end

// Een multiplexer maken op basis van schakelaarinvoeren
always @ (*) begin
    case ({i_switch_1, i_switch_2}) // Concatentatie-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;

// Alternatieve manier om multiplexer te ontwerpen (zoals boven):
// Meer compact, maar moeilijker te lezen, vooral voor nieuwkomers in 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

Volgende stap: Simuleer dit ontwerp in VHDL of Verilog om correct gedrag te bevestigen voordat je het implementeert.

VHDL

  1. Formele verificatie van VHDL-modules met PSL meesteren
  2. Stapsgewijze Handleiding: Je Eerste FPGA LED-knipperder Bouwen
  3. Procedures in VHDL gebruiken: je ontwerp vereenvoudigen met herbruikbare code
  4. In-process procedures benutten voor schonere VHDL FSM-ontwerpen
  5. Willekeurige getallen genereren in VHDL: Van Uniform naar OSVVM
  6. Een klokgetriggerd proces in VHDL bouwen: een praktische gids
  7. Test je VHDL-basis – Interactieve Quiz Deel 1
  8. VHDL Variabelen Uitgelegd: Praktische Voorbeelden & Regels voor Betrouwbaar Ontwerp
  9. Gratis VHDL-simulator & editor setup: Een studentengids
  10. VHDL Records Gebruiken voor Schone, Herbruikbare FIFO-interfaces
  11. FPGA & VHDL Cursus: Bouw een Dot-Matrix LED-controller vanaf nul