Un squelette de projet¶
ATTENTION
TAG GIT pour cette ETAPE : SQUELETTE
Objectif¶
Nous allons mettre en place un squelette de projet, utilisant quelques ressources disponibles sur la carte fpga DE10-Nano. Nous utiliserons quelques interrupteurs, boutons poussoirs, leds et horloges qui serviront tout au long du projet. Partant d'un squelette de projet "prêt à servir" nous vous laisserons amender ce projet de façon à vous familiariser avec l'ensemble des données et informations à fournir pour mettre en œuvre un design réel sur la carte.
Mise en place de l'environnement de travail¶
- Placez-vous dans votre dépot git personnel (cd )
- Importez les codes de testbench de votre futur bloc:
- git checkout main
- git remote add controleur_video_avalon git@gitlab.enst.fr:se204/controleur_video_avalon.git
- git remote update
- git merge --allow-unrelated-histories controleur_video_avalon/main
Le support des blocs matériels déjà codés nécessite une précompilation spécifique . Lancez cette précompilation:
- Ouvrez une fenêtre de terminal, et placez-vous dans le répertoire controleur_video/ips/Qsys
- Executez la commande make qsys_compile
- Cela prend du temps... revenez donc à la lecture du sujet...
Arborescence de travail, règles d'écriture¶
Nous avons préparé une arborescence de travail contenant déjà beaucoup de code, de documents, de scripts...
Vous n'aurez à intervenir que dans le répertoire SoCFPGA
Les sous-répertoires de ce répertoire sont:
- Le répertoire src qui ne devra contenir que du code synthétisables de vos blocs.
- Le répertoire tb_src qui peut contenir tout code pouvant servir à la simulation (testbenchs...)
- Le répertoire sim, répertoire dans lequel se trouvent les scripts de simulation et dans lequel se déroule la simulation.
-
Le répertoire syn, répertoire dans lequel se trouvent les scripts de synthèse et dans lequel se déroule la synthèse.
-
Le nom des fichiers créés devra être impérativement identique au nom des modules concernés (un fichier par module)
- Veuillez respecter les noms proposés pour les signaux et fichiers de façon à faciliter un déboguage ultérieur, et la création de scripts automatiques pour la vérification.
Le module Top¶
Dans le répertoire SoCFPGA/src se trouve un premier fichier SystemVerilog Top.sv destiné à contenir le code global du fpga (module Top) .
- Prenez le temps d'examiner le contenu du code du module. Les explications suivantes vous aideront à en comprendre le contenu
Les entrées/sorties du module sont les suivantes:
Nom | Type | Nombre de bits | Utilisation |
---|---|---|---|
FPGA_CLK1_50 | entrée | 1 | Horloge (à 50 Mhz) |
KEY | entrée | 2 | Boutons poussoir |
LED | sortie | 8 | Affichage LED |
SW | entrée | 4 | Interrupteurs 0/1 |
- Les entrées/sorties indiquées correspondront à de réelles entrées/sorties du FPGA.
- Le module fait appel à une PLL pour générer deux horloges auxiliaires pixel_clk (32 Mhz) et sys_clk (100MHz) à partir de l'horloge entrante à 50MHz. Ces horloges seront les seules utilisées par vos propres codes.
- Le module contient 2 interfaces Avalon de 32bits:
- L'interface avalon_if_sdram permet d'accéder à la mémoire dynamique de carte DE10_Nano
- L'interface avalon_if_stream permet de recevoir un flux vidéo depuis la partie processeur.
- Les interfaces fonctionnent avec l'horloge sys_clk et sont réinitialisées par le signal sys_rst actif à l'état haut.
- Le module Top instancie un sous-module hw_support, chargé
- de gérer les interfaces
- de gérer la connexion aux processeurs du HPS.
- de générer le signal sys_rst à partir du bouton KEY[0]
- de modifier le comportement des processeurs en fonction de l'état de SW[0].
- Enfin, comme, pour l'instant, les interfaces Avalon ne sont connectées à rien (pas d'hôte pour l'interface SDRAM, pas d'agent pour l'interface stream), nous les neutralisons en plaçant des constantes judicieuses.
1/ Première modification du code de Top.¶
L'objectif est d'utiliser les Leds de la carte pour d'une part vérifier l'action de remise à zéro (l'appuis sur le bouton poussoir KEY[0]et signalé par LED[0]) et d'autre part d'afficher un battement de coeur sur LED[1] (la carte est vivante...)
Écrivez un code dans le module (après le commentaire Code Eleves) permettant:
- de recopier la valeur du signal KEY[0] vers la led LED[0]
- de faire clignoter le signal LED[1] à 1Hz en utilisant l'horloge sys_clk. Utilisez un simple compteur binaire dont le reset est sys_rst.
2/ Premier environnement de simulation¶
Il s'agit de créer un environnement minimaliste reproduisant les conditions de fonctionnement réelles du FPGA.
Dans le répertoire SoCFPGA/tb_src, vous disposez d'un squelette de fichier SystemVerilog tb_Top.sv destiné à contenir le testbench. Il contient la définition des différents signaux externes au bloc Top, et l'instance du bloc Top proprement dite.
Complétez ce code (Code elèves) en ajoutant:
- Un premier processus générateur d'horloge à 50Mhz pour générer le signal FPGA_CLK1_50
- Un second processus simulant une action d'initialisation utilisant le bouton KEY[0]
- Le bouton KEY[0] doit valoir 1 au démarrage de la simulation
- Puis passe à 0 au bout de 128ns (valeur arbitraire)
- Puis passe à 1 au bout de 128ns (valeur arbitraire)
- Un troisième processus qui ne fait rien, mais stoppe la simulation au bout de 4ms (par exemple) à l'aide de la tâche
$stop()
Pour les générateurs d'horloge, vous pouvez vous inspirer du testbench du filtre médian median-tb.sv dans le répertoire simulation de votre projet du filtre médian:
- Vous remarquerez que l'on fait simplement une boucle qui fait avancer le temps d'une demie période d'horloge entre chaque changement du signal d'horloge.
- La valeur des unités de temps peut être indiquée, et cela peut être un nombre réel.
- Attention la précision de ce nombre dépend de la précision avec laquelle le simulateur calcule le temps. Nous avons réglé pour vous cette précision à 1ps dans le Makefile de simulation.
3/ Première simulation¶
Dans le répertoire SoCFPGA/sim, vous disposez un fichier Makefile initial que vous adapterez au fur et à mesure des différentes étapes.
Avant de lancer la simulation, prenez le temps d'une petite réflexion: Pour compter une seconde avec une horloge à 100Mhz, il faut simuler quelques millions de cycles de l'horloge, vous risquez d'attendre longtemps devant votre écran avant de voir bouger le signal LED[1] sur les chronogrammes...
Vous pouvez obtenir un comportement différent en simulation et en synthèse en paramétrant vos compteurs de façon conditionnelle:
- Nous avons défini, dans le Makefile, au moment de la compilation des sources, une variable du préprocesseur nommée SIMULATION qui peut servir à accélérer la simulation. Par exemple, si vous avez un compteur qui compte 50000000 cycles pour la version matérielle, la simulation peut se faire avec une valeur plus petite comme 50.
- Vous pouvez utiliser les commandes du préprocesseur
`ifdef, `else, `endif
pour définir des paramètres de comptage différents en fonction de la situation.
Voici un exemple (les valeurs proposées sont ici totalement arbitraires) à insérer dans votre code verilog Top.sv .
`ifdef SIMULATION
localparam hcmpt=50 ;
`else
localparam hcmpt=50000000 ;
`endif
- Adaptez votre code pour tenir compte du contexte (simulation ou synthèse)
- Compilez le code de simulation : make compile
- Executez la simulation : make simu_gui
Vérifiez "visuellement" (chronogrammes) le bon fonctionnement de votre code et de son environnement associé.
4/ Le problème du RESET et de la métastabilité¶
Avant de tester votre code sur la maquette, il nous faut ajouter un peu de code pour gérer convenablement le signal reset de la maquette:
Le bloc matériel chargé d'envoyer des données vers l'écran LCD utilisera l'horloge pixel_clk. Comme tout bloc de logique synchrone il devra disposer d'un signal de réinitialisation. Nous disposons du signal sys_rst, mais il est lié à l'horloge sys_clk. Il ne peut pas être utilisé tel quel pour réinitialiser un bloc matériel utilisant l'horloge pixel_clk. Au moment du passage en reset, il n'y a pas de problème: le système finit toujours par être réinitialisé. Par contre, lorsque le bloc matériel démarre , il peut y avoir des phénomènes de métastabilité : dans un système complexe, certaines bascules changent d'état avant d'autres ce qui peut être très dangereux pour des machines à état (passage dans un état non prévu...) La solution à ce problème est de resynchroniser la mise à zéro dans le domaine de l'horloge pixel_clk.
Le schéma suivant présente une solution classique à ce problème.
- Réinitialisation: Le signal sys_rst provoque la mise 1 asynchrone des deux bascules indépendamment de pixel_clk
- Sortie de l'initialisation: La constante 0 connectée à l'entrée de la première bascule, est transmise de manière synchrone avec l'horloge pixel_clk vers la sortie pixel_rst
- L'emploi de 2 bascules sera expliqué dans le cours sur la resynchronisation de domaines d'horloges.
Complétez le module Top:
- Introduisez un nouveau signal interne pixel_rst
- Générez le signal pixel_rst en respectant le shéma proposé.
- Ajoutez un deuxième compteur permettant de faire clignoter le signal LED[2] à 1Hz en utilisant l'horloge pixel_clk. Utilisez un simple compteur binaire dont le reset est pixel_rst.
- Vérifiez la resynchronisation ainsi que le bon fonctionnement du deuxième compteur en simulation.
5/ Premier environnement de synthèse¶
La synthèse en vue d'un téléchargement sur la maquette DE10-Nano nécessite d'une part de connaître les ressources disponibles et leurs connexions au FPGA et d'autre part de programmer les entrées/sorties d'un FPGA pour s'ajuster aux contraintes électriques et temporelles des composants extérieurs. Les outils de synthèse permettent de préciser cela à l'aide de fichiers de contrainte.
Vous disposez, dans le répertoire SoCFPGA/syn des fichiers suivants, prenez le temps de les examiner, car vous devrez adapter certains d'entre eux.
Makefile: Ce fichier permet de :
- tester la synthétisabilité de votre code : make test_syn
- lancer la synthèse et le placement/routage : make syn
- revoir les messages de l'outil de synthèse sous forme colorée : make log
- programmer le FPGA : make program
- nettoyer le répertoire de synthèse : make clean
Ce fichier n'est normalement pas à éditer. Deux variables d'environnement sont définies pour une utilisation dans les scripts de synthèse.
- PROJECT : c'est le nom du module principal (ici Top)
- PROJECT_DIR : le répertoire principal du projet.
scripts/device_assignment.tcl:
Ce script permet de sélectionner le FPGA cible pour la synthèse. Il s'agit dans notre cas de celui de la carte DE10-Nano. Il faut être précis dans la désignation du circuit pour être d'une part sûr de son brochage et de l'estimation de performances faite par l'outil de synthèse. Si le script ne contient pas les lignes suivantes, alors vous risquez de ne pouvoir programmer votre FPGA...
set_global_assignment -name FAMILY "Cyclone V"
set_global_assignment -name DEVICE 5CSEBA6U23I7
Ce script permet de définir les fichiers HDL à charger (une ligne par fichier). La syntaxe générale à utiliser est :
set_global_assignment -name langage_source chemin_vers_le_fichier
Où :
- langage_source est une des trois valeurs SYSTEMVERILOG_FILE, VERILOG_FILE, VHDL_FILE suivant le langage utilisé
- chemin_vers_le_fichier est le nom du fichier HDL à utiliser. Le chemin peut être absolu, ou relatif. Vous pouvez utiliser l'expression
$PROJECT_DIR
pour vous référer à la racine du projet.
Pour l'instant, vous n'avez pas à modifier ce fichier.
scripts/timing_constraints.sdc:
Ce script utilise une syntaxe devenue quasiment une norme de fait en CAO électronique pour définir les contraintes temporelles d'un design. Le suffixe sdc signifie "Synopsys Design Constraints" du nom de la société de CAD qui a créé cette syntaxe. Le concepteur doit fournir dans ce fichier toutes les informations temporelles susceptibles d'être une contrainte pour le design.
Pour le moment, dans notre cas la première contrainte est d'informer le synthétiseur de l'existence d'un domaine d'horloge liée à l'horloge entrante FPGA_CLK1_50 ayant une fréquence de 50Mhz. Puis une ligne indique au synthétiseur d'examiner les PLL du design pour en déduire la fréquence des horloges internes générées. Enfin nous demandons au synthétiseur de tenir compte des caractéristiques des PLL pour estimer l'incertitude sur les périodes des horloges.
scripts/pins_assignment.tcl:
Ce script permet de définir les entrées/sorties du FPGA. Prenez le temps de lire les nombreux commentaires de ce fichier qui expliquent les différents choix faits pour adapter convenablement les signaux entrant et sortant du FPGA aux caractéristiques des circuits externes.
A vous de jouer
- Vous trouverez, dans le répertoire docs, la documentation technique de la carte DE10-Nano
- Pour chacune des entrées/sorties de votre module (horloge à 50 Mhz, bouton poussoir, interrupteur, leds) déterminez un élément extérieur au FPGA susceptible d'être utilisé en vous aidant du tableau ci-dessous.
Nom de la pin | Ressource pouvant être utilisée |
---|---|
FPGA_CLK1_50 | voir chapitre 3.5 Clock Circuitry |
KEY | voir chapitre 3.6.1 User Push-buttons, Switches and LEDS |
SW | voir chapitre 3.6.1 User Push-buttons, Switches and LEDS |
LED | voir chapitre 3.6.1 User Push-buttons, Switches and LEDS |
- Pour chacun de ces éléments, déterminez la patte du fpga qui est connectée.
- Complétez le fichier
pins_assignments.tcl
sans oublier de définir le standard "électrique" de la connexion voulue
La syntaxe générale à utiliser est :
set_location_assignment PIN_xxx -to yyy
Où xxx est le numéro de la patte choisie, et yyy est le nom du signal dans votre module Top.
Enfin pour chacune des entrées/sorties, il convient de définir le standard électrique retenu pour communiquer avec les circuits externes. Dans notre cas nous utilisons une excursion de tension de 3.3V.
- Pour chacune des entrées sorties que vous avez défini, ajouter la propriété suivante:
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to yyy
Où yyy est le nom du signal dans votre module Top.
6/ Première synthèse¶
Après avoir complété vos fichiers, placez-vous dans le répertoire SocFPGA/syn et lancez un premier test de synthétisabilité (make test_syn). Les messages apparaissant à la console sont colorés:
- en vert pour les informations
- en bleu pour les warnings
-
en rouge pour les erreurs.
-
Vous pouvez utiliser make log pour revoir les messages: n'examinez que les messages concernant votre propre code
- Corrigez les éventuelles erreurs et relancer le test jusqu'à leur disparition.
- Puis lancer la synthèse proprement dite : make syn
- Cela dure quelques minutes...
7/ Test sur la maquette¶
EN PRESENTIEL
La maquette DE10-Nano étant connectée au PC par le câble USB (port USB-Blaster):
- Executez la commande make program pour charger le fpga. Une led orange doit s'allumer pour indiquer le bon chargement du FPGA EN DISTANCIEL
EN DISTANCIEL
Suivez les directives de l'annexe "Programmation de la carte DE10-Nano depuis votre PC personnel" pour installer l'outil de programmation quartus_pgm.
La maquette DE10-Nano étant connectée à votre PC par le câble USB (port USB-Blaster):
- Rapatriez sur votre poste personnel le fichier Top.sof se trouvant dans le répertoire SocFPGA/syn/output_files
- Suivez les mêmes directives pour programmer votre FPGA avec le fichier récupéré.
Vérifiez le fonctionnement du design, et entre autres
- Que LED[0] reproduit l'état de la clef KEY[0]
- Que la LED[1] clignote à 1Hz et s'arrète de clignoter si on appuye sur le bouton KEY[0]
- Que la LED[2] clignote à 1Hz et s'arrète de clignoter si on appuye sur le bouton KEY[0]
Conclusion¶
Vous disposez d'un squelette permettant de développer votre projet:
- Conservez tout au long du projet les LEDs clignotantes qui permettent de savoir que votre design est actif.
- De même, conservez le dispositif permettant de générer un reset "propre".
- Les messages du synthétiseur sont nombreux. Dans les prochains travaux, vous devrez évidemment éliminer les Erreurs, mais aussi examiner soigneusement les Warnings et déterminer s'ils correspondent à un problème potentiel ou non. Dans la mesure du possible, tentez d'éliminer ces Warnings de façon à détecter plus facilement de nouveau problèmes au fur et a mesure que vous faites évoluer le code.
- Vous pouvez à tout moment utiliser la version graphique de l'outil Quartus pour examiner les résultats de synthèse. Pour cela il vous suffit d'ouvrir le projet créé dans l'outil. Faites cependant attention, si vous modifiez votre projet dans l'outil, vous ne retrouverez pas ces modifications dans vos scripts, et ainsi vous ne pourrez plus utiliser le Makefile pour recompiler votre projet.
N'OUBLIEZ PAS
TAG GIT pour cette ETAPE : SQUELETTE