Membuat FPGA Pertama Anda: Tutorial LED Blink (VHDL & Verilog)
Pendahuluan
Selamat datang di panduan praktis yang memandu Anda dalam membuat LED blinker sederhana pada FPGA menggunakan VHDL atau Verilog. Contoh ini menunjukkan konsep inti FPGA: proses konkuren, sintesis frekuensi, dan logika multiplexer—semua didorong oleh clock 25 MHz.
Ringkasan Proyek
- Hasilkan empat frekuensi blink yang dapat dipilih: 100 Hz, 50 Hz, 10 Hz, dan 1 Hz.
- Pertahankan duty cycle 50% untuk setiap frekuensi.
- Aktifkan LED hanya ketika switch
LED_EN diaktifkan. - Pilih frekuensi yang diinginkan melalui dua switch independen.
- Simulasi diperlukan sebelum diterapkan ke hardware untuk menangkap kesalahan sejak dini.
Tabel Kebenaran Pemilihan Frekuensi
| Enable | Switch 1 | Switch 2 | Frekuensi Drive LED |
|---|
| 0 | - | - | (disabled) |
| 1 | 0 | 0 | 100 Hz |
| 1 | 0 | 1 | 50 Hz |
| 1 | 1 | 0 | 10 Hz |
| 1 | 1 | 1 | 1 Hz |
Definisi Sinyal
| Nama Sinyal | Arah | Deskripsi |
|---|
| i_clock | Input | Clock sistem 25 MHz |
| i_enable | Input | Switch enable LED (logika 0 = mati) |
| i_switch_1 | Input | Bit pemilih frekuensi 1 |
| i_switch_2 | Input | Bit pemilih frekuensi 0 |
| o_led_drive | Output | Sinyal drive untuk LED |
Filosofi Desain
Empat proses counter independen berjalan konkuren, masing-masing mengubah sinyal lokal pada frekuensi targetnya. Bahkan ketika frekuensi tertentu tidak dipilih, counternya tetap berjalan—ini adalah ciri khas konkuren FPGA.
Switch mengimplementasikan multiplexer kombinasi yang merutekan sinyal toggle yang diinginkan ke driver LED. Switch LED_EN bertindai sebagai gate aktif-tinggi, memastikan LED mati ketika enable rendah.
Diagram Blok

Implementasi VHDL
Di bawah ini adalah modul VHDL yang lengkap dengan komentar yang memenuhi spesifikasi. Konstanta counter dihitung menggunakan rumus:
count = (frekuensi clock / frekuensi target) × 0,5 untuk mencapai duty cycle 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 -- Konstanta frekuensi (hitung setengah periode) 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 -- Sinyal counter 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; -- Output toggle 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'; -- Sinyal pemilihan multiplexer signal w_LED_SELECT : std_logic; begin -- Toggle 100 Hz process 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; -- Toggle 50 Hz process 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; -- Toggle 10 Hz process 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; -- Toggle 1 Hz process 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 berdasarkan input switch 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; -- Gate drive LED dengan switch enable o_led_drive <= w_LED_SELECT and i_enable; end rtl;
Implementasi Verilog
Di bawah ini adalah modul Verilog yang setara. Filosofi desainnya identik—empat blok always independen, masing-masing mengubah pada frekuensi tertentu, dan multiplexer kombinasi yang didorong oleh switch.
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; // Parameter frekuensi (hitung setengah periode) parameter c_CNT_100HZ = 125000; parameter c_CNT_50HZ = 250000; parameter c_CNT_10HZ = 1250000; parameter c_CNT_1HZ = 12500000; // Register counter 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; // Register toggle reg r_TOGGLE_100HZ = 1'b0; reg r_TOGGLE_50HZ = 1'b0; reg r_TOGGLE_10HZ = 1'b0; reg r_TOGGLE_1HZ = 1'b0; // Sinyal pemilihan multiplexer reg r_LED_SELECT; wire w_LED_SELECT; // Blok toggle 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 // Blok toggle 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 // Blok toggle 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 // Blok toggle 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 // Multiplexer kombinasi 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 dengan gating enable assign o_led_drive = r_LED_SELECT & i_enable; endmodule Simulasi & Verifikasi
Sebelum memprogram FPGA, jalankan simulasi perilaku (misalnya, dengan ModelSim, VCS, atau Vivado Simulator). Verifikasi bahwa setiap sinyal toggle cocok dengan periode yang diharapkan dan bahwa multiplexer dengan benar merutekan sinyal berdasarkan kombinasi switch. Simulasi sejak dini menghilangkan debugging hardware yang mahal dan mengonfirmasi bahwa duty cycle 50% dipertahankan.
Kesimpulan
Tutorial ini menunjukkan cara membuat LED blinker yang kompak dan dapat digunakan ulang yang dapat disesuaikan untuk tugas timing lainnya. Pola sintesis frekuensi berbasis counter yang sama dapat diskalakan ke mesin status yang lebih kompleks, menjadikannya keterampilan dasar bagi setiap pengembang FPGA.