Leçon 6 : Registres

Voici la première étape dans la création effective de votre processeur S3. Le processeur S3 est un processeur simple qui sera réalisable en 7 séances de TP. À la fin de ces séances, vous serez en mesure de faire tourner vos propres programmes écrits en assembleur S3 sur la carte Nexys.

Dans cette première étape, vous découvrirez la notion de registre. Vous serez capable de construire une file de registres partageant un bus. Vous finirez par effectuer un transfert de données entre un et plusieurs registres via ce bus.

Schéma fonctionnel du processeur S3

Registres et transfert de registres

Voici la première étape dans la création effective de votre processeur S3. Le processeur S3 est un processeur simple qui sera réalisable en 7 séances de TP. À la fin de ces séances, vous serez en mesure de faire tourner vos propres programmes écrits en assembleur S3 sur la carte Nexys. Vous aurez peut-être envie de continuer le développement de ce processeur avec vos propres instructions et vos propres circuits. Si tel est le cas, bravo ! Vous serez alors des architectes en puissance.

Connaissances requises

Registre, bus, automates

Rappel

Si vous modifiez un composant, il faut si celui-ci existe recréer le symbole correspondant et faire les mises à jour dans les niveaux supérieurs qui l’instancient !!! Sans cela la version 12.4 d’ISE pourrait ne pas prendre en compte les modifications les plus internes.

Objectif

Dans cette première étape, vous découvrirez la notion de registre. Vous serez capable de construire une file de registres partageant un bus. Vous finirez par effectuer un transfert de données entre un et plusieurs registres via ce bus.

Le projet

Le processeur S3 est composé de 15 registres, une ALU, une unité de contrôle et commande, un incrémenteur pour le CO, des I/O, une mémoire de programme et une mémoire de données. Nous allons construire pas à pas ce processeur en mixant une saisie schématique et un peu de codes VHDL.

Comme toujours cela commence par la création d’un nouveau projet, TP6. Vous pouvez de suite créez le fichier toplevel en mode schématique et placer les options de compilation.

Les registres

Le fichier toplevel.sch servira pour instancier au fur et à mesure des développements les pièces du processeur S3 ainsi que tous les composants liés à la carte Nexys2 ou Nexys3. Vous allez créer de suite une nouvelle source de type schématique appelée S3. La taille de ce schéma S3 une fois créé doit être augmentée pour cela il faut sur le schéma faire un clic droit>Object Properties et vous pouvez choisir la taille A0p.

La bibliothèque de symboles ISE propose déjà des registres. Nous pourrions les créer nous même à partir de bascules mais il est plus simple d’utiliser le symbole fd16ce disponible.

Je vous propose de sélectionner ce symbole dans Flip_Flop et de lire sa spécification par Symbol Info.

Figure 71 Le registre FD16CE de ISE

Il s’agit en fait de 16 bascules D en parallèles. Les entrées Dx sont recopiées sur les sorties Qx lorsque CE = ‘1’ et sur le front montant de l’horloge C. A tout moment on peut remettre à 0 les sorties Qx par un CLR=’1’. En dehors de ces commandes, les Qx ne changent pas et produisent l’effet mémoire désiré.

Vous allez utiliser l’entrée CE pour déclencher ou non une écriture dans ces registres sur le front montant. Je vous propose d’instancier verticalement au milieu de votre schéma et dans l’ordre suivant les 15 registres. Pour chaque instance on changera le nom de l’instance (clic droit>Symbol>Rename…). Je vous conseille de bien aligner vos instances, un outil vous aide pour cela dans le menu Edit. (vous pouvez déjà jeter un œil sur la Figure 76)

Registre généraux : R1 R2 R3 R4 R5

Registres I/O : Rled Rsw R7seg

Registres ALU : Rsrc1 Rsrc2 Rdest

Registres Mémoire : Ram Rdm

Registres de chargement : CO RI

Figure 72 Un nom par registre

Les registres sont prêts à être connectés au bus. N’hésitez pas à sauvegarder vos schémas après chaque saisie…

Bus et connecteur de bus

Le bus n’est rien d’autre ici qu’un ensemble de 16 fils qui permettront de transférer un à un des mots de 16 bits entre les différents registres de votre processeur. Autant il est possible de connecter un bus vers plusieurs registres destinations, autant il est interdit de connecter plusieurs sorties de registres différents vers le même Bus. En effet si deux registres étaient connectés sans précaution aux mêmes fils rien ne garantirait la valeur véhiculée par ce bus. ISE ne serait d’ailleurs pas capable de générer le circuit correspondant !

Figure 73 Pas à faire!!!

Pour partager un bus entre plusieurs producteurs on peut utiliser une logique 3 états : un tel circuit permet sous contrôle d’un signal de validation de laisser passer ou non une valeur en entrée vers la sortie. Non validé la connexion n’est pas effective. Notre FPGA ne supporte pas ce genre de circuit il faut donc combiner avec des portes ET et OU. Notre hypothèse de départ consiste à n’autoriser qu’un seul registre lors d’une période d’horloge donnée à positionner sa valeur sur le bus. Il faudra le garantir par la suite.

Vous allez d’abord créer un symbole qui assure cette connexion pour 1 seul fils. Ajoutez une nouvelle source schématique dans votre projet de nom connecteur. Il y aura trois entrées R, Din et connect, une sortie Dout. La fonction suivante Dout = Din OR connect AND R nous permet de réaliser la connexion entre l’entrée R et la sortie Dout lorsque l’entrée connect est active, sinon le signal Din se propage sur Dout. En plaçant Din à 0 sur le premier connecteur et avec notre hypothèse de départ on peut ainsi réaliser notre bus à moindre coût.

Dans connecteur, il suffit de placer les deux portes AND et OR. Ensuite ajoutez les fils entre les portes AND et OR. Ajoutez les I/O Marker en les nommant Din, connect, R et Dout. On obtient un circuit qui ressemble à celui-ci.

Connecteur 1 bit

Il n’est peut-être pas utile de le simuler vue la simplicité… Vous pouvez créer le symbole connecteur.

Ce que vous venez de faire pour un fil, il faut le faire pour les 16 fils du bus en même temps, et avec le même signal connect pour les 16 connecteurs. Créez une nouvelle source connecteur16 de type schématique. Il faut y placer verticalement 16 instances de connecteur. Pour simuler il sera plus facile de nommer vos instances C0 à C15. Placez un bus de 16 fils nommé Din(15:0), un bus de 16 fils nommé R(15:0) et un fils connect verticalement à gauche, puis un bus de 16 fils nommé Dout(15:0) verticalement à droite des 16 connecteurs. Avec les Bus Tap vous allez pourvoir ventiler les 16 fils de chaque bus sur le port correspondant du connecteur associé. Commencez par Din(15), ISE décrémentera automatique le nom du Bus Tap pour vous. Il faut bien vérifier vos connections ici, indices et liaisons. Placez pour finir les 4 I/O Marker sur Din connect R et Dout. Vous pouvez créer le symbole correspondant quand toutes les connections sont correctes.

Figure 74 Le connecteur16

Figure 75 Connecteur16 avec un zoom sur les 3 premiers connecteurs

Pour simuler ce composant, il suffit de générer le test_bench correspondant connecteur16_tb en plaçant une valeur initiale sur Din, une autre valeur sur R, initialiser le signal connect à 0 puis le mettre à 1 après 100ns. Afin de respecter notre hypothèse, il faut aussi remettre à x0000 l’entrée Din après 100 ns. Vous devriez vous en sortir seul(e) cette fois.

Vous allez pouvoir construire le bus maintenant. A côté (droite) de chaque registre placez un connecteur16. Là encore je vous conseille de les nommer CR1, CR2 …. CCO, CRI. Il suffit ensuite de relier chaque sortie Q(15:0) d’un registre à l’entrée R(15:0) de son connecteur16. Les entrées connect pour l’instant sont forcées à 0 avec un GND. En cascade connectez la sortie Dout à l’entrée Din du connecteur suivant. Pour le premier Din, il faut respecter notre hypothèse ! Vous placez donc une constante que vous initialisez en deux étapes à x0000 et à une longueur de 16 bits. Enfin la dernière sortie doit être reliée aux entrées des registres. Pour l’instant vous allez relier cette sortie Dout du connecteur CRI (écartez le bus des registres pour laisser un peu de place) avec les entrées de Rram, Rsrc2, Rsrc1, R7seg, Rled, R5, R4, R3, R2, R1. Renommez ce bus bus_data(15:0). Pour les autres registres, on y reviendra plus tard.

Tous les registres sont synchrones, vous pouvez de suite placer un fil clk avec son I/O Marker et connecté à tous les ports C des registres

Figure 76 Les registres et le bus

Figure 77 Zoom sur les 3 premiers registres

Pour cette leçon, vous utiliserez les 3 registres I/O Rled, Rsw et R7seg. En ce qui concerne Rsw, le processeur S3 étant un processeur 16 bits, les registres sont eux aussi sur 16 bits. Vous allez ajouter un bus en entrée du registre Rsw, vous le nommez switches(15:0), vous lui ajoutez un I/O marker. Pour Rled et R7seg, c’est la sortie qui doit être récupérée, ajoutez une connexion sur le fil de sortie de chaque registre vers la gauche, nommez les Led(15:0) et D7seg(15:0) et placez-y l'I/O Marker.

Enfin pour l'affichage de R7seg, vous allez réutiliser les composants développés lors de la leçon 4. Il faut donc par Project>Add Copy of Source, insérer clkdiv.sch et afficheur16.sch. Si vous avez construit le testclk.sch lors de la leçon 4, vous pouvez l'utiliser à la place de clkdiv.sch. L’afficheur est construit à partir d’autres composants, il faut aussi que vous les ajoutiez : compteur4.sch, mux4x4.sch et X7seg.vhd. Vous êtes en mesure de recréer pour ce projet les deux symboles associés à clkdiv et afficheur16. Dans toplevel , il suffit de placer une instance de chacun sous le composant S3, connectez l’entrée clk du clkdiv au fil clk déjà présent. Connectez le clk190 à l’afficheur, connectez la sortie D7seg(15:0) sur l’entrée de l’afficheur Data(15:0). Enfin ajoutez sur les deux ports de sortie un bus et son I/O Marker nommés anodes(3:0) et sevenseg(6:0). C’est exactement la même manipulation que pour la leçon 4. ( si votre TP 4 n’a pas été finalisé, vous trouverez une version de ces fichiers en bas de page, il y a deux générateurs de clock qui fonctionnent )

Pour tester votre circuit, je vous propose d’afficher sur les leds et sur l’afficheur 7 segments, la valeur saisie sur les switches de la carte. Comme il n’y a que 8 switches et led, on forcera les 8 bits de poids forts à x00. A chaque top d’horloge, il faut donc charger le registre Rsw, ouvrir le bus en sortie de Rsw, chargez les registres Rled et R7seg. Pour cela vous allez simplement placer un 1 en entrée des trois CE de ces trois registres afin de les rendre actifs. Vous placez également un 1 sur l’entrée connect du connecteur CRsw pour propager sa valeur sur le bus. Le schéma final doit être semblable à celui-ci. A chaque top d’horloge, le registre Rsw est mis à jour alors que sa valeur précédente est recopiée sur Rled et R7seg pour affichage. On appelle cette manipulation un transfert de registre.

Figure 78 Connexion des I/O

Une fois toutes les connexions vérifiées, vous pouvez créer le symbole du composant S3. Il ne reste plus qu’à placer ce symbole S3 dans toplevel, nommez-le mon_S3. Pour le port led(15:0) du processeur S3, vous allez créer un bus ld(15:0) et sur ce bus , vous placez un Bus Tap sur ld(7:0) connectez-y in OBUF8 de la bibliothèque IO qui produit le bus et son I/O Marker led(7:0). Pour l’entrée switches(15:0), connectez-y un bus sw(15:0). Placez 2 Bus Tap sw(7:0) et sw(15:8). Sur le premier vous connectez un IBUF8 lui-même connecté au bus et I/O Marker switches(7:0). Le second Bus Tap est lui connecté à une constante que vous initialisez en deux phases : à la valeur x00 avec une longueur de 8. Pour la clock, vous allez en mesure préventive ajouter un BUFG de la bibliothèque Buffer qui permet d'améliorer la qualité du signal, Sa sortie est connectée sur le clk du S3, sur son entrée placez un fil nommé clk avec son I/O Marker.

Figure 79 Toplevel transfert de registres

Simulation

C’est à peu près la même chose que pour la leçon 4. Vous allez ajouter une nouvelle source de type VHDL test bench associée à toplevel. Dans le code VHDL, il suffit de rajouter le code pour la génération de l’horloge à 50 Mhz. Vous pouvez aussi tester votre circuit avec différentes valeurs sur switches(7:0) ici x12. En mode simulation lancez Isim sur toplevel_tb.

En ajoutant sur la fenêtre de simulation les valeurs q(15:0) des registres Rled, Rsw et R7seg (il suffit d’ouvrir la hiérarchie dans Isim pour retrouver les instances de ces trois registres, ensuite on fait glisser la variable q(15:0) vers la fenêtre de simulation), vous observez le comportement suivant :

Pour observer un changement sur les bus anodes et sevenseg, il faudra pousser la simulation à plus de 5 ms, la fréquence de l’afficheur étant de 190Hz. Vous verrez alors le deuxième digit s’afficher. Si vous changez la valeur des switches avec un fréquence supérieure à 190 Hz, vous risquez de mélanger pour l’affichage le début d’une saisie avec la fin de la suivante. Mais changer les switches à la main en moins de 5 ms et réussir à le voir sur l’afficheur n’est pas humainement possible…

Vérification sur la carte

Vous allez pouvoir faire tourner votre processeur S3 avec cette première fonction de transfert de registres. Comme d’habitude il faut ajouter le fichier S3.ucf à votre projet avant de générer le fichier toplevel.bit. Après chargement par Adept, vous devriez voir sur les leds la valeur saisie sur les switches et sur l’afficheur la valeur « x00zz où zz représente la valeur en hexa saisie sur les 8 switches.

Une fois validé, vous pouvez copier votre projet vers TP7 pour la leçon suivante. Il suffit de sélectionner File> Copy Project, choisir le nom TP7 et de sélectionner Exclude generated files.

Figure 80 Copie d'un projet

A vous de jouer

Question 1 : réalisez l’affichage seulement sur les leds.

Question 2 : réalisez l’affichage que sur l’afficheur 7 segments.

Réponses