Exercices de VHDL

Exercices de VHDL

Chronomètre

L’objectif de cet exercice est de décrire un chronomètre simple.
Son architecture repose autour de deux compteurs, l’un pour les millisecondes, l’autre pour les secondes.
Par conséquent, TIMER_MS s’incrémente à chaque milliseconde, TIMER_S s’incrémente à chaque seconde.
Le signal eoc est égal à 1 en fin de comptage de TIMER_MS. Ce signal permet d’autoriser le comptage de TIMER_S.
REGISTRE_MS et REGISTRE_S permettent de sauvegarder l’état de comptage des 2 compteurs.
Le fonctionnement de l’ensemble est contôlé par le séquenceur ME_CHRONO.
L’utilisateur dispose des commandes :

  • Start : mise en route du comptage.
  • Pause : suspension du comptage ( sans remise à zéro )
  • Rec : Enregistrement de l’état de comptage dans REGISTRE_MS et REGISTRE_S
  • Raz : Remise à zéro des deux compteurs.

La taille des compteurs et des registres est à définir de telle sorte que TIMER_MS puisse s’incrémenter jusqu’à 999, et TIMER_S jusqu’à 59.

chronometre.svg

Fonctionnement en mode RUNNING / SUSPEND / RAZ

Le chronomètre doit respecter le fonctionnement suivant :

  • L’appui sur reset permet de se placer dans un état RESET afin d’initialiser tous les composants.
  • L’appui sur start permet de passer dans un état RUNNING dans lequel on autorise l’incrémentation des compteurs. ( REMARQUE : on reste dans l’état RUNNING même si start repasse à 0).
  • L’appui sur pause permet de passer dans un état SUSPEND dans lequel on interdit l’incrémentation des compteurs ( sans remise à 0). ( REMARQUE : on reste dans l’état SUSPEND même si pause repasse à 0).
  • L’appui sur raz permet de passer dans un état RAZ dans lequel on stoppe le comptage et on force la valeur des compteurs à 0. ( REMARQUE : on reste dans l’état RAZ même si raz repasse à 0).

Q1. Proposer le diagramme d’états correspondant à ce fonctionnement

Q2. Coder la machine d’état correspondante, ainsi que tous les composants constituant le chronomètre en respectant les noms des signaux proposés.

Enregistrement de la valeur de comptage

Quand on est dans l’état RUNNING ( et uniquement dans cet état ), l’appui sur rec doit actionner le chargement des registres REGISTRE_MS et REGISTRE_S.
Attention, on ne doit enregistrer qu’une seule donnée ( au moment du passage à 1 de rec ; l’enregistrement d’une nouvelle donnée n’est possible que si rec est repassé à 0.

Q3. Proposer une modification de la machine d’états précédente permettant d’ajouter la fonctionnalité d’enregistrement de la valeur de comptage.

Modification de l’architecture

Q4. Modifier l’architecture précédente afin de pouvoir compter et enregistrer les minutes.

ELEMENTS DE CORRECTION

chronometre.vhd


Emetteur Liaison Série

L’objectif de cet exercice est de décrire un émetteur simplifié pour liaison série.

liaison_serie.svg

Le registre serialisateur reg_ser_dat contient la donnée à envoyer ( sur 8 bits ).
Ce registre est chargé lorsque le signal data_load vaut 1.
Initialement line_out vaut ‘1’ ( état de repos de la liaison, correspondant à la voie A du multiplexeur ).
Lorsque l’ordre d’envoyer la donnée est reçu ( signal serialize = ‘1’), les 4 bits du fanion doivent être envoyés, puis les 8 bits de donnée.

chronogramme.svg

Q1. Proposer le diagramme d’états correspondant à ce fonctionnement

Q2. Coder la machine d’états correspondante, ainsi que tous les composants constituant l’emetteur en respectant les noms des signaux proposés.

Q3. Modifier l’architecture précédente afin de pouvoir ajouter un bit de parité ( ce bit valant ‘1’ si DATA comporte un nombre pair de ‘1’, ‘0’ sinon )

On modifie la liaison afin de pouvoir envoyer 3 données de 8 bits après le fanion.
Ces valeurs doivent être stockées dans 3 registres tampon, Le chargement de ces registres sera effectué par 3 signaux data_load1, data_load2, data_load3,
Lors de l’envoi des données, chaque registre tampon doit être transféré successivement dans le registre sérialisateur, et le bit de parité, portant sur les 3 données, doit être placé à la fin de la trame.

Q4. Proposer un schéma pour le nouveau système

Q5. Proposer le diagramme d’états correspondant à ce fonctionnement, puis coder le nouveau système

ELEMENTS DE CORRECTION

liaison_serie.vhd


Chaîne de mesure pour télémètre à Ultrasons

Les télémètres à ultrasons utilisent la mesure du temps de vol aller-retour d’une impulsion ultrasonore.
L’émetteur E émet périodiquement une courte impulsion ultrasonore (de l’ordre de 40 kHz), qui se propagera dans l’air à une vitesse de l’ordre de 300 m/s, sera réfléchie par la cible et détectée par le récepteur R.

tel1.png

L’impulsion ultrasonore émise est constituée de 10 périodes d’une sinusoïde à 40 kHz.
Le récepteur remet en forme le signal reçu, pour fournir un signal rectangulaire logique de même durée que l’impulsion.
Néanmoins un couplage direct entre l’émetteur et le récepteur fait apparaître un “signal reçu” parasite peu après le début de l’émission de l’impulsion.

tel2.png

La chaîne de mesure associée aux transducteurs ultrasonores doit :

  • Fournir 10 périodes d’un signal carré à 40 kHz (le transducteur étant un filtre très sélectif, seulement la composante sinusoïdale sera émise)
  • Déclencher un compteur pour la mesure temporelle entre le début de l’émission des 10 périodes et le second front montant du signal reçu.
  • Fournir à un microcontrôleur le résultat de la mesure sur un bus de données 16 bits.

Le télémètre étudié ici (télémètre de poche pour le métrage de pièces de bâtiments) doit pouvoir mesurer des distances sur une plage de 0,5 à 15 m, avec une précision meilleure que le demi centimètre.

Dans tout le problème, on considère que la vitesse de propagation de l’onde ultrasonore est de 300 m/s.

Quelques prédéterminations

L’élaboration d’un signal à la fréquence de 40 kHz est nécessaire pour générer l’onde ultrasonore.

Q1. Montrer que cette fréquence convient pour la mesure, par comptage temporel, du temps de vol, en terme de précision de mesure ( calculer pour cela la variation de temps de vol correspondant à une variation de 0.5 cm de distance, et comparer cette variation avec un comptage à 40kHz )

Q2. Donner la plage de variation du temps de vol en ms ( temps nécessaire pour mesurer les distances minimales et maximales).

Q3. En déduire la capacité minimale que doit avoir le compteur temporel fonctionnant à une fréquence de 40kHz (dans la suite on prendra 16 bits, qui correspond au format du bus de données)

Description du Système

La figure suivante donne l’organisation générale de la chaîne de mesure.

telemetre.svg

Le signal reset ( actif à l’état 1 ) nous place dans un état initial où tous les compteurs sont remis à zéro.
Le signal ordre_mes à 1 nous fait changer d’état afin de générer 10 périodes d’horloge sur sig_tr ( sig_tr reçoit alors clk ).
Le comptage du nombre de périodes est réalisé par compteur_emet ; en parallèle le comptage avec compteur_temps_vol est activé.
Le passage à 1 de sig_rec nous indique que le signal parasite a été reçu (ce passage à 1 peut intervenir lors de l’émission des 10 périodes de clk )  ; il faudra attendre que ce signal repasse à zéro puis à nouveau à 1 pour stopper le comptage de compteur_temps_vol.
On peut alors indiquer qu’une mesure est disponible ( data_available = 1 ), en autorisant en parallèle l’écriture de la donnée sur val_compt.

Q1. Proposer un diagramme d’états du séquenceur permettant de respecter le fonctionnement de l’émetteur-récepteur.

Q2. Réaliser la descrption VHDL du compteur, du séquenceur et de l’émetteur. Réaliser l’instanciation et démontrer le bon fonctionnement de l’ensemble à l’aide d’une simulation pertinente.

Modification de l’architecture

Q3. Proposer une modification de l’architecture pour fournir directement le calcul de la distance au format virgule fixe approprié.

ELEMENTS DE CORRECTION

telemetre.txt

telemetre.vhd


Pile FIFO et Transmission Liaison Série

L’objectif est d’ajouter une pile FIFO ( First In First Out ) au périphérique liaison série étudié en labo.
Cette pile peut contenir 4 données.

uart_ens.svg

Codage de la Pile FIFO

fifo.svg

Fonctionnement de la Pile

REMARQUE : La pile est un composant synchrone, les actions ci-dessous sont réalisées lors d’un front montant de clk.

Initialisation : La forçage à ‘1’ du signal init_FIFO entraîne l’initialisation à 0 du signal adr.

init_fifo.svg

Ecriture : Le forçage à ‘1’ du signal wr_FIFO entraîne l’enregistrement de la donnée présente sur d_in dans la case fifo(adr), puis le signal adr est incrémenté de 1.

wr_fifo.svg

Lecture : la donnee fifo(0) est toujours présente sur d_out. Le forçage à ‘1’ du signal rd_FIFO entraine le décalage des échantillons dans la pile en écrasant le plus vieux, et la décrémentation du signal adr.

rd_fifo.svg

Ecriture et Lecture simultanée: le forçage à ‘1’ de wr_FIFO et rd_FIFO entraîne le décalage des échantillons de la pile et l’enregistrement de la donnée présente sur d_in dans la case fifo(adr-1). La valeur de adr n’est pas modifiée

rd_wr_fifo.svg

REMARQUE :

  • Quand adr vaut 0, le signal FIFO_empty vaut ‘1’, ‘0’ sinon.
  • Quand adr vaut 4, FIFO_full vaut ‘1’, ‘0’ sinon.

Codage et Test de la Pile

Q1. Proposer une description VHDL de la pile FIFO, et valider son bon fonctionnement avec une simulation pertiente ( Faire valider cette simulation par l’enseignant ).

REMARQUES :

  • En VHDL, l’index d’un tableau doit être un Integer, noté 0,1,2…

  • Le décalage des échantillons nécessite l’utilisation d’une boucle for :

    for i in ... to ... loop  
    ...  
    end loop;  
    

Intégration de la pile FIFO dans le périphérique Liaison Série

Après un état d’initialisation de l’ensemble des composants synchrones, le signal ld_FIFO à ‘1’ amène dans un état où les données présentes sur le bus DATA sont enregistrées à chaque coup d’horloge dans la pile.

Lorsque la pile est pleine, le registre d’état doit être forcé à 1, indiquant au processeur qu’il ne faut rien écrire d’autre dans la pile.

Si le signal start vaut ‘1’, il faut :

  • Charger le registre sérialisateur avec la donnée présente en sortie de la pile et le bit de parité
  • Sérialiser toutes les données de la pile jusqu’à ce que la pile soit vide.

REMARQUE : Dès lors que la pile n’est plus pleine, le registre d’état doit être forcé à 0.

Q2. Proposer un diagramme d’états permettant de décrire le fonctionnement du composant sequenceur_serial.

Q3. Proposer une description VHDL du séquenceur, puis compléter l’instanciation des composants afin d’intégrer la pile FIFO dans le système. Réaliser une simulation pertiente pour faire valider le bon fonctionnement de l’ensemble.

Q4. Proposer une modification du diagramme d’états précédent afin de gérer la mise à jour du registre d’état au cours de la sérialisation, et valider par une simulation ce nouveau fonctionnement.

ELEMENTS DE CORRECTION

uart_fifo.vhd


Thermostat

L’objectif de cet exercice est de décrire en langage VHDL un composant permettant de contrôler la température d’une pièce.

1. Division de la fréquence

L’horloge principale m_clk a une fréquence de 1 kHz.
Afin de disposer d’une horloge plus lente ( période 1s), on considère le composant div_freq :

div_freq.svg

diag_temp2.svg

Q1. Proposer une description afin de générer le signal horloge clk_1s correspondant au diagramme temporel.

REMARQUE : sous modelsim, l’unité temporelle de base est la picoseconde.

2. Contrôle du Thermostat

ctrl_therm.svg

Un capteur de température fournit la température ambiante mes_tp sur 8 bits en format signé complément à deux ( l’intervalle de variation est de -50 à 50°C ).
L’objectif est de contrôler la température ambiante et de la maintenir à une consigne donnée cons_tp.
Le contrôle se fait par un seul bit (tout ou rien) qui sera appliqué à un circuit de chauffage.

L’algorithme à suivre est le suivant :

  • A partir d’un état initial ( après reset ), la mise à 1 du signal run fait basculer dans un état acquisition , dans lequel on mesure la température et on la compare avec la consigne.
  • Dans le cas où une différence positive est constatée (consigne plus chaude que la pièce), on envoie ‘1’ en sortie chauffe pendant une durée correspondant à 5 fois le montant de la différence de température en minutes.

( Par exemple si Tcons=26° et Tambiante=19°, on envoie ‘1’ en sortie chauffe pendant (26-19)*5=35 minutes )

  • A la fin de cette durée, on se met dans l’état attente pendant 20 minutes où la sortie chauffe reste à ‘0’ et ensuite on repart à l’état acquisition où une nouvelle lecture de température sera faite.

    Le passage à 0 du signal run renvoit à l’état initial, quel que soit l’état dans lequel on se trouve.

Q2. Combien de bits faut-il pour le signal count afin de pouvoir coder la plus grande durée possible ?
Q3. Proposer un Diagramme d’Etats permettant de réaliser cet algorithme
Q4. Proposer une description VHDL de la machine d’états correspondante, et du compteur associé, et valider le bon fonctionnement de l’ensemble avec une simulation pertiente

REMARQUES :

Le résultat d’une multiplication a un format 2 fois plus grand que les opérandes.
Exemple :
signal A : signed(3 downto 0) ;
signal B : signed(3 downto 0) ;
signal S : signed(7 downto 0) ;

S <= AB ;
La multiplication entre un entier et un tableau signed/unsigned est définie dans le package numeric_std :
S <= 45
B ;

L’extension de format est réalisée avec le symbole & ( concaténation ) :
S <= “0000”&A ;

Pour copier une partie d’un vecteur dans un autre :
A <= S (3 downto 0) ;

3. Gestion du bouton d’allumage du thermostat

L’interface utilisateur pour l’activation ou la désactivation du signal run est constituée d’un seul bouton.
Un appui bref ( inférieur à 2 secondes ) sur le bouton doit activer le signal run.
Un appui long ( supérieur ou égal à 2 secondes ) doit désactiver le signal run.

gestion_bouton.svg

Q5.Proposer un diagramme d’états permettant de respecter ce fonctionnement
Q6. Proposer une description VHDL de la machine d’états correspondante, et du compteur associé, et valider le bon fonctionnement de l’ensemble avec une simulation pertiente

4. Fonctionnement Global

ensemble.svg

Q7. Instancier les éléments précédents afin de mettre en œuvre le système complet ; la simulation doit tenir compte des contraintes temporelles.

ELEMENTS DE CORRECTION

thermostat.vhd


Recepteur Liaison UART

L’objectif de cet exercice est de décrire en langage VHDL un composant permettant de recevoir des données de liaison série RS232.

Pour simplifier, on considèrera que le débit de la trame est fixe, et que le format des données reçues est toujours le même ( un bit de start, 8 bits de données, 1 bit de parité, 1 bit de stop ) :

trame_uart_1.svg

le bit de parité vaut 0 quand l’information utile contient un nombre pair de 1, 1 sinon.

Registre Sérialisateur et machine à états

Nous considérons dans un premier temps un périphérique UART SERIAL_RCV avec les entrées sorties suivantes :

uart_es.svg

  • reset : remise à zéro asynchrone
  • clk : horloge du périphérique
  • linerx : Receive uart, la trame ci-dessus défile sur cette entrée
  • tampon_out : ce signal 8 bit contient l’information utile de la trame quand toute la trame uart a été reçue
  • set_data_av : se met à 1 pendant une période d’horloge quand toute la trame uart a été reçue ( donc au moment de la mise à jour de tampon_out )

L’architecture de SERIAL_RCV est la suivante :

uart_ens_1.svg

reg_ser : registre sérialisateur : son rôle est d’enregistrer chacun des bits présents sur linerx. A chaque nouveau bit reçu ( dans la case N°8) , l’ensemble du registre est décalé vers la droite ( il est conseillé d’utiliser la fonction shift_right() de la bibliothèque numeric_std ). A l’issue d’une trame receptionnée, le reg_ser contient l’ information utile et le bit de parité ( alors présent dans la case N°8, Most significant bit du registre ).

Etant donné que la transition entre les états 0 et 1 n’est pas immédiate ( slew rate ), l’horloge de la machine à états me contrôlant le registre à décalage doit être plus rapide. On considèrera une période de récupération de chaque bit 16 fois plus lente que l’horloge de notre périphérique ; l’action sur le signal shift du registre sérialisateur se fait alors de la manière suivante :

trame_uart_2.svg

Fonctionnement de la machine à états me :

A partir d’un état initial : si le signal line_rx passe à 0, on a un bit de start. On attend donc 24 périodes d’horloge clk pour forcer le signal shift à 1 ( pendant une seule période de clk ) On attendra à nouveau 16 périodes d’horloge pour forcer à nouveau shift à 1 et on réitère cela 7 fois de telle sorte qu’on récupère les 8 bits de donnée utiles et le bit de parité dans le registre sérialisateur. On arrive ensuite dans un état ( de durée une période d’horloge ) où on charge le registre tampon et on actionne set_data_av, puis on retourne dans l’état initial.

Q1. Proposer une description VHDL de reg_ser.

Q2. Proposer un Diagramme d’Etats permettant de respecter le fonctionnement de la machine à états me

Q3. Proposer une description VHDL de SERIAL_RCV.

Gestion des registres tampon et status, interface utilisateur

Nous considérons désormais les entrées sorties et l’architecture suivante :

uart_es_2.svg

uart_ens_2.svg

Dans un contexte de système à processeurs, l’utilisation de notre périphérique est réalisé via l’écriture ou la lecture de registres.

Registre Status

A l’issue d’une réception, le registre status doit indiquer qu’un octet a été reçu ( bit data available d_av ) ; la mise à 1 de ce bit est réalisé par la machine d’états, en même temps que le chargement du registre tampon.
Au même instant, la machine d’états doit autoriser le chargement du bit erreur de parité ( err_p ), résultant de la comparaison entre le bit de parité reçu, et le bit de parité recalculé par le composant det_parite

L’écriture du registre status sur le bus Data a lieu quand oe_status = ‘1’, soit quand le bit Address = 0. L’écriture du registre Tampon sur le bus Data a lieu quand oe_tampon = ‘1’, soit quand le bit Address = 1.

Dès lors que le processeur a lu le registre tampon, les bits err_p et d_av sont réinitialisés à 0

Q4. Modifier la description précédente afin d’ajouter ces éléments au composant final.

ELEMENTS DE CORRECTION

serial_recv.vhd