Étape 1: Un squelette de projet

ATTENTION : TAG GIT pour cette ETAPE : "SQUELETTE" 

0) 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.

1) 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 master
  • git remote add controleur_video git@gitlab.enst.fr:se204/controleur_video.git
  • git remote update
  • git merge --allow-unrelated-histories controleur_video/master

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"
  • Revenez à la lecture du sujet...

2) 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 le quel se trouvent les scripts de synthèse et dans lequel se déroule la synthèse.
  • Le nom des fichiers créés devra être 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.

3) 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) . 

  • Examinez le contenu du code du module et lisez les explications suivantes pour 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   Wishbone de 32bits:
    • L'interface wshb_if_sdram permettra d'accéder à la mémoidre dynamique de carte DE10_Nano
    • L'interface wshb_if_stream permettra 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 instancie un sous-module hw_support, chargé
    • de gérer les interfaces
    • de gérer la connection au processeurs
    • 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 les interfaces Wishbone ne sont connectées à rien, (pas de maître pour l'interface SDRAM, pas d'esclave pour l'interface stream), nous les neutralisons en plaçant des constantes judicieuses.

4) Première modification du code de Top.

 É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.

5) 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 dit.

Complétez ce code (Code elèves) en ajoutant:

  • Un processus générateur d'horloge à 50Mhz pour générer le signal FPGA_CLK1_50
  • Un 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 passer à "0" au bout de 128ns (valeur arbitraire)
    • Puis passer à "1" au bout de 128ns (valeur arbitraire)
  • Un 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 median. Vous remarquerez que l'on fait simplement une boucle qui fait avancer le temps d'une demi 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.

6) 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].

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, 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/synthèse)
  • Compilez le code de simulation : make compile
  • Executez la simulation : make simu_gui

Vérifiez "visuellement" (chronogrammes) le bon fonctionnement de votre "fpga" et de son environnement associé.

7) Mise en place du mécanisme de rééinitialisation dans le domaine d'horloge pixel_clk:  Le problème du RESET et de la métastabilité.

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, que le signal soit utilisé comme reset synchrone ou asynchrone : 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...)

Le schéma suivant se propose de résoudre ce problème d'une façon similaire à celle étudiée pour les changements de domaine d'horloge.

 

 

  • Initialisation : Le passage à "1" du signal sys_rst  provoque la mise à "1" immédiate des deux bascules. 
  • Sortie de l'initialisation : Après le passage à "0" de sys_rst la constante "0" en entrée des bascules est échantillonnée 2 fois pour fournir un signal pixel_rst à "0" en synchronisme avec l'horloge pixel_clk.

A VOUS DE JOUER:

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.

8) Premier environnement de synthèse 

La synthèse en vue d'un téléchargement sur la maquette DE10-Nano nécessite de connaître les ressources disponibles et leurs connexions au FPGA. D'autre part, les entrées/sorties d'un FPGA peuvent être programmées pour s'ajuster aux contraintes éléctriques 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   : make syn
  • revoir les messages de l'outil de synthèse sous forme colorée : make log
  • programmation du 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

scripts/project_list.tcl:

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

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.

9) 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, et en rouge pour les erreurs.   

  • Corrigez les éventuelles erreurs et relancer le test jusqu'à leur disparition.
  • Puis lancer la synthèse proprement dite : make syn
  • Cela dure 7 à 8 minutes...
  • Vérifiez les messages de Warning.
  • Ils sont nombreux, et ne concernent pas forcément le code que vous avez écrit. 
  • Ne vérifiez que ceux qui semblent concerner ce que vous avez écrit 

10) Test sur maquette

EN PRESENTIEL

La maquette DE10-Nano étant connectée au PC par le câble USB (port USB-Blaster)

  • tapez la commande make program pour charger le fpga. Une led orange doit s'allumer pour indiquer le bon chargement du FPGA

EN DISTANCIEL

La maquette DE10-Nano étant connectée au 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 directives de l'annexe "Programmation de la carte DE10-Nano depuis votre PC personnel" pour installer l'outil de programmation quartus_pgm
  • 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]

11) CONCLUSION

 Vous disposez d'un squelette permettant de développer votre projet: 

  1. Conservez tout au long du projet les LEDs clignotantes qui permettent de savoir que votre design est actif. 
  2. Conservez de même le dispositif permettant de générer un reset "propre". 
  3. 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.
  4. 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"