Exercices d’électronique numérique. VHDL.

Ce laboratoire propose une série d'exercices en VHDL pour comprendre la conception de circuits numériques, depuis les processus combinatoires jusqu'aux machines à états séquentielles. Il permet d’apprendre à écrire, analyser et synthétiser des descriptions VHDL, en manipulant signaux, variables, processus et machines d’états.

D'après le document Exercices d’électronique numérique. VHDL.

Cet article a été rédigé automatiquement à partir du document source, puis vérifié avant publication.

Document source

Exercices d’électronique numérique. VHDL.

Programming, Engineering, Electronics · PDF · 9 pages

Afficher l'aperçu du document

Consulter le document original →

Ce laboratoire propose une série d'exercices en VHDL pour comprendre la conception de circuits numériques, depuis les processus combinatoires jusqu'aux machines à états séquentielles. Il permet d’apprendre à écrire, analyser et synthétiser des descriptions VHDL, en manipulant signaux, variables, processus et machines d’états. Pour réaliser ces exercices, un environnement de développement VHDL et un simulateur sont nécessaires.

Objectifs

  • Comprendre la différence entre circuits combinatoires et séquentiels en VHDL.
  • Écrire des processus VHDL avec listes de sensibilités et instructions wait.
  • Analyser et dessiner des schémas à partir de descriptions VHDL.
  • Utiliser correctement variables et signaux dans les processus.
  • Concevoir et coder une machine à états synchrones pour un codeur numérique.
  • Comparer différentes solutions VHDL pour un même problème.

Prérequis et installation

  • Connaissances de base en logique numérique (portes, bascules, machines à états).
  • Notions fondamentales de VHDL : entités, architectures, processus, signaux, variables.
  • Environnement de développement VHDL avec simulateur (ex : ModelSim, GHDL).
  • Matériel non nécessaire, travail purement logiciel.

Du code VHDL au circuit

Ce premier exercice illustre la différence entre processus combinatoires et séquentiels en VHDL à travers trois processus : et, latch et edge.

Le code initial est :

entity comb_seq is
port (
  e1, e2 : in bit ;
  s_et, s_latch, s_edge : out bit
);
end comb_seq;

architecture ww of comb_seq is
begin

et : process
begin
  wait on e1, e2 ;
  if( e1 = '1' ) then
    s_et <= e2 ;
  else
    s_et <= '0' ;
  end if ;
end process ;

latch : process
begin
  wait on e1, e2 until e1 = '1' ;
  s_latch <= e2 ;
end process ;

edge : process
begin
  wait on e1 until e1 = '1' ;
  s_edge <= e2 ;
end process ;

end ww ;

On vous demande :

  • De montrer que les noms des processus correspondent aux opérateurs décrits.
  • De proposer une écriture équivalente utilisant des listes de sensibilités sans instruction wait.
  • De discuter des libertés prises par certains compilateurs de synthèse.

Correction proposée :

architecture ww of comb_seq is
begin

et : process (e1,e2)
begin
  if( e1 = '1' ) then
    s_et <= e2 ;
  else
    s_et <= '0' ;
  end if ;
end process ;

latch : process (e1,e2)
begin
  if( e1 = '1' ) then
    s_latch <= e2 ;
  end if ;
end process ;

edge : process (e1)
begin
  if( e1 = '1' ) then
    s_edge <= e2 ;
  end if ;
end process ;

end ww ;

Explications :

  • Processus et : combinatoire, la sortie s_et dépend directement des entrées e1 et e2.
  • Processus latch : mode transparent, la sortie s_latch suit e2 quand e1 = '1', sinon elle mémorise la valeur précédente.
  • Processus edge : bascule sensible au front montant de e1, s_edge change uniquement lors d’un front montant.

Analyse d’un programme VHDL séquentiel

Considérons le programme suivant :

entity transitm is
  port ( hor, e : in bit ;
         s : out bit );
end transitm ;

architecture quasi_struct of transitm is
  signal qa, qb : bit ;
begin
  s <= qa xor qb ;
  schem : process
  begin
    wait until hor = '1' ;
    qa <= e ;
    qb <= qa ;
  end process schem ;
end quasi_struct ;

Travail demandé :

  • Déduire un schéma composé de bascules et portes logiques à partir de ce code.
  • Compléter un chronogramme (non fourni ici).

Explication :

  • Le processus est sensible à hor et met à jour qa et qb séquentiellement.
  • Le signal s est la sortie XOR de qa et qb.
  • Le schéma comprend deux bascules en série (pour qa et qb) et une porte XOR.

Fonctionnement d’une bascule VHDL

Le programme suivant décrit une bascule :

entity basc is
port ( T, hor, raz : in bit;
       s : out bit);
end basc;

architecture primitive of basc is
signal etat : bit;
begin
  s <= etat ;
  process
  begin
    wait until (hor = '1') ;
    if(raz = '1') then
      etat <= '0';
    elsif(T = '1') then
      etat <= not etat;
    end if;
  end process;
end primitive;

Questions :

  • Comment reconnaître qu’il s’agit d’un circuit séquentiel synchrone ?
  • La commande raz est-elle synchrone ou asynchrone ?
  • Établir le diagramme de transition de la bascule.
  • Déduire les équations logiques et le schéma d’une réalisation avec une bascule D.

Réponses :

  • Le processus attend un front montant sur hor, ce qui indique un circuit synchrone.
  • La commande raz est synchrone car elle est testée dans le processus au moment du front.
  • Diagramme de transition : état etat bascule si T=1, remise à zéro si raz=1.
  • Équation logique : s(t+1) = (raz' · (etat XOR T)) + raz·0 = (not raz)·(etat XOR T).

Variables et signaux en VHDL

Exemple d’opérateur OU exclusif généralisé :

ENTITY ouex IS
generic(taille : integer := 8) ;
PORT ( a : IN BIT_VECTOR(0 TO taille - 1) ;
       s : OUT BIT );
END ouex;

ARCHITECTURE parite of ouex is
BEGIN
process(a)
variable parite : bit ;
begin
  parite := '0' ;
  FOR i in a'range LOOP
    if a(i) = '1' then
      parite := not parite;
    end if;
  END LOOP;
  s <= parite;
end process;
END parite;

Une version incorrecte :

ARCHITECTURE FAUSSE of ouex is
signal parite : bit ; -- MAUVAIS CHOIX
BEGIN
process(a)
begin
  parite <= '0' ;
  FOR i in a'range LOOP
    if a(i) = '1' then
      parite <= not parite;
    end if;
  END LOOP;
  s <= parite;
end process;
END FAUSSE;

Analyse :

  • La première architecture utilise une variable locale parite dont la valeur change immédiatement dans la boucle, ce qui correspond à un calcul séquentiel classique.
  • La deuxième architecture est fausse car les affectations aux signaux ne prennent effet qu’à la fin du processus, donc la boucle ne modifie pas réellement parite en cours d’exécution, ce qui crée un comportement erratique (oscillations).
  • Conclusion : les variables ont un effet immédiat dans un processus, les signaux ne changent qu’à la fin du processus.

Lisibilité du code : diviseur de fréquence par 10

Trois versions sont proposées :

architecture piege of div_10 is
begin
diviseur : process
variable compte : integer range 0 to 5 := 0 ;
begin
  wait until hor = '1' ;
  compte := compte + 1 ;
  if compte = 5 then
    compte := 0 ;
    sort <= not sort ;
  end if ;
end process diviseur ;
end piege ;
architecture perverse of div_10 is
signal compte : integer range 0 to 4 := 0 ;
begin
diviseur : process
begin
  wait until hor = '1' ;
  compte <= compte + 1 ;
  if compte = 4 then
    compte <= 0 ;
    sort <= not sort ;
  end if ;
end process diviseur ;
end perverse ;
architecture correcte of div_10 is
signal compte : integer range 0 to 4 := 0 ;
begin
diviseur : process
begin
  wait until hor = '1' ;
  if compte = 4 then
    compte <= 0 ;
    sort <= not sort ;
  else
    compte <= compte + 1 ;
  end if ;
end process diviseur ;
end correcte ;

Discussion :

  • Les trois versions réalisent un diviseur de fréquence par 10.
  • La première version utilise une variable locale, ce qui peut ne pas être synthétisable partout.
  • La deuxième version provoque un débordement car compte peut dépasser 4 avant d’être remis à zéro, ce qui est dangereux en simulation et synthèse.
  • La troisième version est correcte et sûre, elle évite le débordement en testant la valeur avant l’incrémentation.

Exercice de synthèse : codeur à 3 niveaux

Dans les transmissions numériques, un code binaire est converti en un code à 3 niveaux de tension :

  • Un zéro logique correspond à une tension nulle.
  • Un un logique est codé par une impulsion positive ou négative alternée à chaque occurrence.

Le codeur reçoit une horloge hor et des données din. Il produit deux sorties binaires plus et moins selon :

  • Si din = '0' alors plus = '0' et moins = '0'.
  • Si din = '1' alors plus = '1' et moins = '0' ou plus = '0' et moins = '1', en alternance.

Une machine synchrone à quatre états est proposée (états : mzero, pzero, moins, plus).

Travail :

  • Compléter le diagramme de transitions en précisant les conditions.
  • Déterminer le nombre minimum de bascules nécessaires.
  • Proposer un codage des états et un programme VHDL complet.
  • Proposer une solution où les sorties sont issues directement des bascules du registre d’état.
  • Comparer avantages et inconvénients des deux solutions.

Solutions proposées :

Le nombre minimum de bascules est 2 (4 états).

Première solution :

entity amicod is
  port(hor, din : in bit ;
       plusout, moinsout : out bit );
end amicod ;

architecture sort_decode of amicod is
type ami is (mzero,pzero,moins,plus) ;
signal etat : ami ;
begin
plusout  <= '1' when etat = plus  else '0' ;
moinsout <= '1' when etat = moins else '0' ;
encode : process
begin
  wait until hor = '1' ;
  case etat is
    when mzero =>
      if din = '1' then etat <= plus ; end if ;
    when pzero =>
      if din = '1' then etat <= moins ; end if ;
    when moins =>
      if din = '1' then etat <= plus ;
      else etat <= mzero ; end if ;
    when plus =>
      if din = '1' then etat <= moins ;
      else etat <= pzero ; end if ;
    when others =>
      etat <= mzero ;
  end case ;
end process encode ;
end sort_decode ;

Deuxième solution avec sorties directes des bascules :

architecture sort_direct of amicod is
subtype ami is bit_vector(2 downto 0) ;
constant mzero : ami := "000" ;
constant pzero : ami := "001" ;
constant moins : ami := "010" ;
constant plus  : ami := "100" ;
signal etat : ami ;
begin
plusout  <= etat(2) ;
moinsout <= etat(1) ;
encode : process
begin
  wait until hor = '1' ;
  case etat is
    when mzero =>
      if din = '1' then etat <= plus ; end if ;
    when pzero =>
      if din = '1' then etat <= moins ; end if ;
    when moins =>
      if din = '1' then etat <= plus ;
      else etat <= mzero ; end if ;
    when plus =>
      if din = '1' then etat <= moins ;
      else etat <= pzero ; end if ;
    when others =>
      etat <= mzero ;
  end case ;
end process encode ;
end sort_direct ;

Avantages et inconvénients :

  • La première solution est plus simple à comprendre et à modifier, mais ajoute une couche de logique combinatoire pour générer les sorties.
  • La deuxième solution est plus rapide car les sorties sont directement issues des bascules, mais le codage des états est plus complexe.

Résultats attendus

  • Compréhension claire des différences entre processus combinatoires et séquentiels.
  • Schémas corrects déduits des programmes VHDL.
  • Fonctionnement correct des bascules synchrones avec commandes synchrones.
  • Utilisation correcte des variables et signaux dans les processus.
  • Diviseur de fréquence fonctionnel sans débordement.
  • Codeur à 3 niveaux fonctionnant selon le diagramme d’états proposé.

Pièges courants

  • Confondre variables et signaux : variables changent immédiatement, signaux changent à la fin du processus.
  • Utiliser des instructions wait dans des processus synthétisables sans précaution.
  • Oublier de gérer les débordements dans les compteurs ou diviseurs.
  • Ne pas synchroniser correctement les commandes de remise à zéro (raz) : synchrone vs asynchrone.
  • Choisir un codage d’états inadapté qui complique la génération des sorties.

Partager

Commentaires

Aucun commentaire pour le moment. Posez la première question.

Les commentaires sont relus avant publication. Votre e-mail n'est jamais affiché.

← Toutes les révisions