FPGA : programmer un contrôleur pour écran VGA avec une carte de développement FPGA
Un tutoriel de f-leb
Le 2022-09-16 20:49:53, par f-leb, Responsable Arduino et Systèmes Embarqués
Pour cette rentrée, je vous propose ce tutoriel pour apprendre à configurer un contrôleur d’écran VGA sur une carte de développement FPGA :
Programmer un contrôleur pour écran VGA avec une carte de développement FPGA
Kit FPGA Terasic DE0-nano et interface VGA
Kit FPGA Terasic DE0-nano et interface VGA
Objectif
Bonne lecture, et bonne rentrée à tous
-
f-lebResponsable Arduino et Systèmes EmbarquésMerci
Le langage (Verilog ici) en lui-même n'est pas très compliqué : des affectations, des assignations de signaux, des if/else ou switch/case et on a l'essentiel
Alors c'est vrai qu'il faut penser différemment, par exemple dans ce test (la coloration syntaxique Verilog n'est pas active sur le forum, donc copie d'écran) :
Le bloc always est évalué à chaque front montant de l'horloge (synchronisme).
Le programmeur (non avisé) pourrait croire que si l'entrée in est à 1, la valeur out est d'abord mise à 1 (ligne 9), puis ensuite mise à 3 (ligne 10).
Et donc si l'entrée in est maintenu à 1, la valeur out "clignote" en étant constamment rabaissée à 1 (ligne 9) avant de remonter à 3 (ligne 10).
Que nenni, un FPGA n'est pas un CPU qui exécute séquentiellement l'instruction de la ligne 9, suivie de l'instruction de la ligne 10.
L'ordre des lignes est important, mais seulement pour donner des priorités.
Quand une variable est affectée plusieurs fois, c'est la dernière affectation qui est prioritaire.
Ainsi, si in est à 1 :
- la ligne 9 voudrait affecter 1 à out;
- la ligne 10 voudrait affecter 3 à out;
C'est donc la dernière affectation de la ligne 10 qui est prioritaire sur l'affectation de la ligne 9, et le circuit configuré fera en sorte que out prenne la valeur 3 si l'entrée in est à 1.
C'est un peu fatigant au début ces subtilités (et à la fin aussi d'ailleurs)
Edit 20/09/22 :
Je précise que le code précédent est rédigé pour illustrer un phénomène, mais du point de vue du style de codage, il est mauvaisOn écrira plutôt avec un else :
Code verilog : 1
2if (in) out <= 3; else out <= 1;
le 19/09/2022 à 18:32 -
AuteurExpert éminent sénior
pour cet article.
La conclusion qui décrit bien les difficultés que l'on peut rencontrer quand on souhaite débuter la programmation des FPGA. Il faut donc que j'apprenne à réfléchir autrement pour me lancer dans cette aventure.Envoyé par f-leb le 16/09/2022 à 21:42 -
f-lebResponsable Arduino et Systèmes EmbarquésUn pt'it code pour illustrer :
Code verilog : 1
2
3
4
5
6
7
8
9
10
11
12module test(); reg [2:0] a; // cas le + fréquent reg [0:2] b; initial begin a = 3'b100; b = 3'b100; $display("%0b %0b %0b", a[2], a[1], a[0]); $display("%0b %0b %0b", b[2], b[1], b[0]); end endmodule
Résultat :
Code : 1
2
31 0 0 0 0 1 Done
: <= ou =, affectation non-bloquante (non-blocking) vs affectation bloquante (blocking).
Et il y a bien une différence de comportement entre les deux !! Euhh... je reviens plus tard pour expliquerle 20/09/2022 à 18:43 -
Vincent PETITModérateurSalut,
Effectivement sémantiquement les mots sont proches néanmoins moi aussi je préfère utiliser reconfigurer pour un FPGA. Je m'explique !
Imaginons un calcul de CRC 16 bits (polynôme 0x8005).
En C le programmeur voit ça :
Code C : 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17unsigned int crc16(unsigned int crcValue, unsigned char newByte) { unsigned char i; for (i = 0; i < 8; i++) { if (((crcValue & 0x8000) >> 8) ^ (newByte & 0x80)){ crcValue = (crcValue << 1) ^ 0x8005; }else{ crcValue = (crcValue << 1); } newByte <<= 1; } return crcValue; }
Le designer FPGA lui par contre voit ça (les blocs "stage" sont des bascules logiques) :
Etant donné qu'un FPGA est un réseau de composants logiques qu'on peut rerouter ou reconfigurer "un peu" comme on veut, je pense en tout cas que le terme "reprogrammer" s'y prête un peu moins. Le Verilog et le VHDL sont des langages qui permettent de décrire une config matérielle. La fonction réalisée par cette config matérielle peut aussi, comme le cas du calcul de CRC, être réalisée par du soft.le 24/09/2022 à 13:47 -
AuteurExpert éminent séniorEt deux remarques :
1- je vois que la déclaration de out est la suivante :
Code : output reg [1:0] out
et non (bah, oui programmeur avant tout)
Code : output reg [0:1] out
Ce qui me surprend c'est que tu puisses affecter 3 à une sortie. Dans mon esprit logique c'est 1 ou 0.
ah non finalement.... out est un registre 2 bits donc 3 ça passe
Et l'affectation est le symbole "<=" ce qui est assez perturbant pour moi qui suis habitué au "="le 20/09/2022 à 13:23 -
AuteurExpert éminent séniorah... j'ai compris : little-endian et big-endian ?
ah oui, mais non.le 20/09/2022 à 19:52 -
f-lebResponsable Arduino et Systèmes Embarquésle 20/09/2022 à 20:59
-
AuteurExpert éminent séniorHello
le "=" dans la majorité des langages de programmation est une affectation. En algorithmie, il s'agit bien d'une flèche orientée vers la gauche.
En javascript le "==" est une égalité sur les valeurs, mais "===" est une égalité stricte et l'interpréteur va non seulement comparer les valeurs, mais également les types (entier, chaine, etc.). Il ne s'agit pas d'une lubie du concepteur.
Comme l'a indiqué f-leb il faut penser matériel pas programmation. En automatisme, au démarrage, je me souviens qu'il fallait initialiser certains composants (forcer à 1 ou forcer à 0) pour éviter des états indéterminés et donc des comportements étranges de l'automate. Il doit s'agir de quelque chose de similaire.le 21/09/2022 à 18:18 -
f-lebResponsable Arduino et Systèmes EmbarquésSalut,
J'ai juste dit que c'était perturbant, mais cela n'a rien d'absurde. La comparaison avec d'autres langages n'est pas pertinente ici, Verilog/systemVerilog n'est pas un langage de programmation, c'est un langage de description de matériel (Hardware Description Language). Les lignes du code ne sont pas compilées pour fournir des instructions exécutées séquentiellement par un CPU. On s'attache à décrire des processus qui fonctionneront en parallèle (de façon concurrente). Et quand une « variable » est lue dans un processus pendant qu'elle est modifiée en même temps dans un processus concurrent, on peut se demander quel sera le résultat de l'affectationA noter que les évolutions plus récentes de Verilog (devenu SystemVerilog) avec ses nouveaux blocs always_comb (pour la logique combinatoire) et always_ff (pour la logique séquentielle) facilite la vie du développeur sur les affectations autorisées.
C'est l'idée... Je suis désolé de ne pas pouvoir apporter une explication immédiate et rapide mais cette notion d'affectation bloquante/non-bloquante n'est pas évidente du tout à expliquer et va me prendre du temps.
Je suis en train de regarder un document qui raconte dès le synopsis :
One of the most misunderstood constructs in the Verilog language is the nonblocking assignment. Even very experienced Verilog designers do not fully understand how nonblocking assignments are scheduled in an IEEE compliant Verilog simulator and do not understand when and why nonblocking assignments should be used...
En pratique, tu suis sans trop te poser de questions les quelques guidelines pour savoir quand utiliser l'une ou l'autre et ça marche très bien.
Il faut que je me documente un peu et que je trouve des exemples pertinents, mais j'essaierai d'apporter un éclairage (dans un billet de blog peut-être).le 21/09/2022 à 18:31 -
f-lebResponsable Arduino et Systèmes EmbarquésC'est logique en programmation, mais en langage HDL d'autres questions se posent. Le problème avec les FPGA, c'est de savoir quand tu débloques, et quand tu affectes. J'essaierai de donner un exemple plus tard...
Certes, mais ces concepts qui sont gérés dans les systèmes d'exploitation n'ont rien à voir avec les FPGA...
Quand bien même ça n'intéresserait que ma petite personne, ce forum n'échappera pas à un petit message ou billet d'explication... Fallait pas m'inviterle 21/09/2022 à 19:52