VHDL
Tu ne programmes pas un processeur.
Tu décris des circuits qui s'exécutent tous en même temps.
Tout est expliqué depuis la base — sans rien supposer.
Qu'est-ce que VHDL ?
VHDL signifie VHSIC Hardware Description Language (VHSIC = Very High Speed Integrated Circuit). C'est un langage inventé par le Département de la Défense américain dans les années 1980 pour décrire des circuits numériques. Ce n'est PAS de la programmation classique — c'est la description de comment des fils et des portes logiques sont connectés à l'intérieur d'une puce.
💻 LOGICIEL (Python / C)
- S'exécute sur un CPU séquentiellement
- Ligne 1 termine avant ligne 2
- Variables stockées en RAM
- Tu décris ce que la machine fait
- Pas de limite physique de variables
⚡ VHDL (Matériel)
- Tout s'exécute en parallèle, toujours
- Toutes les opérations simultanément
- Les signaux sont de vrais fils
- Tu décris ce qu'est le circuit
- Limité par les ressources physiques
Description matérielle
VHDL décrit la structure et le comportement de circuits numériques.
FPGA & ASIC
Ton code VHDL est synthétisé en vraies portes logiques sur un FPGA ou gravé dans un ASIC.
Simulation d'abord
Avant le matériel, tu simules avec GHDL, ModelSim ou Vivado.
Norme IEEE 1076
VHDL est une norme IEEE officielle. Version usuelle : VHDL-93 ou VHDL-2008.
Le Squelette d'un Fichier VHDL
Chaque fichier VHDL a la même structure en trois parties : la LIBRARY apporte les outils, l'ENTITY est la forme extérieure (les broches), et l'ARCHITECTURE est ce qu'il y a à l'intérieur (la logique).
Directions des ports
| MOT-CLÉ | DIRECTION | SIGNIFICATION | ANALOGIE |
|---|---|---|---|
IN | Entrée uniquement | Signal entrant dans la puce | Prise micro |
OUT | Sortie uniquement | Signal sortant de la puce | Prise haut-parleur |
INOUT | Bidirectionnel | Peut aller dans les deux sens | Port USB-C |
BUFFER | Sortie lisible | Sortie qu'on peut aussi relire en interne | Écran avec retour |
Signaux — Les Fils
En VHDL, un SIGNAL est un fil. Il transporte une valeur d'un endroit à un autre dans ton circuit. Chaque signal doit avoir un type — le plus important est STD_LOGIC.
| VALEUR | SIGNIFICATION | QUAND ON LA VOIT |
|---|---|---|
'0' | Zéro logique (relié à la masse) | Signal normal à 0 |
'1' | Un logique (relié à l'alimentation) | Signal normal à 1 |
'Z' | Haute impédance — fil flottant | Bus tri-état, fil déconnecté |
'U' | Non initialisé | Simulation — avant toute affectation |
'X' | Inconnu / conflit | Deux sources se battent |
1 bit : guillemets simples
'1' Multi-bits : guillemets doubles "1010"SIGNAL mon_fil : STD_LOGIC; SIGNAL mon_fil2 : STD_LOGIC := '0'; SIGNAL bus8 : STD_LOGIC_VECTOR(7 DOWNTO 0); SIGNAL u_val : UNSIGNED(7 DOWNTO 0); -- Affectation signal : <= mon_fil <= '1'; bus8 <= (OTHERS => '0');
Qu'est-ce qu'un VECTEUR ?
Un STD_LOGIC_VECTOR est un groupe de fils regroupés — un bus. Ensemble, 8 bits peuvent représenter des nombres de 0 à 255.
🎮 Vecteur Interactif — clique sur les bits !
SIGNAL mon_bus : STD_LOGIC_VECTOR(7 DOWNTO 0); mon_bus <= "10110001"; -- binaire mon_bus <= x"B1"; -- hexadécimal mon_bus <= (OTHERS => '0'); -- tous à 0 mon_fil <= mon_bus(3); -- lire bit 3 grand <= a & b; -- concaténer
Instructions Concurrentes
Entre BEGIN et END, toutes les instructions s'exécutent simultanément — ce sont des connexions permanentes de fils.
── 1. AFFECTATION DIRECTE y1 <= a AND b; y2 <= a OR b; y3 <= NOT a; ── 2. WHEN/ELSE (MUX concurrent) y <= a WHEN sel = '1' ELSE b; ── 3. WITH/SELECT (switch concurrent) WITH sel SELECT y <= a WHEN "00", b WHEN "01", '0' WHEN OTHERS;
Toutes les Portes Logiques
Une porte logique est le bloc de base de tout circuit numérique. Clique sur A et B pour voir les chronogrammes se mettre à jour en temps réel.
ENTITY porte_and IS PORT(A,B:IN STD_LOGIC;Y:OUT STD_LOGIC); END porte_and; ARCHITECTURE rtl OF porte_and IS BEGIN Y <= A AND B; END rtl;
ENTITY porte_or IS PORT(A,B:IN STD_LOGIC;Y:OUT STD_LOGIC); END porte_or; ARCHITECTURE rtl OF porte_or IS BEGIN Y <= A OR B; END rtl;
ENTITY porte_not IS PORT(A:IN STD_LOGIC;Y:OUT STD_LOGIC); END porte_not; ARCHITECTURE rtl OF porte_not IS BEGIN Y <= NOT A; END rtl;
ENTITY porte_nand IS PORT(A,B:IN STD_LOGIC;Y:OUT STD_LOGIC); END porte_nand; ARCHITECTURE rtl OF porte_nand IS BEGIN Y <= A NAND B; END rtl;
ENTITY porte_nor IS PORT(A,B:IN STD_LOGIC;Y:OUT STD_LOGIC); END porte_nor; ARCHITECTURE rtl OF porte_nor IS BEGIN Y <= A NOR B; END rtl;
ENTITY porte_xor IS PORT(A,B:IN STD_LOGIC;Y:OUT STD_LOGIC); END porte_xor; ARCHITECTURE rtl OF porte_xor IS BEGIN Y <= A XOR B; END rtl;
Tableau de vérité complet
| A | B | AND | OR | NOT A | NAND | NOR | XOR | XNOR |
|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 1 |
| 0 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | 0 |
| 1 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 |
| 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |
L'instruction PROCESS
Un PROCESS contient des instructions séquentielles (dans l'ordre). Il se réveille uniquement quand un signal de sa liste de sensibilité change.
— À l'intérieur du PROCESS : instructions dans l'ordre.
— Le PROCESS en entier : s'exécute en parallèle avec tout le reste.
PROCESS(signal1, signal2) -- déclenché si signal1 OU signal2 change BEGIN IF signal1 = '1' THEN sortie <= '1'; ELSIF signal2 = '1' THEN sortie <= '0'; ELSE sortie <= 'Z'; END IF; END PROCESS;
WHEN OTHERS. IF → obligatoire ELSE. Sans ça, VHDL infère un LATCH — de la mémoire non voulue.Le Signal d'Horloge
L'horloge est le cœur d'un circuit numérique. Elle alterne 0 → 1 → 0 → 1 … à fréquence fixe. Presque toute la logique séquentielle est pilotée par le front montant (rising edge) : quand CLK passe de '0' à '1'.
-- Modèle universel : reset asynchrone + logique synchrone PROCESS(clk, rst) BEGIN IF rst = '1' THEN -- reset ASYNCHRONE (priorité max) q <= '0'; ELSIF rising_edge(clk) THEN -- sur le front montant q <= d; END IF; END PROCESS;
Compteur Modulo 10
Un compteur modulo 10 compte de 0 à 9, puis revient à 0. Il faut 4 bits (3 bits → max 7 : insuffisant !). Sur chaque front montant d'horloge, il s'incrémente.
⏱ Compteur Modulo 10 — Simulation Live
LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; ENTITY compteur_mod10 IS PORT(clk:IN STD_LOGIC;rst:IN STD_LOGIC;q:OUT STD_LOGIC_VECTOR(3 DOWNTO 0)); END compteur_mod10; ARCHITECTURE rtl OF compteur_mod10 IS SIGNAL cnt : UNSIGNED(3 DOWNTO 0) := (OTHERS => '0'); BEGIN PROCESS(clk, rst) BEGIN IF rst = '1' THEN cnt <= (OTHERS => '0'); ELSIF rising_edge(clk) THEN IF cnt = 9 THEN cnt <= (OTHERS => '0'); ELSE cnt <= cnt + 1; END IF; END IF; END PROCESS; q <= STD_LOGIC_VECTOR(cnt); END rtl;
Quiz 40 Questions
Questions progressives du niveau débutant au niveau avancé. Pour chaque mauvaise réponse, tu verras pourquoi c'est faux et quelle est la bonne réponse.
STD_LOGIC ?PROCESS en VHDL ?'0' AND '1' en VHDL ?NOT '1' en VHDL ?SIGNAL interne dans un fichier VHDL ?DOWNTO dans la déclaration STD_LOGIC_VECTOR(7 DOWNTO 0) ?NAND quand A='1' et B='1' ?'X' pour un signal STD_LOGIC en simulation VHDL ?my_bus ?'1' XOR '1' ?a et b en VHDL ?BEGIN y1 <= a AND b; y2 <= a OR b; END rtl;
NOR quand A='0' et B='0' ?STD_LOGIC_VECTOR(3 DOWNTO 0) ?WHEN OTHERS dans un bloc CASE dans un PROCESS ?PROCESS(clk, rst), pourquoi le test du reset est-il placé AVANT rising_edge(clk) ?SIGNAL et une VARIABLE en VHDL ?q <= (OTHERS => '0') pour un signal q : UNSIGNED(3 DOWNTO 0) ?cnt + 1) ?(a, b, sel) se réveille-t-il ?q <= STD_LOGIC_VECTOR(cnt) où cnt est UNSIGNED(3 DOWNTO 0) ?sel="10", c='1' ?WITH sel SELECT
y <= a WHEN "00",
b WHEN "01",
c WHEN "10",
'0' WHEN OTHERS;TO_INTEGER(UNSIGNED("1010")) ?a est STD_LOGIC_VECTOR(7 DOWNTO 0)) ?q <= a(6 DOWNTO 0) & '0';
y <= a WHEN sel = '1';
PROCESS(clk)
BEGIN
IF rising_edge(clk) THEN
IF en = '1' THEN
q <= d;
END IF;
END IF;
END PROCESS;INTEGER de valeur 5 en UNSIGNED(3 DOWNTO 0) ?PROCESS(clk, rst)
BEGIN
IF rst = '1' THEN
cnt <= (OTHERS => '0');
ELSIF rising_edge(clk) THEN
cnt <= cnt + 1;
END IF;
END PROCESS;
-- cnt est UNSIGNED(7 DOWNTO 0)ARCHITECTURE rtl OF mon_circuit IS, que représente le mot rtl ?SIGNAL s : STD_LOGIC_VECTOR(1 DOWNTO 0); SIGNAL a, b, c, d, y : STD_LOGIC;
PROCESS(clk)
BEGIN
IF rising_edge(clk) THEN
IF cnt = 9 THEN
cnt <= (OTHERS => '0');
tc <= '1';
ELSE
cnt <= cnt + 1;
tc <= '0';
END IF;
END IF;
END PROCESS;Mémo Complet
TOUJOURS EN HAUT
LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL;
AFFECTATIONS
signal <= val; -- planifié variable := val; -- immédiat
MODÈLE HORLOGE (copier !)
PROCESS(clk,rst) BEGIN IF rst='1' THEN q<=(OTHERS=>'0'); ELSIF rising_edge(clk) THEN -- logique ici END IF; END PROCESS;
PORTES LOGIQUES
y<=a AND b; -- ET y<=a OR b; -- OU y<=NOT a; -- NON y<=a NAND b;-- NON-ET y<=a NOR b;-- NON-OU y<=a XOR b;-- OU EXCL. y<=a XNOR b;-- ÉQUIVAL.
TYPES
STD_LOGIC -- 1 fil STD_LOGIC_VECTOR(N-1 DOWNTO 0) UNSIGNED(N-1 DOWNTO 0) SIGNED(N-1 DOWNTO 0) INTEGER RANGE 0 TO N
VECTEURS
v(7 DOWNTO 0) -- tous v(3) -- bit 3 a & b -- concat (OTHERS=>'0') -- zeros
CONVERSIONS
UNSIGNED(slv) STD_LOGIC_VECTOR(u) TO_INTEGER(u) TO_UNSIGNED(n,4)
COMPTEUR MODULO N
IF cnt = N-1 THEN cnt<=(OTHERS=>'0'); ELSE cnt<=cnt+1; END IF;
ERREURS À ÉVITER
❌ '1010' au lieu de "1010" ❌ Oublier END IF; / END PROCESS; ❌ Lire un port OUT en interne ❌ Pas de WHEN OTHERS (latch!) ❌ WHEN/ELSE sans ELSE final ❌ Mélanger <= et :=