Vous êtes sur la page 1sur 31

FPGA : tutoriel pour s’initier au langage Verilog

Programmation d’un pilote pour le capteur de température Si7021

Par f-leb

Date de publication : 20 septembre 2021

La carte de développement utilisée dans ce tutoriel est une carte FPGA Alchitry Au que
je vous avais déjà présentée dans un tutoriel précédent. Un module avec un capteur de
température et d’humidité Si7021 (Silicon Labs) est connecté à la carte.

Après avoir fait vos premiers pas avec Verilog, vous allez apprendre à programmer un
2
pilote qui va gérer le dialogue I C avec le module pour acquérir la température ambiante à
intervalles réguliers. Dans cette démonstration, la valeur de la température sera retournée
via le câble USB pour affichage dans un terminal série.

Commentez

En complément sur Developpez.com


• Découvrir le langage Lucid avec une carte de développement FPGA d’Alchitry
• Description d'un afficheur 7-segments en langage Verilog
• Débuter avec les FPGA dans l’environnement Intel Quartus Prime
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

I - Introduction : microcontrôleur ou FPGA ?.............................................................................................................. 3


II - La carte Alchitry Au............................................................................................................................................... 3
III - L’EDI Alchitry Labs................................................................................................................................................4
IV - Premiers pas en Verilog....................................................................................................................................... 6
IV-A - Un premier blink.......................................................................................................................................... 6
IV-B - Des processus concurrentiels..................................................................................................................... 9
V - Programmation d’un pilote en Verilog pour le capteur Si7021............................................................................11
V-A - Ajout des ports supplémentaires SCL et SDA........................................................................................... 11
V-B - Composants supplémentaires.................................................................................................................... 12
V-C - Dialogue I2C...............................................................................................................................................13
V-D - Description à la façon d’une machine à états finis.................................................................................... 16
V-E - Programmation de la machine à états finis en Verilog.............................................................................. 19
V-F - États temporisés......................................................................................................................................... 21
V-G - Fonctionnement du système...................................................................................................................... 22
V-H - Sources du projet complet......................................................................................................................... 25
VI - Conclusion.......................................................................................................................................................... 31

-2-
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

I - Introduction : microcontrôleur ou FPGA ?

Autant le dire tout de suite… Programmer un microcontrôleur pour communiquer avec un capteur de température en
2
liaison I C est une activité assez simple avec une bibliothèque adaptée pour ce protocole. Avec une carte Arduino
et la bibliothèque du capteur à importer, quelques lignes de programme dans une boucle suffisent. Alors, pourquoi
proposer un tutoriel avec un matériel plus coûteux, qui va généralement vider plus rapidement la batterie de votre
système embarqué, programmé dans un langage HDL (Hardware Description Language) que vous mettrez plus de
temps à assimiler qu’un langage procédural comme C ou C++, et qui vous vaudra des heures supplémentaires en
débogage et mise au point ?

Bien entendu, les FPGA (Field-Programmable Gate Array) ont leurs avantages quand la performance et la flexibilité
d’une architecture reconfigurable sont requises. Un microcontrôleur ne peut exécuter des instructions que l’une après
l’autre, alors que le fonctionnement des FPGA est fondamentalement parallèle. Mais avant d’en profiter pleinement,
il faudra commencer par découvrir les bases d’un langage de description de matériel tel que Verilog. Et c’est
précisément l’objectif de ce tutoriel qui utilise une plateforme pour débutants…

II - La carte Alchitry Au

On rappelle les caractéristiques principales de la carte Alchitry Au :

FPGA Alchitry Au - Image Sparkfun Licence C.C

Caractéristiques principales
• FPGA • Xilinx Artix 7 XC7A35T-1C (33 280
cellules logiques)
• Mémoire • 256 Mo DDR3 via interface 16 bits
(~ 10 Gbit/s)
• Entrées-sorties • 102 broches à 3,3 V, dont 20
peuvent être configurées pour
de la transmission différentielle
basse-tension 1,8 V

-3-
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

• 9 entrées différentielles
analogiques (1 dédiée et 8
partagées avec les entrées-sorties
numériques)
• Périphériques en surface de la • 1 jeu de 8 LED vertes
carte • 1 bouton-poussoir à appui
momentané « Reset »
• 1 LED de statut
• 1 horloge 100 MHz
• 1 interface série port USB type C
via FT2232H (12 MBauds maxi.)
• 2
1 connecteur Qwiic (I C)
SparkFun
• Programmation • JTAG via port USB, interface
FT2232H
• Alimentation • 5 V par port USB type C, trou
métallisé x 2 0,1”
• Dimensions • 65 mm x 45 mm

Notez les quatre plots de connexion femelle qui permettent d’enficher (et même empiler) des cartes d’extension à la
façon des shields Arduino (ou des HAT (Hardware Attached on Top) de la carte Raspberry Pi). Vous avez un aperçu
d’une de ces cartes dans ce billet qui met en œuvre un afficheur 7-segments.

III - L’EDI Alchitry Labs

L’EDI Alchitry Labs vient en renfort du débutant en complément de la suite Vivado de Xilinx qui supporte
gratuitement la puce FPGA Xilinx Artix-7 de la carte Alchitry.

L’EDI est plutôt rudimentaire, un éditeur basique et un bouton pour lancer la chaîne des outils de synthèse : analyse,
synthèse logique, jusqu’à la génération du fichier bitstream. Prenez en compte les deux autres boutons pour téléverser
le fichier du projet en RAM ou en ROM qui va configurer la puce FPGA et vous savez l’essentiel.

L’EDI peut toutefois ne servir que d’intermédiaire étant donné qu’il s’appuie en arrière-plan sur les outils de la suite
Vivado. Une fois votre projet généré, tous les fichiers nécessaires sont dans un dossier spécial pour poursuivre le
travail dans l’environnement professionnel de la suite (pour faire différents types d’analyses, visualiser des schémas,
faire des simulations, etc.).

-4-
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

Le même projet sous la suite Vivado

À la création d’un nouveau projet Verilog dans Alchitry Labs, le code du module principal au_top.v se présente comme
suit :

au_top.v
1. module au_top(
2. input clk, // 100MHz clock
3. input rst_n, // reset button (active low)
4. output [7:0] led, // 8 user controllable LEDs
5. input usb_rx, // USB->Serial input
6. output usb_tx // USB->Serial output
7. );
8.
9. wire rst;
10.
11. // The reset conditioner is used to synchronize the reset signal to the FPGA
12. // clock. This ensures the entire FPGA comes out of reset at the same time.
13. reset_conditioner reset_conditioner(.clk(clk), .in(!rst_n), .out(rst));
14.
15. assign led = 8'h00; // turn LEDs off
16.
17. assign usb_tx = usb_rx; // echo the serial data
18.
19. endmodule

Les premières lignes décrivent les entrées-sorties des périphériques de la carte : l’horloge principale à 100 MHz,
l’entrée du bouton reset et les sorties vers le jeu de 8 LED vertes en surface de la carte, ainsi que les connexions
série Rx et Tx du port USB.

En fin de module, des assignations continues assign :

• pour mettre l’anode des LED à l’état bas afin de les éteindre ;
• pour renvoyer en écho les données reçues en raccordant l’entrée Rx et la sortie Tx de la liaison série USB.

Cette description est résumée dans le schéma structurel ci-dessous :

-5-
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

Schéma structurel

Le bloc reset_conditioner au centre du schéma est instancié avec ses connexions à ligne 13 du code précédent.

reset_conditioner reset_conditioner(.clk(clk), .in(!rst_n), .out(rst));

On voit par exemple dans cette description structurelle que l’entrée in de l’instance est raccordée au signal inversé
(avec !, comme en langage C) du bouton-poussoir rst_n (suffixe n pour négatif, car le signal est à l’état bas lorsque
le bouton est pressé).

reset_conditioner est donc un module complémentaire, ajouté par défaut au projet, et qui permet de conditionner et
synchroniser avec l’horloge, le signal issu de l’appui sur le bouton-poussoir reset en surface de la carte. Le nœud
rst en sortie de ce bloc est pour l’instant non connecté, mais il pourra servir de signal de réinitialisation synchrone
lorsqu’il sera dirigé vers certaines parties du futur système.

IV - Premiers pas en Verilog

IV-A - Un premier blink

Avant de s’attaquer au capteur de température, on propose de découvrir le langage Verilog sur une simple application
de clignotement de LED (une fois n’est pas coutume !)

Le code du module principal au_top.v qui suit fait clignoter une des huit LED du bandeau en surface de la carte en
la dirigeant vers un signal carré de fréquence 1 Hz :

au_top.v
1. module au_top(
2. input clk, // 100MHz clock
3. input rst_n, // reset button (active low)
4. output [7:0] led, // 8 user controllable LEDs
5. input usb_rx, // USB->Serial input
6. output usb_tx // USB->Serial output
7. );
8.
9. wire rst;
10.
11. // The reset conditioner is used to synchronize the reset signal to the FPGA
12. // clock. This ensures the entire FPGA comes out of reset at the same time.
13. reset_conditioner reset_conditioner(.clk(clk), .in(!rst_n), .out(rst));
14.
15. assign usb_tx = usb_rx; // echo the serial data
16.
17. reg [27:0] counter;
18. wire out;
19. localparam PERIOD = 100_000_000; // 1s period

-6-
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

au_top.v
20.
21. assign out = counter > (PERIOD >> 1); // PERIOD >> 1, division by 2
22. assign led = {7'h0, out};
23.
24. always @(posedge clk or posedge rst) begin
25. if (rst) begin
26. counter <= 0;
27. end else begin
28. if (counter < PERIOD) begin
29. counter <= counter + 1;
30. end else begin
31. counter <= 0;
32. end
33. end
34. end
35.
36. endmodule

• Ligne 17 : avec le type reg, on déclare ce qui se rapproche du concept de « variable » dans les langages
procéduraux traditionnels. Ici, un vecteur de largeur 28 bits.
• Ligne 18 : le type wire, lui, n’a pas de capacité de mémorisation et désigne des nœuds représentant des
connexions entre éléments physiques.
• Ligne 19 : PERIOD est un paramètre local initialisé à 100 000 000, le nombre de cycles par seconde de
l’horloge principale.
• Ligne 21 et 22 : des assignations continues pour donner des valeurs aux nœuds. Dans une assignation
continue, tout changement dans l’expression à droite du signe = est répercuté sur le terme assigné à
gauche du signe =. Ainsi, le signal Out basculera à 1 quand le compteur aura dépassé la moitié de la valeur
maximale (au bout de 0,5 s). Avec l’assignation continue qui suit, sept des huit LED du bandeau en surface
de la carte seront éteintes, tandis que la huitième clignotera. Les accolades { } réalisent une concaténation de
bits.
• Lignes 24 à 34 : un processus always exécuté continuellement. La « liste de sensibilité » est définie sur front
montant de l’horloge principale clk et front montant du signal rst (appui sur le bouton Reset). En d’autres
termes, ce processus ne s’exécutera que lors d’un événement sur l’un des signaux de la liste. Le processus
de clignotement de la LED est ensuite décrit de façon comportementale dans le bloc begin… end exécuté
séquentiellement. L’interprétation de ces lignes ne pose pas de difficultés. On incrémente un compteur qui
repasse à zéro soit parce qu’il atteint sa valeur maximale, soit parce que le bouton Reset est appuyé.

La génération complète du projet (build) peut prendre plusieurs minutes…

Dans la suite Vivado, on peut visualiser une première analyse du projet générée sous forme
schématique :

Vivado RTL Analysis

On voit sur ce schéma que le compteur counter est modélisé avec des bascules D (ou flip-
flop). La sortie Q d’une bascule est remise à zéro si le signal CLR est actif. Sinon, elle reproduit
l’état de son entrée D en ne répercutant les changements que sur front montant de l’horloge.
Cette partie du circuit à logique séquentielle est donc capable de « mémoriser » un état jusqu’à
un moment précis qui est le prochain front montant de l’horloge.

-7-
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

La condition if du code s’est traduite par un multiplexeur (ou sélecteur) repéré RTL_MUX et
qui dirige l’une de ses deux entrées vers la sortie en fonction de l’état 0 ou 1 du signal de
sélection S.

Une fois le projet synthétisé, ces blocs fonctionnels deviennent essentiellement des LUT
(Lookup Table) et des bascules flip-flop. 90 cellules logiques sont nécessaires pour ce projet :

Vivado Synthesis

Le schéma n’est pas très sympathique… Si on zoome sur l’état des LED à droite du schéma,
on voit que le système a décidé de diriger la sortie O d’une LUT à 5 entrées vers la LED qui
clignote :

Vivado Synthesis - vue détaillée

L’équation logique de cette LUT est même donnée : O = I0 + I1 & I4 + !I1 & I2 & I3 & I4

-8-
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

Évidemment, il faudra creuser le schéma en amont pour comprendre d’où vient cette équation.

Le schéma (partiel) d’implémentation physique ci-dessous montre en surbrillance la LUT


précédente et sa localisation dans le réseau des cellules logiques de la puce FPGA :

Vivado implementation

Verilog est donc un langage de description de matériel. Une fois le code passé aux mains des outils de synthèse, la
configuration du circuit qui sera implémenté physiquement dans la puce FPGA répondra aux effets décrits par votre
code. Si pour un microcontrôleur le code compilé est traduit en suite d’instructions CPU, le synthétiseur FPGA traduit
le code en circuit logique matériel.

IV-B - Des processus concurrentiels

Et si on voulait faire clignoter deux LED, « en même temps » (c’est-à-dire en synchronisant les signaux sur la même
horloge), mais à des fréquences différentes ? On pourrait dupliquer le bloc always, mettre un autre paramètre pour
une fréquence de clignotement différente et diriger la sortie vers une autre LED du bandeau. Les processus always
fonctionnent effectivement de façon concurrente (en parallèle).

Mais plutôt que dupliquer du code, on le mettra dans un sous-module paramétré. Dans les sources du projet, on
ajoutera le sous-module blinker.v suivant :

blinker.v
module blinker #(parameter PERIOD = 100_000_000) (
input clk, // clock
input rst, // reset
output out
);

localparam WIDTH = 28; // 28 bits, compteur jusqu'à 2^28 - 1 maximum


reg [WIDTH-1 : 0] counter;

assign out = counter > (PERIOD >> 1);

always @(posedge clk or posedge rst) begin


if (rst) begin
counter <= 0;
end else begin

-9-
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

blinker.v
if (counter < PERIOD) begin
counter <= counter + 1;
end else begin
counter <= 0;
end
end
end

endmodule

Dans le module principal, on instancie deux blinkers (nommés blinker_slow et blinker_fast) dont on connecte les
entrées-sorties (description structurelle) :

au_top.v
module au_top(
input clk, // 100MHz clock
input rst_n, // reset button (active low)
output [7:0] led, // 8 user controllable LEDs
input usb_rx, // USB->Serial input
output usb_tx // USB->Serial output
);

wire rst;

// The reset conditioner is used to synchronize the reset signal to the FPGA
// clock. This ensures the entire FPGA comes out of reset at the same time.
reset_conditioner reset_conditioner(.clk(clk), .in(!rst_n), .out(rst));

assign usb_tx = usb_rx; // echo the serial data

wire slow_blink, fast_blink;

blinker #(.PERIOD(100_000_000)) blinker_slow (.clk(clk), .rst(rst), .out(slow_blink));


blinker #(.PERIOD(50_000_000)) blinker_fast (.clk(clk), .rst(rst), .out(fast_blink));

assign led = {slow_blink, 6'h0, fast_blink};

endmodule

Le schéma-blocs sous Vivado donne la structure suivante :

Par contre, même si on évite la duplication de code, il y aura bien deux circuits quasiment identiques qui seront
synthétisés.

Avec la même facilité, vous pourriez faire clignoter en parallèle une troisième, une quatrième LED, voire plus, à des
fréquences différentes…

Exercice : faire le même exercice de clignotement de LED en parallèle avec un


microcontrôleur ?

- 10 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

La LED en bas clignote à une fréquence de 1 Hz. Celle du haut clignote deux fois plus vite.

Cliquer sur ce lien pour lancer l'animation


Verilog permet donc d’implanter des traitements dans des circuits logiques matériels, sans CPU, mais programmés
de façon algorithmique.

V - Programmation d’un pilote en Verilog pour le capteur Si7021

2
L’étude qui suit concerne maintenant la description d’un pilote gérant la communication I C avec le capteur de
température (et d’humidité) Si7021.

Le code source complet de l’étude est donné en fin de chapitre.

On commence par une photo du montage :

Le module Si7021 du fabricant Adafruit comporte des connecteurs au format Qwiic de SparkFun. Un connecteur
Qwiic est également présent sur la carte Alchitry Au depuis que la production des cartes de la plateforme Alchitry
a été confiée au groupe SparkFun.

2
Avec le cordon Qwiic approprié (4 broches JST), la connexion I C devient aisée. Le deuxième connecteur sur le
2
module Si7021 peut servir à relier un autre composant sur le bus I C. Dans ce tutoriel, il aura servi à connecter
l’un de ces analyseurs logiques à bas coût pour observer les trames échangées sur le bus. Les copies d’écran des
trames qui suivent ont été obtenues par ce moyen.

V-A - Ajout des ports supplémentaires SCL et SDA

D’après la documentation, les broches SCL (Serial Clock) et SDA (Serial Data) du connecteur Qwiic sont connectées
respectivement aux ports référencés A24 et A23. Comme ce connecteur Qwiic a été rajouté plus tard par SparkFun,
cette contrainte n’est pas renseignée par défaut dans l’EDI.

Afin d’y remédier, commencez par rajouter au projet un fichier dit « des contraintes » au format ACF (Alchitry
Constraints File), avec ces deux lignes :

pin scl A24;

- 11 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

pin sda A23;

Dans la définition des entrées-sorties du module principal, vous pouvez maintenant rajouter les deux ports scl et sda.
Le système sait maintenant que ces deux ports sont bien dirigés vers les connecteurs Qwiic de la carte :

au_top.v
module au_top (
input clk, // horloge 100 MHz
input rst_n, // bouton Reset, actif à l'état bas
output [7:0] led, // jeu de LED x 8, non utilisé
input usb_rx, // liaison série USB : Rx, non utilisé
output usb_tx, // liaison série USB : Tx
output scl, // Serial Clock I2C, générée par le maître
inout sda // Serial Data I2C, /!\ SDA, port bidirectionnel
);

// etc.

La broche SDA est bidirectionnelle (inout), les données peuvent circuler du maître vers
l’esclave et inversement.

V-B - Composants supplémentaires

Vous avez déjà rencontré précédemment le module reset_conditioner, mais deux autres modules sont nécessaires
encore :

• 2
i2c_controller : contrôleur I C pour communiquer avec le capteur ;
• uart_tx : contrôleur UART pour transmettre des données série via le câble USB.

- 12 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

Sélection de composants supplémentaires

Le code de ces modules est aussi sur github/alchitry/Alchitry-Labs/library/components/. Ces codes sont écrits
en langage Lucid, mais transpilés en Verilog à la génération du projet dans l’EDI Alchitry Labs. La suite Vivado
propose également ses bibliothèques certifiées de composants réutilisables (les Intellectual property (IP) cores). Les
composants réécrits pour Alchitry Labs en sont souvent des versions simplifiées, plus facilement accessibles aux
débutants.

V-C - Dialogue I2C

La séquence pour obtenir la température est décrite dans la datasheet du capteur Si7021 :

- 13 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

Les parties de la séquence avec un fond blanc sont générées par le composant maître (master), c’est-à-dire la carte
FPGA toujours à l’initiative de la communication. Les parties avec un fond gris sont générées par le composant
esclave (slave), c’est-à-dire le capteur de température Si7021 qui répond aux sollicitations du maître.

• S : Start.
• P : Stop.
• Sr : Start Repeated, un Start qui n’est pas précédé d’un Stop.
• A, NA : acquittement ou non-acquittement.
• Slave Adress : adresse du composant sur 7 bits, ici 0x40.
• Slave Adress + W : demande d’accès au composant en écriture.
• Slave Adress + R : demande d’accès au composant en lecture.
• Measure Cmd : le code de la commande pour obtenir la température, ici 0xF3.

Vous trouverez des explications plus détaillées dans le tutoriel de Michel Semal.

Par exemple, le début de la séquence avec le code 0xF3 pour obtenir la température donnera la trame suivante :

- 14 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

Le point vert marque le bit de Start généré par le maître, c’est-à-dire un front descendant du signal SDA lorsque
l’horloge SCL est à l’état haut. Une demande d’accès en écriture est ensuite réclamée au capteur Si7021 à l’adresse
0x40. Le composant esclave doit une première fois acquitter, informant ainsi le composant maître qu’il a bien reçu
la demande et qu’il est disposé à recevoir des données. Pour acquitter, une période d’horloge supplémentaire est
générée par le composant maître, et le composant esclave doit abaisser l’état de la ligne SDA.

Le code 0xF3 (Measure Temperature) est alors transmis au capteur. Lorsque l’octet est transmis, le module acquitte
(ACK) à nouveau pour accuser réception.

2 2
Vous trouverez les spécifications du bus I C en recherchant le document I C-bus specification and user manual
(Rev. 6 — 4 April 2014) sur le site du fabricant de semi-conducteurs NXP qui maintient la norme.

2
Le contrôleur I C proposé dans la bibliothèque de composants de l’EDI Alchitry Labs qui va générer les trames se
présente comme suit :

Contrôleur I2C : à gauche les entrées, à droite les sorties (SDA est un port bidirectionnel)

2
Fonctionnement du contrôleur I C

2
Chaque transaction I C commence par un Start que l’on déclenche en mettant à l’état haut
l’entrée start pendant une période de l’horloge clk. Vous pouvez alors écrire ou lire sur le bus
autant de fois que nécessaire. Pour terminer la transaction, vous devez mettre l’entrée stop
à l’état haut pendant une période de l’horloge clk.

Chaque fois que vous voulez effectuer une opération sur le bus (start, stop, read, write), vous
devez vous assurer au préalable en regardant l’état du signal busy que la ligne n’est pas déjà
occupée avec une autre opération. Si vous ne tenez pas compte de cela, l’opération demandée
risque d’être ignorée.

Classiquement, une transaction démarre par une opération d’écriture d’un octet comprenant
l’adresse du composant esclave sur 7 bits, suivie d’un bit pour indiquer si l’opération est

- 15 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

une lecture ou une écriture sur le bus. Voir la documentation du composant esclave pour
comprendre la séquence des échanges. Les échanges en écriture ou lecture se poursuivent.

Quand le composant maître opère en lecture sur la ligne, vous devez préciser si celui-ci doit
acquitter ou non à chaque octet reçu (ack_read à l’état haut si oui, à l’état bas sinon).

Quand le composant maître opère en écriture sur la ligne, l’état du bit ack_write vous
indiquera si le composant esclave a bien acquitté ou non. (Attention : ack_write à l’état bas si
acquittement, la documentation annonce l’état inverse ?!).

Code d’instanciation du contrôleur en Verilog :

au_top.v (extrait)
/* ---- Instantiacion & connexion du contrôleur I2C
----------------------------------*/
reg i2c_start; // signal Start (S) ou Start Repeated (Sr)
reg i2c_stop; // signal Stop (P)
wire i2c_busy; // =1 si le bus I2C est occupé
wire i2c_out_valid; // =1 quand la donnée renvoyée (1 octet) en
sortie est valide et disponible
reg [7:0] i2c_data_in; // octet à transmettre (maître vers esclave)
wire [7:0] i2c_data_out; // octet renvoyé (esclave vers maître)
reg i2c_write; // =1, demande d'écriture par le maître sur le bus
reg i2c_read; // =1, demande de lecture par le maître sur le bus
reg i2c_ack_read; // =1 si le maître doit acquitter
wire i2c_ack_write_n, i2c_ack_write; // sortie ack_write du contrôleur=0
si l'esclave acquitte, /!\ erreur dans la doc.

assign i2c_ack_write = !i2c_ack_write_n;

i2c_controller #(.CLK_DIV(9)) Si7021_controller ( // fréquence clk =


100_000_000 / 2^9 = 195,3 kHz
.clk(clk),
.rst(rst),
.scl(scl),
.sda(sda),
.start(i2c_start),
.stop(i2c_stop),
.busy(i2c_busy),
.data_in(i2c_data_in),
.data_out(i2c_data_out),
.write(i2c_write),
.read(i2c_read),
.ack_write(i2c_ack_write_n),
.ack_read(i2c_ack_read),
.out_valid(i2c_out_valid)
);

localparam [7:0] I2C_ADR_Si7021 = 8'h40, // adresse du composant I2C


Si7021 = 0x40
I2C_ADR_Si7021_Read = (I2C_ADR_Si7021 << 1) + 1,
I2C_ADR_Si7021_Write = (I2C_ADR_Si7021 << 1);
/*

*/

V-D - Description à la façon d’une machine à états finis

Si on reprend l’extrait de la séquence précédente, on peut en faire une description avec le diagramme d’états-
transitions suivant :

- 16 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

Les rectangles définissent les états de la machine. La transition entre deux états s’opère si la condition portant sur les
entrées, à gauche du /, est vérifiée. À droite du signe /, on trouve l’état des sorties sur la transition. Par exemple, en
supposant que la machine rentre à l’état state_I2C_START : après une temporisation de 1 s, on met la sortie start à
l’état haut, et la machine passe à l’état suivant state_I2C_ADRW. Lorsque la condition est à true, la transition s’opère
toujours, quel que soit l’état des entrées. Ici, on ne vérifie pas si le module a bien acquitté ou non.

Pour obtenir la valeur de température, il faut ensuite faire une demande en lecture (après un Start Repeated). Mais
la conversion analogique-numérique prend un peu de temps (7 ms d’après la documentation), et le module refuse
d’acquitter (NA) tant qu’elle n’est pas terminée.

Pour ce tutoriel, on choisit de renouveler la demande de lecture toutes les 2 ms, jusqu’à ce que le module finisse par
acquitter (typiquement au bout de quatre tentatives, soit 8 ms). Ce qui donne la description suivante :

- 17 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

On voit dans cette description que les sorties de la machine dépendent de l’état en cours, mais aussi des entrées.
Cette description correspond à celle d’une machine de Mealy.

Quand le module acquitte (i2c_ack_write), le composant maître passe en lecture pour récupérer les données (les
trois octets MSB, LSB et CHKSUM), puis marque la fin de la transaction :

- 18 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

Le document suivant récapitule le diagramme états-transitions complet de la machine de


2
Mealy utilisé dans ce tutoriel, accompagné des trames I C obtenues à l’analyseur logique :

Machine à états finis - dialogue Si7021 : format svg - format png

V-E - Programmation de la machine à états finis en Verilog

Le code Verilog ci-dessous est un gabarit pour gérer une machine de Mealy :

1. module au_top (
2. input clk, // horloge 100 MHz
3. input rst_n, // bouton Reset, actif à l'état bas
4. output [7:0] led, // jeu de LED x 8, non utilisé
5. input usb_rx, // liaison série USB : Rx, non utilisé
6. output usb_tx, // liaison série USB : Tx
7. output scl, // Serial Clock I2C, générée par le maître
8. inout sda // Serial Data I2C, /!\ SDA, port bidirectionnel
9. );
10.
11. // etc.
12.
13. /* ------ Gestion de la machine à états finis ------------------------------------ */
14. reg [3:0] I2C_State, I2C_State_Next;
15.
16. localparam state_I2C_RESET_START = 4'd0,
17. state_I2C_RESET_ADRW = 4'd1,
18. state_I2C_RESET_CMD = 4'd2,
19. state_I2C_RESET_STOP = 4'd3,
20. state_I2C_START = 4'd4,
21. state_I2C_ADRW = 4'd5,
22. state_I2C_START_RE = 4'd6,
23. state_I2C_ADRR = 4'd7,
24. state_I2C_MEASURE_CMD = 4'd8,
25. state_I2C_READ_MSB = 4'd9,
26. state_I2C_READ_LSB = 4'd10,
27. state_I2C_READ_CHKSUM = 4'd11,
28. state_I2C_STOP = 4'd12;
29.
30. always @(posedge clk or posedge rst) begin
31. if (rst) begin
32. I2C_State <= state_I2C_RESET_START;
33. end else begin
34. if (!i2c_busy) begin // si pas d'action en cours sur le bus I2C,
35. I2C_State <= I2C_State_Next; // passage à l'état suivant, synchronisé avec
l'horloge
36. end
37. end
38. end
39.
40. always @(I2C_state, ...) begin
41. I2C_State_Next = I2C_State; // par défaut, conserver l’état
42.
43. // valeurs par défaut
44. i2c_stop = 0;
45. i2c_write = 0;
46. i2c_read = 0;
47. i2c_start = 0;
48. i2c_data_in = 0;
49. i2c_ack_read = 0;
50. temperature_enable = 0;
51.
52. case (I2C_State)
53.
54. state_I2C_RESET_START : begin
55. if (<condition>) begin
56. // ...
57. I2C_State_Next = state_I2C_RESET_ADRW;

- 19 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

58. // ...
59. end // else begin ...
60. end
61.
62. state_I2C_RESET_ADRW : begin
63. if (<condition>) begin
64. // ...
65. I2C_State_Next = state_I2C_RESET_CMD;
66. // …
67. end // else begin ...
68. end
69.
70. // etc. pour les autres états
71.
72. state_I2C_STOP : begin
73. if (<condition>) begin
74. // ...
75. I2C_State_Next = state_I2C_START;
76. // …
77. end // else begin ...
78. end
79.
80. endcase
81.
82. end
83.
84. endmodule

Deux processus always s’exécutent en parallèle (Verilog est un langage « concurrent » contrairement à la plupart
des langages comme C, C++, Java, etc. qui sont des langages séquentiels par nature).

• Lignes 30 à 38 : le premier processus always est défini avec la « liste de sensibilité » posedge clk or
posedge rst. Ce processus est donc évalué continuellement à chaque front montant de l’horloge principale ou
chaque front montant du signal rst (détection d’appui sur le bouton-poussoir Reset). Ce processus séquentiel
met à jour l’état présent (I2C_State) par l’état futur (I2C_State_Next) sur front montant de l’horloge principale
2
100 MHz, et à condition que le bus I C soit libre (i2c_busy).
• Lignes 40 à 82 : ce deuxième processus combinatoire suit la logique du diagramme états-transitions avec
une instruction case. Il calcule l’état des sorties ainsi que l’état futur à partir des entrées et de l’état présent.
Par exemple, avec l’extrait du diagramme suivant :

Pour l’état State_I2C_READ_MSB, on voit deux situations selon que le module acquitte ou non. Si le module acquitte,
on descend dans le diagramme pour récupérer les données disponibles de température en commençant par l’octet
MSB de poids fort. Sinon, on doit remonter à un état antérieur pour demander à nouveau si la température est
disponible. Les valeurs des sorties dépendent donc de l’état en cours, mais aussi des valeurs des entrées que l’on
teste avec un if. Ce qui donne pour cet état :

- 20 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

case (I2C_State)

// …

state_I2C_READ_MSB : begin
if (!i2c_ack_write) begin // Si NAK, la conversion n'est pas terminée
I2C_State_Next = state_I2C_START_RE;
end else begin // Sinon si ACK, la conversion est terminée
i2c_read = 1; // Lecture Temperature MSB
i2c_ack_read = 1;
I2C_State_Next = state_I2C_READ_LSB;
end
end

// …

endcase

V-F - États temporisés

Dans le diagramme d’états-transitions, vous remarquerez plusieurs états qui sont temporisés.

Par exemple, à l’état state_I2C_START ci-dessous, il y a une temporisation de 1 s avant de passer à l’état suivant.
Cette temporisation permet ainsi de cadencer les acquisitions de température à intervalles réguliers :

Pour programmer cette temporisation en Verilog, on passera par un troisième processus concurrent :

always @(posedge clk) begin


if (I2C_State != I2C_State_Next) begin // remise à zéro du chrono à chaque changement
d'état
delay <= 0;
end else begin
delay <= delay + 1;
end
end

Un compteur delay est incrémenté à chaque front montant de l’horloge principale 100 MHz, et remis à zéro à chaque
changement d’état. Pour temporiser un état, il suffit de tester la valeur du compteur à l’entrée de l’état :

- 21 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

// ...

state_I2C_START : begin
if (delay > 100_000_000) begin // 1 mesure par seconde
i2c_start = 1;
I2C_State_Next = state_I2C_ADRW;
end
end

// ...

V-G - Fonctionnement du système

Pour vérifier le fonctionnement du système, on visualise les températures dans un terminal série comme RealTerm
(115 200 bauds, 8 bits de données, 1 bit de stop, sans parité).

Une acquisition de température est lancée chaque seconde avant de s’afficher sur une ligne du terminal série.

L’analyseur logique à bas coût ci-dessous (Saleae ou compatible, 8 canaux, 24 MHz) permet de visualiser les trames
échangées :

- 22 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

On voit dans la trame qui suit qu’une acquisition de température est lancée toutes les secondes :

Une acquisition prend 8 ms environ (relance de lecture des données toutes les 2 ms) :

- 23 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

Au début, le module n’acquitte pas (NAK), car la conversion analogique-numérique de la température n’est pas
terminée :

Au bout de 8 ms, le module finit par acquitter, les données image de la température sont alors lues :

Les deux premiers octets (CodeMeasure = 0x6610) permettent de calculer la valeur de température en °C avec la
formule donnée dans la documentation du capteur Si7021 :

Soit environ 23,2 °C.

Verilog peut synthétiser des formules complexes :

always @(posedge i2c_out_valid) begin // si 1 octet est retourné par le capteur


raw_data[7:0] <= i2c_data_out; // on le décale dans le registre raw_data
raw_data[23:8] <= raw_data[15:0];
end

always @(posedge clk) begin


if (temperature_enable) begin

- 24 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

temperature_32bits = ((raw_data[23:8] * 1757) >> 16) - 469; // calcul de T(°C)x10, voir


datasheet Si7021
// Au besoin, CheckSum est dans raw_data[7:0]
end
end

Quand un octet est retourné par le capteur, il est décalé dans un registre 24 bits raw_data[23:0]. Quand la transaction
est terminée, temperature_enable passe à 1, et on calcule une valeur entière 32 bits donnant la température multipliée
par 10. Par exemple, pour une température de 23,21 °C, la valeur calculée sera égale à 232. Ce sera au dispositif
client recevant et affichant les données de faire la division par 10, les arrondis nécessaires ou de placer la virgule.

Le troisième octet est une somme de contrôle (CheckSum), non exploitée dans ce tutoriel, mais qui sert normalement
à vérifier l’intégrité des données transmises.

V-H - Sources du projet complet

On rappelle l’architecture du projet dans Alchitry Labs :

Dans les sources ci-dessous :

• au_top.v : module principal en Verilog.


• serialTemperatureDisplay.v : module prenant en charge la communication série via le port USB pour affichage
de la température (115 200 bauds) dans un terminal. La séquence de préparation et d’envoi des données est
aussi gérée à la façon d’une machine à états finis.

Dans les composants (Components), les modules sont écrits en Lucid (langage Verilog simplifié), mais transpilés
en Verilog à la génération du projet. :

• reset_conditioner.luc : conditionnement et synchronisation du signal du bouton Reset en surface de la carte.


• 2
i2c_controller.luc : contrôleur pour la communication I C avec la capteur.
• uart_tx.luc : contrôleur pour l’envoi de données série UART.

- 25 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

Dans les contraintes : en plus des fichiers constraints par défaut, le fichier io.acf donne la localisation des broches
SDA et SCL du connecteur Qwiic.

io.acf
// I2C Serial Clock (scl) & Serial Data (sda)
pin scl A24;
pin sda A23;

au_top.v
module au_top (
input clk, // horloge 100 MHz
input rst_n, // bouton Reset, actif à l'état bas
output [7:0] led, // jeu de LED x 8, non utilisé
input usb_rx, // liaison série USB : Rx, non utilisé
output usb_tx, // liaison série USB : Tx
output scl, // Serial Clock I2C, générée par le maître
inout sda // Serial Data I2C, /!\ SDA, port bidirectionnel
);

assign led = 8'h00; // LED x 8 éteintes

wire rst; // signal reset synchrone, rst=1 si appui sur bouton Reset
reset_conditioner rst_cond_inst ( // Conditionnement & synchronisation du signal Reset
.clk(clk),
.in(!rst_n),
.out(rst)
);

/* ------- Affichage température en °C via liaison UART Tx 115 200 bauds 8N1-------------- */

integer temperature_32bits; // Pour calcul de température sur 32 bits

reg temperature_enable; // =1 quand la transaction I2C est complète

serialTemperatureDisplay std ( // instance affichage via liaison série UART


.clk(clk),
.rst(rst),
.temperature(temperature_32bits),
.usb_tx(usb_tx),
.enable(temperature_enable)
);
/*
-------------------------------------------------------------------------------------------- */

/* ---- Instanciation & connexion du contrôleur I2C ----------------------------------*/


reg i2c_start; // signal Start (S) ou Start Repeated (Sr)
reg i2c_stop; // signal Stop (P)
wire i2c_busy; // =1 si le bus I2C est occupé
wire i2c_out_valid; // =1 quand la donnée renvoyée (1 octet) en sortie est valide et
disponible
reg [7:0] i2c_data_in; // octet à transmettre (maître vers esclave)
wire [7:0] i2c_data_out; // octet renvoyé (esclave vers maître)
reg i2c_write; // =1, demande d'écriture par le maître sur le bus
reg i2c_read; // =1, demande de lecture par le maître sur le bus
reg i2c_ack_read; // =1 si le maître doit acquitter
wire i2c_ack_write_n, i2c_ack_write; // sortie ack_write du contrôleur=0 si l'esclave
acquitte, /!\ erreur dans la doc.

assign i2c_ack_write = !i2c_ack_write_n;

i2c_controller #(.CLK_DIV(9)) Si7021_controller ( // fréquence clk = 100_000_000 / 2^9 =


195,3 kHz
.clk(clk),
.rst(rst),
.scl(scl),
.sda(sda),
.start(i2c_start),
.stop(i2c_stop),
.busy(i2c_busy),
.data_in(i2c_data_in),

- 26 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

au_top.v
.data_out(i2c_data_out),
.write(i2c_write),
.read(i2c_read),
.ack_write(i2c_ack_write_n),
.ack_read(i2c_ack_read),
.out_valid(i2c_out_valid)
);

localparam [7:0] I2C_ADR_Si7021 = 8'h40, // adresse du composant I2C Si7021 = 0x40


I2C_ADR_Si7021_Read = (I2C_ADR_Si7021 << 1) + 1,
I2C_ADR_Si7021_Write = (I2C_ADR_Si7021 << 1);
/* ------------------------------------------------------------------------------- */

/* ------ Gestion de la machine à états finis ------------------------------------ */


reg [3:0] I2C_State, I2C_State_Next;

localparam state_I2C_RESET_START = 4'd0,


state_I2C_RESET_ADRW = 4'd1,
state_I2C_RESET_CMD = 4'd2,
state_I2C_RESET_STOP = 4'd3,
state_I2C_START = 4'd4,
state_I2C_ADRW = 4'd5,
state_I2C_START_RE = 4'd6,
state_I2C_ADRR = 4'd7,
state_I2C_MEASURE_CMD = 4'd8,
state_I2C_READ_MSB = 4'd9,
state_I2C_READ_LSB = 4'd10,
state_I2C_READ_CHKSUM = 4'd11,
state_I2C_STOP = 4'd12;

always @(posedge clk or posedge rst) begin


if (rst) begin
I2C_State <= state_I2C_RESET_START;
end else begin
if (!i2c_busy) begin // si pas d'action en cours sur le bus I2C,
I2C_State <= I2C_State_Next; // passage à l'état suivant, synchronisé avec l'horloge
end
end
end
/* ----------------------------------------------------------------------------------------
*/

reg [23:0] raw_data; // registre avec données brutes retournées par le capteur : | MSB |
LSB | CheckSum |
reg [30:0] delay; // valeur chronomètre pour temporisation

always @(posedge i2c_out_valid) begin // si 1 octet est retourné par le capteur


raw_data[7:0] <= i2c_data_out; // on le décale dans le registre raw_data
raw_data[23:8] <= raw_data[15:0];
end

always @(posedge clk) begin


if (temperature_enable) begin
temperature_32bits = ((raw_data[23:8] * 1757) >> 16) - 469; // calcul de T(°C)x10, voir
datasheet Si7021
// Au besoin, CheckSum est dans raw_data[7:0]
end
end

always @(posedge clk) begin


if (I2C_State != I2C_State_Next) begin // remise à zéro du chrono à chaque changement
d'état
delay <= 0;
end else begin
delay <= delay + 1;
end
end

/*----------- Génération de la trame I2C ----------------------------------------------- */

- 27 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

au_top.v

always @(I2C_State, i2c_ack_write, delay) begin


I2C_State_Next = I2C_State;

// valeurs par défaut


i2c_stop = 0;
i2c_write = 0;
i2c_read = 0;
i2c_start = 0;
i2c_data_in = 0;
i2c_ack_read = 0;
temperature_enable = 0;

case (I2C_State)

state_I2C_RESET_START : begin
if (delay > 1_000_000) begin // attendre 10ms avant de démarrer
i2c_start = 1;
I2C_State_Next = state_I2C_RESET_ADRW;
end
end

state_I2C_RESET_ADRW : begin
i2c_write = 1;
i2c_data_in = I2C_ADR_Si7021_Write;
I2C_State_Next = state_I2C_RESET_CMD;
end

state_I2C_RESET_CMD : begin
i2c_write = 1;
i2c_data_in = 8'hFE; // commande Reset, voir datasheet Si7021
I2C_State_Next = state_I2C_RESET_STOP;
end

state_I2C_RESET_STOP : begin
i2c_stop = 1;
I2C_State_Next = state_I2C_START;
end

state_I2C_START : begin
if (delay > 100_000_000) begin // 1 mesure par seconde
i2c_start = 1;
I2C_State_Next = state_I2C_ADRW;
end
end

state_I2C_ADRW : begin
i2c_write = 1;
i2c_data_in = I2C_ADR_Si7021_Write; // Slave Address (0x40) + Write
I2C_State_Next = state_I2C_MEASURE_CMD;
end

state_I2C_MEASURE_CMD : begin
/* if (i2c_ack_write) begin... // Si on veut tester que le module acquitte bien... */
i2c_write = 1;
i2c_data_in = 8'hF3; // Command 0xF3, Temperature, No Hold Master Mode. Voir
datasheet Si7021
I2C_State_Next = state_I2C_START_RE;
end

state_I2C_START_RE : begin
/* if (i2c_ack_write) begin... // Si on veut tester que le module acquitte bien... */
if (delay > 200_000) begin // relancer après 2 ms
i2c_start = 1; // Start Repeated
I2C_State_Next = state_I2C_ADRR;
end
end

state_I2C_ADRR : begin
i2c_write = 1;

- 28 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

au_top.v
i2c_data_in = I2C_ADR_Si7021_Read; // Slave Address (0x40) + Read
I2C_State_Next = state_I2C_READ_MSB;
end

state_I2C_READ_MSB : begin
if (!i2c_ack_write) begin // Si NAK, la conversion n'est pas terminée
I2C_State_Next = state_I2C_START_RE;
end else begin // Sinon si ACK, la conversion est terminée
i2c_read = 1; // Lecture Temperature MSB
i2c_ack_read = 1;
I2C_State_Next = state_I2C_READ_LSB;
end
end

state_I2C_READ_LSB : begin
i2c_read = 1; // Lecture Temperature LSB
i2c_ack_read = 1;
I2C_State_Next = state_I2C_READ_CHKSUM;
end

state_I2C_READ_CHKSUM : begin
i2c_read = 1; // Lecture Temperature CheckSum
I2C_State_Next = state_I2C_STOP;
end

state_I2C_STOP : begin
temperature_enable = 1; // transaction complète
i2c_stop = 1;
I2C_State_Next = state_I2C_START;
end

endcase

end

endmodule

SerialTemperatureDisplay.v
module serialTemperatureDisplay(clk, rst, usb_tx, temperature, enable);
input clk; // 100MHz clock
input rst; // reset
output usb_tx; // USB->Serial output
input wire [31:0] temperature;
input enable;

wire busy_tx;
reg [7:0] data_tx;
reg new_data_tx;
reg block_tx;
integer temperature_abs;

localparam LENGTH = 16, STR = "Temp = xxx.x C\r\n"; // gabarit de la chaîne de caractères à
envoyer et sa taille
localparam SIGN = 9, HUNDREDS = 8, TENS = 7, UNITS = 5; // position du signe, des chiffres
centaines/dizaines/unités

reg [LENGTH*8:1] s;
reg[7:0] t1, t2, t3;

reg [7:0] counter, counter_next;

uart_tx #(.BAUD(115200), .CLK_FREQ(100000000)) tx (


.clk(clk),
.rst(rst),
.tx(usb_tx),
.busy(busy_tx),
.data(data_tx),
.new_data(new_data_tx),
.block(block_tx)
);

- 29 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

SerialTemperatureDisplay.v
/* ------ Gestion de la machine à états finis ------------------------------------ */
reg state, state_next;

localparam state_1 = 1'd0,


state_2 = 1'd1;

initial begin
counter <= LENGTH;
state <= state_1;
end

always @(posedge clk or posedge rst) begin


if (rst) begin
state <= state_1;
end else begin
state <= state_next; // passage à l'état suivant, synchronisé avec l'horloge
end
end

always @(posedge clk) begin


counter <= counter_next;
end

always @(posedge enable) begin // préparation de la chaîne de caractères à transmettre


s = STR;

if (temperature[31]) begin // si température négative (bit de poids fort = 1)


s[SIGN*8-:8] = "-";
end else begin
s[SIGN*8-:8] = "+";
end

temperature_abs = (temperature[31]) ? ~temperature + 1 : temperature; // valeur absolue si


négatif

t1 = temperature_abs / 100; // chiffre des centaines


t2 = (temperature_abs % 100) / 10; // chiffre des dizaines
t3 = ((temperature_abs % 100) % 10); // chiffre des unités
s[HUNDREDS*8-:8] = "0" + t1;
s[TENS*8-:8] = "0" + t2;
s[UNITS*8-:8] = "0" + t3;
end

always @(*) begin // transmission UART Tx

// valeurs par défaut


state_next = state;

new_data_tx = 0;
block_tx = 0;
data_tx = "";

counter_next <= counter;

case (state)

state_1 : begin
counter_next <= LENGTH;
if (enable) begin // si nouvelle donnée de température disponible
state_next = state_2;
end
end

state_2 : begin
if (!busy_tx) begin // si le port UART Tx est libre
new_data_tx = 1; // signaler une nouvelle donnée
data_tx = s[(counter*8)-:8]; // caractère à transmettre
counter_next <= counter - 1; // aller au caractère suivant

if (counter == 1) begin // si tous les caractères ont été transmis

- 30 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/
FPGA : tutoriel pour s’initier au langage Verilog par f-leb

SerialTemperatureDisplay.v
state_next = state_1;
end
end
end

endcase

end

endmodule

VI - Conclusion

Une conséquence de la nature des FPGA est que les tâches configurées dans les circuits peuvent être hautement
parallélisées. Rien ne vous empêche de configurer votre FPGA avec 20 générateurs de signaux PWM ou 5 ports série
UART si vous en avez besoin, alors que le nombre de ces périphériques est figé et limité dans un microcontrôleur
classique. Sur microcontrôleur, pour simuler un fonctionnement multitâche, vous devez jouer avec les interruptions,
programmer des machines à états finis ou passer par un OS temps réel, car les traitements du processeur sont
séquentiels par nature. Beaucoup d’algorithmes de traitement d’images par exemple sont naturellement parallèles
et méritent une mise en œuvre sur FPGA.

La dernière version du langage Verilog est sortie en 2005, mais il y a toutefois des évolutions récentes du langage
avec SystemVerilog, dont Verilog est maintenant un sous-ensemble. Même si les européens lui préfèrent le langage
VHDL, la syntaxe de certaines expressions Verilog est très appréciée des développeurs familiers avec les langages
C ou C++.

Dans ce tutoriel, vous avez pu aussi vous rendre compte du haut niveau d’abstraction permis par Verilog et
découvrir différents styles de description dans les projets allant de la description structurelle jusqu’au plus haut niveau
d’abstraction avec la description comportementale :

• description structurelle : assemblage de primitives et blocs logiques que l’on interconnecte ;


• description comportementale : le circuit est décrit non plus par sa structure, mais par son comportement qui
peut être spécifié de façon procédurale, comme les algorithmes programmés sur les ordinateurs.

Notez que les codes ont été écrits en Verilog 2001 standard, et que les sources du projet peuvent être repris
intégralement pour toute autre carte FPGA configurable avec ce langage (à condition de redéfinir la configuration et
la localisation des entrées-sorties de la carte et tenir compte des nouvelles caractéristiques d’horloge).

Les FPGA ne conviennent pas forcément à toutes les utilisations, mais ils constituent de puissants outils quand
les applications exigent de la vitesse de traitement et de la flexibilité (interface intelligente, intelligence artificielle,
apprentissage automatique, traitement d’images et de vidéos, accélération d’algorithme, etc.) Les solutions optimales
reposent maintenant sur la combinaison de processeurs et de FPGA, voire des FPGA intégrant des cœurs de
processeurs matériels.

Vous êtes maintenant prêts à vous lancer dans de nouveaux projets…

Je remercie escartefigue pour la relecture orthographique.

- 31 -
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée
par les droits d'auteur. Copyright ® 2021 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
https://f-leb.developpez.com/tutoriels/fpga/alchitry/verilog/temperature-si7021/

Vous aimerez peut-être aussi