Introduction

FPGA : field-programmable gate array

Dans ce premier article, nous verrons pourquoi le développement d’un projet au travers d’une description, synthèse puis implémentation matérielle est très utilisé dans le monde industriel, et pourquoi les amateurs devraient s’y intéresser. Le développement matériel sur circuits logiques pré-diffusés était en effet une discipline d’élite presque ésotérique dans les années 90, elle est maintenant à la porté des amateurs avec des FPGA relativement complets trouvables à moins de 20€, sur PCB de développement.

La complexité du workflow rebute les néophytes lors de la première approche : la discipline est en effet plus complexe à aborder car des notions d’électronique numérique, de logique combinatoire et séquentielle sont requises. Tout ceci peut néanmoins s’expliquer très rapidement en vulgarisant, nous verrons donc dans cette suite d’articles comment allumer une simple LED avec un FPGA, comme les débutants peuvent le faire sur Arduino dès le plus jeune âge.


Concrètement

De manière vulgarisée, il s’agit de concevoir une puce numérique personnalisée et spécialisée à partir d’un grand nombre de bascules D intégrées sur un unique die de silicium, recâblées entre elles suivant une description matérielle synthétisée à partir d’un langage de description logique : le VHDL.


Processeur / CPLD

Un microprocesseur est un cas particulier de circuit logique : il contient des registres mémoires et des instructions pré-câblées en usine. Ces instructions matérielles sont utilisables par les programmes pour manipuler des informations ou des adresses mémoires, il suffit donc d’écrire puis de compiler du code pour exploiter ces instructions câblées. Les instructions sont exécutées de manière séquentielle, la performance du matériel est donc sacrifiée au prix de la modularité des unités de traitement, généralement pour un seul objectif : faire un tourner un système d’exploitation ou un programme (une simple suite d’instructions/tests).

Ci contre, un microprocesseur Intel i7-6950X :

Intel i7-6950X

Les cœurs (cores) sont des architectures logiques optimisées pour différentes opérations câblées de manipulation d’adresses / données. Sont également présents des registres de différentes tailles, plus ou moins rapides, reliés aux cœurs et entre eux par des pipelines de données sur tout types de bus.

Dans le monde des FPGA/CPLD, il n’a pas de notion de mémoire, d’adressage ou même d’instructions. De base, il n’y a même pas de notion d’horloge. Les travaux de développement se produisent à plus bas niveau : vraiment très proche des ressources matérielles. Par exemple, on manipule très souvent des signaux numériques binaires au sein du VHDL.

On dispose d’une puce dite pré-diffusée, c’est un environnement de développement matériel sur le modèle sandbox : on ne fait rien avec la puce, mais il est possible de décrire complètement l’architecture matérielle désirée pour transformer un FPGA en puce numérique complète.

Voici la surface d’un FPGA Intel EPM7032 :

Altera EPM7032 – 36 I/O – 600 éléments logiques – 230Mhz

On trouve sur ce die énormément de matériel en relation avec le câblage des bascules, un peu de RAM, des pipelines, quelques unités logiques de calcul (multiplications) et des alimentations. Il est possible de se représenter le composant comme un tableau de plusieurs milliers de bascules D contenant tout le matériel nécessaire pour câbler ces bascules.

La puce est reconfigurable : elle charge en général sa description logique au démarrage, lors de sa phase d’initialisation. En production, la description logique n’est pas située dans le FPGA mais en général dans des mémoires externes EEPROM. Cette phase d’initialisation peut durer plusieurs secondes selon la complexité de l’architecture. Un FPGA n’est pas une micro architecture figée, en ce sens les fréquences, timings atteins sont largement inférieurs aux performances obtenues depuis les années 2000 dans les processeurs câblés ou les ASIC (Application Specific Integrated Circuit). Typiquement, les fréquences maximales atteintes pour les horloges dans la série Virtex UltraScale+ (Xilinx, 2016) ne dépassent pas les 600Mhz, quand la génération équivalente de processeurs i386 passe les 4GHz sur 4 cœurs avec du silicium de qualité (i74980HQ).

Il est évidement possible d’accélérer matériellement un système informatique pour exécuter certaines instructions de manière hardware ou gérer un bus à très gros débit :

DNVUF2_HPC_PCIE – Dinie Group


I/O

Un avantage clef du développement matériel sur CPLD se trouve dans le nombre d’I/O : 36 sur ce vieux EPM7032 mais ce chiffre peut être multiplié par 50 si on met le prix. Chaque I/O est indépendant et peut être relié de manière isolée à un circuit logique spécifique, pour une application spécifique. Par exemple, si on doit contrôler 400 ADC en même temps, il est possible de construire une architecture pour tous les piloter en même temps par 400 lignes SPI haute vitesse dédiée, puis de stocker les données sur différentes mémoires, de manière complètement parallèle.

Altera EPM7xxx Series

Le très grand nombre d’I/O rend possible la construction d’une architecture parallèle complète et isolée au sein d’un FPGA, c’est par exemple très utile dans l’aéronautique quand le système doit montrer et démontrer une fiabilité exemplaire et surtout quantifiable. On peut également implémenter une architecture RISC ou ARM complètement décrite en VHDL, des projets existent en ce sens. Il est donc possible d’implémenter un microcontrôleur complet équipé du matériel numérique embarqué que l’on désire.


VHDL : VHSIC Hardware Description Language

La définition dit exactement ce qu’est le VHDL : un langage de description logique. Originalement développé par la défense Américaine depuis l’ADA pour décrire et simuler les systèmes numériques, il est depuis les années 90 possible de procéder à une synthèse du code écrit : le VHDL est analysé et interprété par un algorithme d’implémentation sur circuit qui se charge de recâbler les bascules internes du FPGA pour construire l’architecture demandée.

Le workflow est un peu le même concernant le développement de puces câblées spécifiques (ASIC) : tout commence par une description logique VHDL puis une synthèse, enfin une implémentation, cette fois réalisée en usine (fonderie) sur des waffers de silicium.


Générateur de parité

Nous allons implémenter un générateur de parité : c’est un composant qui prend un bus de données en entrée (ici 8 bits parallèles) et qui dispose d’une sortie binaire qui vaut 1 si le nombre de bits vallant 1 sur le bus est pair, 0 sinon. C’est une vielle astuce pour vérifier si la transmission s’est faite sans pertes de données, mais les limites sont rapidement atteintes. En effet s’il y’a deux erreurs dans la transmission, le bit de parité est juste et pourtant des données ont étés perdues.

En VHDL, on manipule des composants logiques virtuels, il suffit de décrire les I/O et le fonctionnement interne. Ensuite, on affecte les broches aux signaux I/O.

Premièrement on déclare les librairies à utiliser, ici IEEE.STD_LOGIC_1164.ALL permet la manipulation de signaux logiques :

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

Ensuite il faut déclarer les noms des broches virtuelles d’entrées / sortie du composant :

entity parite_8 is
    Port ( input_word : in  STD_LOGIC_VECTOR (7 downto 0);
           parity : out  STD_LOGIC);
end parite_8;

Le type STD_LOGIC_VECTOR (7 downto 0) représente un bus de données 8 bits parallèles, le type STD_LOGIC représente un simple signal binaire (un fil). Le nom du composant virtuel est partite_8.

Maintenant que la vue externe du composant est créé, il suffit de décrire le comportement interne du circuit entre le bus d’entrée input_word et le signal de sortie parity :

architecture Behavioral of parite_8 is begin
    parity <= input_word(0) xor input_word(1) xor input_word(2) xor input_word(3) xor input_word(4) xor input_word(5) xor input_word(6) xor input_word(7);
end Behavioral;

Une alternative fonctionnant en VHDL 2008 :

architecture Behavioral of parite_8 is begin
    parity <= xor input_word
end Behavioral;

Le fichier VHDL décrivant un générateur de parité 8 bits ressemble donc à ça :

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity parite_8 is
    Port ( input_word : in  STD_LOGIC_VECTOR (7 downto 0);
           parity : out  STD_LOGIC);
end parite_8;

architecture Behavioral of parite_8 is begin
    parity <= input_word(0) xor input_word(1) xor input_word(2) xor input_word(3) xor input_word(4) xor input_word(5) xor input_word(6) xor input_word(7);
end Behavioral;

Nous verrons dans un prochain article comment implémenter ce composant dans un FPGA fonctionnel, pour allumer une LED avec le signal de sortie parity.


0 commentaire

Laisser un commentaire