Comment indiquer la version de son projet dans le bitstream vivado ?

En règle générale on aime bien avoir la version du firmware générée sur lequel tourne notre FPGA. Cependant, pour intégrer une date de compile, une version de logiciel ou autre dans un bitstream, cela ne se fait pas très simplement.

L’exemple ici est certainement quick&dirty, mais c’est une solution possible pour résoudre ce problème. Le système est conçu via le «blocs designer» de vivado et contient un microblaze.

Pour pouvoir ajouter des «registres» spécifiques sans avoir à coder en HDL on intégrera un bloc de ROM nommé «Distributed Memory Generator». Pour intégrer ce bloc dans l’espace mémoire du Microblaze on ajoutera un contrôleur de ram AXI comme le montre la saisie d’écran ci-dessous:

Ce bloc peut être configuré via un fichier texte avec l’extension «.coe» qui contiendra les valeurs.


memory_initialization_radix=10;
memory_initialization_vector=1562 1490616824 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;

La variable memory_initialization indique la base (ici du décimal) des valeurs données dans le vecteur memory_initialization_vector. Dans cet exemple, trois valeurs sont données : la période de l’horloge du contrôleur de DDR, la date en secondes unix et la version.

Plutôt que d’avoir à modifier notre fichier *.coe à chaque synthèse, nous allons écrire un script tcl qui sera appelé automatiquement par vivado à chaque synthèse/placement-routage. Le TCL est un langage de script que beaucoup de logiciels d’électronique sont capable d’éxecuter, c’est le cas de vivado (tcl version 8.5).

Le répertoire du projet est donné par la commande tcl :


set current_project_dir [get_property DIRECTORY [current_project]]

On peut l’afficher au besoin dans la console «Messages» de vivado avec puts :


puts $current_project_dir

période du contrôleur de DDR

L’idée ici est d’aller chercher l’information dans le fichier datasheet.txt généré par le fucking MIG. La méthode Quick&Dirty pour récupérer l’info dans le fichier est de découper le texte à coup de split et de lindex pour se focaliser sur la «Design Clock Frequency».

...
/*******************************************************/
/*                  Controller 0                       */
/*******************************************************/
Controller Options :
   Memory                        : DDR3_SDRAM
   Interface                     : AXI
   Design Clock Frequency        : 1562 ps (  0.00 MHz)
   Phy to Controller Clock Ratio : 4:1
   Input Clock Period            : 5077 ps
   CLKFBOUT_MULT (PLL)           : 13
   DIVCLK_DIVIDE (PLL)           : 2
   VCC_AUX IO                    : 1.8V
   Memory Type                   : Components
   Memory Part                   : MT41K1G8SN-125
   Equivalent Part(s)            : --
   Data Width                    : 8
   ECC                           : Disabled
   Data Mask                     : enabled
   ORDERING                      : Normal
...

La période est ainsi stockée dans la variable $period :


# Get DDR period
set fp [open "$current_project_dir/../../../projet.srcs/sources_1/bd/ {...} /datasheet.txt"]
set filedata [read $fp]
set data [split $filedata "\n"]
foreach line $data {
	if {[regexp {Design} $line]} {
		set period [expr [lindex [split [lindex [split $line ":"] 1] "ps"] 0]]
	} 
}

version

Pour la version c’est à nous de définir un «generic» dans le projet avec le nom que nous voulons (par exemple ProjectVersion). Ce generic se définit dans le menu setting du projet, pour cette exemple il sera défini à ‘1’, quelle originalité !

Ce generic se retrouve ensuite dans le fichier xml du projet au format *.xpr. De la même manière que pour la period du contrôleur de DDR, nous allons lire ce fichier au moyen d’une savante boucle de découpage split et lindex:


set fp [open "$current_project_dir/../../project.xpr"]
set filedata [read $fp]
set data [split $filedata "\n"]
foreach line $data {
	if {[regexp {ProjectVersion} $line]} {
		set ProjectVersion [lindex [split [string trim $line] "\""] 3]
	} 
}

date

Pour la date c’est beaucoup plus simple puisqu’il existe une commande tcl (>=8.5) qui nous donne les «seconds unix» : clock seconds.


set thetime [clock seconds]

Enregistrement du fichier coe

Il suffit pour cela d’ouvrir en écriture le pathname que nous désinons écrire puis ajouter les valeurs avec puts :


# Write coe file for rom
set wfp [open "$current_project_dir/../../../../rom_version.coe" w]
puts $wfp "memory_initialization_radix=10;"
puts $wfp "memory_initialization_vector=$period $thetime $ProjectVersion 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;"

Ajout du crochet (hook)

Pour que notre script tcl soit appelé automatiquement par vivado il faut le définir comme un «hook» de pre-synthèse. Pour cela il faut se rendre dans le menu de configuration de la synthèse:

Puis sélectionner notre script name.tcl dans l’option tcl.pre (pour pre-synthèse).

Le script sera exécuté dans le répertoire :

project/project.runs/run_name/

Il suffit maintenant de lancer la synthèse pour que notre «hook» soit lancé avant la synthèse et remplisse correctement la rom de paramètres de notre design.

Ce contenu a été publié dans informatique, avec comme mot(s)-clé(s) , , , . Vous pouvez le mettre en favoris avec ce permalien.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *