Leçon 3 : Additionneur 4 bits

Dans ce TP, vous allez utiliser ISE pour construire des circuits logiques hiérarchiques manipulant des entiers non signés, par assemblage de portes logiques élémentaires. Vous vérifierez par simulation puis par exécution sur la carte que les fonctionnalités des circuits correspondent effectivement à vos spécifications. C’est toujours via l’interface interactive d’Isim, l’outil de simulation proposé avec ISE, que vous programmerez la simulation. L’exécution sur la carte réutilisera les concepts introduits lors des deux précédentes leçons.

Vous trouverez le fichier lecon3.pdf en fin de feuille.

Votre premier calculateur - un additionneur 4 bits

Un circuit combinatoire permet de produire une ou plusieurs valeurs binaires à partir de signaux en entrée. Lorsque l’on donne un sens à ce codage binaire, le circuit électronique produit sans le savoir une information qui peut être bien plus complexe qu’un ‘0’ ou un ‘1’. L’assemblage de plusieurs signaux permet de représenter un ensemble de valeurs dont la cardinalité croit de manière exponentielle en fonction du nombre de signaux. Avec 4 signaux en sorties, vous pouvez représenter 16 éléments d’un ensemble. Un des ensembles les plus intuitifs reste un sous-ensemble des nombres entiers non signés tels que nous les avons déjà utilisés lors du TP1. Sur 4 bits vous avez représenté 0 1 2 3 … E F. Le même assemblage de signaux aurait pu aussi représenter un ensemble de pays de la CE : France, Belgique, …. Pologne. J’insiste sur le fait que c’est vous qui allez donner un sens aux résultats produits par votre circuit, par exemple en lisant les leds de votre carte avec une certaine interprétation de leur signification.

Connaissances requises

Portes logiques, algèbre de Boole

Objectifs

Dans ce TP, vous allez utiliser ISE pour construire des circuits logiques hiérarchiques manipulant des entiers non signés, par assemblage de portes logiques élémentaires. Vous vérifierez par simulation puis par exécution sur la carte que les fonctionnalités des circuits correspondent effectivement à vos spécifications. C’est toujours via l’interface interactive d’Isim, l’outil de simulation proposé avec ISE, que vous programmerez la simulation. L’exécution sur la carte réutilisera les concepts introduits lors des deux précédentes leçons.

Le projet

Vous allez concevoir un système capable de faire la somme de deux nombres entiers codés sur 4 bits. L’addition est bien évidemment réalisée en binaire, mais elle ressemble beaucoup à l’addition décimale que vous posiez sur votre ardoise à l’école primaire. Vous aligniez les deux nombres de votre addition et commenciez par la gauche en ajoutant les deux chiffres des unités. Cette addition produit potentiellement une retenue qu’il faut prendre en compte pour la somme des dizaines etc… En binaire, on doit donc être capable de faire la somme de deux signaux binaires, mais aussi de trois signaux binaires afin de prendre en compte la retenue qui peut être produite par le calcul précèdent. C’est ce que vous allez construire pas à pas. Chaque étape sera simulée et validée sur la carte Nexys.

Un demi-additionneur

Un demi-additionneur (on comprendra le sens du nom par la suite) réalise l’addition de deux bits a et b et produit la somme s et une retenue c. Voici les tables de vérité de s et c.

Vous commencez à avoir l’habitude, vous allez commencer par créer un projet TP3 via File>New Project.

Figure 30 Création du projet

Vous allez ajouter un fichier Schematic à votre projet, Project>New Source, nommé toplevel qui contiendra les versions successives de votre circuit.

Figure 31 Création de toplevel

Le fichier toplevel.sch est alors disponible comme racine de votre design, on y reviendra plus tard. La première étape consiste à créer un symbole demiadd. Comme pour toplevel, ajoutez au projet une nouvelle source Project>New Source de type Schematic. Dans la fenêtre correspondante, vous pouvez saisir le circuit demi-additionneur avec les portes logiques nécessaires, les fils et les I/O Marker : a, b en entrée et s, c en sortie. Une fois sauvegardé, il vous reste à créer votre propre symbole directement dans Design Utilities.

Figure 32 Circuit demiadd

Toujours commencer par la simulation!

Même pour un circuit aussi simple, la simulation composant par composant reste une bonne habitude de design. Je vous propose donc de lancer le simulateur Isim sur demiadd et de vérifier que les 4 combinaisons sur a et b donnent bien les résultats attendus sur s et c.

Figure 33 Lancement simulation demiadd

Figure 34 Résultat simulation demiadd

Une fois la simulation correcte, revenez en mode Implementation et créez le symbole associé par Create Schematic Symbol.

Vérification sur la carte

Vous pourriez directement instancier demiadd sur la carte. Je vous propose plutôt de passer par une instanciation de demiadd dans toplevel où seront spécifiés les ports d’entrée/sortie relatifs à la carte Nexys. Commençez par les ports. Créez deux bus verticaux nommés switches(7:0) et led(7:0). Placez le symbole du composant demiadd entre les deux bus. Enfin avec votre bouton Add Bus Tap, vous allez pouvoir connecter les fils du bus switches et ceux du bus led sur les 4 ports de demiadd. Je vous rappelle la procédure : cliquez sur le bouton Add Bus Tap, sélectionnez le bus sur lequel vous voulez vous brancher avec un premier clic sur ce bus. Changez éventuellement le nom du fil sur net name et enfin cliquez sur le port (ou un autre bus) sur lequel vous voulez connecter ce Bus Tap. Il faut être rigoureux dans ces connections, retournez à la leçon 1 si nécessaire. Pour finir il faut créer les deux I/O Marker sur les bus switches et led. Vous obtenez le schéma suivant.

Figure 35 Toplevel pour demiadd

Il vous reste à créer le fichier ucf. Je vous propose de récupérer celui du TP1. Pour cela dans Project>Add Copy of Source, sélectionnez le fichier S3.ucf depuis votre projet TP1. Optez pour le mode implementation, S3.ucf apparait dans la hiérarchie de toplevel, sans oublier votre JTAG à positionner, vous êtes prêt pour la synthèse par Generate Programming File.

!!!! Process "Translate" failed : j’ai oublié de vous faire nettoyer dans S3.ucf, les ports anodes et sevenseg qui ne sont pas définis dans votre design ici. Donc soit vous commentez les lignes en utilisant le bouton de l’éditeur ISE, soit vous positionnez l’option Allow Unmatched LOC Constraints dans les Process Properties de Implement Design (Clic droit ouvre le menu contextuel). Utilisez plutôt la deuxième solution et relancez la compilation.

Figure 36 Positionnement Unmatched Loc Constraints

!!!!Process "Generate Programming File" failed : encore des erreurs ! En cliquant sur l’onglet Errors de la console (en bas), on obtient les messages d’erreurs. Effectivement ISE ne peut produire une valeur pour les leds 2 à 7 qui ne sont associées à aucun signal. Vous allez devoir modifier votre circuit. Je vous propose de mettre ces 6 leds à 0.

Ajoutez entre les deux bus un symbole constant que l’on peut trouver dans la bibliothèque de symboles General. La valeur par défaut est xFFFFFFFF, il faut donc la positionner à b000000. Un premier double-clic sur le symbole de cette constante va vous permettre de changer ffffffff en 000000, validez par OK.

Figure 37 Constante à b000000

Dans un deuxième temps il faut ré-ouvrir la boite de dialogue précédente, cette fois sélectionnez Cvalue puis sur le bouton Edit Traits. Cette fois une nouvelle fenêtre apparaît, il suffit de préciser 2 Binary comme base et la longueur sur 6 bits. ISE 12.4 ne semble pas permettre de modifier ces arguments lors de la première mise à jour…

Figure 38 Constante : longueur et base

Il vous reste à connecter cette constante par un Bus Tap à led(7:2). La modification du circuit doit ressembler à ça.

Figure 39 Toplevel final

Cette fois le toplevel.bit devrait se créer. Tous les warnings que vous pourriez observer viennent soit de fils non utilisés switches(7:2), soit de lignes de commande de S3.ucf non utilisées.

Additionneur

Passons à l’étape suivante, il faut pouvoir ajouter deux bits en prenant en compte la retenue. Il s’agit donc de faire la somme de trois bits pour produire un résultat. La somme de 3 bits produit un résultat compris entre b00 et b10. Le bit à droite (le poids faible) est le résultat nommé s, le bit à gauche (le poids fort) est la retenue nommé cout, celle-ci servira pour l’addition suivante. Deux méthodes existent, soit vous produisez la table de vérité des deux sorties s et cout en fonction de 3 entrées a, b et cin ; soit vous utilisez successivement deux demi-additionneurs. Bien sûr c’est la seconde qui vous choisirez, elle permet de réutiliser le composant déjà créé demiadd. Un premier demiadd additionne a et b, le second ajoute le résultat produit par le premier à cin qui lui proviendra de la retenue du tour précèdent. Un et un seul des deux demiadd peut produire une retenue, il suffira de faire un OU sur les deux retenues produites pour générer la retenue finale en sortie cout. Allez-y, créez une New Source add1bit de type Schematic. Placez-y deux instances de demiadd, les fils en entrée et sortie, puis les I/O Marker. Enfin vous pouvez créer le symbole add1bit.

Figure 40 Additionneur 1 bit

En mode simulation, sélectionnez add1bit et lancez le simulateur Isim. Vous avez 8 cas à tester c’est encore faisable cas par cas.

Figure 41 Simulation additionneur 1 bit

La simulation étant correcte, vous pouvez programmer la carte pour réaliser cette addition. Utilisez le même toplevel où il faudra supprimer le demiadd pour le remplacer par une instance de add1bit. Il faut bien entendu utiliser un troisième switch pour piloter l’entrée cin, je vous propose d’utiliser le switches(2).

Figure 42 Toplevel additionneur 1 bit

Votre construction hiérarchique vous permet de ne rien changer au fichier S3.ucf. Vous pouvez générer le code toplevel.bit et le tester sur la carte.

Additionneur 4 bits

Pour additionner deux mots de 4 bits a3a2a1a0 et b3b2b1b0, il vous faut donc un demiadd pour les 2 premiers bits a0 et b0, ensuite 3 add1bit pour les autres bits. On construit ainsi une cascade de composants add1bit autant que nécessaire. Je vous propose de créer un New Source add4bit de type Schematic. Vous y instanciez un demiadd et 3 add1bit les uns sous les autres. Ensuite créez deux bus verticaux a(3:0) et b(3:0) à gauche des composants et un bus s(3:0) à droite. A l’aide de Add Bus Tap en mode left, sélectionnez le bus a et connectez le Bus Tap a(3) aux troisième add1bit. Le nom du fil se décrémente automatiquement sur a(2), vous pouvez ainsi rapidement connecter vos 4 fils du bus a, recommencez avec le bus b, puis avec le bus s en changeant le mode sur right. Il vous reste la retenue à faire passer du demiadd au premier add1bit, puis au second et enfin au troisième. Un fil récupère la dernière retenue, nommez le cout. Placez enfin les 4 I/O Marker pour les trois bus et le fil cout. Vous pouvez finalement générer le symbole.

Figure 43 Additionneur 4 bits

Vous êtes maintenant en mesure de simuler puis d’exécuter le circuit sur la carte.

Simulation pilotée

Pour simuler tous les cas de votre composant, il vous faudrait changer 256 fois les valeurs de a(3:0) et b(3:0) et ensuite vérifier les 256 résultats de s(3:0) sur le chronogramme. Ça deviendrait vite fastidieux. Vous allez donc tester quelques jeux d’essais que vous pensez représentatifs. Éventuellement vous ferez plusieurs simulations avec des jeux différents. Afin de vous simplifier la tâche, je vous propose d’ajouter à votre projet un programme testeur. ISE va vous y aider. Créez une New Source de type VHDL test bench, nommez le add4bit_tb. Le premier Next vous permet de choisir quel composant associer à ce programme de test, choisissez ici add4bit.

Figure 44 Création du programme de test_bench

Finissez la création et là ISE vous ouvre une nouvelle fenêtre sur le programme add4bit_tb.vhd qui instancie votre composant add4bit et vous laisse libre choix dans l’implémentation de son architecture. Dans le code c’est le process de simulation que vous devez programmer.

Le process VHDL ici peut être assimilé à une boucle infinie dans laquelle on peut initialiser les signaux en entrées a et b, avec des points d’attente active. Je vous propose une première simulation avec le code suivant qu’il faut recopier devant le wait. Ensuite en mode simulation, lancez le simulateur Isim sur le fichier add4bit_tb.

Figure 45 add4bit : premier test_bench

Vous pouvez essayer une deuxième simulation qui teste 2 jeux d’essai, remplacer les deux lignes, toujours avant le wait par celles-ci:

Figure 46 add4bit : second test_bench

Vérification sur la carte

Il nous reste à instancier votre add4bit dans le circuit toplevel. Comme précédemment il faut supprimer add1bit mais aussi les Bus Tap en entrée et en sortie de ce composant, puis venir placer add4bit. Je vous propose de créer un Bus Tap entre switches(3:0) et a, un second Bus Tap entre switches(7:4) et b : les 4 switches de droite serviront à saisir la valeur de a et 4 switches les plus à gauche celle de b. En sortie, vous créez un Bus Tap entre Led(3:0) et s, et un second Bus Tap entre led(4) et cout. Le résultat de l’addition s’affichera en codage binaire sur les 5 leds de droite. Il nous reste à calibrer notre constante. Un double clic que la constant, puis sélectionnez Cvalue pour lancer Edit Traits. On place ici 3 sur la longueur. On peut alors sur le premier menu y placer la chaine 000. Il faut ensuite modifier le nom du bus en led(7:5). Voici le circuit obtenu.

Figure 47 Toplevel pour add4bit

A vous de jouer : addition sur un afficheur 7 segments

Je vous propose d’afficher le résultat s sur un afficheur hexadécimal en utilisant le composant que vous aviez utilisé au TP1. ISE ne peut s’en sortir seul, il va falloir placer vous-même un OBUF8 pour l’I/O Marker led(7:0). En effet il vous faut définir un bus local myled(7:0). Celui-ci pourra transmettre les data myled(3:0) vers l’afficheur et aussi vers le OBUF8. Je vous guide dans la réalisation.

    1. Ajouter un copie dans votre projet de x7seg.vhd.
    2. Créez le symbole associé à ce composant.
    3. Placez une instance dans toplevel.
    4. Renommez tous les bus led en myled.
    5. Supprimez l’I/O Marker led(7:0).
    6. Placez un OBUF8 sur myled.
    7. Ajoutez un fil en sortie de OBUF8 nommé led(7:0).
    8. Replacez l’I/O Marker sur ce fil .
    9. Ajoutez les bus en sorties sur les ports de sortie de x7seg et les I/O Marker avec les mêmes noms que ceux utilisés dans le fichier S3.ucf.
    10. Reliez l’entrée de x7seg aux 4 fils du bus myled que vous voulez afficher.
    11. Testez sur la carte

Réponses