Linux Embedded

Le blog des technologies libres et embarquées

Introduction aux FPGA

Le FPGA (Field Programmable Gate Array) est désormais très utilisé dans les solutions embarquées. L'approche dite "co-design"  permet, entre autres, de limiter la charge du calculateur. Elle permet également d'avoir une solution adaptable car programmable suivant l'application, tant du côté du CPU (grâce au système d'exploitation) que du FPGA. Certains fabricants fournissent désormais des cartes intégrant directement un FPGA ; citons Armadeus (APFx) et Xilinx (ZebBoard). Le FPGA est souvent un composant assez coûteux, même si certaines cartes comme l'APF27 d'Armadeus sont relativement abordables.

Nous rappelons qu'un FPGA est une matrice de portes logiques que l'on programme avec un fichier "bitstream" issu de la "compilation" (en fait, les phases de synthèse, mapping, placement, routage) d'un fichier source écrit en langage HDL (Hardware Description Language), le plus souvent VHDL ou Verilog. Le fichier source utilise des données abstraites correspondant à des signaux (en entrée et/ou sortie) ou des variables internes.  Dans le cas des signaux, un autre fichier décrira la correspondance entre le nom du signal et la broche utilisée sur le FPGA (voir l'exemple plus loin). On peut également tester le fichier source avec un simulateur. À titre d'exemple, il existe un simulateur libre (Icarus) pour le langage Verilog ici.

Dans la suite de l'article, nous allons présenter quelques bases d'exploitation d'un FPGA  en utilisant l'exemple concret de la carte LOGI PI qui est un "shield" prévu pour aller avec la carte Raspberry Pi (B, B+ ou 2). La page du constructeur de la carte - ValentF(x) - est disponible ici et la LOGI PI est disponible à l'achat chez Farnell. Bien entendu, le prix de la carte (112 €) peut paraître élevé par rapport au prix de la Raspberry Pi (21 € pour la B+). Il faut cependant noter qu'elle est équipée d'un FPGA Spartan-6 de chez Xilinx, qui est un produit récent et performant. La même carte existe pour BeagleBone Black sous le nom LOGI BONE.

L'installation de la carte sur la Raspberry Pi est très bien documentée ici. La page indique également comment installer une distribution Raspbian intégrant directement les outils et les exemples utiles pour la LOGI PI. La communication avec la Raspberry Pi utilisant - principalement - le bus SPI, il suffit d'ajouter les lignes suivantes au fichier /etc/modules de votre Raspbian.

snd-bcm2835
i2c-bcm2708
i2c-dev

L'étape suivante consiste à installer l'outil de chargement logi_loader, ainsi que quelques exemples déjà prêts à l'emploi. Ces éléments sont disponibles sur le compte GitHub du constructeur. Une fois n'est pas coutume, nous compilerons l'outil directement sur la carte Raspberry Pi.

pi@raspberrypi:~$ git clone https://github.com/fpga-logi/logi-tools.git
pi@raspberrypi:~$ cd logi-tools/unified_loader
pi@raspberrypi:~$ make
pi@raspberrypi:~$ sudo make install

Des exemples déjà compilés sont disponibles en utilisant les commandes suivantes :

$ git clone https://github.com/fpga-logi/logi-apps.git
$ cd logi-apps/
$ git checkout logipi

On peut alors tester l'exemple - classique - des leds clignotantes par la commande:

 $ sudo logi_loader blink_led_app/logipi_blink.bit

Nous allons désormais nous attacher à l'écriture d'un exemple similaire à celui que nous avons testé. Le code source (VHDL) de l'exemple est fourni mais nous estimons que le langage Verilog (proche du C) est plus simple à appréhender que le VDHL (proche de l'Ada). De ce fait, il est moins "typé" que le VHDL. Notre exemple sera donc écrit en Verilog et développé avec l'environnement ISE WebPACK de Xilink (gratuit). Le langage Verilog reste très utilisé aux USA, alors que VHDL est plutôt européen (et académique).

Le principe de l'exemple est de faire clignoter les 2 leds de la carte (LED0 et LED1 définies dans un tableau Verilog nommé LED). La fréquence de la LED0 utilise un expression logique issue d'un compteur 32 bits (cnt) qui suit l'horloge interne de la LOGI PI (OSC_FPGA). Le paramètre rpi_gpio correspond à la GPIO 27 de la Raspberry Pi dont on peut modifier l'état depuis le système Linux. La fréquence de la LED1 dépendra donc de l'état de cette GPIO. Les paramètres du module correspondent à des signaux physiques alors que cnt n'est qu'un compteur interne. On remarque la définition du sens des des signaux par output ou input et l'affectation de l'état du signal par assign. L'instruction always(@posedge OSC_FPGA) indique que la commande d'incrémentation de cnt est exécutée à chaque front montant de l'horloge.

module ledblink2 (OSC_FPGA, LED, rpi_gpio);
input OSC_FPGA;
 input rpi_gpio;
 output [1:0] LED;
 reg [31:0] cnt;
 always @(posedge OSC_FPGA) cnt <= cnt + 32'h1;
 // LED0 depends on cnt
 assign LED[0] = ~cnt[22] & ~cnt[20];
 // LED1 depends on cnt + RPi GPIO 27
 assign LED[1] = cnt[25-(rpi_gpio << 2)];
endmodule

Dans le cas d'une cible Xilinx, la correspondance des variables (signaux) avec les broches du FPGA est définie dans un fichier .ucf. On utilise ici les broches P81, P85, P104 et P105 (voir le schéma de la carte).

NET "LED<0>" LOC = "P104" | IOSTANDARD = LVTTL;
NET "LED<1>" LOC = "P105" | IOSTANDARD = LVTTL;
NET "RPI_GPIO" LOC = "P81" | IOSTANDARD = LVTTL;
NET "OSC_FPGA" LOC = "P85" | IOSTANDARD = LVTTL;

On peut alors créer un projet dans ISE par File > New Project. Une boite de dialogue nous permet de préciser le nom du projet.

figure_03

L'action sur Next ouvre une autre fenêtre précisant la cible (Spartan-6) puis le langage utilisé (Verilog).

figure_04

On clique ensuite sur Finish dans la fenêtre résumant le projet. On doit ensuite ajouter les 2 fichiers source au projet par Project > Add SourceDans la fenêtre Processes, il suffit alors de sélectionner l'entrée Generate Programming File par le bouton droit de la souris pour produire le fichier "bitstream".

figure_05

Une fois la compilation terminée, le fichier .bit est alors disponible dans le répertoire du projet et il suffit de le charger sur la LOGI PI en utilisant logi_loaderSi l'on change l'état de la GPIO 27 par de simples commandes shell on peut constater la modification de la fréquence de clignotement de la LED1.

# echo 27 > /sys/class/gpio/export 
# echo out > /sys/class/gpio/gpio27/direction

puis:

# echo 1 > /sys/class/gpio/gpio27/value
# echo 0 > /sys/class/gpio/gpio27/value
...

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée.