Russell Merrick est un ingénieur en électronique qui travail sur des FPGA depuis plus de 15 ans. C’est l’auteur du site internet Nandland qui propose toute une série de tutoriels pour débuter et s’amuser avec des FPGA.
Russell vient de sortir un livre chez No Starch Press pour débuter avec un FPGA.
En seulement 280 pages, on peut dire que l’auteur couvre bien le sujet. Les deux langages HDL du «marché» sont décrits et tous les exemples sont donnés en Verilog ainsi qu’en VHDL.
C’est la première fois que, dans un livre, je vois un vrai comparatif des deux HDL. En effet, l’un est souvent balayé au profit de l’autre avec un «si vous connaissez l’un vous saurez vous servir de l’autre». Même si l’accent est mis sur le ICE40 de Lattice (Célèbre FPGA lowcost reversé dans le projet icestorm), on sent bien qu’il existe d’autres constructeurs et que l’auteur a travaillé avec.
Le livre n’est pas si gros et pourtant il traite vraiment de tout ce qu’il faut savoir pour bien commencer (et avancer) dans le FPGA.
Un chapitre entier est consacré aux bascule D (FlipFlop) et à la problématique de conception synchrone. La notion de domaines d’horloge et son franchissement, les machines d’états, les macro classique (RAM, PLL, DSP) ne sont pas en reste.
Et avant d’aborder les entrées sorties (I/O, LVDS, SerDes) un chapitre particulièrement intéressant sur l’arithmétique est abordé. Tout est dit pour additionner, soustraire, multiplier et diviser (enfin surtout les méthodes de contournement de la division) des entiers mais également des nombres en virgules fixe (Qn.m) dans un FPGA.
C’est un livre que j’aurais adoré avoir pour débuter en FPGA, mais qui fera tout de même un très bon livre de référence au besoin.
Nous avons déjà parlé du Gatemate dans les colonnes du FLF. Mais jusqu’à présent, seul le kit de développement officiel de CologneChip était disponible. Le tarif du kit officiel étant assez élevé on attendait avec impatience d’avoir des cartes développées par des tiers pour pouvoir investir.
Ce qui est chose faite avec les kits suivant. La note reste éditable au grès des sorties de kit muni du FPGA.
Evaluation board officielle par CologneChip
À tout seigneur tout honneur, citons d’abord du kit officiel qui est proposé à un prix de 226€ sur digikey.
Olimex GateMate-A1
Annoncé en décembre 2023 par Olimex, le kit GateMateA1 devrait être proposé au tarif de 50€.
TrenzMicro TEG2000-01-P001
Le SoM de TrenzMicro TEG2000-01-P001 est dans les même ordre de grandeur au niveau tarif (69€) mais nécessitera une carte d’accueil pour s’en servir.
La désormais célèbre société chinoise Sipeed vient de sortir un tout petit kit de développement autour d’un FPGA Gowin et muni d’une sortie HDMI ainsi que d’une entrée caméra : la Tang Nano 4K.
Et non, elle n’est pas compatible avec des écrans HDMI 4K 😉 Le nom marketing bien choisi désigne le nombre de LUT disponibles.
Il est encore difficile de trouver des informations techniques sur cette carte, pourtant disponible (et rapidement livrée) sur aliexpress. Le wiki officiel est encore intégralement en chinois, mais on trouve le code d’exemple sur github. Le schéma de la carte est dispo sur le site de sipeed ici (ou sur le blog du flf si le firewall chinois fait des caprices 😉
À 18$ il n’était pas question de passer à coté, j’ai donc commandé une version avec caméra OV2640 ainsi qu’une version sans caméra :
Le tout pour une quarantaine d’€.
Branchement
Un câble USB-C est fourni dans la boite, voyons ce qu’il se passe au branchement de la version sans caméra:
sudo dmesg -c
[34644.177355] usb 1-2.1.1: new full-speed USB device number 14 using xhci_hcd
[34644.283502] usb 1-2.1.1: not running at top speed; connect to a high speed hub
[34644.305274] usb 1-2.1.1: New USB device found, idVendor=0403, idProduct=6010, bcdDevice= 5.00
[34644.305288] usb 1-2.1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[34644.305292] usb 1-2.1.1: Product: JTAG Debugger
[34644.305295] usb 1-2.1.1: Manufacturer: SIPEED
[34644.305298] usb 1-2.1.1: SerialNumber: FactoryAIOT Pro
[34644.311295] ftdi_sio 1-2.1.1:1.0: FTDI USB Serial Device converter detected
[34644.311336] usb 1-2.1.1: Detected FT2232C
[34644.316362] usb 1-2.1.1: FTDI USB Serial Device converter now attached to ttyUSB0
[34644.316513] ftdi_sio 1-2.1.1:1.1: FTDI USB Serial Device converter detected
[34644.316548] usb 1-2.1.1: Detected FT2232C
[34644.322352] usb 1-2.1.1: FTDI USB Serial Device converter now attached to ttyUSB1
La version avec caméra donne exactement la même chose.
Le dmesg de Linux laisse apparaître deux interfaces tty. L’une est certainement un convertisseur jtag pour configurer le FPGA et l’autre une interface uart permettant de communiquer avec l’application comme on a pu le voir avec la Tang Nano «classique».
Si l’on branche un écran au HDMI on voit défiler quelques «pattern» avant de s’arrêter sur un écran vert sur fond bleu.
Pour le moment je n’ai pas réussi à obtenir grand chose de ces deux uarts.
Par la suite j’éditerais cet article pour vous parler de la configuration du FPGA.
Synthèse et configuration
Le plus simple pour commencer avec le kit est d’aller voir les deux projets proposés par Sipeed sur github et de les cloner.
$ git clone https://github.com/sipeed/TangNano-4K-example.git
$ cd TangNano-4K-example/
Deux projets sont disponible dans ce dépôt, vus de loin l’un est pour faire clignoter une led et l’autre pour l’exemple HDMI programmé par défaut dans l’eeprom du kit :
$ ls
dk_video/ led_test/
Pour se faire la main il est donc naturel de commencer par la led.
Il faut d’abord lancer l’IDE officiel de gowin, comme décrit dans l’article de hackable-32 (le plus compliqué avec l’installation de gowin est d’obtenir la licence, après ça roule). Puis ouvrir le fichier de projet fourni nommé project/led_test.gprj et se trouvant dans le répertoire led_test/projet.
Le FPGA du kit se nomme GW1NSR-LV4CQN48PC7/I6 et le code Verilog de clignotement est le suivant. Quand au pinout le voici au format «cst» ci-dessous :
Le projet est déjà synthétisé, si on souhaite le relancer il suffit de faire un clic-droit «rerun» sur «Synthesize» . Le bitstream est généré au format «fs» et se nomme project/impl/pnr/led_test.fs.
$ openFPGALoader --detect
write to ram
Jtag frequency : requested 6.00MHz -> real 6.00MHz
index 0:
idcode 0x100981b
manufacturer Gowin
family GW1NSR
model GW1NSR-4C
irlength 8
Il suffit donc de programmer le bistrteam (format fs) au moyen de la commande :
$ openFPGALoader led_test/project/impl/pnr/led_test.fs
write to ram
Jtag frequency : requested 6.00MHz -> real 6.00MHz
Parse file Parse led_test/project/impl/pnr/led_test.fs:
Done
DONE
Jtag frequency : requested 2.50MHz -> real 2.00MHz
erase SRAM Done
Flash SRAM: [==================================================] 100.00%
Done
SRAM Flash: Success
Et pour l’écrire dans l’eeprom il suffit d’ajouter l’option -f:
$ openFPGALoader ide/gbhdmi/impl/pnr/gbhdmi.fs -f
write to flash
Jtag frequency : requested 6.00MHz -> real 6.00MHz
Parse file Parse ide/gbhdmi/impl/pnr/gbhdmi.fs:
Done
DONE
Jtag frequency : requested 2.50MHz -> real 2.00MHz
erase SRAM Done
erase Flash Done
write Flash: [==================================================] 100.00%
Done
CRC check: Success
Le truc se programme et la led clignote.
Le HDMI
Le deuxième projet proposé dans le dépôt concerne le HDMI. Bon si on regarde le contenu du Top on se rend compte qu’il fait bien plus que le simple HDMI puisqu’il pilote également la ram, la Nor et la caméra.
Le générateur de pattern se charge également de générer les signaux de synchronisation vidéo. Mais ce qui nous intéresse particulièrement c’est le bloc qui pilote le HDMI. Ce bloc se prénomme DVI_TX_top et … il est encrypté 🙁
Le bloc est tout de même instanciable au moyen d’une BlackBox chisel. Ce qui permet d’adapter le projet GbVGA en GbHDMI
Pour la vidéo du montage en fonctionnement c’est par là.
La caméra OV2640
Je n’ai pas vu d’exemple de code utilisant la caméra ov2640 avec ce kit pour le moment. Il est probable que ça ne soit pas encore disponible.
Ais-je bien téléchargé la dernière version de mon gateware dans ce montage ?
C’est un problème classique quand on fait de l’embarqué, entre l’éditeur de code, la génération du code bas niveau (Verilog dans le cas de Chisel) le logiciel de synthèse/placement-routage et le téléchargement du bitstream, il y a plein de façon de se tromper de version du logiciel s’exécutant réellement dans le montage. Et l’on peu passer des heures à chercher un bug dans son système en modifiant des lignes de code alors que le problème vient d’une même (vieille) version téléchargée éternellement.
Pour s’assurer que le gateware qui se trouve dans le FPGA soit bien le dernier généré il faut trouver une manière d’y enregistrer une valeur qui sera différente à chaque fois.
On pourrait mettre une version «en dur» dans nos sources, mais l’expérience montre que l’on oublie 4 fois sur 5 de l’incrémenter avant de générer le fichier. Toute bonne développeuse et tout bon développeur versionne son projet avec un gestionnaire de version. On pourrait du coup mettre le numéro de commit. Sauf que l’on ne commit pas toujours la modification avant de la tester.
Une autre astuce consiste à mettre la date EPOCH. De cette manière nous avons la date et l’heure précise de la synthèse du gateware. Cette solution est intéressante mais elle pose rapidement un problème d’occupation du FPGA. En effet, le temps en secondes filant assez rapidement nous avons besoin de registres de 32 bits minimum voir même 64bits. Ce qui est plutôt inutile pour compter les builds …
Compter les builds ?
La voila la solution toute simple, il suffit d’enregistrer un compteur dans un fichier texte. À chaque build, une fonction vient lire la valeur et l’incrémente. Pour rester à jour il nous suffit ensuite de versionner ce fichier avec le reste du code. Même si le nombre de build est grand, on n’aura rarement besoin d’en faire plus de quelques millier, ce qui rentrera très bien dans un registre de 16 bits voir moins.
Voici comment faire en Scala avec Chisel.
Dans un package avec les utilitaires «personnel» :
package myutil
On importe les packages d’entrées sorties pour lire/écrire dans les fichiers textes:
// Pour fromFile()
import scala.io.Source
// Pour PrintWriter()
import java.io._
Puis on crée une fonction de lecture écriture dans un objet personnel MyUtility :
def genCountVers(className: String = null): Option[Int] = {
if(className == null){
return None
}
println("generate counter for class " + className)
val filename = "src/main/scala/util/gen_count_vers.txt"
val versmap = scala.collection.mutable.Map[String,Int]()
/* read file to hashmap*/
val fp = Source.fromFile(filename)
for(v <- fp.getLines.map(_.split(",").map(_.trim))){
versmap(v(0)) = v(1).toInt
}
fp.close()
/* get and increment version */
val version = versmap.get(className)
if(version == None){
versmap(className) = 0
} else {
versmap(className) = version.get.toInt + 1
}
/* write back file*/
val fpw = new PrintWriter(new File(filename))
for ((hname, hvalue) <- versmap) {
fpw.write(hname + "," + hvalue + "\n")
}
fpw.close()
/* return version */
version match {
case Some(s) => Some(s.toInt + 1)
case None => Some(0)
}
}
La fonction genCountVers() va ouvrir le fichier texte gen_count_vers.txt, qui est un «CSV» composé du nom de classes et d’un numéro. Si le nom de la classe passé en paramètre n’existe pas la fonction va l’ajouter avec un compteur à zero.
Nous n’avons plus qu’a appeler la fonction genCounterVers() avec le nom de la classe (ou autre) de notre choix pour la fourrer dans un registre lisible via notre interface (spi, wisbone, i2c, jtag, …) directement sur le FPGA :
val buildnum = MyUtility.genCounterVers("MyTopClasse").get
Comme j’en parlais sur LinuxFR, la société QuickLogic propose un kit de développement avec son microcontrôleur EOS S3. Micro qui a la prétention de n’utiliser que des logiciels libre pour son développement.
Réception
Le site web indiquait des «précommande». Je ne m’attendais donc pas à recevoir l’objet en moins d’une semaine, et sans frais de douanes !
Le kit tient dans le creux de la main
Bref, si vous arrivez a trouver quelques amis pour faire une commande groupée (les frais de port pour la France sont plus cher que le kit lui même : $58 pour un kit à $49), n’hésitez pas ! Ça arrivera vite.
Branchement
Au branchement sur l’usb-mini du kit, la led RGB s’allume à fond puis s’éteint progressivement en moins d’une seconde. Et … rien sur les messages kernel.
Il va falloir regarder tout ça de plus près et aller lire la doc. Le code source des exemples est dispo sur un github.
Clignotage de LED
QuickLogic vient de faire une vidéo basique pour donner quelques trucs de mise en route.
Pour que le port série soit détecté dans le kernel il faut notamment appuyer sur le bouton reset. La led bleue va clignoter 5 secondes. Il faudra attendre à nouveau 5 seconde et le port /dev/ttyACM0 apparaîtra dans le dmesg :
[juin30 13:25] usb 3-3.1.2: new full-speed USB device number 17 using xhci_hcd
[ +0,100996] usb 3-3.1.2: New USB device found, idVendor=1d50, idProduct=6140
[ +0,000005] usb 3-3.1.2: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ +0,000575] cdc_acm 3-3.1.2:1.0: ttyACM0: USB ACM device
On peut ensuite simplement s’y connecter avec screen pour récupérer une invite de commande sur le micro :
$ screen /dev/ttyACM0 115200
####################
Quicklogic QuickFeather LED / User Button Test
SW Version: qorc-sdk/qf_apps/qf_helloworldsw
Jun 7 2020 12:04:51
##########################
Hello world!!
#*******************
Command Line Interface
App SW Version: qorc-sdk/qf_apps/qf_helloworldsw
#*******************
[0] >
De la on peut piloter les trois LED et lire le bouton, pour cela il suffit de se mettre en mode diagnostique:
[0] > red
ERROR: no such command: red
[0] > help
help-path: (top)
diag - QuickFeather diagnostic commands
exit - exit/leave menu
help - show help
? - show help
help-end:
[0] > diag
[1] diag > exit
[0] > help
help-path: (top)
diag - QuickFeather diagnostic commands
exit - exit/leave menu
help - show help
? - show help
help-end:
[0] > diag
[1] diag > help
help-path: diag
red - toggle red led
green - toggle green led
blue - toggle blue led
userbutton - show state of user button
exit - exit/leave menu
help - show help
? - show help
help-end:
[1] diag > red
[1] diag > blue
[1] diag > red
[1] diag > green
[1] diag > blue
[1] diag > userbutton
Not pressed
[1] diag > userbutton
Pressed
[1] diag >
Arrow propose un kit de développement nommé AnalogMax pour 80$ environ. L’entreprise qui fabrique la carte est Trenz Electronic qui réalise également le kit gowin.
Cette fois la carte est arrivée par lettre, et non par gros colis.
Le FPGA est relativement gros et la carte possède un certain nombre de périphérique analogiques sympathique comme un détecteur de fumée, un capteur de température, quelque canaux ADC et DAC ainsi que des GPIO.
Au branchement du kit sur l’usb on a juste la led verte allumée. L’appuie sur le bouton à droite allume une des huit leds de la rangée, et l’appui sur l’autre bouton allume l’autre led rouge et inscrit un message sur l’uart (115200):
Arrivée dans un énorme carton, la carte électronique se trouve dans le tout petit «tube» blanc.
Je viens donc de recevoir ma carte petite abeille (littlebee) munie d’un FPGA du chinois GOWIN.
La carte «LittleBee» munie d’un FPGA de chez Gowin
La carte produite et vendue par la société allemande Trenz Electronic permet de se faire la main avec le composant pour moins de 40€ (un peu plus avec les frais de ports UPS …).
Branchement
Au branchement à la sortie du carton les huit leds rouge s’allument ainsi qu’une led verte que je suppose de «power».
Les messages noyau nous donnent deux ports séries ttyUSBx :
$ dmesg [630417.919258] usb 3-1: new high-speed USB device number 35 using xhci_hcd [630418.059577] usb 3-1: New USB device found, idVendor=0403, idProduct=6010 [630418.059581] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 [630418.059583] usb 3-1: Product: Dual RS232-HS [630418.059584] usb 3-1: Manufacturer: FTDI [630418.060116] ftdi_sio 3-1:1.0: FTDI USB Serial Device converter detected [630418.060155] usb 3-1: Detected FT2232H [630418.060352] usb 3-1: FTDI USB Serial Device converter now attached to ttyUSB0 [630418.060499] ftdi_sio 3-1:1.1: FTDI USB Serial Device converter detected [630418.060528] usb 3-1: Detected FT2232H [630418.060648] usb 3-1: FTDI USB Serial Device converter now attached to ttyUSB1
Si on se connecte au port série ttyUSB1 on obtient un affichage de la résolution du problème des philosophes.
Philosopher 0 [P: 3] THINKING [ 750 ms ] Philosopher 1 [P: 2] HOLDING ONE FORK Philosopher 2 [P: 1] EATING [ 450 ms ] Philosopher 3 [P: 0] STARVING nabled Philosopher 4 [C:-1] HOLDING ONE FORK get back, Philosopher 5 [C:-2] EATING [ 375 ms ]
Il est probable que nous ayons ici un RISC-V dans le tiroir.
La connexion d’un terminal sur le port ttyUSB0 ne donne rien par contre.
IDE
Voila pour le déballage, maintenant il va falloir installer les outils pour faire clignoter ces leds !
FireAnt est un kit de développement «de la taille d’un pouce» concu par la société Xips Technology et permettant de se faire la main sur le FPGA Trion T8 de la société Efinix.
Et bien sûr un LDO pour l’alimentation 3v3 à partir de l’USB
Efinix est une toute nouvelle société qui propose des petits FPGA gravés en 40nm. Pour les tout petits FPGA de leur gamme, la société propose ce qu’elle appelle un MPM pour «Mask Programmable Memory» -> la possibilité de figer le design en usine et de ne plus avoir à configurer le FPGA à chaque démarrage.
Un IDE permettant de faire la synthèse, le placement-routage et le bitstream est fourni «gratuitement». À condition de posséder un kit de développement (J’ai beau négocier, ils ne veulent pas me le donner tant que je n’aurais pas reçu le kit 😉 ).
Bref, il n’est pas encore question d’outils libres pour ces FPGA pour l’instant. Cependant, ça fait du bien de voir de nouveaux acteurs dans le domaine des FPGA «physique».