Dans ce billet, je propose une démonstration en mettant en œuvre un afficheur multiplexé 7-segments à quatre digits (anode commune) en langage Verilog.
Un chronomètre au 1/10e de seconde
En mode multiplexé, le fonctionnement de l'afficheur à 7-segments est résumé dans l'animation ci-dessous :
Si on veut afficher le nombre « 1234 », il faut afficher successivement les chiffres qui composent le nombre chacun leur tour à une vitesse suffisante pour tromper le cerveau au point qu’il ne distingue plus les clignotements des digits qui s’allument et s’éteignent à tour de rôle (phénomène de persistance rétinienne). On prépare les segments en mettant à l’état bas les cathodes correspondantes, et on met l’anode du digit où l’on veut que le chiffre apparaisse à l’état haut. Un « court » instant plus tard, on éteint le digit puis on passe au digit suivant avec un nouveau chiffre, et ainsi de suite…
Cette technique peut sembler compliquée à mettre en œuvre, mais elle permet d’économiser un bon nombre de broches à piloter : 8 cathodes + 4 anodes au lieu de 8 x 4 = 32 cathodes + 4 anodes sans multiplexage. 24 sorties économisées...
Le schéma équivalent de l'afficheur est le suivant :
Structurellement, le projet est découpé en trois modules (reset_conditioner.v, tenth_second_counter.v, seven_seg_multiplexing.v). Ci-dessous, le schéma d'analyse obtenu dans la suite Xilinx Vivado (analyse RTL) :
En sortie tout à droite :
- io_sel[3:0] : bus de sortie vers les 4 anodes.
- io_seg[7:0] : bus de sortie vers les 8 cathodes (les 7 segments + point décimal).
Le module principal au_top.v ci-dessous (cliquer sur le bouton [Montrer]) est donc responsable de la structure du projet en instanciant les différents modules.
au_top.v (Top Level hierarchy) :
Module reset_conditioner
Le module reset_conditioner est proposé directement par l'EDI Alchitry Labs. L’instance rst_cond permet de « nettoyer » le signal d’entrée, provenant de l’appui sur le bouton Reset en surface de la carte (signal rst_n), et de le synchroniser sur le front montant de l’horloge (signal clk). Ce signal conditionné servira au besoin à réinitialiser simultanément tous les composants souhaités.
Exemple de signal conditionné sur la sortie out (simulation comportementale Xilinx Vivado) :
reset_conditioner.v :
Module tenth_second_counter
Ce module génère en sortie un nombre entier sur 14 bits (pour afficher des nombres entre 0 et 9999), initialement à zéro, et qui va s'incrémenter tous les dixièmes de seconde. L'appui sur le bouton Reset provoque la remise à zéro du compteur, et maintenir l'appui sur le bouton io_button[1] du shield va stopper le chronomètre.
Évolution du chronomètre, simulation Xilinx Vivado :
On voit les premiers instants de la valeur du chronomètre qui s'incrémente 0, 1, 2, 3... tous les 1/10è de seconde (=100 ms).
tenth_second_counter.v :
Module seven_seg_multiplexing
Ce module prend en charge l'affichage du nombre displayed_number qui se présente à l'entrée. Il faut d'abord activer les digits à tour de rôle selon la séquence : 0111, 1011, 1101, 1110, ... (l'anode du digit est activée en pilotant un transistor MOSFET canal-P, c'est-à-dire à l'état bas de la grille).
La simulation ci-dessous montre que chacun des 4 digits est rafraichi toutes les 5,24 ms, soit à une fréquence de 191 Hz suffisante pour que la persistance rétinienne joue son rôle (et un chiffre des 1/10e affiché garanti avec une précision suffisante). Cette fréquence provient de la fréquence de l'horloge de la carte (100 MHz) divisée par un facteur 219 : 100.106 / 219 = 191 Hz.
On passe par l'intermédiaire des deux bits de poids fort digit_activating_counter = counter[18:17] d'un compteur 19 bits incrémenté à chaque front montant de l'horloge 100 MHz pour établir le signal d'activation des digits à tour de rôle (io_sel[3:0]).
Un peu d'arithmétique permet de récupérer individuellement les chiffres des milliers, centaines, dizaines et unités qu'il faudra présenter en activant les segments.
Pour chaque digit activé, on voit ci-dessous en magenta l'état des 8 cathodes des segments et du point décimal (le segment ou le points décimal s'allume lorsque la cathode est à l'état bas). Dans l'ordre (en commençant par le bit de poids fort) : point décimal dp + segments g, f, e, d, c, b et a.
- 11000000, c'est le dessin du chiffre « 0 » que l'on retrouve sur le 1er, 2e et 4e digit de l'afficheur.
- 01000000, c'est aussi le dessin du chiffre « 0 » mais avec le point décimal allumé en plus, et que l'on retrouve sur le 3e digit uniquement. Normal, le chiffre qui suit est le chiffre des dixièmes.
Au démarrage du chronomètre, c'est donc bien « 000.0 » qui s'affiche.
seven_seg_multiplexing.v :
Exercice :
L'image qui suit montre une simulation à un moment où le chronomètre affiche « 147.4 ». En mode multiplexé, il faut donc présenter les bonnes valeurs aux cathodes et dessiner successivement les chiffres « 1 », « 4 », « 7. » et « 4 ».
- On prépare les cathodes pour dessiner le « 1 », et on active le 1er digit.
- On prépare les cathodes pour dessiner le « 4 », et on active le 2e digit.
- On prépare les cathodes pour dessiner le « 7. », (le « 7 » avec le point décimal), et on active le 3e digit.
- On prépare les cathodes pour dessiner le « 4 », et on active le 4e digit.
- Et on reprend au 1er digit... etc.
Vérifiez que les valeurs présentées aux cathodes sont correctes.
Conclusion :
On ne rencontre pas beaucoup de HDL (Hardware Description Language) sur Developpez... le langage Verilog n'est pas tout jeune non plus, sa dernière version stable remontant à 2005. Il y a toutefois des évolutions récentes du langage avec SystemVerilog, dont Verilog est maintenant un sous-ensemble.
En regardant les codes, vous découvrirez différentes manières de décrire un circuit : de façon structurelle (connexion de signaux et de modules) ou comportementale où certains blocs de code sont exécutés de façon procédurale avec une syntaxe assez proche du C.
Les simulations comportementales et les chronogrammes ont été obtenus avec la suite Xilinx Vivado.
Suite au prochain épisode...