Il existe enfin une vraie solution open source complète pour synthétiser un design sur FPGA. Cette solution est basée sur le logiciel de synthèse Verilog Yosys ainsi que le logiciel de placement routage Arachne-pnr et cible le FPGA iCE40 de Lattice.
Le monde du FPGA est un univers terrible pour un libriste. Si de nombreuses solutions open source existent désormais pour la simulation HDL, ce n'est pas du tout le cas pour la synthèse, le placement routage et la génération du bitstream (fichier de configuration du FPGA). Il existe bien quelques outils universitaires, mais ils ciblent généralement des modèles virtuels de FPGA. Ainsi, l'utilisation des outils constructeurs est un passage obligé si l'on veut développer sur les composants de chez Xilinx, Altera ou autres. Ces outils sont nécessairement restrictifs, car ils ne peuvent être améliorés par la communauté, ne fonctionnent que sur des plateformes x86 quand on a la chance d'avoir des binaires fournis pour Linux et dépendent du bon vouloir du constructeur pour la maintenance de chaque fonctionnalité. Mais grâce au projet icestorm, il est maintenant possible de générer un bitstream à partir d'un code Verilog le tout intégralement avec des outils open source.
Dans cet article, nous allons voir les différentes étapes pour transformer un code Verilog en un bitstream permettant de configurer le FPGA iCE40 intégré au kit de développement icestick.
Un langage HDL, pour Hardware Description Language, est un langage permettant de décrire un composant numérique matériel. VHDL et Verilog sont les deux langages HDL les plus connus et sont supportés par la totalité des outils fournis par les constructeurs de FPGA.
Beaucoup de nouveaux projets de langage HDL émergent aujourd'hui, tous sont des extensions (bibliothèque/module) de langages de programmation existants : MyHDL (Python), Migen (Python), Chisel (Scala), Clash (Haskell). Ils permettent généralement de générer un projet « synthétisable » en Verilog et/ou en VHDL. VHDL/Verilog peuvent ainsi être comparés aux langages assembleurs des microprocesseurs.
1. Le kit iCEstick
Le iCEstick est un simple kit de développement proposé par Lattice pour se familiariser avec les FPGA iCE40. Ce kit est la preuve qu'il n'est pas nécessaire de casser son PEL pour acquérir le matériel pour débuter dans les FPGA puisqu'il ne coûte qu'une vingtaine d'euros.
Il se présente sous la forme d'une clef USB permettant à la fois d'alimenter le kit et de communiquer avec. La communication se fait via un convertisseur usb-série/fifo classique de chez FTDI.
Fig. 1 : Le kit de développement iCEstick (source : datasheet « iCEstick Evaluation Kit – User's Guide » page 2).
Malgré le prix, les performances du FPGA iCE40HX1K intégré au kit sont tout à fait raisonnables :
- 1280 cellules logiques ;
- 64Kbits de RAM embarqué ;
- 1 PLL ;
- 95 I/O dont 11 pouvant être utilisés en I/O différentielles.
Des performances suffisantes pour envisager de faire des bus électroniques simples comme du SPI, I²C ou de l'UART. Le kit possédant un émetteur/récepteur infrarouge, il est tout à fait possible d'implémenter des protocoles classiques de télécommande ou autres.
2. Le projet icestorm
Après avoir développé l’outil de synthèse Verilog Yosys pour sa thèse, Wolf Clifford a cherché une plate-forme FPGA suffisamment simple et peu chère pour en faire l'ingénierie inverse. Le kit de développement IceStick correspondait parfaitement à tous ces critères.
Cependant, même si le ice40 est relativement bien documenté dans la description de son architecture, comme tous les constructeurs, Lattice ne documente pas le format de son bitstream.
Le bitstream est le nom que l'on donne au fichier permettant de configurer le FPGA. La mémoire de configuration d'un FPGA étant volatile, il faut le recharger à chaque démarrage de la carte. Ce qui impose de stocker ce bitstream dans un composant externe au FPGA (souvent une eeprom) qui se chargera de le transférer à chaque redémarrage.
Ce transfert du bitstream entre deux composants sur la carte électronique pose un gros problème aux industriels. En effet, il est assez facile de brancher une sonde sur le bus de communication pour le récupérer, et ainsi pouvoir dupliquer la propriété industrielle. L'une des raisons pour lesquelles les constructeurs ne fournissent pas la description du format de ce bitstream est d'éviter que l'on puisse revenir au design original à partir de ce fichier ...
Le projet Icestorm a donc été lancé pour développer les outils permettant, dans un premier temps, de faire l'ingénierie inverse du bitstream. Puis une fois que le bitstream fut suffisamment documenté, les outils permettant de le générer ont été intégrés au projet.
Le projet est maintenant suffisamment mature pour être utilisé comme chaîne de développement FPGA. Et il permet de réaliser quelques projets simples comme nous allons le voir.
3. Chaîne de développement
La chaîne de développement se compose de trois parties principales :
- la synthèse avec Yosys ;
- le placement routage avec Arachne-pnr ;
- la génération du bitstream avec icepack.
Une quatrième étape consistant à télécharger le bitstream dans le FPGA est spécifique à la plate-forme sur laquelle est soudé le ice40. Dans le cas du iCEstick, la configuration du FPGA se fait via une eeprom sur SPI au démarrage de la carte. L'écriture dans cette eeprom se fait via l'USB par le convertisseur USB-SPI/FIFO FTDI2232 en utilisant le programme iceprog fourni dans le projet icestorm.
Fig. 2 : Chaîne de développement du projet iCEStorm.
4. Le projet d'exemple
Pour illustrer le fonctionnement des outils icestorm, les fichiers d'exemple rot.v et rot.pcf sont donnés dans le projet arachne-pnr. Comme tout bon « hello word » électronique, ce projet permet d'allumer des LED. Dans ce cas, on allume alternativement les 4 LED rouges du kit de manière à voir une lumière « tourner ».
Cet exemple n'étant pas très interactif, nous allons le modifier un peu de manière à provoquer la rotation des LED par l’appui sur une touche de télécommande. Puisque le icestick possède un émetteur/récepteur infrarouge, autant en profiter.
remoteswitch.v :
module top(input clk, output D1, output D2,
output D3, output D4, output power,
input rxd, output txd, output sd);
reg ready = 0;
reg [23:0] divider;
reg [3:0] rot;
reg [23:0] powerdiv;
reg rxd_s, rxd_tmp;
reg rxd_old, rxd_rise;
/* On synchronise le RX du récepteur IR avec l'horloge */
always @(posedge clk) begin
rxd_tmp <= rxd;
rxd_s <= rxd_tmp;
end
/* Détection du front montant de rxd (entrée infrarouge)*/
always @(posedge clk) begin
if(rxd_old == 1'b0 && rxd_s == 1)
begin
rxd_rise <= 1'b1;
end
else
begin
rxd_rise <= 1'b0;
end
rxd_old <= rxd_s;
end
/* Temporisation pour éviter les multiples décalages des LED
à chaque pression d'un bouton de la télécommande */
always @(posedge clk) begin
if (ready)
begin
if (divider == 12000000 && rxd_rise == 1'b1)
begin
divider <= 0;
rot <= {rot[2:0], rot[3]};
end
else if (divider != 12000000)
divider <= divider + 1;
end
else
begin
ready <= 1;
rot <= 4'b1000;
divider <= 0;
end
end
/* Gestion des entrées/sorties */
assign D1 = rot[0];
assign D2 = rot[1];
assign D3 = rot[2];
assign D4 = rot[3];
assign power = 1; /* LED verte de power */
assign sd = 0; /* récepteur IR actif */
assign txd = 0; /* non utilisé */
endmodule
5. Yosys, la synthèse Verilog
Le code de Yosys se trouve sur le GitHub de W.Clifford : https://github.com/cliffordwolf/yosys. Et peut être simplement récupéré via git :
$ git clone https://github.com/cliffordwolf/yosys.git
$ cd yosys
Son installation est relativement aisée, les paquets Debian/Ubuntu à installer pour les dépendances sont donnés dans le readme du projet.
Pour la compilation, on reste dans le très classique :
$ make
$ sudo make install
Yosys peut être utilisé en mode interactif en tapant simplement son nom :
$ yosys
[...]
Yosys 0.5+184 (git sha1 c329233, gcc 4.9.2-10 -fPIC -Os)
yosys> read_verilog remoteswitch.v
[…]
Successfully finished Verilog frontend.
Yosys> synth_ice40 -blif remoteswitch.blif
[…]
Les commandes disponibles sont documentées via la commande help.
Mais il est aussi possible de le lancer en shell, de manière à pouvoir l’intégrer à ses scripts ou makefile :
$ yosys -p "synth_ice40 -blif remoteswitch.blif" remoteswitch.v
La commande synth_ice40 permet de préciser à yosys d'utiliser la librairie de primitives spécifique à l'ice40.
La synthèse est l'étape permettant de transformer le code HDL en une netlist. Plusieurs formats standards de sortie de netlist sont supportés par Yosys : EDIF, BLIF, Verilog.
Dans notre exemple, nous utilisons le format BLIF qui est le format reconnu par le logiciel de placement routage Arachne-pnr.
Maintenant que nous avons la netlist de notre projet, l'étape suivante va consister à placer les portes logiques dans le ice40 et à router les connexions. Pour cela, nous aurons besoin du fichier de placement des entrées/sorties au format pcf.
remoteswitch.pcf :
set_io D1 99
set_io D2 98
set_io D3 97
set_io D4 96
set_io power 95
set_io clk 21
set_io rxd 106
set_io txd 105
set_io sd 107
Ce fichier est l'équivalent de l'UCF chez Xilinx, il permet d'assigner les noms de signaux d'entrées/sorties de notre module aux numéros de pins du FPGA.
6. Arachne-pnr, le placement-routage
Le projet, développé par Coton Seed est disponible sur son GitHub: https://github.com/cseed/arachne-pnr. Et peut être simplement récupéré via git :
$ git clone https://github.com/cseed/arachne-pnr.git
$ cd arachne-pnr
La compilation du programme écrit en C++ est aussi classique que pour Yosys :
$ make
$ sudo make install
Son utilisation se fait en ligne de commandes.
$ arachne-pnr -d 1k -p remodeswitch.pcf remoteswitch.blif -o remoteswitch.txt
Le fichier de sortie indiqué avec l'option -o est un simple fichier texte contenant des matrices de 0 et de 1 pour chaque bloc (appelé tile) de l'ice40. Deux tailles sont supportées pour l'ice40 1k et 8k.
Ce fichier txt est une description complète de la configuration du ice40, cependant ce n'est pas le format accepté par le FPGA. Pour le configurer, il reste à le convertir en un bitstream avec icepack.
7. Icepack, le bitstream
Icepack est un programme intégré au projet icestorm. Le code de ce projet se trouve sur le GitHub de W.Clifford : https://github.com/cliffordwolf/icestorm. Et peut être simplement récupéré via git :
$ git clone https://github.com/cliffordwolf/icestorm.git
$ cd icestorm
Le projet icestorm contient plusieurs utilitaires en C++, C et python3 pouvant tous être compilés d'un coup avec un simple :
$ make
Puis installés avec :
$ sudo make install
L'utilitaire qui nous intéresse ici est icepack, qui permet de convertir le format texte fourni par arachne-pnr en un bitstream reconnu par le FPGA.
$ icepack remoteswitch.txt remoteswitch.bin
Nous obtenons ainsi un bitstream de configuration reconnu par le ice40, puis il suffit de le télécharger dans l'eeprom de configuration du icestick.
8. Iceprog, la configuration du FPGA
Iceprog est un simple utilitaire écrit en C permettant d'écrire le bitstream dans l'eeprom SPI du icestick. Pour le faire, le programme s'appuie sur le convertisseur USB-Série/fifo FTDI2232. Si le icestick est le seul convertisseur ftdi branché sur l'ordinateur, il suffit simplement de lancer le programme avec le nom du bitstream en argument :
$ sudo iceprog remoteswitch.bin
Nous pouvons maintenant apprécier notre « hello world électronique » en pressant le bouton de n'importe quelle télécommande infrarouge du marché, et voir les LED du kit s'allumer alternativement à chaque pression.
9. La voie est libre !
Comme nous venons de le voir, il est tout à fait possible de réaliser un projet simple entièrement avec des outils libres pour le ice40. Cependant, icestorm est encore un projet en cours de développement. Les PLL ne sont, par exemple, pas encore supportées et le placement-routage ne prend pas en compte les informations de timings puisqu'elles ne sont pas disponibles.
L'accès au code de tous ces outils nous permet de rêver par contre à de nouveaux usages des FPGA. Il est notamment possible d'intégrer les outils sur des systèmes embarqués (ARM ou autres) et de générer « à la volée » des bitstreams en fonction de la configuration, ce qui fera peut-être l'objet d'un futur article dans Open Silicium.