Here is a simple, clear, and complete beginner tutorial to help you start programming FPGAs using VHDL — ideal even if you’ve never used VHDL before.
This guide walks you from zero → first blinking LED project → simulation → bitstream → hardware programming.
VHDL = VHSIC Hardware Description Language
You use VHDL to describe hardware circuits, not algorithms.
That means you are creating:
VHDL code becomes a real circuit inside your FPGA.STEP 2 — Install Tools (FREE)
➡️ Install Vivado WebPACK (free).
https://www.xilinx.com/support/download.html
Works for:
➡️ Install Quartus Prime Lite.
A VHDL file has two parts:
entity blink_led is
Port (
clk : in STD_LOGIC;
led : out STD_LOGIC
);
end blink_led;
architecture Behavioral of blink_led is
begin
-- your logic here
end Behavioral;
That’s the skeleton of every VHDL module.This is the FPGA “Hello World”.
Toggle LED every 1 second using a 100 MHz clock.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity blink_led is
Port (
clk : in STD_LOGIC; -- 100 MHz clock input
led : out STD_LOGIC -- LED output
);
end blink_led;
architecture Behavioral of blink_led is
signal counter : unsigned(26 downto 0) := (others => '0');
signal led_reg : STD_LOGIC := '0';
begin
process(clk)
begin
if rising_edge(clk) then
counter <= counter + 1;
if counter = 100000000 then
led_reg <= not led_reg;
counter <= (others => '0');
end if;
end if;
end process;
led <= led_reg;
end Behavioral;
You must tell Vivado which FPGA pin drives the LED.
Example for Basys 3:
set_property PACKAGE_PIN U16 [get_ports {led}]
set_property IOSTANDARD LVCMOS33 [get_ports {led}]
For clock (100 MHz):
set_property PACKAGE_PIN W5 [get_ports {clk}]
set_property IOSTANDARD LVCMOS33 [get_ports {clk}]
create_clock -period 10.00 -name sys_clk_pin -waveform {0 5} [get_ports clk]
To simulate:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity tb_blink is
end tb_blink;
architecture behavior of tb_blink is
signal clk : STD_LOGIC := '0';
signal led : STD_LOGIC;
begin
-- Instantiate the Unit Under Test (UUT)
uut: entity work.blink_led
port map (
clk => clk,
led => led
);
-- Clock generation (10 ns period = 100 MHz)
clk <= not clk after 5 ns;
end behavior;
You should see led toggling.
In Vivado:
✔️ Run Synthesis
✔️ Run Implementation
✔️ Generate Bitstream
Vivado will show:
.bit fileYour LED will blink 🎉
Congratulations — you've programmed your first FPGA with VHDL!
Concepts:
0000 → 1111Concepts:
Display 0–9.
Concepts:
Control LED brightness.
Concepts:
Communicate with PC serial port.
Concepts:
✔️ VHDL syntax and structure
✔️ Clocked vs combinational processes
✔️ Signals and variables
✔️ Constraints and pin mapping
✔️ Simulation and debugging
✔️ Timing and clock domains
✔️ Real hardware implementation