TD1 VHDL

Un livre de Wikibooks.

Sections

[modifier] Généralités

[modifier] Les libraire usuelles

[modifier] Librairie standard

Le VHDL fait appelle de manière implicite à une librairie dite standard. Celle-ci défini plusieurs types de base :

  • boolean
  • bit
  • character
  • severity_level
  • integer
  • real
  • time
  • delay_length
  • now
  • natural
  • positive
  • string
  • boolean_vector
  • bit_vector
  • integer_vector
  • real_vector
  • time_vector
  • file_open_kind
  • file_open_status
  • foreign

Les seuls types utilisés jusqu'à maintenant sont les « bit » et « bit_vector ». Un bit prend seulement deux valeurs et ne permet pas de gérer le trois états par exemple. IEEE propose en supplément une librairie appelée std_logic.

[modifier] Librairie IEEE-1164 standard logic

Les lignes suivantes importent la librairie IEEE-1164 standard logic.

library ieee;
use ieee.std_logic_1164.all;

Cette librairie déclare les types std_logic et std_logic_vector dont les valeurs acceptées sont :

  • 0 : Niveau logique bas à basse impédance (mise à la masse via une faible impédance)
  • 1 : Niveau logique haut à basse impédance (mise à Vcc via une faible impédance)
  • Z : Niveau logique flottant (entrée déconnecté)
  • L : Niveau logique bas à haute impédance (mise à la masse via une résistance de pull-down)
  • H : Niveau logique haut à haute impédance (mise à Vcc via une résistance de pull-up)
  • W : Niveau logique inconnu à haute impédance (pouvant être 'L', 'Z' ou 'H')
  • X : Niveau logique inconnu (pouvant être '0', 'L', 'Z', 'H' ou '1')
  • U : Non défini
  • - : N'importe quel niveau logique (renvoie toujours true lors d'une comparaison avec les 8 autres niveaux logiques)

On dispose de plus des fonctions rising_edge() et falling_edge(), utilisées pour synchroniser un process sur une horloge :

   WIKI: process(CLK_IN) is
   begin
      if rising_edge(CLK_IN) then
         -- Les instructions suivantes seront exécutées à chaque front montant du signal CLK_IN
      end if;
   end process WIKI;

Qui remplacent avantageusement le test classique, dont la couverture en simulation est incomplète (la transition 'X' -> '1' étant interprétée au même titre que la transition '0' -> '1') :

  if ((CLK_IN'event) and (CLK_IN = '1')) then

[modifier] Ecrire son propre package (schémas et netlist)

Lors du TD2 de combinatoire (assemblage de fonctions) nous avons passé sous silence le fait que pour faire la description structurelle présentée il fallait utiliser notre propre package définissant ce qu'est un un et, un ou et un inverseur. Nous écrivons ci-dessous la version complète du programme.

Td2fig3.png
-- fichier : top.vhd
LIBRARY portes; --portes.vif en WARP. Utiliser
--library manager pour dire où est ce fichier
USE portes.mesportes.ALL;
 
ENTITY Fct IS
PORT(e0,e1,e2 : IN BIT;
	s : OUT BIT);
END Fct;
 
ARCHITECTURE truc OF Fct IS
SIGNAL e0e1,e2bar : BIT;
BEGIN
  i1:et PORT MAP(e0,e1,e0e1);
  i2:inverseur PORT MAP(e2,e2bar);
  i3:ou PORT MAP(e0e1,e2bar,s);
END truc;

Voici en condensé comment on réalise un package :

-- fichier : composants.vhd
PACKAGE mesportes IS
  COMPONENT et 
    PORT(e0,e1 : IN BIT;
	s : OUT BIT);
  END COMPONENT;
  COMPONENT ou
    PORT(e0,e1 : IN BIT;
	s : OUT BIT);
  END COMPONENT;
  COMPONENT inverseur 
    PORT(e : IN BIT;
	s : OUT BIT);
  END COMPONENT;
END mesportes;
ENTITY et IS
  PORT(e0,e1 : IN BIT;
	s : OUT BIT);
END et;
ARCHITECTURE aet OF et IS
BEGIN
  s<=e0 AND e1;
END aet;
ENTITY ou IS
  PORT(e0,e1 : IN BIT;
	s : OUT BIT);
END ou;
ARCHITECTURE aou OF ou IS
BEGIN
  s<=e0 OR e1;
END aou;
ENTITY inverseur IS
  PORT(e : IN BIT;
	s : OUT BIT);
END inverseur;
ARCHITECTURE ainv OF inverseur IS
BEGIN
  s<= NOT e;
END ainv;

Il n'y a aucun standard sur les contenus des packages du type ci-dessus. Chaque constructeur propose son propre package pour programmer ses composants ce qui pose des problèmes de portabilité. A noter quand même une initiative avec LPM (Library of Parameterized Modules).

[modifier] Retour sur les styles de programmation VHDL

[modifier] Table de vérité

Nous présentons la technique des BIT_VECTOR ainsi que l'ensemble des styles de programmation. Imaginons que l'on ait la table de vérité (4 entrées 2 sorties) et l'entité correspondante :

Table de vérité
Entrées Sorties
a3 a2 a1 a0 s1 s0
0 1 0 1 1 1
0 1 1 0 0 1
1 1 0 1 1 0

(ce qui n'est pas mentionné dans cette table correspond à 00 en sortie)

et donc l'entité :

ENTITY demo IS PORT(
  a : in BIT_VECTOR(3 DOWNTO 0);-- 4 entrées
  s : out BIT_VECTOR(1 DOWNTO 0));
  -- 2 sorties
END demo;

Le programme VHDL en style "with select when" s'écrit :

	ARCHITECTURE mydemo OF demo IS
	BEGIN
	 WITH a SELECT --style with select when
	 s <= "11" WHEN "0101", -- premiere ligne
	 "01" WHEN "0110", -- deuxieme ligne
	 "10" WHEN "1101", -- troisieme ligne
	 "00" WHEN OTHERS;
	END mydemo;

On écrirait le même programme en style "when else" :

	ARCHITECTURE mydemo OF demo IS
	BEGIN
	 -- style when else
	 s <= "11" WHEN a="0101" ELSE -- premiere ligne
	 "01" WHEN a="0110" ELSE -- deuxieme ligne
	 "10" WHEN a="1101" ELSE -- troisieme ligne
	 "00";
	END mydemo;

Remarque : la structure "when else" ne nécessite pas des conditions mutuellement exclusives. Elle engendre alors une architecture avec priorité. Par exemple dans

j<= w when a='1' else 
    x when b='1' else 
    0;

les conditions ne sont pas mutuellement exclusives. On ne pourrait pas utiliser une structure "with select when" qui nécessite des conditions absolument exclusives.

Le style case when peut être aussi utilisé (en combinatoire comme en séquentiel, il nécessite un process) :

	ARCHITECTURE mydemo OF demo IS
	BEGIN
	 PROCESS(a) BEGIN
	 CASE a is --style case when
	 WHEN "0101" => s <="11"; -- premiere ligne
	 WHEN "0110" => s <="01"; -- deuxieme ligne
	 WHEN "1101" => s <="10"; -- troisieme ligne
	 WHEN OTHERS => s <="00";
	 END CASE;
	 END PROCESS; 
	END mydemo;

Un autre style nécessite un process : if then else :

	ARCHITECTURE mydemo OF demo IS
	BEGIN
	 PROCESS(a) BEGIN
	 IF a="0101" THEN s <="11"; -- premiere ligne
	 ELSIF a="0110" THEN s <="01"; -- deuxieme ligne
	 ELSIF a= "1101" THEN s <="10"; -- troisieme ligne
	 ELSE s <="00";
	 END IF;
	 END PROCESS; 
	END mydemo;

Exercice 1

Ecrire un programme VHDL pour un additionneur 1 bit avec un style "with select when".

[modifier] Le séquentiel

[modifier] Le séquentiel simple (diagramme d'évolution) avec équations de récurrence

Ce problème a déjà été traité ici.

[modifier] Le séquentiel simple (diagramme d'évolution) sans équations de récurrence

Implanter un diagramme d'évolution en VHDL peut se faire de manière systématique :

VHDL fig1.png
ENTITY demo IS PORT(
  clock : IN BIT;
  q : INOUT BIT_VECTOR(1 DOWNTO 0));
END demo;
 
ARCHITECTURE mydemo OF demo IS
BEGIN
   PROCESS(clock) BEGIN
     IF clock'EVENT AND clock='1' THEN
      CASE q IS  --style case when
	WHEN "00" => q <="01"; 
	WHEN "01" => q <="10"; 
	WHEN "10" => q <="11"; 
	WHEN OTHERS => q <="00" ;
      END CASE;
     END IF;
   END PROCESS; 
END mydemo;


Exercice 2

Réaliser un compteur GRAY sur 3 bits en utilisant ces deux méthodes. Un compteur GRAY génère un code GRAY sur front d'horloge : la suite des états du diagramme d'évolution suit un code Gray.

Retour à conception et VHDL