Cours VHDL Complet

Cours VHDL Complet

Langage de Description Materielle

💎 VHDL 🔲 FPGA ⚡ Digital
🎯

Chapitre 1 : Introduction au VHDL

Presentation du langage de description materielle

1.1 Qu'est-ce que le VHDL ?

📖
VHDL - VHSIC Hardware Description Language VHDL est un langage de description materielle utilise pour decrire le comportement et la structure de circuits electroniques numeriques. VHSIC signifie Very High Speed Integrated Circuit.

Historique

  • 1981 : Projet lance par le Departement de la Defense americain (DoD)
  • 1987 : Premiere normalisation IEEE 1076-1987
  • 1993 : Revision majeure IEEE 1076-1993
  • 2008 : IEEE 1076-2008 (VHDL-2008)
  • 2019 : IEEE 1076-2019 (version actuelle)

Pourquoi utiliser VHDL ?

📝

Documentation

Code auto-documente

🔄

Simulation

Test avant fabrication

⚙️

Synthese

Generation de circuits

🔁

Reutilisable

IP cores portables

Standard IEEE

Independant du fabricant

🏭

Industriel

Utilise mondialement

1.2 VHDL vs Verilog

Critere VHDL Verilog
Origine DoD americain (1983) Gateway Design (1984)
Syntaxe Proche de Ada/Pascal Proche de C
Typage Fortement type Faiblement type
Verbeux Plus verbeux Plus concis
Usage Europe Tres repandu Moins utilise
Usage USA/Asie Utilise Dominant
🏗️

Chapitre 2 : Structure d'un Programme VHDL

Entity, Architecture et composants

2.1 Les Unites de Conception

Un programme VHDL est compose de plusieurs unites de conception :

┌─────────────────────────────────────────────────────────┐
│                    FICHIER VHDL                         │
├─────────────────────────────────────────────────────────┤
│  ┌─────────────────┐                                    │
│  │    LIBRARY      │  Bibliotheques utilisees           │
│  │    USE          │  Packages importes                 │
│  └─────────────────┘                                    │
│           │                                             │
│           ▼                                             │
│  ┌─────────────────┐                                    │
│  │     ENTITY      │  Interface (ports E/S)             │
│  │   (Boite noire) │  Vue externe du composant          │
│  └─────────────────┘                                    │
│           │                                             │
│           ▼                                             │
│  ┌─────────────────┐                                    │
│  │  ARCHITECTURE   │  Implementation (comportement)     │
│  │ (Contenu)       │  Vue interne du composant          │
│  └─────────────────┘                                    │
└─────────────────────────────────────────────────────────┘

2.2 Declaration des Bibliotheques

-- Bibliotheque standard IEEE
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;      -- Types std_logic
use IEEE.NUMERIC_STD.ALL;         -- Types signed/unsigned

-- Anciennes bibliotheques (a eviter)
-- use IEEE.STD_LOGIC_ARITH.ALL;
-- use IEEE.STD_LOGIC_UNSIGNED.ALL;
💡
Conseil Utilisez toujours NUMERIC_STD au lieu de STD_LOGIC_ARITH pour les operations arithmetiques. C'est la norme moderne.

2.3 L'Entity (Entite)

L'entity definit l'interface externe du composant : ses ports d'entree et de sortie.

entity nom_entite is
    generic (
        -- Parametres generiques (optionnel)
        N : integer := 8
    );
    port (
        -- Entrees
        clk    : in  std_logic;
        reset  : in  std_logic;
        data_in: in  std_logic_vector(N-1 downto 0);
        
        -- Sorties
        data_out: out std_logic_vector(N-1 downto 0);
        valid  : out std_logic
    );
end entity nom_entite;

Modes des Ports

Mode Description Lecture Ecriture
in Entree uniquement Oui Non
out Sortie uniquement Non Oui
inout Bidirectionnel Oui Oui
buffer Sortie avec relecture Oui Oui

2.4 L'Architecture

L'architecture decrit le comportement interne ou la structure du composant.

architecture behavioral of nom_entite is
    -- Zone de declaration
    signal sig_interne : std_logic;
    constant MAX_VAL : integer := 255;
    
begin
    -- Zone des instructions concurrentes
    
    -- Affectation simple
    data_out <= data_in;
    
    -- Process (sequentiel)
    process(clk, reset)
    begin
        if reset = '1' then
            valid <= '0';
        elsif rising_edge(clk) then
            valid <= '1';
        end if;
    end process;
    
end architecture behavioral;

2.5 Exemple Complet : Porte AND

-- Fichier: porte_and.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity porte_and is
    port (
        A : in  std_logic;
        B : in  std_logic;
        Y : out std_logic
    );
end entity porte_and;

architecture dataflow of porte_and is
begin
    Y <= A and B;
end architecture dataflow;
📊

Chapitre 3 : Types de Donnees

Types scalaires, composites et conversion

3.1 Types Scalaires de Base

Type Description Exemple
bit Valeurs '0' ou '1' signal s : bit := '0';
boolean TRUE ou FALSE signal b : boolean := true;
integer Entiers 32 bits signal i : integer := 42;
natural Entiers >= 0 signal n : natural := 10;
positive Entiers > 0 signal p : positive := 1;
real Flottants (simulation) constant pi : real := 3.14;
character Caracteres ASCII constant c : character := 'A';
time Durees (simulation) constant T : time := 10 ns;

3.2 Types std_logic (IEEE 1164)

Le type std_logic est le plus utilise en synthese car il modelise les 9 etats possibles d'un signal numerique.

Valeur Signification Synthetisable
'0' Niveau bas force Oui
'1' Niveau haut force Oui
'Z' Haute impedance Oui
'X' Inconnu force Non
'U' Non initialise Non
'-' Don't care Oui
'L' Niveau bas faible Non
'H' Niveau haut faible Non
'W' Inconnu faible Non
-- Declaration de signaux std_logic
signal bit_unique  : std_logic;
signal bus_8bits   : std_logic_vector(7 downto 0);
signal bus_ascend  : std_logic_vector(0 to 7);

-- Affectation de valeurs
bit_unique <= '1';
bus_8bits  <= "10101010";         -- Binaire
bus_8bits  <= x"AA";              -- Hexadecimal
bus_8bits  <= (others => '0');    -- Tous a zero

3.3 Types signed et unsigned

library IEEE;
use IEEE.NUMERIC_STD.ALL;

-- unsigned : entier non signe (0 a 2^N-1)
signal compteur : unsigned(7 downto 0);  -- 0 a 255

-- signed : entier signe (complement a 2)
signal valeur   : signed(7 downto 0);    -- -128 a +127

-- Operations arithmetiques
compteur <= compteur + 1;              -- Increment
valeur   <= valeur - 10;               -- Soustraction

3.4 Conversions de Types

signal slv  : std_logic_vector(7 downto 0);
signal u    : unsigned(7 downto 0);
signal s    : signed(7 downto 0);
signal i    : integer;

-- std_logic_vector vers unsigned/signed
u <= unsigned(slv);
s <= signed(slv);

-- unsigned/signed vers std_logic_vector
slv <= std_logic_vector(u);
slv <= std_logic_vector(s);

-- integer vers unsigned/signed
u <= to_unsigned(i, 8);    -- 8 = nombre de bits
s <= to_signed(i, 8);

-- unsigned/signed vers integer
i <= to_integer(u);
i <= to_integer(s);
       CONVERSIONS DE TYPES EN VHDL

  ┌─────────────────┐
  │    integer      │
  └────────┬────────┘
           │ to_unsigned(i, N)
           │ to_signed(i, N)
           ▼
  ┌─────────────────┐
  │ unsigned/signed │ ◄────► Arithmetique (+, -, *, /)
  └────────┬────────┘
           │ std_logic_vector(u)
           │ unsigned(slv) / signed(slv)
           ▼
  ┌─────────────────┐
  │std_logic_vector │ ◄────► Logique (and, or, not)
  └─────────────────┘
🔧

Chapitre 4 : Operateurs

Operateurs logiques, arithmetiques et relationnels

4.1 Operateurs Logiques

Operateur Description Exemple
not NON logique Y <= not A;
and ET logique Y <= A and B;
or OU logique Y <= A or B;
nand NON-ET Y <= A nand B;
nor NON-OU Y <= A nor B;
xor OU exclusif Y <= A xor B;
xnor NON-OU exclusif Y <= A xnor B;

4.2 Operateurs Arithmetiques

-- Necessitent NUMERIC_STD pour unsigned/signed
signal a, b, c : unsigned(7 downto 0);

c <= a + b;        -- Addition
c <= a - b;        -- Soustraction
c <= a * b;        -- Multiplication (attention taille!)
c <= a / b;        -- Division (non synthetisable!)
c <= a mod b;      -- Modulo
c <= a rem b;      -- Reste
c <= abs(a);       -- Valeur absolue
c <= -a;           -- Negation
⚠️
Attention Multiplication La multiplication de deux vecteurs de N bits produit un resultat de 2N bits. Pensez a ajuster la taille du signal de sortie.

4.3 Operateurs Relationnels

-- Comparaisons (resultat : boolean)
if a = b then    -- Egalite
if a /= b then   -- Difference
if a < b then    -- Inferieur
if a <= b then   -- Inferieur ou egal
if a > b then    -- Superieur
if a >= b then   -- Superieur ou egal

4.4 Operateurs de Decalage

-- Decalages logiques (remplissage par '0')
c <= a sll 2;    -- Shift Left Logical (x4)
c <= a srl 2;    -- Shift Right Logical (/4)

-- Decalages arithmetiques (conserve le signe)
c <= a sla 2;    -- Shift Left Arithmetic
c <= a sra 2;    -- Shift Right Arithmetic

-- Rotations
c <= a rol 2;    -- Rotate Left
c <= a ror 2;    -- Rotate Right

-- Alternative avec NUMERIC_STD
c <= shift_left(a, 2);
c <= shift_right(a, 2);

4.5 Concatenation et Selection

signal a : std_logic_vector(3 downto 0);
signal b : std_logic_vector(3 downto 0);
signal c : std_logic_vector(7 downto 0);

-- Concatenation avec &
c <= a & b;                    -- c = a(3..0) & b(3..0)
c <= "0000" & a;              -- Extension a 8 bits

-- Selection de bits
a <= c(7 downto 4);           -- Bits de poids fort
b <= c(3 downto 0);           -- Bits de poids faible

-- Bit unique
signal bit : std_logic;
bit <= c(5);                   -- Bit numero 5
🔀

Chapitre 5 : Logique Combinatoire

Instructions concurrentes et affectations

5.1 Affectation Simple

-- Affectation directe (concurrente)
Y <= A and B;
Z <= A or B or C;
W <= not (A xor B);

5.2 Affectation Conditionnelle (when...else)

-- Multiplexeur 2:1
Y <= A when sel = '0' else
     B;

-- Multiplexeur 4:1
Y <= A when sel = "00" else
     B when sel = "01" else
     C when sel = "10" else
     D;

-- Comparateur
egal <= '1' when A = B else '0';

5.3 Affectation Selective (with...select)

-- Multiplexeur 4:1 avec with...select
with sel select
    Y <= A when "00",
         B when "01",
         C when "10",
         D when "11",
         '0' when others;

-- Decodeur 7 segments
with digit select
    segments <= "1111110" when "0000",  -- 0
                "0110000" when "0001",  -- 1
                "1101101" when "0010",  -- 2
                "1111001" when "0011",  -- 3
                -- ... etc
                "0000000" when others;

5.4 Exemple : Additionneur 4 bits

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity additionneur_4bits is
    port (
        A     : in  std_logic_vector(3 downto 0);
        B     : in  std_logic_vector(3 downto 0);
        Cin   : in  std_logic;
        Sum   : out std_logic_vector(3 downto 0);
        Cout  : out std_logic
    );
end entity;

architecture behavioral of additionneur_4bits is
    signal result : unsigned(4 downto 0);
begin
    result <= ('0' & unsigned(A)) + 
              ('0' & unsigned(B)) + 
              ("0000" & Cin);
    
    Sum  <= std_logic_vector(result(3 downto 0));
    Cout <= result(4);
end architecture;
⏱️

Chapitre 6 : Logique Sequentielle

Process, bascules et registres

6.1 Le Process

Le process est un bloc d'instructions sequentielles execute quand un signal de sa liste de sensibilite change.

-- Syntaxe generale
process(signal1, signal2, ...)  -- Liste de sensibilite
    -- Declarations locales (variables)
begin
    -- Instructions sequentielles
end process;

-- Process avec label (recommande)
mon_process: process(clk, reset)
begin
    -- ...
end process mon_process;

6.2 Bascule D (Flip-Flop)

-- Bascule D avec reset asynchrone
process(clk, reset)
begin
    if reset = '1' then
        Q <= '0';
    elsif rising_edge(clk) then
        Q <= D;
    end if;
end process;

-- Bascule D avec reset synchrone
process(clk)
begin
    if rising_edge(clk) then
        if reset = '1' then
            Q <= '0';
        else
            Q <= D;
        end if;
    end if;
end process;

-- Bascule D avec enable
process(clk, reset)
begin
    if reset = '1' then
        Q <= '0';
    elsif rising_edge(clk) then
        if enable = '1' then
            Q <= D;
        end if;
    end if;
end process;

6.3 Compteur

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity compteur_8bits is
    port (
        clk    : in  std_logic;
        reset  : in  std_logic;
        enable : in  std_logic;
        count  : out std_logic_vector(7 downto 0)
    );
end entity;

architecture behavioral of compteur_8bits is
    signal cnt : unsigned(7 downto 0);
begin
    process(clk, reset)
    begin
        if reset = '1' then
            cnt <= (others => '0');
        elsif rising_edge(clk) then
            if enable = '1' then
                cnt <= cnt + 1;
            end if;
        end if;
    end process;
    
    count <= std_logic_vector(cnt);
end architecture;

6.4 Registre a Decalage

entity shift_register is
    generic (N : integer := 8);
    port (
        clk      : in  std_logic;
        reset    : in  std_logic;
        shift_en : in  std_logic;
        data_in  : in  std_logic;
        data_out : out std_logic_vector(N-1 downto 0)
    );
end entity;

architecture behavioral of shift_register is
    signal reg : std_logic_vector(N-1 downto 0);
begin
    process(clk, reset)
    begin
        if reset = '1' then
            reg <= (others => '0');
        elsif rising_edge(clk) then
            if shift_en = '1' then
                reg <= reg(N-2 downto 0) & data_in;  -- Decalage gauche
            end if;
        end if;
    end process;
    
    data_out <= reg;
end architecture;
🔄

Chapitre 7 : Machines a Etats Finis (FSM)

Moore et Mealy

7.1 Types de Machines a Etats

🔵

Machine de Moore

Sorties dependent uniquement de l'etat courant

🟢

Machine de Mealy

Sorties dependent de l'etat ET des entrees

         MOORE                           MEALY
    ┌─────────────┐               ┌─────────────┐
    │             │               │             │
───►│    Etat     │──► Sorties ───►│    Etat     │───┐
    │   courant   │               │   courant   │   │
    │             │               │             │   │
    └──────┬──────┘               └──────┬──────┘   │
           │                             │          ▼
           │ Entrees                     │      Sorties
           ▼                             ▼          ▲
    ┌─────────────┐               ┌─────────────┐   │
    │   Logique   │               │   Logique   │───┘
    │   d'etat    │               │   d'etat    │
    └─────────────┘               └─────────────┘

7.2 Machine de Moore - Exemple

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity fsm_moore is
    port (
        clk    : in  std_logic;
        reset  : in  std_logic;
        start  : in  std_logic;
        done   : in  std_logic;
        busy   : out std_logic;
        ready  : out std_logic
    );
end entity;

architecture behavioral of fsm_moore is
    -- Definition des etats
    type state_type is (IDLE, RUNNING, FINISHED);
    signal state, next_state : state_type;
begin

    -- Process 1: Registre d'etat (sequentiel)
    process(clk, reset)
    begin
        if reset = '1' then
            state <= IDLE;
        elsif rising_edge(clk) then
            state <= next_state;
        end if;
    end process;

    -- Process 2: Logique de transition (combinatoire)
    process(state, start, done)
    begin
        case state is
            when IDLE =>
                if start = '1' then
                    next_state <= RUNNING;
                else
                    next_state <= IDLE;
                end if;
                
            when RUNNING =>
                if done = '1' then
                    next_state <= FINISHED;
                else
                    next_state <= RUNNING;
                end if;
                
            when FINISHED =>
                next_state <= IDLE;
                
            when others =>
                next_state <= IDLE;
        end case;
    end process;

    -- Process 3: Logique de sortie (Moore: depend de l'etat)
    process(state)
    begin
        case state is
            when IDLE =>
                busy  <= '0';
                ready <= '1';
            when RUNNING =>
                busy  <= '1';
                ready <= '0';
            when FINISHED =>
                busy  <= '0';
                ready <= '0';
            when others =>
                busy  <= '0';
                ready <= '0';
        end case;
    end process;

end architecture;
🧪

Chapitre 8 : Testbench et Simulation

Verification du design

8.1 Structure d'un Testbench

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity tb_compteur is
    -- Pas de ports pour un testbench!
end entity;

architecture test of tb_compteur is
    -- Composant a tester
    component compteur_8bits
        port (
            clk    : in  std_logic;
            reset  : in  std_logic;
            enable : in  std_logic;
            count  : out std_logic_vector(7 downto 0)
        );
    end component;
    
    -- Signaux de test
    signal clk_tb    : std_logic := '0';
    signal reset_tb  : std_logic := '0';
    signal enable_tb : std_logic := '0';
    signal count_tb  : std_logic_vector(7 downto 0);
    
    constant CLK_PERIOD : time := 10 ns;
    
begin
    -- Instanciation du DUT (Device Under Test)
    DUT: compteur_8bits
        port map (
            clk    => clk_tb,
            reset  => reset_tb,
            enable => enable_tb,
            count  => count_tb
        );
    
    -- Generation de l'horloge
    clk_tb <= not clk_tb after CLK_PERIOD/2;
    
    -- Process de stimuli
    stimulus: process
    begin
        -- Reset initial
        reset_tb <= '1';
        wait for 20 ns;
        reset_tb <= '0';
        
        -- Activer le compteur
        wait for 10 ns;
        enable_tb <= '1';
        
        -- Compter pendant 200ns
        wait for 200 ns;
        
        -- Desactiver
        enable_tb <= '0';
        wait for 50 ns;
        
        -- Fin de simulation
        report "Simulation terminee";
        wait;
    end process;
    
end architecture;

8.2 Assertions

-- Verifications dans le testbench
process
begin
    wait for 100 ns;
    
    -- Assert simple
    assert count_tb /= "00000000"
        report "Erreur: compteur devrait avoir compte!"
        severity ERROR;
    
    -- Assert avec note
    assert false
        report "Valeur du compteur: " & 
               integer'image(to_integer(unsigned(count_tb)))
        severity NOTE;
    
    wait;
end process;
⚙️

Chapitre 9 : Synthese et Implementation

Du code au circuit

9.1 Regles de Codage Synthetisable

  • Utiliser uniquement std_logic et std_logic_vector
  • Eviter les boucles while et for avec limites variables
  • Pas de wait dans le code synthetisable
  • Pas de real ou time
  • Toujours specifier le cas others dans les case
  • Initialiser les signaux dans le reset, pas a la declaration
  • Un seul signal d'horloge par process
🚀

Chapitre 10 : Projets Pratiques

Applications completes

10.1 Diviseur de Frequence

entity clock_divider is
    generic (DIV_FACTOR : integer := 50000000);  -- 50MHz -> 1Hz
    port (
        clk_in  : in  std_logic;
        reset   : in  std_logic;
        clk_out : out std_logic
    );
end entity;

architecture behavioral of clock_divider is
    signal counter : integer range 0 to DIV_FACTOR-1 := 0;
    signal clk_div : std_logic := '0';
begin
    process(clk_in, reset)
    begin
        if reset = '1' then
            counter <= 0;
            clk_div <= '0';
        elsif rising_edge(clk_in) then
            if counter = DIV_FACTOR-1 then
                counter <= 0;
                clk_div <= not clk_div;
            else
                counter <= counter + 1;
            end if;
        end if;
    end process;
    
    clk_out <= clk_div;
end architecture;

Cours VHDL Complet | Electronique et Informatique Industrielle

yacine.love