Leçon 1 : ISE pour Nexys

Dans cette leçon, Vous allez réaliser votre première conception (j’utiliserai aussi le mot design) simple qui va vous permettre de découvrir les entrées et sorties de la carte Nexys2 ou Nexys3. Ces concepts d’entrées/sorties seront utilisés dans toutes les séances suivantes. Par la même occasion, ce TP vise à fournir une initiation à l’utilisation des outils de Xilinx et Digilent. De par sa simplicité, c’est aussi un bon exemple pour comprendre le fonctionnement de la chaîne de transformation : comment à partir d’un code de description ou un schéma de circuit vous allez, par ISE, produire un fichier mondesign.bit. Ce fichier est ensuite chargé sur la carte afin d’implanter sur celle-ci le circuit spécifié dans ISE...

Le fichier lecon1.pdf est disponible en fin de feuille!

Lancement de ISE en salle TP

La Figure suivante identifie les principaux éléments de l’interface du Navigateur de Projet ISE utilisé dans ces TPs. Pour installer ce logiciel sur les machines de l’université de Lille 1 :

  1. Récupérer le fichier de licence et l'enregistrer sur votre compte l'adresse vous sera donnée par l'enseignant. Sur votre machine personnelle utilisez votre propre licence.
  2. Depuis un terminal, lancer le gestionnaire de licences par la commande: /opt/Xilinx/12.4/ISE_DS/common/bin/lin64/xlcm
  3. Dans l'interface de gestion de licences choisir "Get free webpack licence"
  4. Cliquer sur "connect now" puis sur "copy licence"
  5. Charger le fichier de licence puis cliquer sur "close". Remarque: les étapes de 1 à 5 ci-dessus sont à réaliser par chacun sur son propre compte (une seule fois pour tout le semestre)
  6. Le logiciel ISE est maintenant prêt à être utiliser. Il se lance avec la commande: /opt/Xilinx/12.4/ISE_DS/ISE/bin/lin64/ise

Alias ISE

Si vous utilisez bash, rajoutez dans .bashrc la ligne suivante:

alias ise='/opt/Xilinx/12.4/ISE_DS/ISE/bin/lin64/ise'

enregistrez et fermez .

ensuite la commande source .bashrc pour recharger le nouveau bashrc dans votre terminal

Nous actons que les installations d’ISE pour la simulation et la compilation et Adept pour les exécutions sur la carte sont réalisées avec succès.

Objectifs

Dans cette leçon, vous allez réaliser votre première conception (j’utiliserai aussi le mot design) simple qui va vous permettre de découvrir les entrées et sorties de la carte Nexys2 ou Nexys3. Ces concepts d’entrées/sorties seront utilisés dans toutes les séances suivantes. Par la même occasion, ce TP vise à fournir une initiation à l’utilisation des outils de Xilinx et Digilent. De par sa simplicité, c’est aussi un bon exemple pour comprendre le fonctionnement de la chaine de transformation : comment à partir d’un code de description ou un schéma de circuit vous allez, par ISE, produire un fichier mondesign.bit. Ce fichier est ensuite chargé sur la carte afin d’implanter sur celle-ci le circuit spécifié dans ISE.

Le projet

C’est parti! Connectez la carte via le câble USB et placez l’interrupteur en position ON. Lancez le logiciel ISE 12.4 ! Si vous avez installé vous-même ISE et la licence vous l’avez déjà lancé. Pour ceux qui ont accès à une machine d’une salle TP préinstallée, il suffit dans le menu démarrer de Windows de lancer votre application dans Xilinx ISE Design Suite 12.4> ISE Design Tools> Project Navigator.1

Nexys2

Nexys3

Pour cette première expérience, nous aborderons les dispositifs de communication directe avec la carte Nexys, le vecteur de 8 switches (interrupteurs), les 8 Leds et l’afficheur quatre fois 7 segments. La première partie est assez simple: vous afficherez sur les 8 Leds les résultats des 8 switches : ‘0’ ou ‘1’ pour éteint ou allumé. Ensuite vous utiliserez 4 interrupteurs SW0 à SW3 pour représenter un nombre de 4 bits codé en binaire dont la valeur peut évidemment s’afficher en hexadécimal sur un seul afficheur : x0 à xF, soit b000 à b1111 en binaire, soit 0 à 15 en décimal (Notation : b pour nombre binaire, x pour nombre hexadécimal, rien pour décimal). Vous placerez cette valeur sur l’afficheur le plus à droite des 4 afficheurs 7 segments. A partir de cette mise en œuvre je vous proposerai d’autres expériences du même type que vous pourrez réaliser par vous-même.

Dans ce premier exemple, vous allez mixer la conception par schéma et la conception par code. Les schémas sont propres à ISE, le code lui respecte le standard VHDL. C’est un langage de conception que vous découvrirez au fur et à mesure des séances. Cela ne vous empêche pas de regarder d’un peu plus près ce puissant langage de synthèse dont vous ne verrez lors des séances de TP que quelques éléments. Des milliers de références sur le net, ce lien Syntaxe VHDL vous sera néanmoins suffisant pour vos développements.

Le choix entre code ou schéma n’est pas exclusif et parfois on préférera avoir une vision structurelle d’une portion du circuit et donc adaptée à la vue schématique, parfois on voudra exprimer un comportement et la vision « algorithme » est alors favorisée. Dans vos séances, nous favoriseront au maximum la vision schématique qui est très intuitive et ne demande pas un apprentissage du langage VHDL en tant que tel, même si la rigueur dont il faut faire preuve lors de l’assemblage graphique est parfois laborieuse. Mais « c’est en designant qu’on devient designer »

Création d’un projet

Pour commencer la conception, il faut créer un nouveau projet avec File>New Project. Lorsque vous spécifiez le nom du projet et le répertoire, évitez les espaces dans le chemin, j’ai choisi TP1.

Figure 2 Création du projet TP1

La prochaine étape sert à préciser le type de FPGA que vous ciblez. C'est pour nous celui de la carte Nexys2 (1200) ou celui de la carte Nexys3.

Figure 3 Caractéristiques de la carte Nexys2

Figure 4 Caractéristiques de la carte Nexys3

Enfin, Next puis Finish vont clôturer cette partie.

Inclure une source dans le projet

Pour décrire le système, vous ajoutez un nouveau fichier à votre projet. Ce fichier contiendra le schéma du circuit que vous allez définir. Donc ici vous sélectionnez Project>New Source…, puis remplissez la boîte de dialogue permettant à l’outil de créer un nouveau fichier toplevel.sch en sélectionnant Schematic et donc le nom toplevel.

Figure 5 Création d'un schématique

En cliquant Next et Finish, vous créez le fichier toplevel.sch et ISE ouvre de suite la fenêtre de conception schématique pour ce fichier. Vous comprendrez vite qu’ISE est capable d’ouvrir plusieurs fenêtres et que l’on passe de l’une à l’autre par les onglets associés à chacun des noms. Le logo

apparaît devant toplevel.sch et indique la racine de votre projet.

Saisie du circuit

Les principaux boutons de saisies (les mêmes actions sont accessibles par le menu Add) permettent de manipuler des symboles, des fils, des bus2.

La construction du circuit va pouvoir commencer. La première étape est simple, vous allez relier les 8 switches aux 8 leds sur la carte. Aucune logique n’est nécessaire, c’est comme si vous réalisiez par ISE la «soudure» de fils entre les switches et les leds. Même simpliste, c’est quand même une architecture qui sera programmée!

Vous allez donc placer dans votre schéma toplevel, un ibuf8 et un obuf8 (ce sont des buffers nécessaires pour les entrées/sorties de la carte). En cliquant sur le bouton ajouter un symbole (Add Symbol), une liste de symboles disponibles apparaît. Choisissez dans la sous-liste IO les deux symboles cités précédemment. Cliquez sur le nom dans la liste et recliquez dans la fenêtre associée au schéma pour créer une instance. (Ctrl Z pour annuler une action)

Si vous avez besoin de savoir ce que fait un symbole, il suffit de le sélectionner et de cliquer sur Symbol Info.

Figure 6 Sélection d'un symbole

Vous ajoutez 3 fils (Figure 8) en sélectionnant le bouton correspondant Add Wire et en cliquant sur l’emplacement d’une extrémité puis en cliquant sur l’emplacement de l’autre, une double clic permet de rester en mode création entre deux fils. ATTENTION il faut être attentif à ce que les fils soient bien connectés au composant, n’hésitez pas à zoomer afin de mieux voir les 4 petits carrés sous le curseur qui vous garantissent la bonne connexion une fois le curseur sur le port du composant. Ajoutez deux I/O Marker aux deux extrémités libres de vos fils, là encore en sélectionnant le bon bouton et en cliquant sur les 2 extrémités libres. Il vous reste à renommer les 2 I/O Marker. Pour cela sélectionnez un à un les fils connectés aux deux I/O Marker. Utilisez le bouton nommer un fil. Il vous suffira de nommer switches(7:0) l’entrée et led(7:0) la sortie. Une fois le nom saisi, placez-le dans le schéma par un clic sur le fil concerné.

Figure 7 Nommage des fils et bus

Voici les résultats de votre saisie, vous devriez sauver votre projet. Sans effort vous venez de créer un circuit qui est composé de 8 fils associant chaque switches(i) à la led(i) de votre carte. Cet ensemble de 8 fils est appelé un BUS la représentation sous ISE correspond à la notation name(Upper:Lower).

Figure 8 Votre toplevel.sch

Remarque : Pour vous simplifier la vie, ISE insère les iobuf par défaut. Ici ils sont explicites car ils permettent de spécifier deux noms différents aux deux I/O Marker.

Vous avez utilisé des noms logiques choisis par vous-même (sous mon influence) pour vos fils et I/O Marker. Pour qu’ISE puisse associer ces noms logiques aux noms physiques des broches de votre puce programmable, il faut explicitement donner toutes les correspondances :

un nom logique = un nom physique

Pour ce faire, vous devez créer une nouvelle source de type Implementation Constraints File (.ucf). Cela sera fait par Project > New Source.

Figure 9 Création du fichier S3.ucf

Next et Finish comme toujours créent le fichier et ISE ouvre l’éditeur sur ce fichier pour sa saisie. Il faut ici insérer le code qui correspond à la carte Nexys2 ou Nexys3 puisque chaque carte intègre un FPGA différent.

UCF de la Nexys2

Voici les noms des broches du Spartan3E et ses connexions sur la carte.

Figure 10 Les broches sur la carte Nexys2 - document Digilent

Voici le code correspondant à insérer et à sauvegarder dans le fichier S3.ucf.

Le fichier S3.ucf apparaît aussi sous la hiérarchie de toplevel.sch.

UCF de la Nexys3

Voici les noms des broches du Spartan6 et ses connexions sur la carte.

Figure 11 Les broches sur la carte Nexys3 - document Digilent

Voici le code correspondant à insérer et à sauvegarder dans le fichier S3.ucf.

Le fichier S3.ucf apparaît aussi sous la hiérarchie de toplevel.sch.

Simulation et compilation du circuit

Il n’y a pas grand-chose à simuler sur cet exemple, par contre vous allez pouvoir tester le circuit sur la carte!

ISE vous propose un mode simulation et un mode implementation. Il vous faudra choisir implementation en revenant sous l’onglet design.

Figure 12 Chaîne de compilation

C’est la partie la plus simple ! C’est ISE qui va faire le travail. Il reste néanmoins un ensemble d’informations à lui donner pour qu’il s’en sorte.

Il vous reste à positionner le mode de l’horloge utilisé lors du chargement du FPGA. Sélectionnez toplevel.sch, puis dans la fenêtre processes, cliquez droit sur Generate Programming File et dans le menu déroulant sur Process Properties. Positionnez la FPGA Start-UP Clock à JTAG Clock dans Startup Options. Pour chaque nouveau projet, il faudra lors de la première compilation vérifier ce paramètre. Vous pouvez générer le fichier toplevel.bit avec un double clic sur Generate Programming File.

Figure 13 Option JTAG

Lorsque la compilation est un succès, il vous reste à charger le code produit sur la carte. Celle-ci doit être connectée et allumée. Vous allez pour cela utiliser le logiciel Adept que Digilent vous a fourni.

Chargement sous windows

Le fichier généré se trouve dans votre projet et se nomme ici toplevel.bit. Lancez Adept depuis le menu demarrer de votre PC. Il vous suffit de sélectionner le bon fichier avec Browse et une fois effectué vous pouvez charger le code produit par ISE sur le FPGA de la carte Nexys. Cliquez sur Program.

Figure 14 Chargement sur Nexys2 sous Windows

Figure 15 Chargement sur Nexys3 sous Windows

Chargement sous linux :

Le chargement du design sur le FPGA sous Linux se réalise en mode ligne de commande. Vérifiez que votre carte FPGA soit branchée et allumée. Ouvrez un terminal, seulement 2 commandes sont utiles.

La commande djtgcfg enum : cette commande permet de lister toutes les cartes connectées à l’ordinateur.

La commande djtgcfg -d Nexys2 prog -i 0 -f toplevel.bit permet de charger le fichier sur la carte Nexys2.

La commande djtgcfg -d Nexys3 prog -i 0 -f toplevel.bit permet de charger le fichier sur la carte Nexys3.

A vous de vérifier que la position des switches positionne les leds correspondantes.

L’afficheur 7 segments

Poursuivons le développement de ce projet en ajoutant une nouvelle fonctionnalité. Vous allez afficher en hexadécimal la valeur représentée par les 4 switches (3:0), sur l’afficheur le plus à droite des 4. Il manque un circuit logique qui transformera une valeur codée sur 4 fils en entrée vers 7 fils en sortie, chacun allumant ou éteignant un segment parmi les 7 afin d’obtenir une représentation visuelle de sa valeur en hexadécimal (b0000=x0, b0001=x1, b0010=x2 … b1110=xE, b1111=xF). C’est un circuit combinatoire, nous verrons dans les leçons suivantes comment les réaliser sous ISE… Je vous propose plutôt d’utiliser le langage VHDL pour définir le comportement de votre circuit et donc spécifier ce que vous voulez transformer plutôt que comment vous allez le transformer. ISE se débrouillera pour, à votre place, générer les circuits nécessaires à la réalisation du comportement.

Ajoutez une nouvelle source à votre projet. Vous savez déjà le faire. Cette fois choisissez de créer un VHDL Module. Je vous propose comme nom x7seg.

Figure 16 Création fichier VHDL x7seg

En cliquant Next, vous serez invité à entrer les ports de votre nouveau module. C’est facultatif mais cela vous permet d'économiser la saisie manuelle d’une partie du code VHDL. Que vous le remplissiez ou non, le fichier texte obtenu reste complètement modifiable par la suite. Entrez les ports qui seront alors insérés dans l’entête de votre fichier VHDL. Le composant convertit les 4 bits en entrée afin de produire une combinaison sur les 7 segments en sortie afin d’afficher les chiffres de x0 à xF. En plus, insérez le port anodes qui sera utilisé pour activer/désactiver chacun des 4 afficheurs individuellement, c’est ce port qui permettra de choisir l’afficheur de droite parmi les 4 disponibles dans votre cas. Le sens des ports doit être spécifié également IN (entrée) ou OUT (sortie).

Figure 17 Création des ports

Next et Finish vous produisent automatiquement le squelette du module VHDL x7seg.vhd. ISE ouvre son éditeur de texte , il contient ce squelette. Vous pouvez remarquer que x7seg.vhd n’est pas pour l’instant dans la hiérarchie toplevel.sch. Normal il n’y a encore aucune instanciation de ce composant!

Le code VHDL est composé de deux parties : la partie ENTITY qui reprend les ports que vous avez spécifiés lors de la création de ce module VHDL et la partie ARCHITECTURE qui en spécifie le comportement. La syntaxe de VHDL est suffisamment explicite pour s’y retrouver. C’est cette seconde partie encore vide qu’il faut maintenant écrire. Vous insérerez ce comportement entre le BEGIN et END de cette ARCHITECTURE.

Pour chaque valeur présente sur le port sw(3:0), il faut expliciter les segments à afficher sur le port de sortie sevenseg(6:0). On utilise pour cela un WITH SELECT. La notation x"0" représente un nombre de 4 bits en hexadécimal. Le signe <= permet de relier la valeur du signal de sortie à la valeur présente sur le signal d’entrée à un instant particulier. De façon intuitive, les signaux ne sont pas des variables rangées en mémoire mais plutôt des valeurs qui circulent sur des fils et évoluent avec le temps…. Pas la peine d’en savoir plus pour l’instant.

Voici le codage sur 7 bits de votre afficheur Nexys, ‘1’ pour éteint et ‘0’ pour allumé, il y a donc 7 fils pour les 7 segments à piloter (G F E D C B A), par exemple b1111001 allume B et C. Les 4 fils anodes permettent de sélectionner un ou plusieurs afficheurs parmi les quatre afficheurs, ici on choisit l’afficheur le plus à droite en positionnant anodes à b1110.

Figure 18 L'afficheur 7 segments - document Digilent

Voici le code VDHL correspondant :

Après avoir inséré ce code VHDL entre BEGIN … END, enregistrez le fichier, sélectionnez-le et vérifiez la syntaxe en cliquant sur Check Syntax dans la fenêtre Processes. Ça doit être bon. Vous allez donc pouvoir générer un symbole pour ce composant qui sera ensuite instancié dans votre circuit toplevel. Toujours dans la même fenêtre Processes, il faut ouvrir la hiérarchie Design Utilities et lancer Create Schematic Symbol.

Figure 19 Création d'un symbole pour x7seg

En retournant dans la fenêtre associée à toplevel.sch, vous pouvez ajouter le symbole créé. Il suffit de sélectionner le bouton Add Symbol, cette fois en premières lignes apparaissent vos bibliothèques de symboles personnels. Vous ouvrez cette bibliothèque et vous sélectionnez x7seg pour venir en placer par double clic une instance dans votre circuit toplevel.

Figure 20 Insertion d'un symbole personnel

Une fois x7seg placé dans votre schéma vous devez ajouter les fils à ses sorties. Placez deux I/O Marker sur les sorties. Renommez les en renommant les fils correspondants sevenseg(6:0) et anodes(3:0). Avant de connecter le port en entrée, renommez le bus entre IBUF8 et OBUF8 avec le nom data(7:0).

Figure 21 Instanciation du composant x7seg

Il vous reste donc à connecter les 4 fils de data(3:0) au port sw(3:0). Le bouton ajouter une connexion à un bus est fait pour ça (Bus Tap). Cliquez sur ce bouton et la fenêtre associée apparaît, vous pouvez choisir le sens du connecteur, ici Top semble adéquat. Ensuite vous cliquez une première fois sur le bus sur lequel vous voulez vous connecter, ici data(7:0). Dans la fenêtre le nom data(7:0) apparaît, dans cette fenêtre il faut à ce moment spécifier les fils que vous voulez effectivement sélectionner. Vous modifiez Net Name de data(7) en data(3:0). Il ne reste plus qu’à placez votre Bus Tap sur le port que vous voulez connecter, ici le port est connecté à sw(3:0). Là encore il faut être rigoureux sur la connexion et si besoin zoomer pour observer les 4 carrés de connexion sur l’extrémité de votre Bus Tap.

Figure 22 Initialisation du Bus Tap

Voici le résultat final de votre design! Une fois le schéma toplevel sauvé, le composant x7seg apparaît dans la hiérarchie de celui-ci puisque une instance de ce composant y a été placée.

Figure 23 Toplevel final

Vous avez ajouté deux I/O Marker (sans les iobuf qui seront ajoutés d’office par ISE), il faut les prendre en compte dans le fichier S3.ucf. Vous allez donc mettre à jour ce fichier en ajoutant les commandes qui correspondent aux broches de votre carte Nexys2 (Figure 10) ou Nexys3 (Figure 11):

UCF Carte Nexys2

UCF Carte Nexys3

Prêt pour la synthèse !! Recompilez le tout par Generate Programming File sur toplevel.sch. Enfin rechargez le toplevel.bit par Adept pour un test sur la carte. Vous devriez afficher la valeur saisie depuis les 4 premiers switches sur les leds et sur le premier afficheur 7 segments.

A vous de jouer

Question 1 : Affichez la valeur codée depuis les switches sur les 4 afficheurs en même temps.

C’est anodes qui pilotent les 4 afficheurs. Il faudra modifier le code VHDL. Lorsque l’on change l’ARCHITECTURE d’un symbole personnel, il n’est pas utile de modifier les schémas qui l’utilisent. Par contre si l’on modifie son nombre de ports (ENTITY), ISE vous demandera de mettre à jour votre schéma sur ce symbole obsolète en cliquant sur le schéma ou en ouvrant le schéma dans l’éditeur. A vous alors d’ajouter ou retirer les fils nécessaires.

Il existe une commande ISE qui met à jour l'ensemble des symboles après une modification. Selectionnez le projet et lancez sous Design Utilities la commande Update All Schematic Files.

Question 2 : Réalisez un afficheur qui affiche un seul segment parmi les 7 en fonction du numéro saisi sur les 3 premiers switches : afficher A= si 1 , B si 2, etc…

Là aussi il faudra modifier le code VHDL.

Question 3 : Construire le circuit qui allume les segments A, B… G, pour toutes les combinaisons des 7 premiers switches de la carte. Exemple en positionnant les switches 0 et 1, les segments A et B s’allument. On peut alors se passer du composant x7seg…

Question 4 : Pour compléter la question 2, utilisez en même temps 4 switches restants pour choisir quels afficheurs afficheront la valeur saisie sur les 3 premiers.

Réponses

1. Sous linux : /opt/Xilinx/12.4/ISE_DS/ISE/bin/lin/ise

2. Un bus est un ensemble de fil ayant le même nom. On y ajoute un indice c’est un tableau de fils. Exemple : Bus(15:0)