Vous êtes sur la page 1sur 534

Cours

UNIVERSITE TUNIS EL MANAR


Institut Supérieur d'Informatique d'El Manar

Conception des systèmes


embarqués

De manière générale le cours vise à: présenter des méthodes de vérification pour s'assurer que le logiciel
d’un système embarqué travaille correctement avec le matériel et que le matériel a été correctement conçu
pour exécuter le logiciel ; sensibiliser l’étudiant au compromis à faire entre les réalisations logicielles et
matérielles, et rendre les étudiants conscients du gain potentiel de productivité que permet la conception
et la vérification conjointe du logiciel et du matériel. Au terme de ce cours, l'étudiant: pourra faire la
conception (design et vérification) conjointe d’un système embarqué comprenant des composants
logiciels et matériels; pourra faire le lien entre certains aspects du génie logiciel et de la micro-
électronique; sera au courant des travaux de recherche et de développement récents dans le domaine de la
conception et de la vérification de systèmes embarqués numériques, et pourra évaluer un outil de
conception et de vérification de niveau système. Rendre capable de spécifier, de concevoir et de vérifier
des systèmes digitaux à l'aide des outils modernes de conception assistée par ordinateur.

Ridha Ghayoula, Ph.d, Eng

Maître de conférences
Table des matières
Introduction ............................................................................................................................... 8
Chapitre 1 Introduction aux systèmes embarqués ................................................................. 10
1.1. Introduction ..........................................................................................................................................10
1.2. Caractéristiques des systèmes embarqués .........................................................................................10
1.3. Complexité des systèmes embarqués ...............................................................................................11
1.4. Définition des systèmes embarqués .................................................................................................11
Comparaison aux systèmes informatiques standards : ........................................................... 12
1.5. Classification des systèmes embarqués .............................................................................................13
1.5.1. Système Transformationnel ........................................................................................................13
1.5.2. Système Interactif.........................................................................................................................13
1.5.3. Système Réactif ou Temps Réel :...............................................................................................13
Exercices .......................................................................................................................................................14

Chapitre 2 Conception de circuits (Co-Design) .................................................................... 33


2.1. Introduction ..........................................................................................................................................33
2.2. Technologie des Circuits intégrés ......................................................................................................33
2.2.1 Définition de classes d'intégration ...............................................................................................33
2.2.2. Notion de niveaux logiques .........................................................................................................33
2.2.3. Compatibilité des niveaux logiques ............................................................................................34
2.2.4. Temps moyen de propagation.....................................................................................................34
2.2.5. Facteur de charge : Sortance N. ..................................................................................................35
2.2.6. Notion de familles de circuits logiques ......................................................................................35
2.2.7. Un inverseur en technologie CMOS ..........................................................................................36
2.2.8. Porte NAND .................................................................................................................................36
2.2.9. Porte AND.....................................................................................................................................37
2.2.10. Porte NOR...................................................................................................................................37
2.2.11. Autres Portes ...............................................................................................................................37
2.2.12. Porte XOR ...................................................................................................................................38
2.2.13. Arithmétique (Demi additionneur)...........................................................................................39
2.2.14. Arithmétique (Additionneur) ....................................................................................................39
2.2.15. Comparateur ................................................................................................................................40
2.2.16. Multiplication 2x2 bits ................................................................................................................40
2.2.17. Bascule (RS) .................................................................................................................................41

Page | 2 © ISI 2018 Ridha Ghayoula


2.2.18. Bascule D .....................................................................................................................................41
2.2.19. Les mémoires à semi-conducteur .............................................................................................42
2.3. Circuits Programmables ......................................................................................................................44
2.3.1. FPGA ..............................................................................................................................................45
Exercices .......................................................................................................................................................50

Chapitre 3 Les Processeurs Embarqués dans les FPGA........................................................ 59


3.1. Introduction ..........................................................................................................................................59
3.2. PicoBlaze ...............................................................................................................................................60
3.2.1. La partie matérielle du PicoBlaze ................................................................................................60
3.2.2. La partie logicielle du PicoBlaze .................................................................................................65
3.3. Processeur Xilinx MicroBlaze ...........................................................................................................68
3.3.1. Architecture MicroBlaze ..............................................................................................................69
3.3.2. Interfaces ........................................................................................................................................70
3.3.3. Simple Hardware Design using AXI ..........................................................................................71
Exercices .................................................................................................................................................... 100

Chapitre 4 Conception d’un processeur dédié au calcul PGCD .......................................... 105


4.1. Introduction ...................................................................................................................................... 105
4.2. Conception d’un processeur dédié au calcul PGCD (plus grand commun diviseur) de deux
entiers ......................................................................................................................................................... 105
4.2.1 . Multiplexeur MUX.................................................................................................................... 108
4.2.2 . Registre X_Reg,Y_Reg et Out_Reg ....................................................................................... 109
4.2.3. Comparateur: comparateur_lt .................................................................................................. 110
4.2.4. Comparateur: comparateur_neq .............................................................................................. 111
4.2.5. Soustracteur : .............................................................................................................................. 112
4.2.6 . FSM ............................................................................................................................................. 113
4.2.7. Programme principal ................................................................................................................. 114

Chapitre 5 Implémentation de l'Algorithme Cordic .............................................................117


5.1. Introduction ...................................................................................................................................... 117
5.2. Algorithme CORDIC ....................................................................................................................... 117
5.2.1. Généralisation de l'algorithme .................................................................................................. 120
5.2.2. Fonctions trigonométriques ..................................................................................................... 120
MATLAB ............................................................................................................................................... 121
Langage C .............................................................................................................................................. 121
5.3. Description matérielle ...................................................................................................................... 122
i1) Additionneur (ADDi): .................................................................................................................... 123

Page | 3 © ISI 2018 Ridha Ghayoula


Exemple : abus=16 et bbus=8 ........................................................................................................... 124
i2) Shiftn: ................................................................................................................................................ 124
Exemple : ibus=8 et n=8..................................................................................................................... 126
i4) FSM: .................................................................................................................................................. 130
Chapitre 6 Linux Embarqué ................................................................................................. 132
6.1. Introduction ....................................................................................................................................... 132
6.2. Linux Embarqué ............................................................................................................................... 132
6.2.1. Les différentes commandes ...................................................................................................... 133
6.2.2. Variables Linux ........................................................................................................................... 134
6.2.3. Notion de redirection ................................................................................................................ 135
6.2.4. Script en Linux: codification exécution .................................................................................. 139
6.3. Composants de Linux embarqué .................................................................................................... 144

Chapitre 7 Le processeur Softcore LEON ........................................................................... 153


7.1. Introduction ....................................................................................................................................... 153
7.2. Caractéristiques.................................................................................................................................. 153
7.3. Configuration et implémentation .................................................................................................. 155
7.3.1. Configuration du GRLIB .......................................................................................................... 155
7.3.2 Installation et configuration....................................................................................................... 155
7.3.3 Génération du fichier leon3mini.qpf ........................................................................................ 159
7.3.4 Génération du fichier leon3mini.sof ........................................................................................ 159
7.4. Configuration du Snapgear .............................................................................................................. 161
7.4.1. Vue d’ensemble .......................................................................................................................... 161
7.4.2. Installation et configuration...................................................................................................... 161
7.4.3 Génération du fichier image.dsu ............................................................................................... 166
7.5 Implémentation des fichiers ............................................................................................................. 166
7.5.1 Implémentation du fichier leon3mini.sof ................................................................................ 166
7.5.2 Implémentation du fichier image.dsu....................................................................................... 167

Chapitre 8 Serveur Web Embarqué ...................................................................................... 173


8.1. Introduction ....................................................................................................................................... 173
8.2. Serveurs web ..................................................................................................................................... 175
8.3. Quelques exemples de serveurs web ............................................................................................. 175
8.4. Exemples d'applications .................................................................................................................. 176
8.4.1 .La carte Raspberry Pi ................................................................................................................. 176
8.4.2. Serveur WEB .............................................................................................................................. 178
8.4.3. Connexion à la Raspberry Pi sur un poste distant ................................................................ 180

Page | 4 © ISI 2018 Ridha Ghayoula


Chapitre 9 Les Applications Arduino .................................................................................... 184
9.1. Introduction ....................................................................................................................................... 184
9.2. Apprentissage des bases ................................................................................................................... 185
9.2.1. Matériel ........................................................................................................................................ 185
9.2.2. Le logiciel .................................................................................................................................... 185
9.3. Afficheurs 7 segments ...................................................................................................................... 190
9.4. Réseau de LED 8x8 MAX7219 ...................................................................................................... 196
9.4.1. Principe ........................................................................................................................................ 196
9.4.3. Fonctionnement ......................................................................................................................... 196
9.4.4. Codage de nouveaux motifs et caractères .............................................................................. 199
9.5.1. Commande électronique d'un servo-moteur.......................................................................... 200
9.5.2. Raccordement d'un servo-moteur ........................................................................................... 201
Noir, Rouge, Blanc ............................................................................................................................... 201
Marron, Rouge, Jaune .......................................................................................................................... 201
9.5.3. La librairie Servo ........................................................................................................................ 202

Chapitre 10 Universal Asynchronous Receiver Transmitter UART ..................................... 206


10.1. Introduction ..................................................................................................................................... 206
10.3. Diagramme UART ......................................................................................................................... 207
10.3.1. Niveaux de tension ...................................................................................................................... 207
10.3.2. Vitesse de transmission ................................................................................................. 208
10.4. VHDL Testbench (UART_TB.vhd): ........................................................................................... 213

Chapitre 11 Wishbone dans les systemes embarqués ........................................................... 216


11.1. Introduction ..................................................................................................................................... 216
11.2. Topologies des bus Wishbone ...................................................................................................... 216

Chapitre 12 Le Bus Serial Port Interface SPI ........................................................................ 242


12.1. Introduction ..................................................................................................................................... 242
12.2. Interface ........................................................................................................................................... 243
12.3. Fonctionnement .............................................................................................................................. 244
12.3. Synthese VHDL d'un Bus Serial Port Interface SPI ................................................................. 246

Chapitre 13 Le Bus I2C Inter Integrated Circuit................................................................... 252


13.1. Introduction ..................................................................................................................................... 252
13. 2. Caractéristiques .............................................................................................................................. 252
13.3. Le protocole I2C ............................................................................................................................. 253
13.3.1. La prise de contrôle du bus ................................................................................................... 253
13.3.2. La transmission d'un octet ..................................................................................................... 254

Page | 5 © ISI 2018 Ridha Ghayoula


13.3.3. La transmission d'une adresse ............................................................................................... 254
13.3.4. Ecriture d'une donnée ............................................................................................................ 255
13.3.5. Lecture d'une donnée ............................................................................................................. 256
13.4. La gestion des conflits .................................................................................................................... 256
13.4.1. Mise en situation ..................................................................................................................... 256
13.4.2. Principe..................................................................................................................................... 256
13.4.3. Analyse : ................................................................................................................................... 257
13.4.4. Les nouvelles caractéristiques ............................................................................................... 257
13.5. Les adresses réservées .................................................................................................................... 258
13.5.1. Adresses d'appel général ........................................................................................................ 258
13.5.3. Début d'adresse CBUS ........................................................................................................... 258
13.5.4. Autres ....................................................................................................................................... 258
13.6. Exemples .......................................................................................................................................... 259

Chapitre 14 Synthese d'un filtre FIR passe-bas pour les Signaux ECG ............................... 296
14.1. Introduction ..................................................................................................................................... 296
14.2. Filtre à réponse impulsionnelle finie ............................................................................................ 297
15.1. Introduction ..................................................................................................................................... 303

Chapitre 15 Programmation des microcontrôleurs PIC en langage C .................................319

Chapitre 16 Programmation des microcontrôleurs STM32..............................................333

Chapitre 17 Altium Designer ................................................................................................. 392


17.1. Introduction ..................................................................................................................................... 392
17.3. Flot de conception d’une carte électronique ............................................................................... 400
17.10. Conception FPGA avec Altium Designer ................................................................................ 423

Chapitre 18 Introduction à la création et à la Packaging Custom IP ................................... 436


18.1. Introduction ..................................................................................................................................... 436
18.2. Creating a custom IP in Vivado.................................................................................................... 436

Chapitre 19 Introduction à la programmation avec Python ................................................ 449


19.1. Introduction ..................................................................................................................................... 449
19.2. Calculer avec Python ...................................................................................................................... 449

Chapitre 20 TCL/TK Vivado ................................................................................................ 457

Page | 6 © ISI 2018 Ridha Ghayoula


20.1. Introduction ..................................................................................................................................... 457
20.1. TCL ................................................................................................................................................... 457
20.1. 1. Exemple de script: flux de compilation non-projet ............................................................... 459
20.2. Conseils d'automatisation Tcl pour Vivado et Xilinx SDK ...................................................... 468

Chapitre 21 Création des fichiers MCS (Configuration Memory File) Vivado .................... 472
21.1. Introduction ..................................................................................................................................... 472
21.2. Conventions..................................................................................................................................... 472
21.3. Architecture matérielle ................................................................................................................... 472
22.4. Chargement de la clé de cryptage ................................................................................................. 486

Chapitre 22 Génération de fichiers cryptés pour les Series 7............................................481

Chapitre 23 Vivado Design Suite avec les contraintes XDC ................................................. 493
23.1. Introduction ..................................................................................................................................... 493
23.2. Organisation des contraintes ......................................................................................................... 493

Chapitre 24 Software Development Kit (SDK)................................................................... 508

Les Références Bibliographiques .......................................................................................... 533

Page | 7 © ISI 2018 Ridha Ghayoula


Introduction

Un système embarqué est un système complexe qui intègre du logiciel et du matériel conçus
ensemble afin de fournir des fonctionnalités données. Il contient généralement un ou plusieurs
microprocesseurs destinés à exécuter un ensemble de programmes définis lors de la conception et
stockés dans des mémoires. Le système matériel et l'application (logiciel) sont intimement liés et
immergés dans le matériel et ne sont pas aussi facilement discernables comme dans un
environnement de travail classique de type ordinateur de bureau PC( Personal Computer) .
Un système embarqué est autonome et ne possède pas des entrées/sorties standards tels qu'un
clavier ou un écran d'ordinateur. Contrairement à un PC, l'interface IHM (Interface Homme
machine) d'un système embarqué peut être aussi simple qu'une diode électroluminescente LED(
Light Emitter Diode) qui clignote ou aussi complexe qu'un système de vision de nuit en temps réel ;
les afficheurs à cristaux liquides LCD (Liquid Crystal Display) de structure généralement simple sont
couramment utilisés. Afin d'optimiser les performances et la fiabilité de ces systèmes, des circuits
numériques programmables FPGA (Fild Programmable Gate Array), des circuits dédiés à des
applications spécifiques ASIC (Application Specific Integrated Circuits) ou des modules analogiques
sont en plus utilisés. Le logiciel a une fonctionnalité fixe à exécuter qui est spécifique à une
application. L'utilisateur n'a pas la possibilité de modifier les programmes. Bien souvent, il n'a pas
conscience d'utiliser un système à base des microprocesseurs.
Les systèmes embarqués sont désormais utilisés dans des applications diverses tels que le transport
(avionique, espace, automobile, ferroviaire), dans les appareils électriques et électroniques (appareils
photo, jouets, postes de télévision, électroménager, systèmes audio, téléphones portables), dans la
distribution d'énergie, dans l'automatisation, …, etc.
Ces systèmes représentent le premier marché de l'électronique. Ils sont interconnectés et agissent à
travers des réseaux, dans un environnement où la vitesse et la quantité de données échangées
croissent rapidement. Les enjeux dans ce domaine se situent dans la maîtrise de la complexité, la
diminution de coûts de production du logiciel, la performance et la robustesse des architectures
matérielles et logicielles.
Linux a fait des percées plus que significatives dans ce domaine. Dans un contexte où robustesse,
légèreté et interopérabilité sont essentielles, le système libre Linux se révèle un excellent choix : open
source et libre de droits, il peut être adapté et diffusé à grande échelle pour un coût de licence nul. À
travers ce cours orienté vers la pratique, les étudiants développent une expertise dans la conception,
le développement et l'intégration du matériel et du logiciel. Celle-ci leur permet d'adapter les
solutions technologiques aux contraintes des différents environnements de déploiement. Les
étudiants œuvrent par la suite au sein d'équipes multidisciplinaires dans des domaines d'emploi très
variés tels les équipes de conception et développement de produits ou les bureaux d'études.

Objectif et plan de cours


De manière générale le cours vise à:
présenter des méthodes de vérification pour s'assurer que le logiciel d’un système embarqué travaille
correctement avec le matériel et que le matériel a été correctement conçu pour exécuter le logiciel ;
sensibiliser l’étudiant au compromis à faire entre les réalisations logicielles et matérielles, et rendre les
étudiants conscients du gain potentiel de productivité que permet la conception et la vérification
conjointe du logiciel et du matériel.

Page | 8 © ISI 2018 Ridha Ghayoula


Au terme de ce cours, l'étudiant:
Pourra faire la conception (design et vérification) conjointe d’un système embarqué comprenant des
composants logiciels et matériels ; pourra faire le lien entre certains aspects du génie logiciel et de la
micro-électronique; sera au courant des travaux de recherche et de développement récents dans le
domaine de la conception et de la vérification de systèmes embarqués numériques, et pourra évaluer
un outil de conception et de vérification de niveau système.

Page | 9 © ISI 2018 Ridha Ghayoula


1
Introduction aux systèmes embarqués

1.1. Introduction
Un système embarqué est défini comme un système électronique et informatique autonome, souvent
temps réel, spécialisé dans une tâche bien précise. Le terme désigne aussi bien le matériel
informatique que le logiciel utilisé. Ses ressources sont généralement limitées. Cette limitation est
généralement d'ordre spatial (encombrement réduit) et énergétique (consommation restreinte).
Le premier système moderne embarqué reconnaissable a été le Apollo Guidance Computer, le
système de guidage de la mission lunaire Apollo, développé par Charles Stark Draper du
Massachusetts Institute of Technology. Chaque mission lunaire était équipée de deux systèmes
(AGC), un chargé du système de guidage inertiel et un pour le Module lunaire.

Un système embarqué est un système servant à résoudre des fonctions et des tâches spécifiques et
limitées.
Associé à contraintes en temps réel
 Souvent conçu en matériel avec des parties en logiciel.
 La complexité du système et des fonctions varient largement
 Contrôleur d’un lave-vaisselle
 Portable MP3
 Contrôleur de missiles
 Le logiciel est utilisé pour la flexibilité
 Le matériel est utilisé pour la performance et la consommation

1.2. Caractéristiques des systèmes embarqués


Les systèmes embarqués fonctionnent généralement en Temps Réel (TR) : les opérations de calcul
sont alors faites en réponse à un événement extérieur (interruption matérielle). La validité et la
pertinence d'un résultat dépendent du moment où il est délivré. Une échéance manquée induit une
erreur de fonctionnement qui peut entraîner soit une panne du système (plantage), soit une
dégradation non dramatique de ses performances.
Lorsque les systèmes embarqués sont utilisés dans les produits de grande consommation, ils sont
fabriqués en grande série. Les exigences de coût se traduisent alors en contraintes sur les différentes
composantes du système : utilisation de faibles capacités mémoires et de petits processeurs (4 bits ou
8 bits), mais en grand nombre. Ainsi, les systèmes embarqués sont particulièrement sensibles au coût
de production. Il existe des applications dans lesquelles les contraintes de coût de production et de
maintenance ont une importance de même niveau que les performances envisagées.

Page | 10 © ISI 2018 Ridha Ghayoula


Dans les systèmes embarqués autonomes, la consommation d'énergie est un point critique pour le
coût. En effet, une consommation excessive augmente le prix de revient du système embarqué, car il
faut alors des batteries de forte capacité.

1.3. Complexité des systèmes embarqués


Les système embarqués requièrent souvent un faible encombrement (faible poids) PDA(Personal
Digital Assistant) , Internet et téléphone mobiles, …). Leur technologie fait alors appel à une
électronique et à des applications portables où l'on doit minimiser aussi bien l'encombrement que la
consommation électrique. Par conséquent, la réalisation du packaging afin de faire cohabiter sur une
faible surface de l'électronique analogique, de l'électronique numérique, des composantes RF
(Radiofréquence) sans interférences est une tâche difficile. En effet, les performances des systèmes
sur carte deviennent obsolètes dans le contexte des besoins actuels. Dans les stratégies de
conception actuelles, un système embarqué est généralement intégré sur un support silicium unique
constituant ainsi un système complet intégré sur une puce SoC(System on a Chip).

Les systèmes sur puce contiennent généralement une grande variété de dispositifs programmables
tels que des microcontrôleurs, des processeurs de traitement de signaux DSP (Digital-Signal
Processor) et des ASIC qui sont développés pour des applications complexes nécessitant une
production en grande série.

Les mémoires (ROM et RAM) y sont intégrés pour le stockage des données et des programmes. Ces
composants digitaux cohabitent généralement sur le même support de silicium avec des composants
analogiques et mixtes divers tels que des composantes radiofréquence (RF) comme moyen de
communication, des composantes optiques pour le transfert de données à haut débit, des MEMS
(Micro Electro Mechanical System) pour l'interfaçage avec le monde externe, des convertisseurs
analogiques/numérique et numérique/analogique requis pour le dialogue interne. L'objectif est
d'obtenir une coopération harmonieuse entre composants embarqués afin de garantir des services
globaux. Des contraintes d'implémentation physique sont liées à la consommation de ressources et
au contexte de déploiement tel que le poids, la taille physique, la résistance aux vibrations, ou aux
irradiations, …, etc.

1.4. Définition des systèmes embarqués


Quelle que soit la nature et la complexité du système, on décompose un système embarqués en :

 le système contrôlé
 le système de contrôle

Le système contrôlé = environnement (procédé) équipé d'une instrumentation qui réalise


l'interface avec le système de contrôle

Le système de contrôle = éléments matériels (microprocesseurs…) et logiciels dont la mission est


d'agir sur le procédé via les actionneurs en fonction de l'état de ce procédé indiqué par les capteurs
de manière maintenir ou conduire le procédé dans un état donné

Page | 11 © ISI 2018 Ridha Ghayoula


Interface Capteurs

Systeme
informatique
Procédé

Interface Actionneurs

Environnement
Figure 1.1. Système électronique embarqué

Un système électronique embarqué ou enfoui est un élément constitutif d'un système plus complexe
pour lequel il rend des services bien précis (contrôle, surveillance, communication…). Il est
constitué de parties matérielles et logicielles qui sont conçues spécifiquement pour réaliser une
fonction dédiée.

Système embarqué = Système électronique/informatique conçu pour réaliser une ou plusieurs tâches
précise.

Les caractéristiques principales d'un système électronique embarqué sont :

 Autonomes: Une fois enfouis dans l'application ils ne sont (le plus souvent) plus accessibles
 Temps réel: Les temps de réponses de ces systèmes sont aussi importants que l'exactitude
des résultats
 Réactifs: Il doit réagir à l'arrivée d'informations extérieures non prévues

Comparaison aux systèmes informatiques standards :


Informatique : Embarqué :

 Processeur standard  Processeur dédié (contrôleur)


o Multiples unités fonctionnelles o Architecture adaptée
(flottant) o Vitesse faible (~200 MHz)
o Vitesse élevée (> GHz) o 8-32bits : mémoire limitée
o Consommation électrique o Basse consommation
élevée o Petite taille, grand volume =>
o Chaleur faible coût
o Taille  Processeur DSP (traitements)
 MMU (mémoire virtuelle) o Très puissants
 OS  Quelques Mo de mémoire

Page | 12 © ISI 2018 Ridha Ghayoula


 Cache  RTOS
 Grand nombre de périphériques

1.5. Classification des systèmes embarqués


 Temps réel dur (‘hard real-time’) : le non respect des contraintes temporelles entraîne la faute
du système
– Exemple : contrôle de trafic aérien, système de conduite de missile, ...
 Temps réel souple (‘soft real-time’) : le respect des échéances est important mais le non
respect des échéances n’a pas de graves conséquences
– Exemple : système d'acquisition de données pour affichage
 Temps réel ferme (‘firm real-time’) : temps réel souple, mais si l’échéance est dépassée le
résultat obtenu n’a plus de valeur (et est donc écarté)
– Exemple : Projection vidéo

1.5.1. Système Transformationnel

Activité de calcul, qui lit ses données et ses entrées lors de son démarrage, qui fournit ses sorties,
puis meurt.

1.5.2. Système Interactif

Système en interaction quasi permanente avec son environnement, y compris après l'initialisation du
système; la réaction du système est déterminée par les événements reçus et par l'état courant
(fonction des événements et des réactions passés); le rythme de l'interaction est déterminé par le
système et non par l'environnement.

1.5.3. Système Réactif ou Temps Réel :

Système en interaction permanente avec son environnement, y compris après l'initialisation du


système; la réaction du système est déterminée par les événements reçus et par l'état courant
(fonction des événements et des réactions passées); mais le rythme de l'interaction est déterminé
par l'environnement et non par le système.

Page | 13 © ISI 2018 Ridha Ghayoula


Exercices
Exercice1 : Compteur/DécompteurConception d'un système de
gestion de parking
Le but de notre système est de gérer la disponibilité des places de parking. Ce système possède 4
signaux d’entrée (mode in) les captures d’entrée-sortie de type std_logic, l’horloge et le nombre
maximal de places dans le parking (mot binaire de 4 bits de type std_logic_vector). Les entrées
capteurs servent à incrémenter ou à décrémenter le compteur (4 bits). La sortie de compteur est
comparée au nombre maximal de places dans le parking.
Les signaux de sortie (mode out) sont :
PD = 1 s’il reste des places disponibles si non PD=0 (type std_logic).
PC= 1 si le parking est complet si non PC=0 (type std_logic).

Capteur
d’entrée
Compteur
Horloge
Nombre Max
de places
Capteur
de sortie

Comparateur
≥ <

Parking « Passer » Places


Complet PC disponibles PD

Figure 1. Système de gestion de parking

1. Ecrire l’entité et l’architecture en VHDL d’un compteur 4 bits et d’un comparateur 4bits de
système de gestion de parking.
2. En déduire la description structurelle pour ce système.

Exercice 2 : Gestionnaire de réservoir d’essence de voiture


Soit un circuit d’un gestionnaire de réservoir d’essence de voiture niveau_réservoir. Deux jeux de
senseurs sont positionnés aux deux niveaux du réservoir comme illustré par la Figure 1.
Ces senseurs sont placés dans le réservoir. Ils donnent une valeur logique quand ils baignent dans
l'essence, et une valeur 0 autrement. Ces signaux permettent de calculer le niveau d'essence du
réservoir. Le niveau d’essence est calculé comme suit :
• Si les senseurs du niveau_H sont égaux et leurs valeurs sont différentes de zéro alors le niveau de
sortie niv_out prendra la valeur de niv_S2_A.

Page | 14 © ISI 2018 Ridha Ghayoula


• Dans le cas contraire, le niveau de sortie niv_out sera égal à la valeur de niv_S1_A si les valeurs de
niv_S1_A et niv_S1_B sont égales, sinon niv_out prendra la valeur zéro.

Niveau_H
Niv_S2_A Niv_S2_B

Niveau_L

Niv_S1_A Niv_S1_B

Figure 1. Exemple de positionnement de senseurs dans le réservoir

N Niv_S1_A N
Niv_out
N Niv_S1_B

N
Niv_S2_A N
N Erreur
Niv_S2_B

Figure 2. Interface de réservoir

Les ports de l’entité niveau_réservoir sont décrits comme suit :


• Les entrées niv_S2_A et niv_S2_B donnent la valeur du niveau supérieur.
• Les entrées niv_S1_A et niv_S1_B donnent la valeur du niveau inférieur.
• Le port de sortie niv_out aura la valeur niv_S2_A si le niveau supérieur est actif à savoir que
niv_S2_A et niv_S2_B sont égaux et que leur valeur est différente de zéro. Niv_out prendra la valeur
de niv_S1_A dans le cas contraire et seulement si niv_S1_A et niv_S1_B sont égaux sinon niv_out
aura la valeur zéro.
• Le port de sortie erreur sera activé si niv_S2_A et niv_S2_B ont des valeurs différentes OU si
niv_S1_A et niv_S1_B ont des valeurs différentes.
Le port erreur est un std_logic alors que les ports, niv_s2_B, niv_S1_A, niv_S1_A et niv_out sont des
vecteurs de N bits non-signés (unsigned).

1. Donnez l’entité et l’architecture synthétisable de niveau_réservoir.

Exercice 3 : Système de télécommunication embarqué


Nous présentons dans cet exercice une plateforme électronique dédiée à la mise en œuvre d’un
système de télécommunication embarquée. Nous arborons dans un premier temps notre démarche
de conception d’une carte de commande à base de Spartan-3E. Notre approche ici vise une
architecture générique, dynamiquement reconfigurable permettant l’implémentation directe des

Page | 15 © ISI 2018 Ridha Ghayoula


phases synthétisées sur une carte Spartan-3E capable de supporter tous les cas de synthèse de
diagrammes de rayonnement (un lobe directif seul, un lobe directif et zéro, deux lobes directifs). Le
Circuit de commande est élaboré sous forme d’une propriété intellectuelle codée en VHDL et
synthétisable sur FPGA ou ASIC.
Dans un second temps, deux aspects principaux sont développés dans cet exercice. Une
présentation générale de la constitution matérielle du prototype de communication embarqué, de
son fonctionnement et de sa mise en œuvre avec des techniques de modulations (AM, Modulation
en quadrature,…).

1. Conception.
1.1 Le synoptique de la carte.
A partir des différentes solutions techniques énumérées, nous pouvons établir un synoptique de la
carte Xilinx Spartan-3E où le composant central est le circuit XC3S500-4fg320. Sur le coté gauche
du FPGA, nous trouvons toutes les entrées (Sector_lobe, Sector_zero,…), alors que de l’autre coté
nous retrouvons celles de la face avant de notre carte (les phases synthétisées).
De ce fait, nous avons pu déterminer le nombre d’entrées sorties nécessaires à notre FPGA pour le
bon fonctionnement de notre carte (Figure .1).
Deux organes de liaison avec la carte Xilinx Spartan-3E ont été introduits :
- les entrées (Sector_lobe, Sector_zero,…)
- La liaison parallèle (les phases synthétisées) avec la carte fille.

Page | 16 © ISI 2018 Ridha Ghayoula


OL

SMA SMA
DEM

Sector_lobe Sector_zero
1 1

FPGA
FPGA
1 2

AD8347
Registre

Phase Shifters
1 i 

FPGA
FPGA 1 8
Carte Fille

SPARTAN-3E
(XC3S500- SMA SMA
4fg320)
DEM

1 1

1 2
8 i 
Registre

1 8

Figure.1. Schéma synoptique de l’architecture proposée.

En général, Quelles sont Les composants hardware and software nécessaire dans notre système?
1.2. Le synoptique du programme.
Pour réaliser la gestion de notre carte, nous avons établi le synoptique du programme. Dans celui-ci
sont regroupés huit fonctions principales que sont :
 Trois espaces mémoires : pour le stockage des phases synthétisées par le réseau de neurones
dans les cas : d’un lobe et zéro "Mem_LZ" , d’un seul lobe" Mem_L" et deux lobes
"Mem_2L ".
 Trois décodeurs d’adresses pour convertir le résultat de pointage angulaire pour adresser aux
blocs mémoires "Mem_L", " Mem_LZ " et " Mem_2L ".

Page | 17 © ISI 2018 Ridha Ghayoula


 la fonction “Multiplexeur” qui délivre des phases synthétisées suivant le type de pointage.
 La fonction “Registre de décalage à chargement parallèle synchrone ”.
Le synoptique qui suit regroupe toutes les fonctions énumérées précédemment ainsi que toutes les
entrées sorties de celles-ci. On remarque que toutes les fonctions d’acquisitions de paramètres seront
synchrones avec l’horloge 4 Mhz. De plus, il n’existe non seulement les entrées sorties du FPGA,
mais également des entrées sorties internes au FPGA telles que le déclenchement, la sélection des
fonctions, etc.…( Figure .2)

Load_L
Load_LZ
Load_2L
Act_L_Z
Sector_zero
9 bits
Dec_adr (LZ)

Adress_mem

Sector_lobe
Mémoire
(phases)
17 bits
[Lobe_zero]

Act_L
FPGA
Registre à décalage à chargement parallèle

5 bits
1 i 
Dec_adr (L)

Sector_lobe
2 i 
3 i 
Adress_mem

17 bits Mémoire
(phases) 4 i 
MUX

[Lobe] 5 i 
6 i 
7 i 
8 i 
Act_2L

9 bits
Sector_2lobe
Dec_adr (2L)

Adress_mem

Mémoire
(phases)
17 bits
[2lobes]

Figure 2. Schéma bloc détaillé

Page | 18 © ISI 2018 Ridha Ghayoula


L’algorithme de commande, donne la schématisation de haut niveau (top Level) de l’IP
implémentant le circuit FPGA.
On distingue trois modes de fonctionnement :
 Le mode de commande (Act_L). Il s’agit dans ce cas d’un accès direct au mémoire
mem_lobe.
 Le mode de commande (Act_L_Z), Il s’agit d’un accès direct au mémoire mem_lobe_zero.
 Le mode de commande (Act_2L_Z), Il s’agit d’un accès direct au mémoire mem_2lobes.
- Ecrire les programmes VHDL de différentes composantes de notre carte de commande
a. Mémoires (Mem_L, Mem_LZ et Men_2L)
Les Figures (a,b,c) schématisent les entrées/ sorties de différents blocs mémoires "Mem_L",
"Mem_LZ"et "Mem_2L".
17..0 17..0
5 bits 9 bits
Adress_mem

Adress_mem
Mémoire Mémoire

clk
Mem_L clk
Mem_LZ
rst 8 7..0 rst (a) 8 7..0
(b)

Entrées /sorties du bloc « Mem_L »


Entrées /sorties du bloc « Mem_LZ »

17..0
9 bits
Adress_mem

Mémoire

clk
Mem_2L
rst 8 7..0

Entrées /sorties du bloc « Mem_2L»


Figure 3. Memoires

Chaque bloc mémoire génère huit signaux de sortie ( 1 7..0 ,…,  8 7..0]) et une entrée
Adress_mem est destinée à l’adressage aux blocs mémoires (Tableau 1).

Page | 19 © ISI 2018 Ridha Ghayoula


[Adress_mem(0)] 1 7..0 …… 8 7..0
[ Adress_mem(1)] 1 7..0 …… 8 7..0
… … ……
[Adress_mem(n-2)] 1 7..0 …… 8 7..0
[Adress_mem(n-1) 1 7..0 …… 8 7..0

Tableau 1. Adressage aux blocs mémoires


b. Des décodeurs d’adresse
Le but de ces fonctions est de décoder les signaux d’entrées en adresses mémoires suivant le type et
la position du pointage angulaire. En effet par l’intermédiaire du bus“ Sector_lobe” et “
Sector_zero” l’utilisateur pourra écrire les différents états angulaires (1 bit = 1 pointage).

Adress_mem

Adress_mem
Sector_zero
Sector_lobe Décodeur des Décodeur des
adresses 5 bits adresses
Dec_Adress_L Dec_Adress_LZ
Sector_lobe
17 bits
5 bits 9 bits
17 bits

(a) Entrées /sorties du bloc « Dec_Adress_L» (b) Entrées /sorties du bloc


« Dec_Adress_LZ »
Adress_mem

Sector_lobe Décodeur des


adresses
Dec_Adress_2L
17 bits
9 bits

(c) Entrées /sorties du bloc « Dec_Adress_2L »


Figure 4. Decodeurs

A titre d’exemple (Décodeur d’adresse Lobe),

Page | 20 © ISI 2018 Ridha Ghayoula


Adresse 1 Sector_lobe_1

Adresse 2 Sector_lobe_2

Adresse n Sector_lobe_n

Figure 5.Table des adresses de la mémoire.

c. La fonction Registre à décalage à chargement parallèle "DECAL_P8"


Pour la gestion de notre carte par le bus des phases synthétisées (64 bits), nous utilisons différents
registres à décalage à chargement synchrone. De ce fait, pour lire une donnée d’un bloc mémoire il
faut dans un premier charger les phases de façon parallèle, puis dans un second envoyer ces phases
en série pour résoudre la contrainte matérielle (nombres des connecteurs FX2) posée par la carte.
C’est pour cela que nous avons utilisé ces registres dans notre carte.

1 2 8

1 1 1
D Q D Q D Q
0 0 0 OUT
R R R

Clk
Load
Rst

Figure 6. Registre à décalage à chargement parallèle "DECAL_P8"


d. La fonction Multiplexeur"MUX"
Cette fonction permet de gérer le multiplexage des phases suivant le mode de fonctionnement de la
carte. En effet c’est par cette fonction on peut lire les différents sorties de registres à décalages.

Page | 21 © ISI 2018 Ridha Ghayoula


Act_L Act_LZ Act_2L

MEM_L
MEM_LZ

MEM_2L

 7..0  7..0  7..0


Figure 7. Commande du bloc «MUX »

17..0
MEM_L
8 7..0
1i 

17..0
MUX

MEM_LZ
8 7..0
8 i 

17..0
MEM_2L
8 7..0

Act_L
Act_LZ
Act_2L

Figure 8. Entrées /sorties du bloc «MUX »


2. Implémentation.
Le matériel utilisé pour cette implémentation est le « Spartan-3E Starter Kit » de la société Xilinx.
Cette carte d’évaluation contient un FPGA de la famille Spartan-3E (XC3S500-4FG320), ainsi que
de la RAM statique, des ports PS/2, VGA et RS232, 4 DAC, Intel StrataFlash Flash Memory 128
Mbit, Xilinx XC2C64A, CoolRunner-II CPLD, Maxim DS2432 serial EEPROM, des connecteurs

Page | 22 © ISI 2018 Ridha Ghayoula


d’extension (Hirose 100-pin FX2 Connector, J1 6-pin Accessory Header,…), des LEDs, switches,
afficheur LCD…

Figure 9.Photo de la carte de prototypage Figure 10.Photo de la carte de prototypage


FPGA FPGA
Les logiciels utilisés sont ceux fournis gratuitement par Xilinx ISE 8.1i Foundation Evaluation pour
la conception et la simulation. Nous avons utilisé aussi le ModelSim XE III Starter 6.1e (version
gratuite) disponible en téléchargement chez Xilinx, ce simulateur étant plus complet que celui d’ISE.
2.1. En général, citez le Plateforme et outils logiciels de développement ?
2.2. A partir des résultats de simulations expliquer le principe de fonctionnement de notre carte de
commande et déterminer les phases synthétisées dans chaque cas ?

Figure 11. Résultats de la simulation du testbench de carte Spartan (dans les trois cas : un lobe, un
lobe et zéro et deux lobes)
Exercice 4 : Processeur à but spécifique
Nous désirons concevoir un processeur à but spécifique qui gère une machine à café. L’entité du
gestionnaire de la machine à café est comme suit :

Page | 23 © ISI 2018 Ridha Ghayoula


entity gest_machine_a_cafe is
generic (
prix_cafe1 : positive;
prix_cafe2 : positive
);
port ( reset : in std_logic;
clk : in std_logic;
piece_introduite : in unsigned(6 downto 0);
piece_introduite_valide : in std_logic;
choix_cafe : in std_logic;
fermer_entree_piece : out std_logic;
annuler : in std_logic;
servir_cafe : out std_logic;
cafe_servi : in std_logic;
activer_cafe1 : out std_logic;
activer_cafe2 : out std_logic;
piece_a_rendre : out unsigned(6 downto 0);
piece_a_rendre_valide : out std_logic
);
end gest_machine_a_cafe;

reset
fermer_entree_piece
Clk
FPGA servir_cafe piece

piece_introduite
( Processeur à but activer_cafe1 piece

piece_introduite_valide spécifique) activer_cafe2 piece


de
choix_cafe
piece_a_rendre
annuler piece
piece_a_rendre_valide piece
cafe_servi

Le client a le choix entre café1 (choix_cafe = ‘0’) ou café2 (choix_cafe = ‘1’). Les prix des cafés sont
des paramétres génériques : prix_cafe1 et prix_cafe2.
La partie mécanique de la machine à café comprend la fente dans laquelle le client introduit des
pièces, la sortie par laquelle les pièces de la monnaie sont rendues et la structure qui sert les cafés.
Ces parties mécaniques envoient et/ou recoivent des requêtes au gestionnaire. Ce dernier attend que
le client fasse son choix et qu’il glisse des pièces dans la fente jusqu’à ce que le total des pièces
introduites soit supérieur ou égal au montant du café à servir. Lorsque ce montant est atteint alors
un ordre sera émis à la partie mécanique pour que le café soit servi (servir_cafe = ‘1’). Ensuite, le
gestionnaire calculera le montant de la monnaie à rendre.
La machine ne peut recevoir ou retourner que des pièces de 1$, 25 cents, 10 cents ou 5 cents.
Le montant de la piece introduite est en cents donc lorsqu’une pièce de 1$ est introduite l’entrée
piece_introduite sera égale à 100.

Page | 24 © ISI 2018 Ridha Ghayoula


Pour éviter de considérer la même pièce plusieurs fois, le gestionnaire devra attendre que le signal
pièce_introduite_valide transite de ‘0’ à ‘1’ avant de considérer la nouvelle pièce.
Après avoir reçu l’avis que le café est servi (cafe_servi = ‘1’), le gestionnaire procédera à la remise de
la monnaie. Par rapport au montant introduit, le gestionnaire devra émettre des requêtes de remise
de pièces. Donc, par exemple, si le gestionnaire doit remettre 35 cents, il devra émettre l’ordre de
remettre une pièce de 25 cents puis d’une de 10 cents. Les ordres de remise de pièce doit être
séparée à savoir que le port piece_a_rendre_valide doit transiter de ‘1’ à ‘0’, pour que le second ordre
soit considéré.
Pendant que les pièces sont entrées, le client peut décider d’annuler sa commande. Dans ce cas, le
port annuler sera égal à ‘1’ et le gestionnaire devra émettre les ordres de remise de pièces afin de
rendre au client le montant de pièces qu’il avait introduit avant l’annulation.
Pour éviter que le client introduise des pièces pendant que le café est servi ou que la monnaie est
remise, la fente des pièces entrées doit est fermée (fermer_entree_piece = ‘1’).
Les interfaces du gestionnaire de la machine à café se décrivent comme suit :

Port Description Port Description


reset Il réinitialise les ports et bascules internes du gestionnaire.
clk L’horloge du processeur.
piece_introduite Le montant de la pièce introduite en cents.
La pièce introduite doit être considérée que lorsque ce port est égal à ‘1’. Ce port
piece_introduite_valide doit transiter de ‘0’ à ‘1’ entre l’introduction de deux pièces.
choix_cafe Lorsque ce port a la valeur ‘0’ alors le prix à charger devra correspondre à
prix_cafe1 sinon c’est prix_cafe2 qui sera utilisé.
Le gestionnaire doit mettre ce port à ‘1’ pour éviter que le client continue à
introduire des pièces pendant que le café est servi ou que la monnaie est remise.
fermer_entree_piece En attendant que le client introduise une nouvelle pièce et que le montant d’un
café soit introduit, le gestionnaire mettra ce port à ‘0’.
Lorsque ce port à la valeur ‘1’, cela signifie que le client veut annuler sa
commande et reprendre ses pièces. L’ordre d’annulation ne sera pas considéré
annuler pendant qu’un café est servi ou que la monnaie est rendue.

Ce port est égal à ‘1’ lorsque le total des pièces introduites est supérieur ou égal au
servir_cafe montant du café à servir. Ce port sera égal à ‘1’ jusqu’à ce que le café soit servi
(cafe_servi=‘1’), ensuite il retombera à ‘0’.
activer_cafe1 Ce port est égal à ‘1’ quand le montant du café a été introduit et que choix_cafe
est égal a ‘1’.
Ce port est égal à ‘1’ quand le montant du café a été introduit et que choix_cafe
activer_cafe2 est égal à '0'.

Ce port est égal à ‘1’ pour signifier que le café a été servi au client. Le gestionnaire
cafe_servi devra remettre la monnaie du client s’il y a lieu.
piece_a_rendre Le montant de la pièce à rendre.
piece_a_rendre_valide Lorsque ce port est égal à ‘1’, la partie mécanique sortira la pièce équivalente au
montant sur le port “piece_a_rendre”.

Pour concevoir le processeur à but spécifique, vous devez :


a) Compléter le diagramme de l’architecture simplifiée de votre circuit en montrant les signaux et ports qui sont
utilisés par le chemin de données et l’unité de contrôle.

Page | 25 © ISI 2018 Ridha Ghayoula


Chemin de
données

Unité de
contrôle

b) Donner le diagramme de la machine à états de l’unité de contrôle.

Exercice 4 : Télécommande Infrarouge


Une télécommande 16 touches à infra-rouge doit permettre à l’utilisateur de sélectionner un certain
programme (ici une LED) à distance. En entrée du circuit nous aurons donc les 16 touches de
l’appareil (l’horloge étant générée par une puce externe au circuit et la remise à zéro une touche à
part). Pour réaliser notre télécommande nous décrirons notre circuit comme ci-dessous :

Encodeur
E0
E1 Sequenceur
E2
E3
E4 Q(3:0) Q(3:0)
E5 APPUI APPUI S
E6
E7 H_10kHz
E8 RESET
E9
E10
E11
E12
E13
E14
E15
Compteur_3
APPUI Start
H_10kHz Code
Diviseur Frequence
RESET Stop
H
H H_10kHz

Reset

Nous utiliserons tout d’abord un encodeur pour transformer le signal 16 bits en signal 4 bits. En
sortie de ce bloc, un signal 4 bits comme prévu et un signal 1 bit APPUI qui permet de lancer le
compteur modulo 8 et le séquenceur, les deux autres principaux blocs. On mettra un diviseur de
fréquence pour avoir l’horloge du circuit à 10kHz au lieu des 250kHz en entrée. Le compteur 3 bits

Page | 26 © ISI 2018 Ridha Ghayoula


(modulo 8) nous permettra de définir précisément à tel instant donné quel doit être le signal de
sortie, à savoir le bit START ou le code Manchester ou bien le bit STOP. Quant au séquenceur il
renfermera la machine d’états accompagnée d’un registre à décalage ainsi que d’un générateur de
code Manchester et d’un multiplexeur.

A. DESCRIPTION BLOC PAR BLOC


La télécommande 16 touches possède donc 4 blocs que l’on va décrire dans les paragraphes
suivants. Le nombre de blocs est arbitraire puisqu’on aurait pu tous les grouper en un seul ensemble
ou au contraire les détailler plus (le séquenceur principalement).

1. ENCODEUR
Les 16 touches de la télécommande correspondent chacuneà un signal d’entrée à 16 bits.Ensortie on
aura logiquement un signal de 4 bits de "0000"à "1111", puisqu’il existe 24=16 possibilités, par
exemple pour 5 nous aurons5 => "0101", pour 1 =>"0001"etc.
Pour réaliser l’encodeur en VHDL, nous utiliserons la structure "case ... is when ... ", dontle code,
"touche" est l’entrée de 16bits, "S"la sortie de 4 bits etappui une autre sortiequi contrôle l’état du
bloc COMPTEUR_3et SEQUENCEUR.

a) CODEVHDL

Sur le premier signal on envoie successivement le code touche 9 (1111110111111111) puis un code
erroné (0111110111111111). Lorsque la touche est valide (nombre entre 1 et 16) la sortie correspond
(9 en binaire s’écrit bien 1001) et appui est active. Lorsque le code touche est erroné (donc pas
d’appui) le bit appuipasse bien à 0.

Page | 27 © ISI 2018 Ridha Ghayoula


2. COMPTEUR MODULO 8.
En sortie de notre télécommande nous devons avoir un signal composé de 3 signaux préalablement
préparés: leBit START sur 2 périodes T puis le Code Manchester sur 4 T et enfin -toujours à la suite
-le Bit STOP sur 2 T. Le signal de sortie sera donc une succession de signaux d’une longueur chacun
de 8 T. Pour déterminer lequel parmi les 3 signaux primaires doit être envoyé à l’instant t, on va
utiliser un compteur 3 bits, c’est-à-dire 8 possibilités, chacune correspondant à une période. A
chaque période on affectera les bits start, codeet stopselon le besoin:
Principalement, pour 0 et 1, on activera start, pour 2, 3, 4 et 5 on mettra codeà ‘1’ et enfin pour 6 et
7 on passera stopà ‘1’.
a) CODE VHDL

Page | 28 © ISI 2018 Ridha Ghayoula


3. DIVISEUR DE FREQUENCE
La fréquence d’entrée sur le CPLD est de 250 kHz et il est demandé de travailler en 10 kHz. On va
donc appliquer un diviseur de fréquence pour obtenir la fréquence d’horloge désirée. On va utiliser
un compteur modulo 25. Tant quel compteur n’est pas égal à 24 (de 0 à 24) on incrémente ce dernier
à chaque front montant d’horloge à 250kHz et à chaque fois que l’on arrive à 24, on applique le
signal inverse de celui obtenu à la fin du comptage précédent.
a) VHDL

Page | 29 © ISI 2018 Ridha Ghayoula


b) SIMULATION
On voit bien sur la simulation que la sortie clk_out change d’état tous les 25 fronts montants: on a
désormais une fréquence d’horloge divisée par 25, ce qui nous donne ici 10 kHz.

4. SEQUENCEUR
En entrée du séquenceur on aura tout d’abord le signal 4 bits sortant de l’encodeur, suivi du signal
appui permettant l’activation du circuit. D’une autre part on aura les 3 bits start, code et stop
synchrones qui aideront à déterminer la situation de la machine d’états. En sortie se trouvera
directement le signal final.
Dans le séquenceur se trouve la machine d’états. La voici en détails:
4 différents états sont gérés par l’automate

reset + appui
Etat
stop.appui REPOS appui

stop start

Etat stop.appui Etat


STOP START

code

Etat 1 start
CODE
code

4 différents états sont gérés par l’automate:


 Au REPOS: rien ne se passe, le signal S de sortie est à 0. Tant que l’on n’appuie pas sur une
touche (appui=0) ou que le reset est actif, l’état ne change pas. Par contre dès que l’on
appuie sur un bouton(appui=1), l’état passe à l’état START.
 À START: le premier bit start entre en jeu: tant qu’il est à 1, l’état reste inchangé. Pendant ce
temps, la sortie est à 1, puis au bout de 2 périodes, le bit start passe à 0: l’état passe quant à
lui à l’état CODE.
 À CODE: le bit code permet tant qu’il est à 1 de rester dans ce même état. Pendant ce
temps, le signal de sortie sera le code de notre touche au préalable convertis en code
Manchester. Au bout de 4 périodes, le bit code passe à 0, l’état devient l’état STOP.

 A STOP: même principe que pour les deux états précédents, tant que le bit stop est à 1
pendant les 2 périodes, l’état reste le même et le signal est 0 pendant cette durée, puis, dès
que stop est à 0, si on appuie toujours sur la touche (appui=1), on retourne à l’état START,
sinon à l’état REPOS.

Page | 30 © ISI 2018 Ridha Ghayoula


A l’automate s’ajoutent deux fonctions : un Registre à Décalage et un Convertisseur en Code
Manchester.
La première permet de rendre un signal d’entrée parallèle en signal de sortie série. En entrée on a
effectivement le code de la touche Q qui est un signal LOGIC VECTOR (3:0) et en sortie, un signal
LOGIC (0 ou 1). Par exemple, pour la touche 13 on a Q = 1101, donc au 1ier front montant la sortie
s décalage= 1, au 2èmesdécalage= 1, au 3èmesdécalage= 0 et au 4èmesdécalage= 1.
Le convertisseur en code Manchester va utiliser le signal série de la touche et le transformer. On
combinera (ou exclusif: XOR) l’horloge et s décalage pour obtenir le codage Manchester.

a) CODE VHDL

Page | 31 © ISI 2018 Ridha Ghayoula


Il a été très difficile de simuler le séquenceur tout seul car ses entrées (start/code/stop et H)sont
synchronisées par les autres blocs (compteur modulo 8 et diviseur de fréquence) et retranscrire ces
données sur le fichier FORCE est assez complexe. On a donc simulé le registre à décalage et le
convertisseur en code Manchester à part, quant au séquenceur on l’a simulé avec le fichier top level.
Nous avons finalement bien pu obtenir le signal de sortie demandé : 1 bit start / le code Manchester
/ le bit stop. Le plus compliqué a été d’ordonner le séquenceur entre le registre à décalage et la
machine d’états. Lors de l’implémentation sur la télécommande, les diodes ne s’allumaient
correctement. Nous avons essayé de résoudre les problèmes mais avons manqué de temps pour re-
tester le fichier .jed sur la télécommande.

Page | 32 © ISI 2018 Ridha Ghayoula


2
Conception de circuits (Co-Design)

2.1. Introduction
Ce chapitre vise à permettre de faire l'étude des différents circuits intégrés (circuits logiques
standards, circuits intégrés programmables, circuits intégrés pour application spécifiques, mémoires),
et de leurs applications dans la conception des systèmes embarqués; de maîtriser les outils CAO et la
méthodologie de conception pour la synthèse des circuits intégrés. Rappels sur les circuits logiques :
logique combinatoire (décodeurs, multiplexeurs, unités arithmétiques) et séquentielle (bascules,
compteurs, machines à états), considérations temporelles, de puissance et de surface. Technologies
de circuits intégrés : circuits logiques standards, circuits intégrés programmables (FPGA, CPLD),
circuits intégrés pour application spécifiques (ASIC), mémoires : SRAM, DRAM, FLASH EPROM.
Méthodologie de conception des circuits intégrés. Langages de description de circuits intégrés
numériques. Méthodes et outils pour la synthèse des circuits intégrés. Études de cas avec des
composants programmables.

2.2. Technologie des Circuits intégrés


2.2.1 Définition de classes d'intégration
Dans l’ordre chronologique, on distingue 4 classe d’intégration :
- Les microcircuits SSI (Single Size Intégration ) :  100 transistors par cm2.
- Les circuits intégrés MSI ( Médium Size Intégration ) :  1000 transistors par cm2.
- Les circuits LSI (Large Size Intégration) :  10000 à 100000 transistors par cm2.
- Les circuits VLSI (Very Large Size Intégration ) :  0.1 à 1 million transistors par cm2.

2.2.2. Notion de niveaux logiques:


Pour une famille donnée, les niveaux logiques « 0 » et « 1 » ne correspondent pas à une tension
précise, mais à une certaine « plage » de tension.
 On appellera pour les valeurs de tension en entrée (Input ):
- VIHmin : Tension minimale en entrée qui assure le niveau logique haut.
- VILmax : Tension maximale en entrée qui assure le niveau logique bas.

Page | 33 © ISI 2018 Ridha Ghayoula


Vcc
1
Caractéristique d’entrée


VIHmin

( Etat indéfini )

VILmax 0
Figure 2.1. Niveaux logiques (entrée)
On appellera pour les valeurs de tension en sortie ( Output ):
VOHmin : Tension minimale de sortie à l’état logique haut.
V0Lmax : Tension maximale de sortie à l’état logique bas.
Vcc
1
VOHmin


Caractéristique de sortie

( Etat indéfini )
VOLmax
0
Figure 2.2. Niveaux logiques (sortie)

2.2.3. Compatibilité des niveaux logiques

Vcc VOHmin - VIHmin Vcc


1 1
VOHmin
VIHmin
 
( Etat indéfini )
VILmax - VOLmax ( Etat indéfini )

VOLmax VILmax
0
0
0 0
Niveaux de sortie circuit 1 Niveaux d’entrée circuit 2
Figure 2.3. Niveaux logiques

Compatibilité au niveau haut : Il faut que VOHmin > VIHmin


Compatibilité au niveau bas : Il faut que VILmax > VOlmax

2.2.4. Temps moyen de propagation


Lorsqu’on applique à l’entrée d’un circuit un niveau logique, il y a un certain retard pour que la sortie
réagisse. Cette durée est le temps moyen de propagation tPD.
tPHL tPLH
S
Entrée Sortie

50%

t
Figure 2.4. Temps moyen de propagation

tPHL: Temps de propagation du niveau haut au niveau bas.

Page | 34 © ISI 2018 Ridha Ghayoula


tPLH: Temps de propagation du niveau bas au niveau haut.
tPD = (tPHL + tPLH ) / 2

Remarque : Ce temps détermine la fréquence maximale FMAX à laquelle les circuits intégrés sont capables de
réagir.

2.2.5. Facteur de charge : Sortance N.


Ce paramètre caractérise le nombre N maximal d’entrées de portes logiques pouvant être
commandées par la sortie d’un autre opérateur logique de la même famille.

IO II
X X
IOH : Courant de sortie maximal à l’état haut
II IOL : Courant de sortie maximal à l’état bas
X
IIH : Courant d’entrée maximal à l’état haut
II IIL : Courant d’entrée maximal à l’état bas
X

Sortance N ( A l’état haut ) = IOH / IIH


Sortance N ( A l’état bas ) = IOL / IIL

Remarque : La documentation constructeur fournie les données suivantes : IOH, IIH, IOL, IIL.

2.2.6. Notion de familles de circuits logiques


Il existe plusieurs familles de circuits technologiques. Les 2 plus utilisées sont :
- TTL ( Transistors Transistors Logic )
Exemples :
TTL standard (n ’est plus utilisée) 74 00
TTL Low Power 74 L 00
TTL Schottky (Rapide) 74 S 00
TTL Low Power Schottky 74 LS 00
TTL Advanced Schottky 74 AS 00
TTL Advanced Low Power Schottky 74 ALS00

Caractéristiques de fonctionnement :
Gamme d’alimentation : 5 V +/- 5%.
Gamme de température : de 0 °C à + 70 °C.
Puissance dissipée : environ 2 mW par porte (série LS).
Fréquence de fonctionnement : jusqu’à 3 MHz.
Sortance : jusqu’à 20 (série LS).
(Nombre d’entrées que l’on peut relier à une sortie de porte)

- CMOS (transistors à effet de champ MOS - Complémentaire - Métal - Oxyde - Semiconducteur)

Exemples :
Série 4000 :
40 00 B (sorties bufférisées : amplifiées)
Page | 35 © ISI 2018 Ridha Ghayoula
40 00 UB (sorties non-bufférisées)
Série 74 :
74 C 00 (identique à la série 4000)
74 HC 00 (High-speed CMOS : CMOS rapides)

Caractéristiques de fonctionnement :
Gamme d’alimentation : de 3 V à 15 V.
Gamme de température : de – 40 °C à + 85 °C.
Puissance dissipée : environ 10 nW par porte.
Fréquence de fonctionnement : jusqu’à 12 MHz.
Sortance : jusqu’à 50 (série 4000B).
(Nombre d’entrées que l’on peut relier à une sortie de porte)
Excellente immunité aux bruits.

2.2.7. Un inverseur en technologie CMOS


L’inverseur propose la fonction suivante: si l’entrée vaut 1, la sortie vaut 0, sinon elle vaut 1. La table
de vérité est donnée ci-dessous. Le symbole de l’inverseur est non équivalent CMOS sont aussi
reportés.

Figure 2.5. Un inverseur en technologie CMOS


2.2.8. Porte NAND
La porte NAND contient 4 transistors tandis que la porte AND comportera 6.
- Le réseau des transistors N est chargé de ramener la sortie a zéro.
- Le réseau des transistors P est chargé de ramener la sortie a un.

Figure 2.5. porte NAND en technologie CMOS


L’intégration de la porte AND repend la structure de la porte NAND et comporte un inverseur
supplémentaire. Le délai de la porte complète sera donc la somme des délais de la porte NAND et
l’inverseur.

Page | 36 © ISI 2018 Ridha Ghayoula


2.2.9. Porte AND

Figure 2.6. porte AND en technologie CMOS

2.2.10. Porte NOR


La structure électrique de cette porte ressemble a celle de la porte NAND. Le réseau des
transistors N est en parallèle, tandis que celui des transistors P est en série pour le réseau N.

Figure 2.7. porte NOR en technologie CMOS

2.2.11. Autres Portes

Page | 37 © ISI 2018 Ridha Ghayoula


Figure 2.8. Exemples des circuits en technologie CMOS

La technique d’implémentation des portes complexes est la suivante. Nous supposons une fonction
F exprimée sous la forme d’une combinaison de AND et OR ainsi que de parenthèse. Le réseau N
sera la transcription exacte de la fonction F ou l’opérateur AND signifie nMOS en série,L’opérateur
OR signifie nMOS en parallèle.
Dans l’exemple précèdent:
- Le réseau des MOS canal n a été conçu de la fonction suivante:
A AND (B OR C)= nMOS(A) en série avec (nMOS(B) en parallèle avec nMOS(C))
-Le réseau P sera la transcription exacte de la fonction F,c’est-à-dire que l’opérateur AND signifie
pMOS en parallèle,l’opérateur OR signifie pMOS en série.
A AND (B OR C)= pMOS(A) en parallèle avec (pMOS(B) en série avec pMOS(C))

2.2.12. Porte XOR


La fonction OU exclusif, souvent appelée XOR (eXclusive OR), est un opérateur logique de
l'algèbre de Boole. À deux opérandes, qui peuvent avoir chacun la valeur VRAI ou FAUX, il associe
un résultat qui a lui-même la valeur VRAI seulement si les deux opérandes ont des valeurs distinctes.

Figure 2.8. Porte XOR en technologie CMOS

Page | 38 © ISI 2018 Ridha Ghayoula


L'opérateur XOR est défini par sa table de vérité, qui indique pour toutes les valeurs possibles de A
et B la valeur du résultat S :
Table de vérité de XOR
A B S
0 0 0
0 1 1
1 0 1
1 1 0

2.2.13. Arithmétique (Demi additionneur)


L’intégration et la simulation de ce circuit ne posent pas de problèmes particuliers. La porte XOR est
réalisée au moyen de la cellule comporte 6 transistors étudiée précédent. La porte AND est la
combinaison d’une porte NAND et un inverseur.
La porte XOR est a gauche, la porte AND a droite.

Figure 2.9. Demi additionneur

Figure 2.10. Demi additionneur en technologie CMOS

2.2.14. Arithmétique (Additionneur)


L’additionneur effectue l’addition des deux valeurs A et B plus une retenue précédente. Cette
troisième entrée est notée R. Le calcul effectué est donc l’additionneur booléenne A+B+R. Il y a
toujours deux sorties, La somme et la retenue.

Figure 2.11. Additionneur complet

Page | 39 © ISI 2018 Ridha Ghayoula


L’additionneur peut être vu sous forme d’un simple symbole comportant 3 entrées Ai, Bi et Ri et
deux sorties Si et Ri.

Figure 2.12. Additionneur 4 bits


2.2.15. Comparateur
- Voyons maintenant comment comparer deux valeurs logiques A et B.
- La porte XNOR crée la fonction A=B. Cette porte est dérivée de la porte XOR a 6 transistors.
Simplement la connexion interne est modifiée afin de réaliser directement la fonction XNOR sans
devenir rajouter un inverseur
- Les portes NOR et leur inverseur associée génèrent les fonctions A>B et A<B

Figure 2.13. Comparateur

2.2.16. Multiplication 2x2 bits


- Voyons maintenant comment multiplier deux valeurs entières. La table de vérité d’une cellule de
multiplication élémentaire AxB est équivalente à celle d’un circuit d’addition.
- Les entrées sont (A ET B) la retenue précédente (RetIn) et le produit précédent (PrIn).

Page | 40 © ISI 2018 Ridha Ghayoula


Figure 2.14. Multiplication 2x2 bits
2.2.17. Bascule (RS)
L’entrée S (Set = mise à 1) force la sortie Q à 1.
L’entrée R (Reset = mise à 0) force la sortie Q à 0
. L’activation simultanée de ces deux entrées pourrait provoquer un conflit.

Figure 2.15. Multiplication 2x2 bits


2.2.18. Bascule D
- La bascule qui réalise cette fonction est la bascule D.
- Elle copie la valeur d’entrée lorsque l’horloge est active, sinon elle reste à l’état mémoire

Figure 2.16. Multiplication 2x2 bits

Page | 41 © ISI 2018 Ridha Ghayoula


2.2.19. Les mémoires à semi-conducteur
 Classification par mode opératoire
 Mémoires à écriture et lecture : mémoires vives
• Mémoires statiques
• Mémoires dynamiques
 Mémoires à lecture seule : mémoires mortes ou ROM (Read-Only Memories)
• Procédé d'inscription inaccessible à l'utilisateur : ROM
• Procédé d'inscription accessible à l'utilisateur :
- PROM (Programmable ROM) : inscription irréversible
- REPROM (REprogrammable ROM) : inscription réversible
 Classification par type d'accès
 Mémoires à accès aléatoire ou direct
• Les cellules mémoires sont accessibles directement par une adresse
 Mémoires à accès séquentiel
• Les cellules sont chaînées (id. registre à décalage), et ne sont accessibles qu'aux extrémités de
la chaîne
 Performances des mémoires
 Capacité
• Nombre de bits ou de mots binaires mémorisés
 Temps d'accès / temps de cycle
• Temps d'accès : temps écoulé entre une demande de lecture et la présence de l'information sur la
sortie de la mémoire
- dépend du type d'accès
• Temps de cycle : durée minimale à respecter entre deux accès à la mémoire

Figure 2.17. Mémoire

 Les mémoires vives à accès aléatoire : RAM


RAM = Random Access Memory (mémoires vives seulement)
Page | 42 © ISI 2018 Ridha Ghayoula
 Deux offres technologiques
• Les RAM statiques (SRAM)
Élément de mémorisation = bistable
• Les RAM dynamiques (DRAM)
Élément de mémorisation = condensateur

2.2.19.1. Cellule mémoire RAM


Le CPU voit la mémoire RAM comme une suite linéaire d’octets, mais l’organisation physique est
matricielle
• Les puces RAM réelles n’emmagasinent pas des octets, mais des bits individuels répartis dans
une matrice, auxquels on accède par rangée (« word line) et colonne (« bit line »)
• Cellule mémoire RAM
- Écrire: il faut écrire une donnée sur la fil D et écrire son inverse sur le fil nD. Une fois sélectionner,
la cellule prend la valeur imposée.
- Lire: il suffit de sélectionner la cellule qui présente alors sa valeur sur D, et son inverse sur nD.

Figure 2.18. Mémoire SRAM

Figure 2.19. Mémoire SRAM en technologie CMOS

2.2.19.2. Cellule mémoire ROM


- Une mémoire ROM est un ensemble de cellules contenant soit une valeur 0, soit une valeur 1
- Il est impossible de modifier leur valeur.
- Mémoire a lecture seule.
- Le principe de la cellule mémoire est très simple: le fil D étant supposé a 1, un transistor signifie
l’information 0,son absence l’information 1.

Page | 43 © ISI 2018 Ridha Ghayoula


Figure 2.20. Cellule mémoire ROM

2.2.19.3. Cellule mémoire ROM (4x4 bits)

Figure 2.21. Cellule mémoire ROM

Figure 2.22. Cellule mémoire ROM (4x4 bits)

2.3. Circuits Programmables


Un circuit logique programmable, ou réseau logique programmable, est un circuit intégré logique qui
peut être reprogrammé après sa fabrication. Notons qu'il serait impropre de parler de
programmation au sens logiciel (contrairement à un microprocesseur, il n'exécute aucune ligne de
code). Ici, mieux vaudrait parler de « reconfiguration » plutôt que de reprogrammation (on modifie

Page | 44 © ISI 2018 Ridha Ghayoula


des connexions ou le comportement du composant, on connecte des portes logiques entre elles,
etc.). Le verbe programmer est toutefois le plus fréquent, mais au sens de personnaliser. Il s'agit bel
et bien de réseaux logiques reconfigurables et modifiables.
Il est composé de nombreuses cellules logiques élémentaires et bascules logiques librement
connectables (c'est justement la reconfiguration, ou programmation, du composant qui définit les
connexions faites entre portes logiques).
Ce type de composant électronique est communément désigné par différents sigles anglais dont
notamment :
FPGA (field-programmable gate array, réseau de portes programmables in situ) ;
PLD (programmable logic device, circuit logique programmable) ;
EPLD (erasable programmable logic device, circuit logique programmable et effaçable) ;
CPLD (complex programmable logic device, circuit logique programmable complexe) ;
PAL (programmable array logic, réseau logique programmable) ;
PLA (programmable logic array, réseau logique programmable).

2.3.1. FPGA
Ces systèmes programmables sont initialement destinés au prototypage de systèmes numériques
complexes. Ils sont une bonne alternative aux circuits spécifiques, les ASIC (Application Specific
Integrated Circuit), pour des petites ou moyennes séries.
Il existe plusieurs grands fabricants : ALTERA, ACTEL (composants spécialisés) et XILINX. Pour
les TP, nous utiliserons des FPGA de chez Xilinx.

2.3.1.1. Implantation
Chaque fabricant propose aussi des composants de taille variable : de 100.000 à 10.000.000 portes
logiques. Par comparaison, les portes standards commerciales possèdent entre 2 et 8 portes logiques
pour une surface de silicium quasiment identique.
Quelque soit la technologie utilisée, aucune porte logique n’est réellement implantée. Il s’agit en fait
de blocs logiques programmables, mais très versatiles (RAM), et d’une mer de connexions
programmables. Chez Xilinx, ces blocs logiques sont appelés CLB (Common Logic Blocks).

2.3.1.2. Avantages et inconvénients


_ Très haute densité
_ Grande vitesse (100 MHz à quelques GHz)
_ Très grand nombre d’entrées/sorties (boîtiers BGA)
_ Prix élevé (mais en baisse)
_ Alimentation di_cile (plusieurs tensions, courants élevés, connexions multiples)
_ Volatiles (cellules RAM)
_ Circuits imprimés (PCB - Printed Circuit Board) multicouches

2.3.1.3. Structure d’un FPGA - Xilinx


L’architecture, retenue par Xilinx, se présente sous forme de deux couches : une couche circuit
configurable et un réseau de mémoire SRAM. La structure d’un FPGA est donnée dans la figure
suivante. L’échelle est loin d’être réelle, les fonctions logiques n’occupant qu’environ 5% du circuit.

Page | 45 © ISI 2018 Ridha Ghayoula


Figure 2.22. Structure d’un FPGA - Xilinx

Les FPGA sont un rassemblement et une combinaison de différents blocs : d’entrées/sorties (IOB -
Input Output Blocks), de routage (PSM - Programmable Switch Matrix), de logique programmable
(CLB - Configurable Logic Blocks) et d’autres blocs plus spécifiques.

2.3.1.4. Spartan XL 3E
Les Spartan 3E, que nous allons utiliser par la suite, sont basés sur ce type de structure. La figure
suivante détaille leur architecture. Le tableau rassemble les différentes caractéristiques de cette
famille de FPGA.

Figure 2.23. Structure interne de circuit FPGA

Les CLB (voir figure 3) sont décomposés en 2 ou 4 SLICE (appellation de Xilinx). Ces SLICE sont
eux-mêmes décomposés en 2 LUT (Look-Up Table) et 2 bascules D.

Page | 46 © ISI 2018 Ridha Ghayoula


Figure 2.24. Bloc logique configurable - Xilinx Spartan 3
2.3.1.5. LUT et bascule
Les fonctions combinatoires sont implantées sur des mémoires SRAM (LUT = Look-Up Table). La
table de vérité est alors chargée dans ces LUT. La figure 4 montre le cas de LUT à 2 entrées. En
général, les FPGA sont équipés de LUT à 4 ou 6 entrées.

Figure 2.25. LUT - Xilinx Spartan 3


Les éléments séquentiels (synchrones sur front ou niveau) sont implantés sur des bascules (D le plus
fréquemment).

2.3.1.6. Carte d’étude BASYS2 - Digilent


L’ensemble des exemples et applications qui seront demandés dans ces TP seront réalisés sur une
carte de développement
BASYS2, proposé par la société Digilent. Ces cartes sont basées sur le FPGA Spartan 3E-250 de
Xilinx.

Page | 47 © ISI 2018 Ridha Ghayoula


Figure 2.26. Carte BASYS2 - Digilent

2.3.1.6.1. Entrées-sorties logiques


Les entrées logiques sont essentiellement réalisées par 8 interrupteurs dénommés SW0 à SW7 et par
4 boutonspoussoirs dénommés BTN0 à BTN3.
Les sorties pourront être visualisées sur 8 diodes électroluminescentes (LD0 à LD7) ou bien 4
afficheurs 7 segments multiplexés (DISP1).

Figure 2.27. Entrées-sorties logiques

Page | 48 © ISI 2018 Ridha Ghayoula


Elément Broche Elément Broche Elément Broche Elément Broche
SW7 N3 LD7 G1 BTN3 A7 RED0 C14
SW6 E2 LD6 P4 BTN2 M4 RED1 D13
SW5 F3 LD5 N4 BTN1 C11 RED2 F13
SW4 G3 LD4 N5 BTN0 G12 BLU1 H13
SW3 B4 LD3 P6 MCLK B8 BLU2 J13
SW2 K3 LD2 P7 GRN0 F14
SW1 L3 LD1 M11 HS J14 GRN1 G13
SW0 P11 LD0 M5 M5 K13 GRN2 G14

2.3.1.6.2. Horloges
Il y a trois horloges de caractéristiques différentes produites par un circuit spécial : 25, 50 et 100
MHz. Ces trois signaux sont connectés à la même broche spécifique du FPGA.

2.3.1.6.3. Afficheurs 7 segments multiplexés


Le multiplexage de l’affichage permet de limiter le nombre de connexions pour ces 4 afficheurs.
Mais son fonctionnement exige la mise en œuvre de composants séquentiels.
Pour activer un segment (cathode), on doit placer un ’0’ (zéro) sur la sortie correspondant au
segment seg. Pour activer un afficheur, il faut également placer un ’0’ sur la sortie an désirée, (en
raison de la présence d’un transistor amplificateur inverseur). a...g, dp = cathodes des segments et du
point décimal de tous les afficheurs ; an = commandes des anodes communes des afficheurs.

Figure 2.28. Afficheurs 7 segments multiplexés


Elément Broche type
an(0) F12 Commande anode gauche
an(1) J12 Commande anode
an(2) K14 Commande anode
an(3) M13 Commande anode droite

Elément Broche type


A,seg(6) L14 Sortie
A,seg(5) H12 Sortie
A,seg(4) N14 Sortie
A,seg(3) N11 Sortie
A,seg(2) P12 Sortie
A,seg(1) L13 Sortie
A,seg(0) M12 Sortie
DP N13 Sortie

Page | 49 © ISI 2018 Ridha Ghayoula


Exercices
Exercice 1 : Pipeline et parallèle
On considère les circuits logiques schématisés par les figures suivantes dont les entrées A, B, C, D,
hor1, expression et la sortie S.
a- Structure pipeline

b- Structure parallèle

3. Décrire en VHDL les circuits Additionneur 4 bits, Registre 4bits a entrées parallèles, sorties
parallèles, comparateur pour les deux structures (a et b)
4. En déduire la description structurelle pour la structure pipeline et parallèle.

Exercice 2 : Compteur/Séquenceur
Partie I : séquenceur
On souhaite réaliser une structure délivrant les signaux ci-dessous.

Page | 50 © ISI 2018 Ridha Ghayoula


1. Donnez une architecture pour cette entité qui respecte les spécifications données par ce
séquenceur.

Partie II : Compteur
Un composant compteur doit être implanté sur circuit intégré. Ses spécifications fonctionnelles sont
les suivantes :
Il compte sur front montant de son horloge CLK, de 0 à 9.
Le bus de sortie sur 4 bits évolue donc de « 0000 » à « 1001 ».
Un signal RESET, actif à niveau bas, effectue de manière asynchrone la remise à 0 du compteur.
Un signal ENABLE, actif à niveau haut, autorise le comptage, qui est donc inhibé lorsque ENABLE
est à niveau bas.
Un signal OVERFLOW synchrone, actif à 1, signale le passage de « 1001 » à « 0000 ».
1. Ecrire une description en VHDL de ce compteur.
2. La première solution d’implantation est un FPGA. Quel est le nombre approximatif de CLB
qui seront utilisés par le composant compteur ?
3. Pourquoi la solution d’implantation sur FPGA est-elle généralement la première envisagée ?
4. La deuxième solution est l’implantation de « compteur » sur un ASIC. Quels sont pour vous
les 3 principaux avantages et 3 principaux inconvénients de cette solution d’implantation par
rapport à la première solution ?
5. Le fabricant de l’ASIC propose des technologies de fabrication CMOS, SiGe et BiCMOS.
Lequel de ces 3 types de technologies choisirez-vous pour le compteur ? Justifiez votre
réponse en classant ces technologies selon les 5 critères les plus pertinents pour votre
composant.

Exercice 3 : FPGA, EEPROM


.
a. Énumérez quatre (4) éléments fondamentaux qu’on peut retrouver sur un FPGA présentement
en vente sur le marché.

Page | 51 © ISI 2018 Ridha Ghayoula


b. Expliquez, à l’aide d’un diagramme, le principe de la programmation d’un dispositif
programmable EEPROM ou Flash par grille flottante.
c. Expliquez en deux ou trois phrases chacune les étapes de synthèse, d’association (mapping), de
placement et de routage.
d. Considérez l’énoncé suivant : « Pour un circuit numérique implémenté sur FPGA, il n’y a pas de
désavantage à utiliser le principe du pipeline au maximum, parce que les bascules sont à toutes fins
pratiques gratuites. » Dites si vous êtes en accord ou en désaccord avec cet énoncé, et expliquez en
quelques lignes pourquoi ?

Exercice 4 : Cellule d'une mémoire vive


I. Cellule statique d'une mémoire vive :
La Figure 2 présente une RAM statique 16 bits organisée en matrice 4 x 4.
1. Expliquer brièvement le principe de fonctionnement de cette RAM statique.
2. Ecrire une description en VHDL de décodeur ligne d’une RAM statique 16 bits.
3. Ecrire une description en VHDL de décodeur colonne d’une RAM statique 16 bits.

Figure 1. RAM statique 16 bits organisée en matrice 4 x 4

Page | 52 © ISI 2018 Ridha Ghayoula


Figure 2. cellule de mémorisation d’une RAM statique

II. Cellule dynamique d'une mémoire vive


L'information est stockée dans une capacité, le "1" logique correspond à la capacité chargée et le "0"
logique correspond à la capacité déchargée.
La Figure 3 présente une RAM dynamique 16 bits organisée en matrice 4 x 4.
1. Expliquer brièvement le principe de fonctionnement de cette RAM dynamique.

Figure 3. RAM Dynamique organisée en matrice 4 x 4 avec son circuit de lecture écriture

Page | 53 © ISI 2018 Ridha Ghayoula


Figure 4. Cellules de mémorisation d’une RAM dynamique

Exercice 4 : L’architecture de l’implantation de l’algorithme de Montgomery


Les opérations de chiffrage et de déchiffrage de la plupart des systèmes de cryptographie à clés
publiques sont basées sur l’arithmétique modulaire. A titre d’exemple, la performance d’un système
comme le RSA( Rivest ,Shamir et Adleman) est déterminée par l’opération de produit modulaire. Par
conséquent, les opérateurs arithmétiques modulaires demandent des méthodes spécifiques de calcul,
et une implémentation efficace en matériel pour garantir les performances du système .Pour réaliser
la multiplication modulaire, il existe plusieurs algorithmes dont le plus connu et l’un des plus
efficaces est celui de Montgomery.
En 1985 Peter Montgomery a publié des études sur une façon de calculer le produit modulaire sans
avoir besoin de réaliser la division par le module. Cette caractéristique facilite l’implémentation
matérielle, puisque La multiplication modulaire est généralement considérée comme opération
arithmétique compliquée en raison de l’inhérente opération de la multiplication et de la division,
donc c’est une opération trop coûteuse du point de vue surface d’implantation.
Schéma bloc de l’algorithme de Montgomery
Ce bloc représente l’algorithme de Montgomery MonPro2 (A, B, M), il contient trois variables
d’entrées A, B et M de longueur n bits et un signal horloge (CLK) et deux signaux de commandes
RST (reset), LOAD (charge) pour le chargement de variables de l’algorithme et une sortie R qui
représente le résultat de calcul. Cet algorithme calcule l’opération suivante AB (2n)-1mod M.

Figure 1.Algorithme 2: MonPro2 Figure 2.(a) Schéma bloc de la multiplication


de Montgomery
Pour implanter l'algorithme (2) (Figure.1.Algorithme 2: MonPro2), nous avons besoins de cinq
registres (A, B, M, Si-1, RES), deux additionneurs et deux multiplieurs binaires de 8 bits.
pour obtenir qi c'est-à-dire le reste de division euclidienne de (Si-1+biA) par deux nous avons pris
directement LSB de la somme de Si-1 et de biA de même la division par 2 de Si-1 est prise

Page | 54 © ISI 2018 Ridha Ghayoula


directement, c'est-à-dire MSB… LSB+1 (décalage vers la droite) et pour réaliser la multiplication de
Abi et de Mqi, nous avons utilisé un registre de décalage à droite (B) et des portes logiques (AND)
comme est illustré à la Figure suivante pour obtenir Abi, de même façon nous avons utilisé des
portes logiques (AND) qui retient les sorties du registre M et qi pour obtenir le produit Mqi et
finalement nous pouvons adapter cette algorithme à une architecture matérielle.

Figure 2. (b) Schéma bloc de la multiplication de Montgomery

Page | 55 © ISI 2018 Ridha Ghayoula


Figure 2. (c) Schéma bloc de la multiplication de Montgomery
1. Ecrire les codes VHDL de cinq registres (A, B, M, Si-1, RES), deux additionneurs et deux
multiplieurs binaires de 8 bits (Figure.2. (c) Schéma bloc de la multiplication de
Montgomery)
Avec :
RES : Registre à chargement parallèle de 8 Bits (Si-1+qiM+biA )
Reg_A,Reg_B,Reg_M,Si-1 : Registre à chargement parallèle de 8 Bits

- Les registres Reg_A, Reg_B et Reg_M sont utilisés pour stocker les variables d’entrée de
l’algorithme Monpro2 (A, B, M) pour cela trois registres de type entrées parallèles sorties
parallèles sont nécessaires. L’opération de chargement de ces registres est commandé par
l’entée LOAD.

Page | 56 © ISI 2018 Ridha Ghayoula


Les registres Reg_A, Reg_M

Le Registre à décalage B

- Les registres Reg_Si-1 et Reg_RES sont des registres de type entrées parallèles, sorties
parallèles. Ils sont utilisés pour mémoriser soit le calcul intermédiaire soit le résultat final
de la multiplication de Montgomery Monpro2.
Reg_Si-1,Reg_RES : Registre à chargement parallèle de 8 Bits

- Deux Additionneurs de 8 Bits


Ce bloc présente un additionneur à propagation de retenue (Ripple Carry Adder RCA) à
8 bits, son principe est basé sur la mise en cascade de modules élémentaires
d’additionneur 1 bit .cette structure itérative présente une complexité croissante avec N,
du fait de la propagation de le retenue à travers tous les modules, l’additionneur RCA est
le moins rapide mais contient le minimum de portes logiques.

- Deux multiplieurs Abi et Mqi (Figure2. (c))


Le terme Abi est le résultat du produit de la sortie du registre à décalage B par le contenu
de registre A. Cette opération est réalisée par des portes logiques ET comme le montre la
Figure2.(c)

Page | 57 © ISI 2018 Ridha Ghayoula


Multiplieur Abi

Multiplieur Mqi
2. Déduire la description structurelle ce cet architecture.

Page | 58 © ISI 2018 Ridha Ghayoula


3
Les Processeurs Embarqués
dans les FPGA

3.1. Introduction
Un « système sur une puce », également souvent désigné dans la littérature scientifique par le terme
anglais system on a chip (d'où son abréviation SoC), est un système complet embarqué sur une seule
puce, pouvant comprendre de la mémoire, un ou plusieurs microprocesseurs, des périphériques
d'interface, ou tout autre composant nécessaire à la réalisation de la fonction attendue.

Il faut noter que lorsque l'on conçoit un système numérique complexe, on met en œuvre
généralement un processeur embarqué. Ce processeur embarqué est :
– Soit un bloc IP : on parle de processeur softcore.
– Soit déjà implanté dans le circuit électronique en « dur » : on parle de processeur hardcore.
Le processeur de ce type est généralement plus performant que le processeur du type précédent. Le
processeur embarqué allie la souplesse du logiciel à l'accélération du temps d'exécution du matériel.
Une fonctionnalité particulière peut donc être composée d'une partie matérielle couplée à une
fonctionnalité logicielle dédiée : on a donc une conception conjointe matérielle-logicielle ou
Codesign. Le codesign implique donc une conception en même temps du matériel et du logiciel, ce
qui est une nouvelle méthodologie par rapport à la méthodologie de conception classique
(Conception matérielle puis conception logicielle.
Le choix d'un processeur pour le SoPC peut se faire sur différents critères :
– Processeur hardcore : pour ses performances au détriment de la flexibilité.
– Processeur softcore : pour sa flexibilité de mise à jour au détriment de performances moindres que
le précédent. La portabilité vers n'importe quel circuit FPGA est assurée en étant donc circuit
FPGA indépendant. Il est aussi possible de migrer vers un circuit de type ASIC en cas d'une
production en grande série.
Généralement, on privilégie les processeurs softcore pour s'affranchir des problèmes d'obsolescence
et pour pouvoir bénéficier facilement des évolutions apportées en refaisant une synthèse.
Le processeur softcore peut être propriétaire : il est distribué par exemple sous forme d'une netlist
pour être implanté dans un circuit FPGA. Il est généralement lié à un fondeur de circuit FPGA
particulier (comme Altera ou Xilinx). On ne peut pas l'utiliser dans un circuit FPGA autre que celui
pour lequel il est prévu. On a donc ici une boîte noire.

Page | 59 © ISI 2018 Ridha Ghayoula


Le processeur softcore peut être libre : il est décrit en langage de description de matériel (VHDL,
Verilog) dont le code source peut être librement distribué et implanté dans n'importe quel circuit
Programmable FPGA. On est alors indépendant du type de circuit FPGA.
On trouvera principalement au niveau des processeurs softcores propriétaires :
– Le processeur picoblaze et Microblaze de Xilinx.
– Le processeur NIOS et NIOS II d'Altera.

On trouvera principalement au niveau des processeurs softcores libres :


– Le processeur Leon.
– Le processeur OpenRISC.
– Le processeur F-CPU.

3.2. PicoBlaze
3.2.1. La partie matérielle du PicoBlaze
PicoBlaze est la désignation d'une série de trois processeurs softcore faits par Xilinx pour être
utilisés sur leurs FPGA et CPLD. Ils sont basés sur une architecture RISC de 8 bits et peuvent
atteindre une vitesse de 100 millions d'instructions par seconde sur la famille de FPGA Virtex 4. La
licence des cœurs en permet une utilisation libre, mais seulement sur les appareils Xilinx. Des outils
de développement sont fournis par le constructeur, mais des outils tiers sont disponibles,
notamment chez Mediatronix. Il existe aussi une implémentation libre, indépendante du composant,
disponible sous licence BSD sous le nom de PicoBlaze. La conception du PicoBlaze s'appelait à
l'origine KCSPM (pour Constant(K) Coded Programmable State Machine, auparavant Ken
Champan's PSM). Ken Chapman était le concepteur système de Xilinx qui avait inventé et conçu le
microcontrôleur. Quand on instancie un microcontrôleur PicoBlaze en VHDL, le nom du
composant KCSPM respectif doit être utilisé. par exemple, pour un processeur PicoBlaze:

Le PICOBLAZE est un microprocesseur qui est très rapide mais ses données peuvent être sorties
seulement en 8 bits. Ce processeur peut être assimilé à un DSP. N'utilisant que très peu de
ressources, il est prévu pour être embarqué en quantité ( ressources utilisées = 2%). Il peut se
représenter de la façon suivante:
La plus petite application consiste à lui ajouter une mémoire avec les instructions correspondantes
dedans. Cela nous donne le schéma ci-dessous où toutes les entrées ainsi que les sorties seront
reliées à de la logique du FPGA comme cela sera partiellement détaillé dans la section suivante

Page | 60 © ISI 2018 Ridha Ghayoula


8 bits 8 bits
IN_PORT[7:0] OUT_PORT[7:0]
8 bits
INTTRERUPT PORT_ID[7:0]
Interface to Logic
REST
READ_STROBE
CLK WRITE_STROBE

INSTRUCTION[17:0] ADRESS[9:0]

KCPSM3

ADRESS[9:0] INSTRUCTION[17:0]

BLOCK MEMORY
PROGRAM
CLK

Figure 3.1. Implantation standard utilisant un bloc RAM 1Kx18 pour stocker les instructions

3.2.1.1. Les entrées /sorties


Nous allons apprendre dans cette partie à interfacer des ports au PicoBlaze. Commençons par les
entrées.
a) Interfacer un PORT d'entrée
Le diagramme temporel correspondant est présenté maintenant.

Figure 3.2. Timing de l'instruction INPUT

Pour faire l'acquisition d'une valeur externe, il faut réaliser une instruction « INPUT» en précisant un
numéro de port sur 8 bits. Il y a donc 256 ports possibles.
On remarque que l'instruction «INPUT» est réalisée en deux fronts d'horloge (comme toutes les
instructions) et qu'un signal READ_STROBE est disponible sur un seul front d'horloge. La partie
matérielle peut être réalisée comme suit:

Page | 61 © ISI 2018 Ridha Ghayoula


8 bits
RD R_DATA OUT_PORT[7:0]
8 bits 8 bits
IN_PORT[7:0] PORT_ID[7:0]

Logique
de READ_STROBE
décodage CLK WRITE_STROBE
RD R_DATA

PicoBlaze
RD R_DATA

RD R_DATA

Figure 3.3. Schéma d'interface entre PORTS d'entrée et PicoBlaze

Dans cet exemple on dispose de 4 registres 8 bits pour lesquels on n'a pas dessiné les entrées
arrivant de l'extérieur. Le multiplexeur ainsi que la logique de décodage peuvent n'utiliser que les 2
bits de poids faible du signal PORT_ID. Il est possible de rajouter un registre entre le multiplexeur
et l'entrée du PicoBlaze pour augmenter les performances (pipeline).
On donne un exemple de programme VHDL correspondant aux deux composants ajoutés, le
multiplexeur et la logique de décodage ainsi qu'une partie du registre.

Page | 62 © ISI 2018 Ridha Ghayoula


b) Interfacer un PORT de sortie
Le diagramme temporel de l'instruction OUTPUT est donnée ci-dessous.

Figure 3.4. Timing de l'instruction OUTPUT

On n'a pas représenté les signaux de sorties du circuit de décodage mais ils ont légèrement décalés
par rapport à WRITE_STROBE puisqu'ils l'utilisent. Nous montrons ci-dessous un exemple de
circuit pouvant réaliser une sortie sur un des quatre ports présents :

Page | 63 © ISI 2018 Ridha Ghayoula


D Q

8 bits
OUT_PORT[7:0]
8 bits 8 bits
IN_PORT[7:0] PORT_ID[7:0] Logique
de
décodage D Q
READ_STROBE
CLK WRITE_STROBE

D Q
PicoBlaze

D Q

Figure 3.5. Schéma d'interface entre PORTS de sortie et PicoBlaze

Pour quatre ports seuls les deux bits de poids faible de PORT_ID[7:0] peuvent être utilisés. On
donne pour une meilleure compréhension les programmes VHDL correspondants :

Remarquons qu'il est possible de simplifier largement le décodage si on utilise comme numéros de
PORT : 1, 2, 4 et 8 (au lieu de 1, 2, 3 et 4) et du coup les 4 bits de poids faible de PORT_ID[7:0] :

Page | 64 © ISI 2018 Ridha Ghayoula


Un autre problème va nous intéresser maintenant : les interruptions.

3.2.1.2. Les interruptions


La gestion des interruptions est en général très dépendante de l'application à réaliser. Encore une
fois le PicoBlaze ne comprend par défaut que le minimum de logique pour gérer les interruptions.
Quand on dit minimum, c'est le minimum : même pas de gestion de timer par exemple. C'est à
l'utilisateur de réaliser la logique correspondante charger de réaliser le seul signal « INTERRUPT »
présent (une seule source d'interruption donc par défaut). L'activation de ce signal force le PicoBlaze
à réaliser un saut vers l'adresse 3FF (dernière adresse de la mémoire programme). A noter qu'après
un RESET le signal d'interruption est inactif : une instruction « ENABLE INTERRUPT » doit être
réalisée pour l'activer. A noter que l'exécution d'une interruption préserve les bits C et Z du registre
d'état.

3.2.2. La partie logicielle du PicoBlaze


L'architecture d'un programme assembleur gérant une interruption sera comme :
ADDRESS 000
main: ...
ENABLE INTERRUPT
1 ADD s0,s3
INPUT S1,01
...
CALL temps_critique
...
JUMP main

temps_critique:
; ===code temps critique===
DISABLE INTERRUPT 2
4 ...
ENABLE INTERRUPT
RETURN

isr:
; === code d'interruption ===
TEST s2,01
...
3 RETURNI ENABLE

; === vecteur
d'interruption ===
ADDRESS 3FF
JUMP isr

Page | 65 © ISI 2018 Ridha Ghayoula


Lorsqu'une interruption (1) arrive, le programme est dérouté (2) à l'adresse 3FF. Cette adresse
branche (3) à la routine d'interruption proprement dite. Puis quand la routine est terminée on revient
là où l'on a été interrompu (4).
La routine d'interruption n'est pas instantanée dès réception du signal d'interruption. L'instruction en
cours continue à s'exécuter puis une fois terminée l'ensemble des opérations décrites dans la section
précédente sont synchronisées avec l'horloge comme indiqué sur le chronogramme suivant:

Scratchpad RAM

Store Fetch

Registers Output
Input
IN_PORT OUT_PORT
Load sX,sY

Input sX,(sY)
Load sX,kk Output sx,(SY)
Input sX,kk
Output sx,kk
Instruction store PORT_ID

Figure 3.6. La partie logicielle du PicoBlaze

Le picoblaze est un cœur de microcontrôleur 8bits disponible sous forme d’un fichier VHDL :
KCPSM3.VHD

Page | 66 © ISI 2018 Ridha Ghayoula


Il possède :
- 16 registres s0,s1….sF polyvalents.
- 64 octets de RAM interne
- 1 port d’entrée, 1 port de sortie multiplexable avec le registre PORT_ID => 256 ports
d’entrées/sorties
- un compteur ordinal 10bits pour adresser la mémoire programme (1024 adresses maxi)
- 1 entrée d’interruption qui pointe sur l’adresse $3ff.
- il peut fonctionner à plus de 44Mips avec une horloge 88MHZ sur le Spartan3 et prend
environ 5% des ressources.

8 bits
8 bits 8 bits Port PORT_ID
Address READ_STROBE
8 bits control
8 registres WRITE_STROBE

8 bits 8-bit
8 bits

IN_PORT 8 bits
ALU
scratch pad
memory
64 bytes
Zero Interrup
& Carry shadow
INTERRUPT Falgs Flag

Interrupt
INSTRUCTION 8 bits ADRESS
18 bits Program
flow Program
8 bits Counter 8 bits
Operational control
Control
CONSTANT DATA
RESET Inst Dec
CLK Program
Counter
stack

Figure 3.7. Structure interne picoblaze

Implantation standard utilisant un bloc RAM 1Kx18 pour stocker les instructions

Page | 67 © ISI 2018 Ridha Ghayoula


Figure 3.8. PBlaze IDE

3.3. Processeur Xilinx MicroBlaze


Le MicroBlaze est un processeur soft-core (processeur implémenté sur un FPGA) 32 bits, à jeu
d’instructions RISC basé sur une architecture Harvard conçu par la société Xilinx. Il est hautement
configurable avec pas moins de 70 options permettant de spécifier entre autre le niveau de pipeline,
l’utilisation d’une FPU, d’un barrel shifter, d’un cache ou encore d’une logique de débug. Sa
principale utilisation se trouve dans les FPGA (field programmable gate array), permettant la
conception de système correspondant aux besoins de l’utilisateur, notamment lors de la phase de
conception. Le processeur utilisé ici est la version 8.20. Cette version pouvant atteindre une
fréquence de 210 MhZ. Plusieurs OS supportent ce type de processeur, comme le noyau Linux,
Xilinx MicroKernel, uClinux (linux pour micro-contrôleurs), FreeRTOS (système en temps réel).

Le MicroBlaze n’est pas dissociable du FPGA (field programmable gate array). C’est un circuit
logique dont le principal intérêt est de pouvoir être re-programmé après sa fabrication. Il est
composé de blocs logiques contenants principalement une table de correspondances (LUT). Il s’agit
d’une table servant à implanter des fonctions logiques booléennes à plusieurs entrées et donnant un
résultat en sortie. Cela permet une grande souplesse et permet d’adapter le matériel à un algorithme
particulier lui permettant de s’exécuter dans un temps plus court. Les FPGA sont généralement
contenus sur des cartes regroupant plusieurs composants divers. Une carte Xupv5-LX110t de Xilinx
était à ma disposition avec un port Ethernet, un port serial, un port dvi/vga, des LED, switchs et

Page | 68 © ISI 2018 Ridha Ghayoula


boutons push, un mémoire SRAM, DDR2, ... Le FPGA est entièrement programmable grâce à la
suite d’outils proposée par Xilinx nommée EDK (Embedded Development Kit)

3.3.1. Architecture MicroBlaze


Les caractéristiques du MicroBlaze sont les suivantes :
• L’architecture du MicroBlaze est une architecture «Harvard » avec ses bus de programme et bus de
données séparés.
• Le « core » du processeur embarqué MicroBlaze est un RISC (Reduced Instruction Set Computer).
Les instructions lues par le processeur sont réduites de telle sorte que la lecture puisse se faire en un
cycle machine.
• Ses instructions sont de 32-bits avec 3 opérandes e t 2 modes d’adressage.
• Il ne possède pas d’unité de gestion de mémoire (MMU : Memory Management Unit).
• Il posséde 32 registres de 32-bits à usage général.
• Ses bus d’adresse sont également de 32-bit
• Il possède un « pipeline » de 5 étages et de profondeur 3. En effet, 3 instructions sont exécutées en
9 cycles d’horloge

Figure 3.9. Architecture MicroBlaze


Les parties en couleur grise sont optionnelles et montrent à quel point le MicroBlaze est
configurable. Les caches permettent au processeur de gagner en temps d’exécution en récupérant
des données directement àl’intérieur sans aller les chercher dans la mémoire. Le « Barrel Shift », le «
Multiplier », le « Divider »et le « FPU : Floating Point Unit » permettent d’accélérer des traitements
de données.
Ce diagramme met aussi en évidence les 5 étages du « pipeline » :
1. La lecture de l’instruction dans le buffer d’instruction.
2. Le décode de l’instruction dans le décodeur d’instruction

Page | 69 © ISI 2018 Ridha Ghayoula


3. L’accès mémoire pour la lecture des opérandes
4. Le calcul ou l’exécution de l’instruction dans l’ALU
5. L’écriture du résultat dans la mémoire spéciale.

3.3.2. Interfaces
• Supporte 3 buses:
- LMB (Local Memory Bus) - 1 cycle de latence, connecté à un ou plusieurs blocks BRAM
- XCL (Xilinx Cache Link) - possibilité de le configurer avec une cache d’instructions et
une cache de données.
- AXI (Advanced eXtensible Interface)

Figure 3.10. Cache du Microblaze

 Interconnexion AXI4
• Conçu pour la haute performance: grande bande passante et faible latence.
• Phase dʼadresse et de contrôle séparées.
• Permet plusieurs transactions simultanées.
• Des transactions burst avec une seule adresse générée.
• Transactions intérlacées (deux adresses en deux cycles consécutifs: lʼesclave a le temps de
préparer les données).
• Terminaison dans le désordre (Out-of-order).
• La possibilité dʼajout de registres supplémentaires de façon à pouvoir arriver à la fréquence
de fonctionnement désirée.
 Unité point flottante
• On peut ajouter au MicroBlaze un unité point flottant (FPU) en doublant le nombre de LUT
(1000).
 On obtient toutefois une accélération de 100 par rapport à une émulation de point flottant
 Interruptions et exceptions
Event Vecteor Address Register File return Address
Reset Ox 00000000-Ox00000004 -
User Vector (Exception) Ox 00000008-Ox0000000C Rx
Interrupt Ox 00000010-Ox00000014 R14
Break: Non-maskable hardware R16
Break: hardware Ox 00000018-Ox0000001C
Break: Software

Page | 70 © ISI 2018 Ridha Ghayoula


Hardware Exception Ox 00000020-Ox00000024 R17 or BTR
Reserved by Xilinx for future Use Ox 00000028-Ox0000004F -
 Gestion des interruptions externes
– Le Microblaze a un port d’interruption connecté au contrôleur d’interruptions du
système.
– Le contrôleur d’interruptions a 32 entrées de demande d’interruptions.
– Une routine logicielle traite les demandes d’interruptions en se basant sur la valeur du
registre de statut du contrôleur d’interruptions.
 Port de MicroC sur le Microblaze
• Un ensemble de fichiers en C qui permettent d’utiliser le noyau d’ucos-II sur le Microblaze
pour des applications multitâches avec des contraintes temps réel.
• Le port utilise des périphériques du FPGA pour assurer le bon fonctionnement du RTOS.
• En particulier:
- Il faut une composante Timer pour assurer les ticks du RTOS. (fonction OSTick( ))
- Il faut un contrôleur d’interruption pour assurer au minimum le fonctionnement du Timer
du RTOS.
• Le port fourni le support pour la gestion des interruptions, et le changement de contexte
suite à une interruption ou au ré-ordonnancement d’une nouvelle tâche.

3.3.3. Simple Hardware Design using AXI

AXI4 AXI DDR2


AXI4 AXI Memory
MDM MBDEBUG Memory Controller
AXI4 interconnect
Block

MicoBlaze

D-LMB AXI4
BRAM AXI
I-LMB interconnect
Block

AXI4-Lite
UARTLITE RS232

Figure 3.11. Configuration de MicroBlaze

Page | 71 © ISI 2018 Ridha Ghayoula


Figure 3.12. Co-Design

3.3.3.1. Ressources logicielles


Pour la configuration de la carte, on a utilisé deux environnements de développement. Ce sont les
logiciels de Xilinx : EDK et ISE. Dans un premier lieu on a utilisé le logiciel EDK (acronyme de
Embedded Development Kit) pour la configuration de la carte (conception, mapping, connexion
entre les périphériques, choix des ressources utilisés de la carte…) Voici une allure du logicielle :
Description général pour la configuration de Microblaze avec kintex-7:

Step 1: Step 2: Step 3: Step 4: Step 5:


Create a Analyse the Generate Analyse the Generate
project using created Netlist and created Netlist and
the Base project Bitstream project Bitstream
System Builder

Figure 3.13. Configuration de Microblaze avec kintex-7

3.4.3.1.1. Création du projet à l'aide du Base System Builder


La carte Kintex-7 FPGA KC705 Evaluation Kit nous a permis de faire un premier test du
microblaze fourni. Il y a deux possibilités de faire les tests, en simulation grâce à XPS et sa
plateforme virtuelle, ou bien directement sur la carte, avec utilisation du débogueur pour charger le
microblaze et visualiser ce qui se passe. Les parties suivantes nous permettront de sortir des
données, pour un débogage plus aisé. Le chargement se fait en plusieurs temps :

 Il faut d'abord que XPS compile le projet matériel en lui même, pour en faire un fichier *.bit.
 Ce fichier est ensuite transféré sur la carte via un câble JTAG
 La dernière étape consiste alors à lancer le débogueur et à charger le fichier binaire obtenu.

Page | 72 © ISI 2018 Ridha Ghayoula


Figure 3.14. kintex-7

i1) Launch Xilinx Platform Studio (XPS) and create a new project. Use Base
System Builder to generate a MicroBlaze processor based hardware system using AXI system,
targeting the Atlys Board.

i1.1) Open XPS by selecting Start > All Programs > Xilinx Design Tools > ISE Design Suite
14.3 > EDK > Xilinx Platform Studio.

Figure 3.15. Xilinx Platform Studio

i1.2) Click Create New Project Using Base System Builder to start the wizard. You can select File >
New BSB Project and the same dialog box will appear.

Page | 73 © ISI 2018 Ridha Ghayoula


Figure 3.15. New BSB Project

Figure 3.16. New BSB Project


i1.3) Browse to c: labs directory, create a new folder called lab1, select it, and click
Open followed by click Save. Click OK.
i1.4) Make sure to select the AXI system and click OK.

Page | 74 © ISI 2018 Ridha Ghayoula


Figure 3.17. New BSB Project

i1.5) In the Board and System Selection dialog box, specify the settings below and click Next to
continue.
- Board Vendor: Digilent
- Board Name: Kintex-7 KC705 Evaluation Platform
- Board Revision (Verify on board): C
- Select a System : Single MicroBlaze Processor System

Figure 3.18. Board and System Selection

Page | 75 © ISI 2018 Ridha Ghayoula


i1.6) In the Processor, Cache, and Peripheral Configuration dialog box, set the value of
Processor
Frequency and Local Memory as 100 MHz and 8 KB respectively.
i1.7) In the Included Peripherals for microblaze_0 field, click on Select All, then using Ctrl-key
deselect RS232_Uart_1 and MCB_DDR2.
i1.8) Click on the <Remove button to remove the selected devices, leaving RS232_Uart_1 and
MCB_DDR2 as the only external devices to be used.
i1.9) Configure RS232_Uart_1 with 115200 baud rate.

Figure 3.19. RS232_Uart_1

You could use Add to add additional IO peripherals and internal peripherals, but you will see an
alternative method in the next lab for adding internal peripherals to an existing project.
i1.10) Click Finish.

Page | 76 © ISI 2018 Ridha Ghayoula


Figure 3.20. BSB Project
i1.11) A System Assembly View will be displayed showing peripherals and busses in the system, and
the system connectivity.

Figure 3.21. BSB Project


i2. Analyze the Hardware Step 2
i2.1)Select the Graphical Design View tab and study the system components and interconnections.
Look in the System Assembly View and analyze the interface and port connections.

Page | 77 © ISI 2018 Ridha Ghayoula


i2.2) Click the Graphical Design View tab. You can use Ctrl key and mouse scroll to zoom in and
out the view. You can also use to change the colors of the objects in the view. Observe the various
components that are used in the design

Figure 3.22. Graphical Design View

You will see the MicroBlaze processor, two AXI Interconnects blocks- one for AXI capable devices
and another for AXI-Lite capable devices. You will also see that the MDM and LMB are connected
to the MicroBlaze ports directly.
i2.3) In the System Assembly View click on plus button and observe the expanded (detailed) bus
connection view of the system.

Page | 78 © ISI 2018 Ridha Ghayoula


Figure 3.23. System Assembly View

Figure 3.24. System Assembly View


i2.4) Click on the Ports tab and have an expanded view. This is where you can make internal and
external net connections. If you can’t find Net column then right click on the Connected Port on
the ribbon to see available options and choose Net to get displayed.

Page | 79 © ISI 2018 Ridha Ghayoula


Figure 3.25. Connexion des Ports
i2.5) Click on the Addresses tab. This is where you can assign or change base/high addresses of
the peripherals in the system.

Figure 3.26. Adresse

i3) Run Platgen to generate the netlist and run implementation tools to
generate the hardware bitstream.
i3.1) Run PlatGen by selecting Hardware > Generate Netlist. You can also find Generate
Netlist in the Implement Flow section of the Navigator window.

Page | 80 © ISI 2018 Ridha Ghayoula


Figure 3.27. Connexion des Ports

It will generate implementation, hdl, and synthesis directories. The generated peripherals and system
netlists along with system.bmm will be placed in the implementation directory.
i3.2) Run implementation tools (xflow) by selecting Hardware > Generate BitStream. You can
also find Generate BitStream in the Implement Flow section of the Navigator window

Figure 3.28. Connexion des Ports


It will take more than ten minutes (depends on your computer).
i3.3) Click on the Design Summary tab. The Design Summary allows you to quickly access design
overview information, reports, and messages. It displays information specific to your targeted device

Page | 81 © ISI 2018 Ridha Ghayoula


and software tools. The pane on the left side of the Design Summary allows you to control the
information displayed in the right pane.

i3.4) Browse to the Lab1 project directory using Windows Explorer. Several directories containing
VHDL wrappers and implementation netlists have been created

Page | 82 © ISI 2018 Ridha Ghayoula


i4) Generate Memory TestApp in SDK
i4.1)Start SDK from XPS, generate memory test project with default software
platform project.
Start SDK by clicking Project > Export Hardware Design to SDK … from XPS.

Page | 83 © ISI 2018 Ridha Ghayoula


i4.2)Click on Export & Launch SDK button with default settings (Include bitstream and BMM file
checked).

i4.3)In Select a workspace window, browse to c:\ .... and click OK.

Page | 84 © ISI 2018 Ridha Ghayoula


i4.4)In SDK, select File > New > Xilinx C Project, select Memory Tests from the Select Project
Template window, and then click Next.

3.3.4. Microblaze avec l'environement vivado et Arty-7

Arty Board est une carte de développement a base de circuit FPGA Artix-7. C'était développé par
Xilinx pour une utilisation avec le processeur sofcore MicroBlaze qui est un processeur HDL défini
qui peut être écrit sur le Artix-7 FPGA. La carte est illustré à la Figure 1. L’évaluation de la carte
fournit la connectivité telle que des commutateurs, des boutons, des LED, LED RVB, connecteurs

Page | 85 © ISI 2018 Ridha Ghayoula


Pmod, connecteurs de blindage, USB et Ethernet pour travailler avec des composants HDL et ceux
définis à travers le MicroBlaze

Instr. Port A
CLK
CPU Local
Microblaze memory
RST Data Port B

Peripheral Bus (AXI)

UART GPIOs Timer

Block Design after Connecting the UART

Figure 1. Arty Board


a) Installation Vivado
La première étape de la mise en œuvre de ce projet a été installer le logiciel Vivado en téléchargeant
depuis https://www.xilinx.com/support/download. Dans Afin d'installer ce logiciel, un compte
Xilinx devait d'abord être créé. Une fois le compte créé, la version de téléchargement a été choisi. La
version utilisée pour ce projet et est suggéré d'installer est le 2017.2 WebPack Windows self
extraction du programme d'installation Web illustré à la Figure 2. Une fois que ceci a été téléchargé,
l'installateur a été exécuté, suivant toutes les instructions d'installation standard. Notez que le nom
d'utilisateur et mot de passe pour le compte Xilinx qui a été créé étaient nécessaire pour l'installation.
Lorsque l'étape choisie par l'utilisateur quels paquets installer a été atteint, le SDK et 7 Seriecs les
options de l'appareil ont été vérifiées, car elles étaient nécessaires pour le projet. Celles-ci sont
illustrées à la Figure 3.

Figure 2. Install Version

Page | 86 © ISI 2018 Ridha Ghayoula


Une fois que ceci a été téléchargé, l'installateur a été exécuté, suivant toutes les instructions
d'installation standard. Notez que le nom d'utilisateur et mot de passe pour le compte Xilinx qui a
été créé étaient nécessaire pour l'installation. Lorsque l'étape choisie par l'utilisateur quels paquets
installer a été atteint, le SDK et 7 Seriecs les options de l'appareil ont été vérifiées, car elles étaient
nécessaires pour le projet. Celles-ci sont illustrées à la figure 3.

Figure 3. Install Packages

Après cette étape, les options d'installation standard ont été choisies et l'assistant d'installation a été
suivi jusqu'à ce que le programme était installé avec succès.

b) Implementation Microblaze
Le processus de mise en œuvre du projet est mis en évidence ci-dessous.
• Open Vivado SDK
• Créer un nouveau projet
• Créer un diagramme
• Remplir le diagramme avec les ports, blocs,
et IP
• Diagramme de câblage si nécessaire
• Assurez-vous que les paramètres et les noms de tous les blocs sont comme vous le souhaitez
• Validation de la conception
• Générer un flux binaire
• Exporter le flux binaire
• SDK ouvert
• Créer un projet SDK
• Ecrire le code Microblaze

Page | 87 © ISI 2018 Ridha Ghayoula


• compiler le code
• Ecrire bitstream sur le tableau
• Ecrire du code à bord et exécuter le programme

La première étape de la mise en œuvre du projet était d'ouvrir Vivado 2017.2 et pour créer un
nouveau projet. Un répertoire et Le nom de fichier sans espaces a été utilisé et il a été configuré
comme Projet RTL avec le "Ne pas spécifier les sources pour le moment" case cochée Après avoir
cliqué sur «Suivant», le tableau Arty devrait être sélectionné en sélectionnant l'icône ”Boards” et en
sélectionnant "Arty". Une fois le projet terminé créé, un nouveau design de bloc a été créé, en
cliquant sur le”Créer un bloc de conception” sous le volet ”IP INTEGRATOR”. Le diagramme a
été ouvert et le processus de le remplissage du diagramme a été commencé.

Figure. 4. Select Arty Board

Page | 88 © ISI 2018 Ridha Ghayoula


Figure. 5. Create Block Design In New Project

Un bloc d’horloge système a été ajouté en cliquant sur le «Board» volet, et en faisant glisser le bloc
”Horloge système” dans le bloc diagramme Figure 6. Le bloc est représenté par la Figure 7.
L'horloge les paramètres de bloc ont été définis comme indiqué dans la Figure 8 et la Figure 9 à
avoir 3 sorties d'horloge avec une remise à zéro active.

Figure. 6. Add Clock Block

Figure. 7. Clock Block

Page | 89 © ISI 2018 Ridha Ghayoula


Figure. 8. Clock Settings

Figure 9. Clock Settings Ctd.

Ensuite, l’interface de mémoire externe DDR3 SDRAM était ajoutée. Ceci est illustré à la figure 10.
Une fois ajouté, le logiciel ajouté automatiquement le bloc générateur d'interface mémoire avec
l'interface mémoire, comme illustré à la Figure 11.

Figure 10. DDR3 Menu Item

Figure 11. DDR3 Interface avec MIG Block


La reset du système a été ajoutée et les blocs ont été connectés comme le montre la Figure 12.

Page | 90 © ISI 2018 Ridha Ghayoula


Figure 12. MIG Block avec Clock Block

L'IP Microblaze a été ajouté ensuite. Pour ajouter cet élément, l’icône «+» illustrée à la Figure 14 a
été cliquée et l’IP Microblaze a été choisie. Ensuite, l'assistance du concepteur «Run Block
Automation», affichée en vert en haut du diagramme, a été utilisée. Les paramètres de la mémoire
locale, de la configuration du cache et de la connexion d'horloge ont été modifiés pour refléter la
Figure 13. Une fois cette étape terminée, le diagramme ressemblait à la Figure 15.

Page | 91 © ISI 2018 Ridha Ghayoula


Figure 13. Microblaze Block Automation Settings

Figure 14. Add Microblaze IP

Page | 92 © ISI 2018 Ridha Ghayoula


Figure 15. Microblaze Block Automation Result

Jusqu'à ce point, les connexions de fils spécifiques dans le diagramme seraient largement modifiées,
de sorte que peu d'attention a été accordée à la configuration du câblage de cette manière. Les ports
GPIO illustrés à la Figure 16 et le port UART ont été ajoutés
prochain. La carte Arty configure automatiquement les ports LED GPIO pour partager un bloc
AXI GPIO, tandis que les boutons et les commutateurs en partagent un autre. Après l’ajout de ces
broches, le résultat est illustré par la figure 17. Les blocs ont ensuite été renommés pour avoir
des noms plus intuitifs, comme le montre la figure 18. Le port UART a également ajouté un bloc
GPIO, mais ce bloc n'a pas été renommé.

Figure 16. Adding GPIO Ports

Figure 17. Added LED and Button Ports

Page | 93 © ISI 2018 Ridha Ghayoula


Figure 18. Renamed GPIO Blocks

À ce stade, l'automatisation de la connexion était exécutée sur les ports GPIO pour ajouter tous les
blocs nécessaires restants au diagramme, mais les connexions effectuées n'étaient pas
(nécessairement) utilisées. Les blocs ont été renommés et connectés comme le montre la figure 19
(voir annexe pour une plus grande image). Notez que certains éléments ont été supprimés et que
certains ont été dupliqués et / ou renommés pour obtenir le résultat affiché.

Figure 19. Final Block Diagram Layout

L'étape suivante consistait à valider la conception en cliquant sur l'icône de la case à cocher illustrée
à la Figure 20. Une fois terminé, un message confirmant qu'aucune erreur de connexion n'existait.

Figure 20. Block Diagram Validation


Après cela, un wrapper HDL a été créé en naviguant vers «Sources», en cliquant avec le bouton droit
sur la conception du diagramme et en cliquant sur «Créer un wrapper HDL». Figure 21. Notez que
chaque fois que le diagramme est modifié et un nouveau créé.

Page | 94 © ISI 2018 Ridha Ghayoula


Figure 21. HDL Wrapper Creation

La conception doit ensuite être synthétisée et un flux binaire généré. Pour ce faire, l'icône «Générer
un flux binaire» (Generate Bitstream) illustrée à la Figure 22. Les paramètres par défaut dans la
fenêtre suivante ont été sélectionnés Figure 23.
Pendant une courte période, une barre d’état a montré, puis la synthèse et le processus de mise en
œuvre ont suivi. Son statut peut être vu en regardant l'indicateur d'état en haut à droite du logiciel
Vivado, à côté du bouton de sortie. Figure 24.

Figure 22. Generate Bitstream Icon

Page | 95 © ISI 2018 Ridha Ghayoula


Figure 23. Generate Bitstream Icon

Figure 24. Bitstream Generation Status


Lorsque la génération de flux binaire(Generate Bitstream) est terminée, une boîte de message
apparaît, demandant si l'utilisateur souhaite voir la conception mise en œuvre, afficher les rapports,
ouvrir le gestionnaire de matériel ou générer un fichier de configuration de mémoire. Depuis aucun
de ces options étaient pertinentes, "Annuler" a été sélectionné.
L'étape suivante consistait à exporter du matériel. Cela a été fait en sélectionnant "Fichier - Exporter
- Exporter le matériel", en cochant la case "Inclure Bitstream" et en cliquant sur "OK". Figure 25. Si
une boîte de dialogue de remplacement apparaît.

Figure 25. Export Hardware Step


Enfin, le SDK a été ouvert en sélectionnant «Fichier - Lancer SDK». Le SDK permet à l'utilisateur
d'écrire le flux binaire sur l'Arty et d'écrire des programmes pour le processeur logiciel Microblaze.
c) La programmation avec SDK

Page | 96 © ISI 2018 Ridha Ghayoula


Lorsque le SDK est lancé, il doit ouvrir une nouvelle fenêtre. Une fois cette nouvelle fenêtre
ouverte, un nouveau projet a été créé en allant dans «Fichier - Nouveau projet d'application» (File -
New Application Project ). Une fenêtre apparaîtra dans laquelle le projet peut être nommé. Le reste
des informations doit être rempli automatiquement, comme illustré Figure 26. Une fois le projet
nommé, «Suivant» a été sélectionné, puis le modèle «Hello World» a été sélectionné. Figure 27.

Figure 26. Name SDK Project

Figure 27. Select Hello World Template

Une fois que cela est construit, le fichier ”src” sous l'explorateur de projet a été ouvert et
”helloworld.c” a été ouvert car il s'agissait du fichier principal pour le code C SDK à écrire sur le
périphérique. Le code initialement contenu dans ce fichier a ensuite été remplacé par

Page | 97 © ISI 2018 Ridha Ghayoula


le code illustré à la figure 28. Ce code est configuré pour lire les boutons et les commutateurs de la
carte de développement, puis écrire sur les voyants. Pour ce faire, les périphériques Gpio sont
initialisés puis leurs directions ont été définies. Puis à l'intérieur d'une boucle, les valeurs des
commutateurs et des boutons ont été lues. La valeur des commutateurs a été écrite sur les sorties
LED. Les valeurs des boutons étaient affichées en écrivant sur le port série.

Figure 28. C-Code pour implementer avec MicroBlaze

Page | 98 © ISI 2018 Ridha Ghayoula


Une fois le code écrit, il a été enregistré, ce qui compilera automatiquement et vérifiera le code. Une
fois le code compilé, il peut être écrit sur le FPGA. Avant cette étape, la carte Arty était branchée sur
l'ordinateur.
Dans la barre d'outils de sélection rapide, vous avez cliqué sur le bouton Program FPGA qui ouvre
la fenêtre de programmation du FPGA illustrée à la Figure 29. Les paramètres ont été vérifiés pour
correspondre à ceux de la Figure 29. Après ce programme a été programmé.

Figure 29. Programmer Arty-7

Une fois le FPGA programmé, le programme devait être exécuté. Cela a été fait en sélectionnant le
menu déroulant à côté du bouton vert, puis en sélectionnant « Run as - Launch on Hardware

Page | 99 © ISI 2018 Ridha Ghayoula


(System Debugger) (débogueur système)». Cela exécutera le programme sur le FPGA qui peut être
testé en retournant les commutateurs sur la carte et en veillant à ce que les voyants correspondants
s'allument. La sortie série peut être testée en ouvrant un terminal série tel que Putty et en se
connectant correctement au port COM auquel la carte est connectée.

Exercices
Exercice 1 : Questions de Cours
1. Donnez des exemples de processeurs softcore et hardcores ?
2. Quelles sont les avantages et les inconvénients des processeurs « softcore » ?
3. Quelles sont les avantages et les inconvénients des processeurs « Hardcore » ?
4. Que signifient Microblaze et NIOS ? citez le Plateforme de développement ?
5. Quelle est la démarche générale de conception d’un système embarqué ?

Exercice 2 : Exemple de hw-sw co-conception avec PicoBlaze


Le PicoBlaze est un microcontrôleur 8 bits de type RISC développé par Xilinx utilisé principalement
sur les cartes Spartan 3E.
.
Partie I: HARD

Page | 100 © ISI 2018 Ridha Ghayoula


8 bits
8 bits 8 bits Port PORT_ID
Address READ_STROBE
8 bits control
8 registres WRITE_STROBE

8 bits 8-bit
8 bits

IN_PORT 8 bits
ALU
scratch pad
memory
64 bytes
Zero Interrup
& Carry shadow
INTERRUPT Falgs Flag

Interrupt
INSTRUCTION 8 bits ADRESS
18 bits Program
flow Program
8 bits Counter 8 bits
Operational control
Control
CONSTANT DATA
RESET Inst Dec
CLK Program
Counter
stack

Figure 1. Architecture interne de Picoblaze KCPSM3

1. Identifiez et donnez le rôle de chaque bloc à partir de l’architecture interne de Picoblaze


(Figure.1)
2. L’ALU du PicoBlaze permet d’effectuer de petites opérations élémentaires sur 8 bits.
L’ALU utilise un opérande située dans un registre sX et retourne le résultat dans ce même
registre. Si il est nécessaire d’utiliser un second opérande, il est possible de spécifier un
registre sY ou bien une constante kk sur 8 bits dans le programme. Les opérations d’addition
et de soustraction peuvent faire appel au CARRY flag pour effectuer des opérations sur des
mots de plus de 8 bits.
Donnez l’entité et l’architecture d’ALU.
3. Le PicoBlaze contient 16 registres de 8 bits nommés de S0 à SF. Donnez une description en
VHDL de ces blocs.

Partie II : SOFT
On considère que les registres du processeur contiennent les huit chiffres hexadécimaux suivants :
S0 0000 0000
S1 1234 5678
S2 1111 0000

1. Donner le contenu des registres S0 à S2 (sous forme de huit chiffres hexadécimaux) après
exécution des instructions suivantes.
a) ADD S0, 1
b) SUB S1, 4
c) SR0 S2

Page | 101 © ISI 2018 Ridha Ghayoula


2. On suppose qu'en adresse $02 se trouvent des valeurs (octets) provenant de l'extérieur du
PicoBlaze. Les détails sur la façon dont cela peut marcher ne nous intéressent pas ici.
Ecrire un programme qui fait l'acquisition de 2 de ces valeurs et les stocke dans un tableau.
Ensuite on calculera la somme de ces 2 cases divisée par 2 et le résultat sera rangé à l'adresse
$06
Exercice 3 : Partie soft (Micro contrôleur embarqué : le PicoBlaze)
On suppose qu'en adresse $00 se trouvent des valeurs positives (octets) provenant de l'extérieur du
PicoBlaze. Les détails sur la façon dont cela peut marcher ne nous intéressent pas ici. La lecture de
cette adresse (on parle de port) se fait avec l'instruction INPUT. Faire un programme qui fait sans
arrêt l'acquisition de 4 de ces valeurs, fait la somme et divise par 4 le résultat pour le ranger le tout à
l'adresse $04 (écriture d'un port avec l'instruction OUTPUT).
Indication : la division par 4 peut être réalisée par deux divisions par deux à la suite. Une division par
deux se réalise par un décalage à droite d'un bit. Mais il vous faut décaler un nombre plus grand que
8 bits (s_msb s_lsb). Cela peut se faire avec les instructions SR0 et SRA.

Exercice 4 : Partie soft (Micro contrôleur embarqué : le PicoBlaze)


On suppose qu'en adresse $00 se trouvent des valeurs (octets) provenant de l'extérieur du PicoBlaze.
Les détails sur la façon dont cela peut marcher ne nous intéressent pas ici.
1. Faire un programme qui fait l'acquisition de 4 de ces valeurs et les stocke dans un tableau.
Ensuite on calculera la somme de ces 4 cases divisée par 4 et le résultat sera rangé à l'adresse
$04.
2. Modifier ce programme pour qu'il calcule le maximum des 4 valeurs du tableau et le range en
mémoire à la suite du tableau.

Exercice 5 : Mapping d’une architecture


La Figure 1 illustre le schéma d’un microsystème embarqué. Il est conçu autour d’un microsystème 8
bits en architecture minimale, les circuits de mémoires sont partagés en RAM1 et RAM2 ainsi qu’un
boitier ROM, deux circuits PIA et ACIA servent d’interface avec les périphériques.

Page | 102 © ISI 2018 Ridha Ghayoula


D7-D0

D7-D0 D7-D0 D7-D0 D7-D0 D7-D0

µP ROM
CS
RAM RAM PIA ACIA
Y7 Y0 CS 1 CS 2 CS CS
Y1 Y2 A1-A0
A10-A0 A7-A0 A7-A0 Y4 A0

A10-A0

Décodeur
3/8
A13 Y0

A14
74LS138

A15
Y7

Figure 2. Microsystème embarqué

Les bits d’adresse A13, A14 et A15 servent au codage des différents circuits du système moyennant
un décodeur 3 vers 8 (Figure1 donne la Table de vérité du décodeur)
INPUTS OUTPUTS
A15 A14 A13 Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7
X X X H H H H H H H H
X X X H H H H H H H H
L L L L H H H H H H H
L L H H L H H H H H H
L H L H H L H H H H H
L H H H H H L H H H H
H L L H H H H L H H H
H L H H H H H H L H H
H H L H H H H H H L H
H H H H H H H H H H L
Table 1. 74(LS) 138 : Décodeur/Démultiplexeur 3 vers 8

Page | 103 © ISI 2018 Ridha Ghayoula


- Pour sélectionner RAM1 : il faut que CS (chip Select)=0 (Y0=0)
- Pour sélectionner RAM2 : il faut que CS (chip Select)=0 (Y1=0)
- Pour sélectionner ROM : il faut que CS (chip Select)=0 (Y7=0)
- Pour sélectionner PIA : il faut que CS (chip Select)=0 (Y2=0)
- Pour sélectionner ACIA : il faut que CS (chip Select)=0 (Y4=0)
1. préciser le mapping de cet architecture minimale (partage de zone mémoire et la taille des
différents boitiers)

Page | 104 © ISI 2018 Ridha Ghayoula


4
Conception d’un processeur dédié au calcul
PGCD

4.1. Introduction
Si m et n sont des nombres entiers, le plus grand diviseur commun à m et n est le plus grand nombre
entier positif qui divise à la fois m et n.
On note par l’expression PGCD(a, b, c) le plus grand commun diviseur des nombres a, b et c.
L’objectif de ce chapitre est de familiariser avec la conception des processeurs dediés a des
applications specifiques. Les premières sections s’attacheront à présenter l'architecture materielle
d'un processeur dedié au calcul PGCD . Nous nous intéresserons ensuite à l’intégration « système »
de ce type de ressources, en présentant les différents blocs. Nous présenterons finalement le flot de
conception utilisé pour ce type de technologie, en insistant plus particulièrement sur les outils de
synthèse de haut-niveau.

4.2. Conception d’un processeur dédié au calcul PGCD (plus grand commun
diviseur) de deux entiers

En arithmétique élémentaire, le plus grand commun diviseur, abrégé en général PGCD, de deux
nombres entiers naturels non nuls est le plus grand entier qui divise simultanément ces deux entiers.
Par exemple le PGCD de 20 et 30 est 10. En effet, leurs diviseurs communs sont 1, 2, 5 et 10.

Exemples

 On cherche le PGCD de 15 et 12.


Les diviseurs positifs de 15 sont : 1, 3, 5, 15.
Les diviseurs positifs de 12 sont : 1, 2, 3, 4, 6, 12.
Les seuls diviseurs communs à 15 et 12 sont donc 1 et 3. On en déduit PGCD(12, 15) = 3.
 Les diviseurs communs à 36, 48 et 60 sont 1, 3, 4 et 12 donc PGCD(36, 48, 60) = 12.

Page | 105 © ISI 2018 Ridha Ghayoula


go_i

Unité de contrôle

!1
0000 :1
1 !(!go_i)
0001 :2

!go_i

0010 : 2-J

0011 : 3 x_sel=0
x_ld=1

x_i [31..0] y_i [31..0]

y_sel=0
0100 : 4
y_ld=1 32 bits 32 bits Unité
opérative
!x_neq_y
0101 : 5 x_sel MUX MUX
y_sel
x_neq_y
0110 : 6
x_ld 0:x 0:y
x_inf_y !x_inf_y
y_ld

y_sel=1 x_sel=1
y_ld=1 x_ld=1

0111 : 7 1000 : 8
Comparateur Comparateur Soustracteur Soustracteur
<
!= - -
1001 : 6-J

5: x!=y 6: x<y 8: x-y 7: y-x

1010 : 5-J

x_neq_y

1011 : 9 d_ld = 1
x_inf_y

d_ld 9:d
1100 : 1-J

d_o [31..0]

Figure 4.1. Conception d’un système numérique de calcul du PGCD

Dans cette partie on introduit le modèle de base, sous forme d’unité opérative et d’unité de
contrôle, d’un processeur dédié à une seule tâche spécifique (Figure 1). Une méthodologie de
conception systématique de tels processeurs à partir de la description fonctionnelle de la tâche et en
se basant sur des éléments de base en logique combinatoire et séquentielle (registres, unités
fonctionnelles, machine d’états) est présentée. Cette méthodologie est détaillée à travers un exemple
de conception d’un processeur dédié au calcul PGCD (plus grand commun diviseur) de deux entiers
(Figure 1). A partir de la représentation sous forme de boîte noire du processeur en définissant ses
entrées/sorties, la première étape consiste à écrire l’algorithme qui réalise la fonctionnalité désirée
sous forme de pseudo-code. La deuxième étape convertit cet algorithme en machine d’état
‘complexe’, contenant la partie opérative du processeur, appelée FSMD (finite-state machine with

Page | 106 © ISI 2018 Ridha Ghayoula


datapath). Cette conversion est rendue systématique grâce à l’emploi de gabarits pré-définis pour
tous les types des instructions de calcul et de contrôle (affectation, boucle, branchement, etc).
0: int x, y;
1: while (1) {
2: while (!go_i);
3: x = x_i;
4: y = y_i;
5: while (x != y) {
6: if (x < y)
7: y = y - x;
else
8: x = x - y;
}
9: d_o = x;
}

Exemple 1: Le PGCD de ces nombres, est le plus grand diviseur commun, c'est-à-dire 1.
PGCD(26;15)=1

Figure 4.2. PGCD(26;15)=1

Exemple 2: PGCD(96;36)=12

Figure 4.3. PGCD(96;36)=12

Exemple 3: PGCD(161;14)=7

Figure 4.4. PGCD(161;14)=7

Page | 107 © ISI 2018 Ridha Ghayoula


Logic Utilization Used Available Utilization
Number of Slices 117 768 15%
Number of Slice Flip Flops 168 1536 10%
Number of 4 input LUTs 189 1536 12%
Number of bonded IOBs 99 184 53%
Number of GCLKs 2 4 50%
Tableau 4.1.Résumé d’utilisation de ressources dans la phase de synthèse de l'architecture de calcul
du PGCD (xcv50-5bg256)

Le Tableau 2.1 montre les résultats de la synthèse de l’architecture globale et donne un résumé sur
les ressources utilisées après optimisation, placement et routage.
L’architecture du réseau a utilisé 99 blocs entrée-sortie sur un total de 184 (53%), elle a occupé 117
"SLICES" sur un total de 768 c'est-à-dire 15% du circuit xcv50-5bg256.

4.2.1 . Multiplexeur MUX


val_init [31..0]

result[31..0]
32 bits

MUX
sel

output [31..0]

Page | 108 © ISI 2018 Ridha Ghayoula


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
entity mux is
port( rst, sel: in std_logic ; -- std_logic représente un bit
-- sel = select line, soit x_sel ou y_sel
val_init, result: in std_logic_vector( 31 downto 0 );
-- val_init est la valeur initiale de x ou de y
-- result est le résultat de la soustraction
output: out std_logic_vector( 31 downto 0 ) );
end mux;

architecture mux_arc of mux is


begin
process( rst,sel, val_init, result )
begin
if (rst='1') then output<="00000000000000000000000000000000";
elsif (sel = '0') then
output <= val_init; -- load inputs c-a-d soit x_i, soit y_i
elsif (sel ='1') then
output <= result; -- load results c-a-d le résultat d'une soustraction
end if;
end process;
end mux_arc;
4.2.2 . Registre X_Reg,Y_Reg et Out_Reg

input_reg [31..0]

rst

clk 0:x load

output_reg [31..0]

Page | 109 © ISI 2018 Ridha Ghayoula


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

entity registre is
port( rst, clk, load : in std_logic; -- reset, horloge, signal load
input_reg : in std_logic_vector( 31 downto 0 );
-- valeur d'entrée ex :x_i, résultat de la soustraction..
output_reg : out std_logic_vector( 31 downto 0 ) -- valeur de sortie
);
end registre;

architecture regis_arc of registre is


begin
process( rst, clk, load, input_reg )
begin
if ( rst = '1' ) then
output_reg <= "00000000000000000000000000000000";
elsif (clk'event and clk='1') then
if( load = '1' ) then -- si le chargement est activé alors entrée sera affecté a sortie
output_reg <= input_reg;
end if;
end if;
end process;
end regis_arc;

4.2.3. Comparateur: comparateur_lt


x [31..0] y [31..0]

Comparateur
!=

x_lt_y

Page | 110 © ISI 2018 Ridha Ghayoula


library IEEE;
use IEEE.std_logic_1164.all;
--use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

entity comparateur_neq is
port(
x, y: in std_logic_vector( 31 downto 0 ); -- les entrées à comparer
x_neq_y: out std_logic -- le résultat de la comparaison, 1 si vrai, 0 sinon
);
end comparateur_neq;

architecture comparateur2_arc of comparateur_neq is


begin
process( x, y )
begin
if( x = y ) then
x_neq_y <= '0'; -- si x != y
else
x_neq_y <= '1'; -- si x = y
end if;
end process;
end comparateur2_arc;

4.2.4. Comparateur: comparateur_neq


x [31..0] y [31..0]

Comparateur
<

x_neq_y

Page | 111 © ISI 2018 Ridha Ghayoula


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity comparateur_lt is
port(
x, y: in std_logic_vector( 31 downto 0 ); -- les entrées à comparer
x_lt_y: out std_logic -- le résultat de la comparaison, 1 si vrai, 0 sinon
);
end comparateur_lt;

architecture comparateur_arc of comparateur_lt is


begin
process( x, y )
begin
if( x < y ) then
x_lt_y <= '1'; -- si x < y
else
x_lt_y <= '0'; -- si x > y
end if;
end process;
end comparateur_arc;

4.2.5. Soustracteur :

x [31..0] y [31..0]

x_neq_y
Soustracteur
rst -

output[31..0]

Page | 112 © ISI 2018 Ridha Ghayoula


4.2.6 . FSM
go_i clk rst

x_lt_y

x_neq_y
FSM

x_sel y_sel x_ld y_ld d_ld

Page | 113 © ISI 2018 Ridha Ghayoula


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

entity FSM is
port( rst, clk, go_i: in std_logic;
x_lt_y, x_neq_y : in std_logic;
x_sel, y_sel, x_ld, y_ld,d_ld: out std_logic
);
end FSM;
architecture fsm_arc of fsm is
type states is ( init, s00,s0, s1, s2, s3, s4, s5 ); -- les differents etats de notre FSM
signal nState, cState: states; -- next state , et current state
begin
process( rst, clk )
begin
if( rst = '1' ) then
cState <= init;
elsif( clk'event and clk = '1' ) then
cState <= nState;
end if;
end process;
process( go_i, x_lt_y, x_neq_y, cState )
begin
case cState is
when init =>
if( go_i = '0' ) then nState <= init; else nState <= s00; end if;
when s00 => d_ld<='0'; x_sel <= '0'; y_sel <= '0'; x_ld <= '0'; y_ld <= '0';nState <= s0;
when s0 => d_ld<='0'; x_sel <= '0'; y_sel <= '0'; x_ld <= '1'; y_ld <= '1';nState <= s1;
when s1 => x_ld <='0'; y_ld <='0'; d_ld<='0'; if ( x_neq_y = '1' ) then nState<= s2;
else nState<=s5; end if;
when s2 => x_ld <= '0'; y_ld <= '0'; if( x_lt_y = '1' ) then nState <= s3;
else nState <= s4;
end if;
when s3 => d_ld<='0'; x_sel <= '0'; y_sel <= '1'; x_ld <= '0'; y_ld <= '1';nState <= s1;
when s4 => d_ld<='0'; x_sel <= '1'; y_sel <= '0'; x_ld <= '1'; y_ld <= '0';nState <= s1;
when s5 => d_ld<='1'; nState <= init;
when others => nState <= s00;
end case;
end process;
end fsm_arc;

4.2.7. Programme principal


x_i[31..0] y_i [31..0]

rst

clk
PGCD

d_o [31..0]

Page | 114 © ISI 2018 Ridha Ghayoula


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use work.all;

entity pgcd is
port( rst,clk,go_i: in std_logic;
x_i, y_i: in std_logic_vector( 31 downto 0 );
d_o: out std_logic_vector( 31 downto 0 )
);
end pgcd;

architecture pgcd_arc of pgcd is


component FSM is
port( rst,clk,go_i: in std_logic;
x_lt_y, x_neq_y: in std_logic;
x_sel, y_sel, x_ld, y_ld, d_ld: out std_logic -- d_ld signal de fin
);
end component;
component mux is
port( rst, sel : in std_logic; -- std_logic représente un bit
-- sLine = select line, soit x_sel ou y_sel
val_init, result: in std_logic_vector( 31 downto 0 );
output: out std_logic_vector( 31 downto 0 )
);
end component;
component comparateur_neq is
port(
x, y: in std_logic_vector( 31 downto 0 ); -- les entrées à comparer
x_neq_y: out std_logic -- le résultat de la comparaison, 1 si vrai, 0 sinon
);
end component;
component comparateur_lt is
port(
x, y: in std_logic_vector( 31 downto 0 ); -- les entrées à comparer
x_lt_y: out std_logic -- le résultat de la comparaison, 1 si vrai, 0 sinon
);
end component;

component soustracteur is
port( rst: in std_logic;
x_lt_y: in std_logic; -- signal de commande
x, y: in std_logic_vector( 31 downto 0 );
output: out std_logic_vector( 31 downto 0 )
);
end component;

component registre is
port( rst,clk,load: in std_logic; -- reset, horloge, signal load
input_reg: in std_logic_vector( 31 downto 0 );
-- valeur d'entrée ex :x_i, résultat de la soustraction..
output_reg: out std_logic_vector( 31 downto 0 ) -- valeur de sortie
);
end component;
signal x_ld, y_ld, x_sel, y_sel, d_ld: std_logic;

Page | 115 © ISI 2018 Ridha Ghayoula


signal x_lt_y,not_x_lt_y, x_neq_y: std_logic;
signal result: std_logic_vector( 31 downto 0 );
signal xsub, ysub, xmux, ymux, xreg, yreg: std_logic_vector( 31 downto 0 );
begin
not_x_lt_y <= not(x_lt_y);
TOFSM: FSM port map( rst,clk,go_i, x_lt_y, x_neq_y, x_sel, y_sel, x_ld, y_ld, d_ld );
X_MUX: mux port map( rst,x_sel, x_i, xsub, xmux );
Y_MUX: mux port map( rst, y_sel, y_i, ysub, ymux );
X_REG: registre port map(rst,clk,x_ld, xmux, xreg );
Y_REG: registre port map(rst,clk,y_ld, ymux, yreg );
neq_COMP: comparateur_neq port map( xreg, yreg, x_neq_y );
lt_COMP: comparateur_lt port map( xreg, yreg, x_lt_y );
Y_SUB: soustracteur port map( rst,x_lt_y, xreg, yreg, ysub );
X_SUB: soustracteur port map( rst,not_x_lt_y, yreg, xreg, xsub );
OUT_REG: registre port map( rst,clk,d_ld, xreg, result );
d_o <= result;
end pgcd_arc;

Figure 4.4. PGCD(161;14)=7

Page | 116 © ISI 2018 Ridha Ghayoula


5
Implémentation de l'Algorithme Cordic

5.1. Introduction
CORDIC (sigle de COordinate Rotation DIgital Computer : « calcul numérique par rotation de
coordonnées ») est un algorithme de calcul des fonctions trigonométriques et hyperboliques,
notamment utilisé dans les calculatrices. Il a été décrit pour la première fois en 1959 par Jack E.
Volder. Il ressemble à des techniques qui avaient été décrites par Henry Briggs en 1624. Il s'agit d'un
algorithme de choix lorsqu'aucune implantation matérielle d'un multiplicateur n'est disponible (sur
certains microcontrôleurs simples ou des FPGA). De plus, l'algorithme du CORDIC s'adapte bien
au calcul à la chaîne. À l'origine, la programmation du CORDIC reposait sur un système binaire.
Durant les années 1970, les versions décimales du CORDIC (avec des nombres codés en BCD)
commencèrent à apparaître, notamment dans les calculatrices où les critères de coût du matériel sont
plus importants que la vitesse de traitement. Un autre avantage du CORDIC est sa flexibilité
puisqu'il permet de calculer plusieurs fonctions avec quasiment le même code [5.1].

5.2. Algorithme CORDIC


L’algorithme CORDIC, (acronyme de COordinate Rotation DIgital Computing) a été créé pour
effectuer des calculs tels que les rotations de vecteurs ou les changements de coordonnées
cartésiennes-polaires et polaires-cartésiennes dans le plan euclidien, dans des applications de
navigation aérienne. C’est une méthode simple et efficace pour le calcul d’une gamme de fonctions
complexes qui s’appuie sur une technique d’additions et de décalage entre vecteurs. L’algorithme
CORDIC est basé sur des calculs de fonctions trigonométriques, son principe est d’effectuer des
rotations sur un vecteur de base pour un angle donné. La transformation élémentaire des rotations
s’exprime sous forme matricielle comme suit :
 x   cos m  m sin m   x 
 y     
  1 / m sin m cos m   y 
Le paramètre m
peut prendre les trois valeurs suivantes :

Page | 117 © ISI 2018 Ridha Ghayoula


• m = 1 : cas circulaire, il permet de calculer différentes fonctions trigonométriques (sinus, cosinus,
arc tangente) ainsi que des racines carrées,
• m = -1 : cas hyperbolique, il permet de calculer les fonctions sinus, cosinus et arg-tangente
hyperboliques ainsi que l’exponentielle,
• m = 0 : cas linéaire il permet également le calcul direct de multiplications et de divisions.
Il est à noter qu’en combinant ces différentes fonctions on peut calculer de manière indirecte les
tangentes circulaire et hyperbolique, ainsi que les logarithmes. La résolution de fonctions telles que
sinus ou cosinus par l’algorithme de CORDIC s’appuie sur une méthode de rotation de vecteur dans
le plan cartésien. Supposons la rotation du vecteur V(x, y) d’un angle φ telle qu’illustrée à la Figure
5.1.

V'
y'

y V
φ

x' x X
Figure 5.1 – Rotation du vecteur V dans le plan cartésien

Les coordonnées du vecteur V' sont exprimées selon les équations :


x   x cos    y sin 
y   y cos    x sin 

V'
y'

y
β2 V
φ

β1
On a x' x X
x  cos 1
y  sin  1

x   cos  2
y   sin  2
   2  1

Page | 118 © ISI 2018 Ridha Ghayoula


x   cos  2  cos   1   cos  cos 1  sin  sin 1  x cos    y sin 
y   sin  2  sin  1   cos  sin 1  sin  cos 1  y cos    x sin 
La matrice de rotation Ri s'obtient selon la formule suivante :
 cos  i  sin  i 
Ri   
 sin  i cos  i 
En factorisant le terme cos   on obtient
 1   i tan  i  xi 
vi 1  Ri vi  cos  i   
 i tan  i 1  yi 
1
avec v 0   
0
Le facteur  i prend les valeurs +1 ou -1 et sert à indiquer le sens de la rotation. Si l'on restreint les
choix possibles pour l'angle  de manière à ce que tan   soit égal à 2 i alors la multiplication par la
tangente devient une multiplication par une puissance de 2. Une opération aisée à réaliser
informatiquement puisqu'en binaire il s'agit d'un décalage de bits.
Le calcul devient :

  
 1
vi 1  Ri vi  cos arctan 2 i 
  2 i
  i 2 i 
1 
 xi   x   i 2 i y i 
   K i  i
 x  2 i  y 

 i  yi   i i i

avec

K i  cos arctan 2 i  
Ces coefficients K i peuvent être ignorés pendant les itérations et factorisés en un seul coefficient
multiplicatif final (dépendant de n) :

n 1 n 1 n 1
K n         1
Ki  cos arctan 2 i 
i 0 i 0 i 0 1  2  2i

Qui peut être calculé à l'avance et prémémorisé. Également, lorsque n tend vers l'infini, ce produit
tend vers une constante :

K  lim K n   0.6073 .......


n

Après suffisamment d'itérations, l'angle du vecteur sera proche de l'angle  voulu.

La dernière étape consiste à déterminer à chaque itération le sens de rotation, trigonométrique ou


horaire (un résultat reporté sur la valeur de  i ). Pour ce faire, on regarde l'angle  n1 actuel du
vecteur que l'on soustrait à l'angle désiré. On teste si cette différence est positive (rotation dans le
sens horaire) ou négative (sens trigonométrique), de façon à s'approcher de l'angle  .

Page | 119 © ISI 2018 Ridha Ghayoula


 i 1   i   i  i et  i  arctan 2 i

Les valeurs de  n sont précalculées dans une table prémémorisée de valeurs. Toutefois, pour des
angles petits, on utilise l'approximation arctan  n    n dans une représentation en virgule fixe,
permettant ainsi de réduire la taille de cette table. Comme illustré dans le schéma ci-dessus, le sinus
de l'angle  est la coordonnée y du vecteur final v n , alors que la coordonnée x correspond au
cosinus.

5.2.1. Généralisation de l'algorithme

En 1971, John Stephen Walther de Hewlett Packard, a présenté une généralisation de l'algorithme
qui fut mise en œuvre dans la calculatrice HP-35. Cette méthode permet de calculer notamment les
fonctions hyperboliques mais également d'autres fonctions comme l'exponentielle, la division ou la
multiplication. La généralisation se présente comme suit :

 x k 1  x k  m k y k 2  k

 y k 1  y k   k x k 2  k
 z k 1  z k   k  k

avec m   1; 0;1,  k des constantes définies à l'avance et  k   1; 1 (en fonction de la valeur de z k ).

5.2.2. Fonctions trigonométriques

On utilise la généralisation avec les paramètres :

m 1
 
 k  a tan 2  k
 k  sgn z k 
x0  1
y0  0
z 0   en radians 

À la fin de n itérations, on a x n  cos  et y n  sin  .

Cette méthode ne fonctionne que si :


   a tan 2   1,7
i 0
i

En pratique cela ne pose pas de problème car les fonctions trigonométriques peuvent toujours être

ramenées au cas 0   
2

Page | 120 © ISI 2018 Ridha Ghayoula


Exemples de programmation

MATLAB
function v=cordic(beta,n)
% Calcul de 'cos' et 'sin' d'un angle 'beta' (en radians)
% par l'algorithme CORDIC. Résultat dans le vecteur 'v'.
% 'n' est le nombre d'itérations (la précision augmente avec lui).
% Initialisation
v=[1;0];
sigma=1;
Kn=prod(1./sqrt(1+2.^(-2*(0:(n-1)))));
%%Itérations
for i=0:n-1;
R=[1 -sigma*2^-i;sigma*2^-i 1];
v=R*v;
beta=beta-sigma*atan(2^-i);
sigma=sign(beta);
end
%% Calcul final
v=v*Kn;
Langage C
Le code suivant utilise les flottants étendus (double). Beta est l'angle voulu en radians. On démarre
par le vecteur v = (1;0), pré-multiplié par K.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int nb_iter; // Nombre d'itérations
double K = 0.6073; // Valeur de K
double x = K, y = 0; // Valeur approchante de cos(beta) et sin(beta)
double x_Nouveau; // Variable temporaire
double beta = 0; // Angle à chercher
double Pow2; // Valeur de la puissance de deux
printf("Calcul par la methode CORDIC de sinus : \n\n\n Veuillez entrer beta\n");
scanf("%lf",&beta); // entrer la valeur de beta
printf("Veuillez entrer le nombre d'iterations voulues\n");
scanf("%d",&nb_iter); // Entrer le nombre d'itération
int i = 0; // declaration de l'indice d'iteration
for(i = 0; i < nb_iter; i++)
{
Pow2 = pow(2,-i);
// Si beta<0 rotation dans le sens trigo
if(beta < 0) {
x_Nouveau = x + y*Pow2;
y -= x*Pow2;
beta += atan(Pow2);
}
// sinon dans l'autre sens
else {
x_Nouveau = x - y*Pow2;
y += x*Pow2;
beta -= atan(Pow2);
}
x = x_Nouveau;
}

Page | 121 © ISI 2018 Ridha Ghayoula


printf("cos(beta) = %lf , sin(beta) = %lf \n", x,y); // Affichage du résultat
return 0;
}

5.3. Description matérielle


Le but de cette description est de réaliser une architecture matérielle permettant de calculer le sinus
et le cosinus d’un angle en utilisant la méthode de CORDIC.
Le principe de la méthode consiste à effectuer des rotations successives d’un vecteur initial. Ces
rotations sont telles que l’angle de rotation tend vers 0. La somme des angles des rotations est égale
à l’angle dont on cherche à calculer le sinus et le cosinus.

COS SIN
Angle start done

init_s init_s init_s


CLK
X_Register Y_Register CLK
Z_Register
CLK
load_s xreg_s load_s yreg_s load_s zreg_s
CLK FSM
reset

init_s
CLK Counter init_s
MSB: Sign bit
cnt_s:(4:0) cnt_s:(4:0) as_s<=zreg_s(width-1 );
load_s
as_s load_s
eb7
cnt_s:(4:0)
n ibus sxreg_s syreg_s n ibus
Shiftn obus obus
Shiftn atran32
LUT
xreg_s tan-12-1
xreg_s atan_s
abus bbus abus bbus abus bbus
as_s
ADD1 as as ADD2 ADD3 as
obus obus obus

newx_s newy_s

Figure 5.2. Description matérielle

Page | 122 © ISI 2018 Ridha Ghayoula


Figure 5.3. CORDIC
i1) Additionneur (ADDi):
Suivant l’état de l’entrée Add/Sous, le circuit devra réaliser :
- Soit une addition (si as = 1) : obu:= abu + bbu;
- Soit une soustraction (si as = 0): obu:= abu - bbu;
32 bits 32 bits

abu bbu
ass ADD1 s
obu
s
32 bits

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
ENTITY addsub IS
GENERIC(
WIDTH : integer := 32 );
PORT(
abus : IN std_logic_vector (WIDTH-1 DOWNTO 0);
bbus : IN std_logic_vector (WIDTH-1 DOWNTO 0);
obus : OUT std_logic_vector (WIDTH-1 DOWNTO 0);
as : IN std_logic);
END addsub ;
architecture synthesis of addsub is
begin
process(as,abus,bbus)
begin
if as='1' then
obus <= abus + bbus;
else
obus <= abus - bbus;
end if;
end process;
end synthesis;

Page | 123 © ISI 2018 Ridha Ghayoula


Exemple : abus=16 et bbus=8
si as=1 o bus= 24
si as=0 o bus= 8
i2) Shiftn:

cnt_s:(4:0)

32 bits

n ibus 32 bits
obus
Shiftn

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
ENTITY shiftn IS
GENERIC( width : integer := 32 );
PORT(
ibus : IN std_logic_vector (WIDTH-1 DOWNTO 0);
obus : OUT std_logic_vector (WIDTH-1 DOWNTO 0);
n : IN std_logic_vector (4 DOWNTO 0) );

END shiftn ;
architecture synthesis of shiftn is
constant null_s : std_logic_vector(31 downto 0):=X"00000000";
signal ibus_s : std_logic_vector(31 DOWNTO 0);
signal obus_s : std_logic_vector(31 DOWNTO 0);

begin
ibus_s <= ibus & null_s(31-WIDTH downto 0);
obus <= obus_s(31 downto 32-WIDTH);
process(n,ibus_s)
begin
case n is
when "00000" => obus_s <= ibus_s(31)&ibus_s(30 downto 0); -- ibus_s
when "00001" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(30 downto 1);
when "00010" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30 downto 2);
when "00011" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30 downto 3);
when "00100" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30 downto 4);
when "00101" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30
downto 5);
when "00110" => obus_s <=ibus_s(31)&ibus_s(31)&ibus_s(31) &ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31
&ibus_s(30 downto 6);
when "00111" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&
ibus_s(31)&ibus_s(30 downto 7);
when "01000" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&
ibus_s(31)&ibus_s(31)&ibus_s(30 downto 8);
when "01001" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&
ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30 downto 9);

Page | 124 © ISI 2018 Ridha Ghayoula


when "01010" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&
ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30 downto 10);
when "01011" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&
ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30 downto 11);
when "01100" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&
ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30 downto 12);
when "01101" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&
ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30
downto 13);
when "01110" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&
ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30 downto 14);

when "01111" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&


ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30
downto 15);

when "10000" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&

ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)
& ibus_s(30 downto 16);
when "10001" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&

ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)
& ibus_s(31)&ibus_s(30 downto 17);
when "10010" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&

ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)
& ibus_s(31)&ibus_s(31)&ibus_s(30 downto 18);
when "10011" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&

ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)
& ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30 downto 19);
when "10100" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&

ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)
& ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30 downto 20);
when "10101" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&

ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)
& ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30 downto 21);
when "10110" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&

ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)
& ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30 downto 22);
when "10111" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&

ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)
& ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30 downto 23);
when "11000" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&

ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)
& ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30 downto
24);
when "11001" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&
ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)
&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30
downto 25);

Page | 125 © ISI 2018 Ridha Ghayoula


when "11010" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&

ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)
&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31
)& ibus_s(30 downto 26);
when "11011" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&

ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)
&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31
)&ibus_s(31)&ibus_s(30 downto 27);
when "11100" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&

ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)
&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31
)&ibus_s(31)&ibus_s(31)&ibus_s(30 downto 28);
when "11101" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&

ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)
&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31
)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30 downto 29);
when "11110" => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&

ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)
&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31
)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(30);
when others => obus_s <= ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&
ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)
&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31
)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31);
end case;
end process;
end synthesis;

Exemple : ibus=8 et n=8


si n=0 obus= 8
si n=1 obus= 4
si n=2 obus= 2
si n=3 obus= 1
si n=4 obus= 0

i3) atran32:
Tab. 3.1 – Constante K n en fonction du nombre d’étages
http://babbage.cs.qc.cuny.edu/IEEE-754.old/Decimal.html

Kn
Etage Décimal Hexadécimal Binaire
0 1 3F800000 0 01111111 00000000000000000000000
1 0.7071 3F350481 0 01111110 01101010000010010000001
2 0.6325 3F21EB85 0 01111110 01000011110101110000101

Page | 126 © ISI 2018 Ridha Ghayoula


3 0.6136 3F1D14E4 0 01111110 00111010001010011100100
4 0.6088 3F1BDA51 0 01111110 00110111101101001010001
5 0.6076 3F1B8BAC 0 01111110 00110111000101110101100
6 0.6074 3F1B7E91 0 01111110 00110110111111010010001
7 0.6073 3F1B7803 0 01111110 00110110111100000000011
8 0.6073 3F1B7803 0 01111110 00110110111100000000011
9 0.6073 3F1B7803 0 01111110 00110110111100000000011
10 0.6073 3F1B7803 0 01111110 00110110111100000000011
11 0.6073 3F1B7803 0 01111110 00110110111100000000011
12 0.6073 3F1B7803 0 01111110 00110110111100000000011
13 0.6073 3F1B7803 0 01111110 00110110111100000000011
14 0.6073 3F1B7803 0 01111110 00110110111100000000011
15 0.6073 3F1B7803 0 01111110 00110110111100000000011
16 0.6073 3F1B7803 0 01111110 00110110111100000000011
17 0.6073 3F1B7803 0 01111110 00110110111100000000011
18 0.6073 3F1B7803 0 01111110 00110110111100000000011
19 0.6073 3F1B7803 0 01111110 00110110111100000000011
20 0.6073 3F1B7803 0 01111110 00110110111100000000011
21 0.6073 3F1B7803 0 01111110 00110110111100000000011
22 0.6073 3F1B7803 0 01111110 00110110111100000000011
23 0.6073 3F1B7803 0 01111110 00110110111100000000011
24 0.6073 3F1B7803 0 01111110 00110110111100000000011
25 0.6073 3F1B7803 0 01111110 00110110111100000000011
26 0.6073 3F1B7803 0 01111110 00110110111100000000011
27 0.6073 3F1B7803 0 01111110 00110110111100000000011
28 0.6073 3F1B7803 0 01111110 00110110111100000000011
29 0.6073 3F1B7803 0 01111110 00110110111100000000011
30 0.6073 3F1B7803 0 01111110 00110110111100000000011
31 0.6073 3F1B7803 0 01111110 00110110111100000000011

Norme IEEE 754


Le format simple IEEE 754 se compose de trois champs:
1. 23 bits représentant la mantisse (f)
2. 8 bits représentant l'exposant (e)
3. 1 bit représentant le signe
Ces champs sont stockés de façon contiguë dans un mots de 32 bits.
31 30 23 22 0
s Exposant ( e ) Mantisse ( f )

Les bits 0 à 22 représentent la mantisse (f), avec le bit 0 comme LSB de la fraction et le bit 22 comme
MSB. Les bits 23 à 30 représentent exposant base 2 (e), avec le bit 23 comme LSB et le bit 30 comme
MSB. Le bit 31 contient le signe (s) avec s=0 pour le signe positif et s=1 pour le signe négatif.

Exemple 1:
Convertir le nombre décimal 8,625 en virgule flottante suivant la norme IEEE 754 :

Corrigé :
 Conversion de 8,625 en binaire :

o Partie entière : 8 => 1000


8,625 => 1000,101
o Partie décimale : 0,625 => 0,101

Page | 127 © ISI 2018 Ridha Ghayoula


 Normalisation : 1000,101 x 20 <=> 0,1000101 x 24
 Pseudo-normalisation IEEE 754 : <=> 1,0001010 x 23
(de la forme 1,xxxx où xxx = pseudo mantisse)
 Décomposition du nombre en ses divers éléments :
o Bit de signe : 0 (Nombre >0)
o Exposant sur 8 bits biaisé à 127 => 3 + 127 = 130 => 10000010
o Pseudo mantisse sur 23 bits : 0001010 00000000 00000000

Signe Exposant biaisé Pseudo mantisse


0 100 0001 0 000 1010 0000 0000 0000 0000

Exemple 2:
En utilisant le codage virgule flottante utilisé par IBM pour la famille d’ordinateurs 370 (1) , exprimez sous forme normalisée le nombre
fractionnaire 7/64.
(1)
(Signe de la mantisse sur un bit, Exposant sur 7 bits décalé de 64, Mantisse à 24 bits avec la virgule binaire située à gauche de la
mantisse, la base d’exponentiation étant 16)
Corrigé :
 Conversion de 7/64 en Hexadécimal :
o Première méthode : 7/64 = 0,109375
Le nombre ne comporte pas de partie entière et il suffit de convertir la partie décimale en hexadécimal :
0,109375 => 0,1C
Autre méthode :
7 / 64 = (7 x 4) / (16 x 4) = 28 / 256 = 28 x 16 –2
ce qui donne en hexadécimal : 1C x 16-2 et en normalisant : 0,1C x 160
Valeur normalisée : 0,1C x 160
 Décomposition du nombre en ses divers éléments :
o Bit de signe : 0 (Nombre >0)
o Exposant sur 7 bits biaisé à 64 => 0 + 64 = 64 => 1000000
o Mantisse sur 24 bits : 00011100 00000000 00000000
Signe Exposant biaisé Pseudo mantisse
0 100 0000 0001 1100 0000 000 0000 00000

za 5 bits

atran32
LUT
tan-12-1
zdata
32 bits
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity atan32 is
GENERIC(
WIDTH : integer := 24 );
Port ( za : in STD_LOGIC_VECTOR (4 downto 0);
zdata : out STD_LOGIC_VECTOR (32 downto 0));
end atan32;
architecture Behavioral of atan32 is
signal ZData_s : std_logic_vector(31 downto 0);
Begin
ZData <= ZData_s(31 downto 32-WIDTH);

Page | 128 © ISI 2018 Ridha Ghayoula


process(ZA)
begin
Case ZA is
when "00000" => ZData_s <= X"3F800000";
when "00001" => ZData_s <= X"3F350481";
when "00010" => ZData_s <= X"3F21EB85";
when "00011" => ZData_s <= X"3F1D14E4";
when "00100" => ZData_s <= X"3F1BDA51";
when "00101" => ZData_s <= X"3F1B8BAC";
when "00110" => ZData_s <= X"3F1B7E91";
when "00111" => ZData_s <= X"3F1B7803";
when "01000" => ZData_s <= X"3F1B7803";
when "01001" => ZData_s <= X"3F1B7803";
when "01010" => ZData_s <= X"3F1B7803";
when "01011" => ZData_s <= X"3F1B7803";
when "01100" => ZData_s <= X"3F1B7803";
when "01101" => ZData_s <= X"3F1B7803";
when "01110" => ZData_s <= X"3F1B7803";
when "01111" => ZData_s <= X"3F1B7803";
when "10000" => ZData_s <= X"3F1B7803";
when "10001" => ZData_s <= X"3F1B7803";
when "10010" => ZData_s <= X"3F1B7803";
when "10011" => ZData_s <= X"3F1B7803";
when "10100" => ZData_s <= X"3F1B7803";
when "10101" => ZData_s <= X"3F1B7803";
when "10110" => ZData_s <= X"3F1B7803";
when "10111" => ZData_s <= X"3F1B7803";
when "11000" => ZData_s <= X"3F1B7803";
when "11001" => ZData_s <= X"3F1B7803";
when "11010" => ZData_s <= X"3F1B7803";
when "11011" => ZData_s <= X"3F1B7803";
when "11100" => ZData_s <= X"3F1B7803";
when "11101" => ZData_s <= X"3F1B7803";
when "11110" => ZData_s <= X"3F1B7803";
when "11111" => ZData_s <= X"3F1B7803";
When others => ZData_s <= "--------------------------------";
End Case;
end process;
end Behavioral;

Page | 129 © ISI 2018 Ridha Ghayoula


i4) FSM:
start done

CLK FSM
reset

init_s
cnt_s:(4:0) load_s

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
ENTITY fsm IS
PORT(
clk : IN std_logic;
reset : IN std_logic; -- Active low reset
start : IN std_logic;
cnt : IN std_logic_vector (4 DOWNTO 0);
init : OUT std_logic;
load : OUT std_logic;
done : OUT std_logic);
END fsm ;

ARCHITECTURE synthesis OF fsm IS


TYPE STATE_TYPE IS (s0,s1,s2 );
ATTRIBUTE state_vector : string;
ATTRIBUTE state_vector OF synthesis : ARCHITECTURE IS "state" ;
SIGNAL state : STATE_TYPE ;
SIGNAL nextstate : STATE_TYPE ;

BEGIN
clocked : PROCESS( clk, reset )
BEGIN
IF (reset='0') THEN
state <= s0;
ELSIF (clk'EVENT AND clk = '1') THEN
state <= nextstate;
END IF;

END PROCESS clocked;


state_nextstate : PROCESS (cnt, start,state )

Page | 130 © ISI 2018 Ridha Ghayoula


BEGIN
CASE state IS
WHEN s0 =>
IF (start='1') THEN
nextstate <= s1;
ELSE
nextstate <= s0;
END IF;
WHEN s1 =>
IF (cnt="11111") THEN
nextstate <= s2;
ELSE
nextstate <= s1;
END IF;
WHEN s2 =>
IF (start='0') THEN
nextstate <= s0;
ELSE
nextstate <= s2;
END IF;
WHEN OTHERS =>
nextstate <= s0;
END CASE;

END PROCESS state_nextstate;


output : PROCESS ( state)
BEGIN
CASE state IS
WHEN s0 => done <= '0';
init <= '1';
load <= '0';
WHEN s1 => done <= '0';
init <= '0';
load <= '1';
WHEN s2 => done <= '1';
init <= '0';
load <= '0';
WHEN OTHERS =>
done <= '-';
init <= '-';
load <= '-';
END CASE;
END PROCESS output;
END synthesis;

Page | 131 © ISI 2018 Ridha Ghayoula


6
Linux Embarqué

6.1. Introduction
Linux est une alternative de taille au monopole Microsoft. Transparence, cout, stabilité, sécurité, ses
nombreux avantages devraient faire réfléchir a deux fois avant de choisir. Linux est un système
d'opération, tout comme Windows. Un système d'opération est le lien entre vous et votre ordinateur.
Chaque système d'opération, Linux comme Windows, a ses avantages et ses inconvénients.
Linux est ce qu'on appelle un logiciel libre. Ceci signifie que Linux n'appartient a personne et que
chacun peut donc en disposer comme bon lui semble. Linux est en quelque sorte un immense projet
communautaire ou chacun peut apporter sa contribution, recevant en retour la contribution des
autres.
Les progrès techniques de ces dernières années ont permis de faciliter l'utilisation de systèmes à
microprocesseurs. Ils font parti de notre vie de tous les jours. Grâce à eux, l'électronique est de plus
en plus présente de varié forme : Les téléphones portables apparaissent par tout. Ces machines à
microprocesseurs sont utilisées dans le monde de l'industrie afin de réguler un processus chimique
ou d'automatiser une chaîne de montage…etc. Même les machines utilisées à la maison ont
également les microprocesseurs. Les exemples concrets pourraient remplir plusieurs pages. Mais, Un
point commun : plus petit, plus puissant et moins cher. Sur ce point, l'informatique puisera
l'électronique en remplaçant des systèmes matériels par solution logicielle. Comme on la sait
certainement, une solution logicielle a forcément besoin d'un composant logiciel essentiel : C'est un
système d'exploitation. Aujourd'hui, Linux considère comme un OS alternative d'OS propriété, dans
l'informatique générale, grâce à sa stabilité et sa gratuité, Malgré son jeune âge dans le monde
embarqué, mais linux embarqué a montre sa puissance, et sa disponibilité pour la construction des
systèmes embarqués.

6.2. Linux Embarqué


Linux est un système d'exploitation libre de type UNIX lancé par le finlandais Linus Torvalds en
1991 avec l'assistance de milliers de développeurs dans le monde pour son évolution. Son succès
tient au fait qu'il est développé sous licence GPL1, ce qui signifie que le code source Linux est
disponible à tous le monde et gratuit.
 Linux est stable et robuste.
 Linux tourne originellement sur plateforme i386 et supérieure avec 8 Mode RAM.

Page | 132 © ISI 2018 Ridha Ghayoula


 Linux est complète des outils/logiciels GNU.
 Linux est disponible sous forme de distributions.
 Linux est utilisé avec une interface graphique comparable à Microsoft Windows : Gnome,
KDE.
A partir de ces deux définitions, On donne une définition sur Linux embarqué : C'est une adaptation
du noyau Linux à un système embarqué. Suivant les capacités du système, on ne retrouve qu'une
partie des fonctionnalités du noyau :
 Moins de services disponibles en général
 Moins de mémoire requise (<8Mo)
 Boot depuis une mémoire ROM.
 Pas de clavier ou de souris requis.
 Logiciels spéciaux pour piloter les périphériques du système Les dispositifs peut être souvent
l’écran LCD, Flashdisk, DiskOnChip, et touchscreen....

6.2.1. Les différentes commandes

Chemins
Les chemins de fichiers et de dossiers sous Unix utilisent le slash '/' pour separer les noms des
dossiers.
Exemples :
/ Dossier 'racine'
/usr Dossier usr (sous-dossier du dossier 'racine')
/usr/STRIM100 STRIM100 est un sous-dossier de /usr

Besoin d'aide : La commande man


La plupart des commandes ont une page de manuel qui donne une description de leurs utilisations
plus ou moins détailles, parfois utiles, parfois obscures.
Exemple:
man ls : affiche la page de manuel pour la commande ls
Pour obtenir des man pages en francais : sudo apt-get install manpages-fr

Se déplacer dans le système de fichiers


pwd montre le nom du dossier de travail courant (Present Working Directory)
cd change le dossier de travail pour le dossier HOME
cd /usr/STRIM100 change le dossier de travail pour /usr/STRIM100
cd INIT change le dossier de travail pour INIT, qui est un sous-dossier du dossier courant
cd .. change le dossier de travail pour le dossier parent
cd $STRMWORK change le dossier de travail pour le dossier defini par la variable
d'environnement ‘STRMWORK'

Lister le contenu d'un dossier


ls liste le dossier de travail courant
ls -l dossier liste au format detaille le dossier dossier
Par exemple :
$ ls -l /home/sheherazade/work/

Page | 133 © ISI 2018 Ridha Ghayoula


6.2.2. Variables Linux
Nommer :
–débute par une lettre ou signe soulignement (_)
 NE DOIT PAS débuter par un chiffre
 Éviter le tiret (-) : confusion avec les options (exemple –fa)
 Éviter les noms associés à des commandes (exemple man, cat, ls, pwd . . .)
–Consulter la documentation pour connaître la liste !

Affectations
–signe = exemple var1=4
_ récupération
–IL FAUT précéder le nom de la variable par le signe $
•exemples
–echo $var1 retourne 4 (contenu de la variable)
–echo var1 retourne var1 (affiche la chaîne littérale

a) Variables numériques : opérations arithmétiques


_ Évaluer une expression arithmétique ou logique :
–Méthode No 1: avec les doubles parenthèses

–Méthode No 2: Usage de la fonction = expr


–Utiliser l’apostrophe inversée (accent grave): position différente selon le clavier choisi!
udiant1@ubu:~$ var1

b) Variables: variables d’environnement


 Effacer une variable locale:
–unset nom_variable

Page | 134 © ISI 2018 Ridha Ghayoula


grep: programme de recherche par filtration

–Aide supplémentaire
–https: //openclassrooms.com/courses/reprenez-le-controle-a-l-aide-de-linux/afficheret-
manipuler-des-variables
–http: //www.epons.org/shell-bash-variables.php
–https://doc.ubuntu-fr.org/variables_d_environnement

c) Variables: variables d’environnement


 Variables « visibles » de toutes les consoles
- env commande pour afficher l’ensemble des variables
- Exemple: afficher toutes les variables d’environnement; faire une pause à chaque page
affichée

- Exemple: operation semblable; mais ne retenir que les variables qui contiennent la chaine
HO dans le nom

6.2.3. Notion de redirection


- Entrées/sorties standard :
• Par défaut. lorsque l'on exécute un programme, les données sont lues à partir du clavier
(entrées) et le programme envoie sa sortie et ses erreurs sur l'écran,
• Il est possible de lire les données à partir de n'importe quel périphérique d'entrée, voire à
partir d'un fichier et d'envoyer la sortie sur un périphérique d'affichage, un fichier, etc.

Exemples :
• Où est affiché le résultat de la commande ls -la?
• par défaut, la sortie est la l’écran
• rediriger la sortie vers un fichier :

Page | 135 © ISI 2018 Ridha Ghayoula


• ls -l > ListeFichiers.txt
• Le résultat n’apparaît pas à l'écran; il est envoyé dans le fichier ListeFichiers.txt
redirection

Ecran
Fichier

Clavier
Figure 6.1. Notion de redirection

Notion de redirection en sortie


Linux possède des mécanismes permettant de rediriger les entrées sorties standards vers des
fichiers.
• Ainsi, l'utilisation du caractère «>» permet de rediriger la sortie standard d'une commande
située à gauche vers le fichier situé à droite :
• Faire un ls -al dans /home/etudiant1
• Faire maintenant ls -al /home/etudiant1 > ListeFichiers.txt
• puis cat listefichiers.txt
• (*) cat est un programme qui affiche le contenu d’un fichier (équivalent de notepad.exe de
Windows)
Commandes ”filtres”
• grep : recherche de lignes avec des expressions régulières (*,? [-] { } ).
• Exemple 1 : lister les fichiers scripts du répertoire courant

• Possibilité de rediriger la sortie vers un fichier temporaire

• Commande cat affiche le contenu d’un fichier texte

La commande extrait les lignes contenant le critère de recherche.


• Exemple 2: chercher le compte etudiant11 dans le fichier /etc/passwd

Page | 136 © ISI 2018 Ridha Ghayoula


Exemple 3 : rechercher les groupes auquel le compte étudiant appartient

Exemple Le fichier /etc/group contient la liste des groupes de travail


• grep etudiant1 group donne la liste des groupes auquel etudiant1 appartient
_ Champs d’un enregistrement séparés par le caractère 2points (:)
_ 1) nomGroupe
_ 2) sécurité
_ 3) NoGrID
_ 4) nom usage

Compter: nombre de lignes, de mots ou de caractères


- wc –l : compte le nombre de lignes (line).
- wc –w : compte le nombre de mots (word).
- wc –c : compte le nombre de caractères (caracter).
Exemples

Page | 137 © ISI 2018 Ridha Ghayoula


Séparer une ligne en colonnes
_ Commande cut [-c | -d -f ] couper la ligne en champs
_ 2 formats de base: -c ou -d
_ -c découpe la ligne selon la position du caractère
–Syntaxe: cut –c<debut>[-] <fin>[, debut[-] [<fin>]]
–(exemple -c1-10 afficher les caractères de 1 à 10)
_ -d découpe la ligne selon un caractèrre de de délimitation
–Syntaxe: cut –d <delimiteur><caractère> -f <Nodeb> [, [<Nofin>]]

_ (exemple -d: -f 3 délimiter les champs par le : et retenir le 3ième champ)

Syntaxe: cut –c<debut>[-] <fin>[, debut[-] [<fin>]]

sécurité « user » c2-4 « groupe »C-5-7« autres » 8-10

Même commande avec affichage uniquement les scripts

Syntaxe: cut –d <delimiteur><caractère> -f <Nodeb> [, [<Nofin>]]


Étape 1) Lister les groupes d’usagers

Étape 2) retenir uniquement ceux dont le compte étudiant fait partie

Page | 138 © ISI 2018 Ridha Ghayoula


Étape 3) n’afficher que le nom de groupe pour les comptes débutant par étudiant

6.2.4. Script en Linux: codification exécution


1) Coder le script
Un script Linux DOIT débuter par #!/bin/bash au laboratoire
_ commandes telles que lancées sur la ligne de commande
_ Exemple: afficher un texte à l’écran

_ 2) Rendre le script exécutable (chmod u+x script1.sh)


_ Exécuter le script (./script1.sh) (observer le point barre)

2) Programmation de scripts réseaux


Création d’usagers:
 Forme simple sudo adduser <nom>
 Options ajouter un nom complet, un home directory etc
 En mode interactif: Exemple adduser etudiant2

 Vérification :
cat /etc/passwd | grep etudiant2
et cat /etc/group | grep etudiant2
 L’usager créé aura l’arborescence du répertoire /usr
ct /etcss grep etudiant2

Page | 139 © ISI 2018 Ridha Ghayoula


Comptes usagers et groupes
 Création de groupes et d'usagers
 Exemple pour l’entreprise “Café International” (1):
 3 groupes “entreprise”, “ventes” ainsi que “informatique”.
 2 comptes “usager” “vendeur1” “tech1”
 Pourquoi?: les “politiques générales” s'appliquent aux groupes. La sécurité particulière est
appliquée sur le compte de l’individu (ici vendeur1).
(1) entreprise fictive

Ventes
Vendeur1
Informatique
Tech1
Entreprise

Figure 6.2. Comptes usagers et groupes

Gestion de groupes
• Créer un groupe ~$ sudo addgroup <nom>
• Ajouter un compte usager à un groupe
~$ sudo adduser nom_compte nom_groupe OU
~$ sudo usermod –aG nom_groupe nom_compte
Exemple

Page | 140 © ISI 2018 Ridha Ghayoula


Gestion de la sécurité
 Compte usager: à la création d’un fichier, le créateur est le « propriétaire »
 Peut transférer la propriété à un autre usager
 Propriétaire: celui qui détient les droits (colonnes 2-4)
 Groupe: ensemble désignant des comptes ayant des rôles communs
(exemple: entreprise, ventes, . . . ) (colonnes 5-7)
 Autres « others »: autres comptes pouvant accéder au fichier (colonnes 8-10)

 Changer le groupe associé au fichier


 # chgrp <nomGroupe> <nomFichier> [-options]
- Avant la modification

–Après la modification
 Tous les « membres » du groupe tech1 auront la sécurité « group » (colonnes 5-7) pour le
fichier script1.sh

Groupe
Gestion de la sécurité
3 types de sécurité avec 3 niveaux
 Propriétaire, groupe, autres comptes
3 niveaux
 –Read Write Execute
Droits Fichier Repertoire
r Lire le contenu Lister (cd,ls)
w Modifier le contenu Modifier (rmdir,mkdir,pic..)
x Executer le fichier Acceder aux entrees

Page | 141 © ISI 2018 Ridha Ghayoula


 Syntaxe de la commande chmod (lire changer le mode)
 2 formats possibles: format symbolique et format numérique octal
 1) Format symbolique

chmod {u|g|o} {+|-|=} {r|w|x} {nom }


veut dire type ajouter/retirer/appliquer Read Write nomFichier
eXecute
effet sur le mode;
 Exemple 1: chmod u-x script1.sh propriétaire NE peut PLUS exécuter script1.sh
 Exemple 2: chmod g+x script1.sh membres du groupe tech1 peuvent exécuter script1.sh
 Exemple 3: chmod o=r script1.sh tous les autres usagers peuvent lire uniquement script1.sh

 Allouer du droit d’accès: commande chmod


 1) Format symbolique
chmod { u | g | o } { + | - | = } { r | w | x } {<nom > }
type ajouter/retirer Read Write eXecute nomFichier
 2) Format octal
 Chaque position r,w,x occupe une valeur binaire 4 2 ou 1, sur trois digits
Proprirtaire Groupe Autres Partie
r w x r w x r w x Acces
4 2 1 4 2 1 4 2 1 Valeur Binaire
Valeurs Possibles

•Exemple 1: chmod 764 script1.sh


•Equivaut à rwxrw-r--
•Exemple 1: chmod 700 script1.sh
•Equivaut à rwx------

Page | 142 © ISI 2018 Ridha Ghayoula


Exemples
–Chmod u+rw
équivaut à
–chmod 600
Proprirtaire Groupe Autres Partie
r w x r w x r w x Acces
4 2 1 4 2 1 4 2 1 Valeur Binaire
1 1 0 0 0 0 0 0 0 Valeurs Possibles
6 0 0
–chmod u=rwx && chmod g=rw && chmod o=r
Équivaut à
–chmod 764
Proprirtaire Groupe Autres Partie
r w x r w x r w x Acces
4 2 1 4 2 1 4 2 1 Valeur Binaire
1 1 1 1 1 0 1 0 0 Valeurs Possibles
7 6 4

–chmod u=rwx && chmod g=rwx && chmod o=rwx


–Équivaut à
–chmod 777

Proprirtaire Groupe Autres Partie


r w x r w x r w x Acces
4 2 1 4 2 1 4 2 1 Valeur Binaire
1 1 1 1 1 1 1 1 1 Valeurs Possibles
7 7 7

Modifier les permissions et les droits


chmod 755 file change les droits de file afin qu'ils deviennent rwx pour le proprietaire, et rx pour le
groupe et les autres. ( on veut rwx lire/ecrire/executer donc 111 en binaire qui vaut 7 en decimal.
On veut rx
lire/pas ecrire/executer donc 101 en binaire qui vaut 5 en decimal).
chgrp staff fichier change le fichier fichier afin qu'il appartienne au groupe staff.
chown sheherazade fichier fait de sheherazade la proprietaire du fichier fichier.
chown -R sheherazade dir fait de sheherazade la proprietaire du dossier dir et de tous ses sous-
dossiers.

Vous devez etre le/la proprietaire du fichier/dossier ou etre root avant de taper ces commandes.
Sous Ubuntu il faut les prefixer par sudo.
Déplacer, renommer et copier des fichiers
cp fichier_source fichier_destination copie un fichier
mv fichier1 nouveau_nom_fichier1 deplace ou renomme un fichier
rm fichier1 [fichier2 ...] supprime un fichier (ou une liste de fichiers)

Page | 143 © ISI 2018 Ridha Ghayoula


rm -r dossier1 [dossier2...] supprime un dossier et tous ses sous-dossiers
mkdir dossier1 [dossier2...] crée un dossier
rmdir dossier1 [dossier2...] supprime un dossier vide

Visualiser et éditer les fichiers


cat fichier affiche le contenu du fichier a l'ecran en ASCII
more fichier affiche progressivement un fichier a l'ecran : Entrer = descend d'une ligne, Espace =
descend d'une page, q = quitte
less fichier comme more, mais on peut utiliser la touche Page Precedente. Pas disponible sur tous
les systemes.
vi fichier editer un fichier avec l'editeur vi. Tous les systemes Unix ont un editeur a la vi.
emacs fichier editer un fichier avec l'editeur emacs. Pas disponible sur tous les systemes.
head fichier affiche les premieres lignes d'un fichier
head -n fichier affiche les n premieres lignes d'un fichier
tail fichier affiche les dernieres lignes d'un fichier
tail -n fichier affiche les n dernieres lignes d'un fichier

Linux Embarqué
Avoir un système permettant une grande palette d'applications dans un environnement système bien
connu supporté par une très large communauté ouverte et participative. Pouvoir bénéficier au
maximum des logiciels libres et des développements communautaires en facilitant leur portage sur
notre plateforme d'exécution.

Solution : distribution Linux embarqué (noyau + applications):

Le noyau Linux est modulaire et peut -être décliné/taillé avec des versions occupant des volumes
réduits compatibles avec les limites des plateformes embarquées d'aujourd'hui mais il implique :
Une machine 32 bits (mini) et une MMU (sinon μClinux)
Le nombre d'applications peut être limité au strict minimum nécessaire sur une plateforme
embarquée et des versions allégées existent pour la plupart des outils sous Linux.

6.3. Composants de Linux embarqué


Une distribution Linux c’est :
- un noyau qui est chargé en mémoire au moment du boot et y demeure
- un root file system (rootfs) système de fichiers qui contient :
- Les modules drivers chargés dynamiquement (/lib ...)
- Les fichiers de configurations du système (/etc ...)
- Les exécutables des outils standards (shell, réseau, ...)
- Des applications (/opt /usr ...)
Minimum : /dev, /proc, /bin, /etc, /lib, /usr, /tmp,

Linux est démarré par un boot loader (exécutable présent sur la carte) U-boot pour ARMADEUS
qui est aussi une sorte de « BIOS » ou « moniteur interactif »:

Page | 144 © ISI 2018 Ridha Ghayoula


1 - récupère le noyau Linux et le root file system (rootfs racine /) en local (flash ou MMC) ou via le
réseau.
2 - il charge le code du noyau Linux avec un système de fichiers minimaliste en RAM et lance son
exécution
3 - lorsque les initialisations minimums du hardware ont été faites, Linux peut charger/monter son
vrai rootfs et lancer sa séquence d'initialisation complète avec tous les drivers. Dans le cas de
l'APF27 le système de fichier est un RAMFS système de fichier tout en mémoire car il n'y a pas de
disque connecté.
On ne peut développer en natif sur une plateforme embarquée si elle est assez puissante mais on
peut utiliser une autre machine (station de travail avec un bel écran et tout et tout) pour faire du
développement croisé et ensuite exécuter le code produit sur la plateforme cible.

Code Source

Chaine de developpement Chaine de developpement


native croisee

X86

Binaire X86 Binaire ARM9

X86 APF27

Figure 6.3. Composants de Linux embarqué (a)

Page | 145 © ISI 2018 Ridha Ghayoula


Composants pour le developpement

Binutils Kernel headers


(fichier.h)
Librairies C/C++
Compilateur
Debugger GCC
(Optinnel)

Figure 6.4. Composants de Linux embarqué (b)

Kernel headers
La librairie C et les applications utilisent/appellent les fonctions du noyau, elles ont besoin d'avoir
accès :
- aux fonctions système (signature)
- constantes utilisées par le système
- structures de données propres au système

La librairie C encapsule de nombreux appels au système, certaines applications peuvent appeler


directement le Système. Elles ont donc besoin de connaître des définitions de ces interfaces
disponibles dans les fichier.h du système.
Exemples:
<linux/...>
<asm/...>
Sous le répertoire include/ des sources du système.

Noyau

kernel headers

Librairies C

Applications
Figure 6.4. Composants de Linux embarqué (c)

Compilateur et librairie C

Page | 146 © ISI 2018 Ridha Ghayoula


GCC c'est le compilateur GNU associé à Linux peut compiler différents langages (C, C++, Ada,
Fortran, Java, Objective C, Objective C++) pour une variété de plateformes (NIOS2, ARM, MIPS,
X86 etc ...)

La librairie C est l'outil principal d'appel au système. Il en existe plusieurs versions : glibc (la plus
complète mais volumineuse), uClibc, eglibc, dietlibc, newlibc etc ...

Pour le l'APF27 c'est uClibc qui est utilsée elle plus compacte que la glibc.
Attention : la même librairie doit être utilisée pour construire la chaîne de développement et les
applications
glibc uClibc
« hello world » 475K 25K
busybox 843K 311
Tableau 6.1. Exemple en compilation statique

Construction de Linux pour APF27


Pour construire une chaine de construction « buildtool » et Linux il faut (entre autre):
- Récupérer les headers du noyau
- Récupérer, configurer, compiler et installer les binutils
- Récupérer, configurer, compiler et installer une première version de GCC pour cross
compiler les librairies
- Reconfiguration et recompilation de GCC pour la cible qu'on utilise avec les librairies.
- Récupérer les sources, configurer et construire Linux Ces opérations sont complexes et
pénibles.
Des chaînes de développement ont été créées pour automatiser toutes ces étapes. L'outil open
source qui a été sélectionné pour APF27/ARM9 est Buildroot

Pour Linux sur APF27 un TWIKI est accessible qui documente toutes les étapes de construction
avec un buildroot adapté par ARMADEUS pour l'apf27.

http://www.armadeus.com/wiki/index.php?title=Setup

On récupère non seulement le noyau Linux standard pour ARM9 mais aussi les drivers spécifiques à
la plateforme cible : i.MX27 (freescale) et APF27(ARMADEUS).

1- Il faut s'assurer d'avoir tous les outils de développement standards sous sa machine Linux : (gcc
gcc-c++ make autoconf automake libtool bison flex gettext patch subversion texinfo git ...)
2- Récupère le tar file d'armadeus avec l'arborescence de construction tar xjvf armadeus-3.1.tar.bz2
Ou on peu récupèrer la dernière version du projet en cours de dévoppement chez armadeus avec git
git clone git://armadeus.git.sourceforge.net/gitroot/armadeus/armadeus armadeus
3- Et on construit dans le répertoire racine « armadeus » La commande make apf27_defconfig
permet de fixer les paramètres de construction : Construction du noyau (processeur, taille mémoire
...) Type de systèmes de fichiers supportés Driver à inclure ou pas Applications/Packages à inclure
ou pas une configuration par défaut est proposée qu'il suffit de modifier/compléter

4-Puis la commande make permet de lancer toute la construction buildtools + Linux.

Page | 147 © ISI 2018 Ridha Ghayoula


Les répertoires de construction
armadeus/
buildroot/
binaries/apf27/ (binaires à charger noyaux, rootfs, U-boot)
build_armv5te/ (sources non configurables python, zlib, strace ...)
project_build_armv5te/apf27/ (sources configurables busybox, linux, u-boot ...)
project_build_armv5te/stagging_dir/usr/bin (exécutables compilateurs et binutils)
project_build_armv5te/stagging_dir/lib (librairies dont uClibc)
toolchain_build_armv5te/ (source de la chaine de cross compilation)
target/device/aramdeus/rootfs/target_skeleton (squelette du rootfs a produire modifiable)
...

target/linux/modules (sources et binaires drivers sous forme de modules chargeables Linux)


Les fichiers systèmes produits par la construction sont:
- apf27-linux.bin (le noyau linux bootable)
- rootfs.arm.jffs2 (image du FileSystem/RootFS a utiliser avec U-Boot)
- rootfs.arm.tar (autre format du FileSystem/RootFS utilisable pour le boote NFS ou MMC
(carte mémoire))
- u-boot.bin (le binaire de u-boot)

Mémoires utilisées

Page | 148 © ISI 2018 Ridha Ghayoula


FLASH MMC
256M Carte mem

Download ftp/ RAM


2x64K

execution
reset/load
i.MAX37

Figure 6.5. Mémoires utilisées

Initialisation/configuration
Lancer une application au démarrage (rootfs): créer un fichier /etc/init.d/S99app très simple
#!/bin/sh
/usr/bin/monApplication &
Exit 0
Paramètres réseau de la carte (via U-boot):
BIOS> setenv netmask 255.255.255.0
BIOS> setenv ipaddr 192.168.0.10
BIOS> setenv serverip 192.168.0.2 (adresse du server/PC contenant les fichiers à télécharger)
BIOS> setenv rootpath "/tftpboot" (pour booter sur le file system Linux via NFS)
BIOS> saveenv (mémorise ces paramètres en flash)
Peuvent aussi aussi être mis via un serveur dhcp si on boote de cette façon

Différentes façons de travailler


Quand l'application est au point : faire une release et flasher:
1 - l'intégrer comme application dans l'arbre de construction buildroot
2 - écrire le fichier /etc/init.d de lancement de celle-ci dès la fin du boot
3 - générer le noyau + rootfs + Uboot qu'on copie dans /tftpboot
4 - paramétriser les valeurs de l'application sous U-boot: setenv para valeur
5 - les sauvegarder : saveenv (autre solution via un serveur dhcp sur lequel on déclare ces valeurs
pour un boot dhcp)
6 - flasher le noyau dans la cible run update_kernel
7 - flasher le rootfs dans la cible run update_rootfs

Au prochain reset de la carte : - elle bootera - elle lancera les applications de service listées dans
/etc/init.d
Interfaces de commande :
Console: via la liaison série
Terminaux : possibilité par telnet d'avoir d'autres fenêtres, utile en exploitation

Noyau: Le noyau doit être (re)téléchargé par la liason série sous U-boot après chaque modification
(inclus les drivers intégrés)
Copier le noyau dans /tftpboot

Page | 149 © ISI 2018 Ridha Ghayoula


BIOS> setenv rootpath "/tftpboot "
BIOS> tftpboot ${loadaddr} apf27-linux.bin (charge le noyau en mémoire RAM et boote dessus)

Développement facile avec NFS:


Monter un répertoire de développement sur la cible permet de profiter d'un l'environnement de
travail confortable sur la station et d'avoir les binaires à tester immédiatement accessibles (driver
sous forme de modules chargeables inclus)

- A la main: mount -t nfs 192.168.0.2:/home/duval/DEV /mnt/nfs


- Automatiquement monté par /etc/fstab en ajoutant la ligne: 192.168.0.2:/local/export /mnt/host
nfs hard,intr,rsize=8192,wsize=8192 0 0

Boot NFS (seulement le rootfs mais pas le noyau qui reste celui en flash):
Permet de tester les configurations du système Copier le rootfs dans le répertoire de boot nfs de la
station par exemple /local/export
BIOS>setenv rootpath /local/export
BIOS>saveenv
BIOS>run nfsboot

Figure 6.6. Exemple


Écrire un driver Linux sur apf27
Définiton du driver:
Dans le répertoire armadeus/target/linux/modules

1- Créer le répertoire de ce driver mkdir armadeus/target/linux/modules/unDriver


2- Editer les références à ce nouveau driver dans les fichiers Makefile et Kconfig
3- Dans le répertoire unDriver:
 Mettre les codes source
 Créer les fichiers locaux Makefile et Kconfig (en s'inspirant d'autres modules)

Génération du driver:
Pour le compiler
make -C target/linux/modules/
Pour le compiler et créer le rootfs qui le contient
make linux26

a) GPIO driver
Le processeur I.MX27 (freescale/multimedia) dispose de 6 ports 32bits general purpose IO (GPIO)
qui peuvent: - générer des IT sur front montant ou descendant - être multiplexés entre diverses
fonctions prédéfinies

Page | 150 © ISI 2018 Ridha Ghayoula


GPIO driver standard

Le driver standard de GPIO permet d'accéder aux ports à travers le système de fichier via les
fichiers de type /proc de type ascii utilisables dans des commandes du shell ou par programme
(X=A-B-C-D-E-F).
1. /proc/drivers/gpio/portX mode pour configurer une pin comme gpio
2. /proc/drivers/gpio/portX dir pour lire par cat, ou parametrer par set, leur direction (in-0/out-1)
pin par pin
3. /proc/drivers/gpio/portX pour lire par cat, ou parametrer par set, leur valeur/état pin par pin
4. /proc/drivers/gpio/portXirq: pour configurer les IT GPIO 0->pas d'IT, 1->up, 2->down, 3-
>up down
5. /proc/drivers/gpio/portXpullup: pour (de)activer pull-up interne du i.MX pour ce GPIO

Exemples:
Mettre en mode GPIO le bit 31 du port A
# echo -n 10000000000000000000000000000000 > /proc/driver/gpio/portAmode Vérifier si les
pin du port D sont en entrée ou sortie
# cat /proc/driver/gpio/portDdir >>01101100111100000110110011110000 (ordre des pins:
[31...0]) Mettre la pin 10 du port B en mode IT
# echo -n 00000000000000000000010000000000 > /proc/driver/gpio/portBirq

Page | 151 © ISI 2018 Ridha Ghayoula


On peut aussi accéder bit par bit en lecture/écriture en utilisant directement les nœuds /dev
associés aux fichiers-drivers /dev/gpio/PXy X = port (A-B-C-D-E) y= bit [0-31]
Exemple:
Lire le bit 0 du port D
# cat /dev/gpio/PD0

Pour accéder par programme en C il existe des constantes IOCTL pour lire/écrire via ioctl() sur
/dev ou on peut directement travailler avec des read()/write() sur les pseudos fichiers /proc

Ecriture formatée en ascii sur /proc Ecriture via IOCTL sur /dev
FILE *GPIO,*GPIODIR, *GPIOMODE; char int fd, i, iomask,result; unsigned char
buffer[32]; char * bufferDir= dev_buffer[BUF_SIZE+1]; fd =
"00000000011111111000000000000000"; char * buffer1= open("/dev/gpio/portD", O_RDWR); printf("Opened
"00000000000000011000000000000000"; char * buffer2= on /dev/gpio/portD\n"); iomask=0xFFFFFF00;
"00000000000001100000000000000000"; GPIODIR = ioctl(fd,GPIOWRDIRECTION,&iomask);
fopen("/proc/driver/gpio/portDdir","w"); iomask=0x003F0000;
setvbuf(GPIODIR,buffer,_IONBF,32); fwrite(bufferDir, for (i=0;i<2;i++)
sizeof(char), strlen(bufferDir), GPIODIR); {
fclose(GPIODIR); GPIO = printf("Led ON\n"); iomask=0x007F8000;
fopen("/proc/driver/gpio/portD","w"); ioctl(fd,GPIOWRDATA,&iomask); sleep(1);
setvbuf(GPIO,buffer,_IONBF,32); while(1) { ioctl(fd,GPIORDDATA,&iomask); printf("read
fwrite(buffer1, sizeof(char), strlen(buffer1), GPIO); /dev/gpio/portD 0x%x\n",iomask); printf("Led
sleep(1); fwrite(buffer2, sizeof(char), strlen(buffer2), OFF\n"); iomask=0x00000000;
GPIO); sleep(1); ioctl(fd,GPIOWRDATA,&iomask); sleep(1);
} } close(fd);
fclose(GPIO);

Figure 6.7. Exemple


Pour le WIFI installer WCID: sudo apt-get install wicd
Fichier /etc/interfaces
auto lo iface lo inet loopback
auto eth0
iface eth0 inet static
address 192.168.0.2
netmask 255.255.0.0 #gateway 192.168.0.1

Page | 152 © ISI 2018 Ridha Ghayoula


7
Le processeur Softcore LEON

7.1. Introduction
LEON est un processeur 32 bit RISC libre, compatible SPARC V8 (1987) développé par l'ingénieur
suédois Jiri Gaisler pour l'ESA. Il est téléchargeable sous licence LGPL (version 2) et GPL (version
3). Une version tolérante aux erreurs ("Fault Tolerant" - implémentant une détection d'erreurs
permettant son usage en conditions de radiations élevées) est aussi accessible pour LEON3.
Le processeur softcore Leon3 est un modèle de processeur écrit en langage VHDL. Comme son
prédécesseur, le Leon3 est basé sur une architecture RISC 32 bit. Le code source est entièrement
disponible sous licence GPL.

7.2. Caractéristiques
 Jeu d'instructions SPARC avec l'extension V8
 Pipeline de 7 étages
 Contient des multiplieurs, diviseurs et unités MAC (multiplicateur-accumulateur)
 fonctionne jusqu'à 125 MHz sur FPGA et 400 MHz sur un ASIC 0.13 µm
 Cache de données et d'instructions séparés
 Cache configurable : 1 à 4 étages, 1 à 256 kbytes par étage. Mémoire virtuelle LRU ou LRR
 MMU
 interface de bus AMBA 2 (AHB, APB)

Il est disponible en libre sous forme d’un module IP VHDL (opencore) à l'adresse
http://www.gaisler.com/index.html.

Du point de vue logiciel, on a à disposition les outils suivants :


– Chaîne d’outils GNU (compilation croisée).
– Simulateur LEON TSIM.
– OS supportés : μClinux, Linux, eCos, RTEMS (noyau Temps Réel).

Page | 153 © ISI 2018 Ridha Ghayoula


(a)

(b)
Figure 7.1. Architecture du processeur Leon

Page | 154 © ISI 2018 Ridha Ghayoula


http://www.gaisler.com/index.php/downloads/leongrlib

7.3. Configuration et implémentation


Nous commencerons par la configuration du GRLIB. Nous passerons ensuite à la compilation du
fichier projet à l’aide du logiciel Quartus, Puis, nous détaillerons la configuration du snapgear et nous
finirons par l’implémentation des deux fichiers sur la carte.

7.3.1. Configuration du GRLIB


Cette configuration va être basé sur le modèle leon3-ge-hpe-mini qui se compose principalement
de trois fichiers :
• config.vhd - un paquet contenant des paramètres de configuration VHDL design.
Généré automatiquement par le xconfig outil GUI .
• leon3mini.vhd - contient l’entité de haut niveau et instancie tous les coeurs sur une puce IP. Il
utilise config.vhd pour configurer les noyaux IP instancié.
• testbench.vhd - banc d’essai avec une mémoire externe.
La Bibliothèque GRLIB IP est un ensemble de coeurs IP réutilisables, conçu pour les systèmes sur
puce (SOC) de développement. Elle est conçue pour être indépendant de la technologie, et
facilement mis en œuvre sur les deux technologies FPGA et ASIC.

7.3.2 Installation et configuration


La conception "leon3-ge-hpe-mini" peut être avantageusement utilisé un modèle pour
d’autres projets à base d’Altera.
Après l’extraction de la bibliothèque grlib-gpl-1.1.0-b4104.zip, nous configurons le modèle
"leon3-ge-hpe-mini", se trouvant sous le répertoire design, à l’aide de l’outil graphique
en exécutant la commande ci-dessous : make xconfig.

Page | 155 © ISI 2018 Ridha Ghayoula


Figure 7.2. Interface graphique du GRLIB

• Tout d’abord, nous commençons la configuration par le choix de la technologie cible pour la
mémoire qui est «Altera-Others » dans le menu « synthesis ».

Figure 7.3. Technologie cible

• Ensuite dans le menu « processor » nous utilisons le noyau leonFT à tolérance de pannes au lieu de
la norme FT non leon3.

Page | 156 © ISI 2018 Ridha Ghayoula


Figure 7.4. Interface de processeur

• Par la suite, il est également important de choisir le support MMU si le matériel de protection
mémoire est disponible pour utilisation.
Une MMU est un élément hardware qui fournit différents emplacements mémoire protégés pour le
noyau et les processus, renforce la protection de la mémoire et facilite l’exploitation de la mémoire
virtuelle. Sans MMU, ces options ne sont tout simplement pas accessibles. Il faut donc remarquer
qu’il est bien plus facile de travailler sur un processeur équipé d’une MMU.
Donc cette étape consiste à activer l’unité de gestion de mémoire.

Page | 157 © ISI 2018 Ridha Ghayoula


Figure 7.5. Activation de l’MMU
• Puis, nous passons à la configuration du lien de débogage, on peut choisir RS232, JTAG, Ethernet
ou USB. Le plus pratique est probablement d’utiliser JTAG. Dans cette étape nous allons changer
l’adresse IP qui est par défaut 192.168.0.51 en 192.168.1.50 pour qu’elle soit compatible avec notre
connexion réseau.

Figure 7.6. Lien du débogage

Page | 158 © ISI 2018 Ridha Ghayoula


• Enfin, nous activons Gaisler Research 10/100/1000 Mbit Ethernet MAC pour avoir
une connexion réseau local ou Internet.

Figure 7.7. Support Ethernet


7.3.3 Génération du fichier leon3mini.qpf
Lorsque la configuration est enregistrée et l’interface graphique à été quitté à l’aide du bouton « save
and exit », le fichier config.vhd est automatiquement mis à jour avec la configuration choisie. Nous
exécutons par la suite la commande make scripts qui va générer un fichier projet Quartus
leon3mini.qpf qui va être compilé à l’aide du logiciel Quartus II.

7.3.4 Génération du fichier leon3mini.sof


Après la mise à jour du fichier config.vhd et la génération du fichier leon3mini.qpf, nous passons à la
compilation du fichier projet avec le logiciel Quartus II.

Présentation du logiciel Quartus II


Quartus est un logiciel proposé par la société Altera, permettant la gestion complète d’un flot de
conception CPLD ou FPGA. Ce logiciel permet de faire une saisie graphique ou une description
HDL (VHDL ou Verilog) d’architecture numérique, d’en réaliser une simulation, une synthèse et
une implémentation sur cible programmable.

Page | 159 © ISI 2018 Ridha Ghayoula


Figure 7.8. IDE Quartus II version 10.1

Après avoir installé Quartus II, nous allons compiler le fichier projet générer précédemment. Dans
l’onglet « File », nous choisissons « Open » pour sélectionner le fichier projet leon3mini.qpf qui va
être compilé à l’aide du bouton Start compilation se trouvant dans la barre d’outils.

Page | 160 © ISI 2018 Ridha Ghayoula


Figure 7.9. Exemples d’erreurs après compilation

Après la correction des erreurs, nous relançons la compilation pour générer un fichier
leon3mini.sof c’est le fichier qui va être implémenté dans la carte.

7.4. Configuration du Snapgear


Une fois les étapes de la configuration de la bibliothèque Grlib et la compilation du fichier sont
achevés avec succès, nous nous préoccupons de la configuration du Snapgear.

7.4.1. Vue d’ensemble


SnapGear Linux est un paquet source complet, contenant le noyau, les bibliothèques et le code
d’application pour le développement rapide de systèmes Linux embarqués.

7.4.2. Installation et configuration


7.4.2.1. Installation du toolchain
Le processus d’installation pour les différentes chaînes de compilation est le même, ce n’est que les
noms et les chemins qui diffèrent.

Voici les étapes d’installation du sparc-linux-3.4.4 :


$ mkdir /opt
$ cd /opt

Page | 161 © ISI 2018 Ridha Ghayoula


$ tar –xvjf /path/to/toolchain/sparc-linux-3.4.4.tar.bz2

Ajouter la chaine de compilation à la variable PATH de préférence dans un script shell de


démarrage. Pour les shell bash le texte suivant est ajoute a ~ /. profil :
$ export PATH=$PATH :/opt/sparc-linux3.4.4/bin
Après avoir installé le toolchain il est possible de compiler des applications pour Linux
SPARC LEON.

7.4.2.2 Installation du Snapgear


SnapGear est livré avec une interface graphique similaire à l’utilitaire de configuration du noyau
Linux. De l’interface graphique, il est possible de choisir le processeur, la version Linux, la
bibliothèque C et les applications qui seront inclus dans le système de fichiers racine (image
ROMFS) accessible par Linux en cours d’exécution.
Tout d’abord, nous décompressons le paquet snapgear-2.6-p42.tar.bz2 en exécutant la commande
suivante : tar -xvjf snapgear-2.6-p42.tar.bz2. Puis, nous commençons la configuration en tapant
make xconfig qui va nous afficher une interface graphique.

Figure 7.10. Interface de configuration graphique Snapgear

7.4.2.3 Configuration générale


• Dans le menu « Vendor/product selection », nous choisissons "leon3mmu" pour le produit gaisler.

Figure 7.11. Menu de Selection du produit

Page | 162 © ISI 2018 Ridha Ghayoula


Nous passons à la configuration du chargeur de démarrage qui met en place le matériel de bas
niveau avant d’entrer dans le noyau Linux.
• Dans le menu « Gaisler/Leon2/3 MMU options » nous allons activer les options " leon has
mul/div (v8) " et " leon has FPU ", fixer la fréquence à 40000 Khz et choisir romfs comme système
de fichier racine.

Figure 7.12. Gaisler/Leon2/3 MMU options


• Dans le menu « Kernel/Library/Default Selection », nous choisissons "linux-2.21.1" pour la
version du noyau, "glibc-from-compiler" pour la version du bibliothèque C et nous activons
"Customize kernel Settings" pour personnaliser les paramètres du noyau et "Customize
Vendor/User Settings" pour personnaliser les applications.

Figure. 7.13. Menu de selection noyau, LibC et applications

Page | 163 © ISI 2018 Ridha Ghayoula


7.4.2.4 Configuration du noyau
Après l’interface graphique a été fermé et les paramètres ont été enregistrés en cliquant sur « save
and exit », une seconde interface graphique apparaît qui est spécifique pour le noyau sélectionné.
Nous devons installer les paquets suivants : libqt3-mt et qt3-dev-tools avec la commande :
apt-get install
Pour la configuration du noyau, nous allons choisir les paramètres ci-dessous :
• Le procfs «pseudo système de fichiers » est directement lié au noyau interne et peut afficher des
informations pertinentes pour le fonctionnement du système. Sous la rubrique « Grlib : Amba device
driver configuration » nous activons AMBA_PROC.

Figure 7.14. Support AMBA procfs


• Nous ajoutons le driver grlib ethermac sous la rubrique « Vendor gaisler ».

Figure 7.15. Configuration. APBUART et GRETH Linux


• Dans le menu « ATA/ATAPI/MFM/RLL support » nous utilisons le pilote IDE complet pour
contrôler jusqu’à dix ATA/IDE interfaces, chacune étant capable de servir un maitre et un esclave.

Figure 7.16. ATACTRL support

• Nous activons « SCSI device support » pour que nous puissions relier des périphériques à notre
ordinateur.

Page | 164 © ISI 2018 Ridha Ghayoula


Figure 7.17. Configuration de SCSI support
• Dans le menu « File systems » nous activons le standard système de fichier ext2 et ext3. Fig

Figure 7.18. Configuration système de fichiers (a)

Figure 7.19. Configuration système de fichiers (b)


7.4.2.5 Configuration des applications
Une fois la configuration du noyau est achevée, nous passons à la configuration des applications qui
vont être intégrées dans le système de fichiers.
Pour la configuration des applications, nous allons ajouter Busybox. BusyBox combine des versions
de nombreux utilitaires Unix en un exécutable unique et de petite taille. Il permet de remplacer la
plupart des utilitaires qui se trouvent dans les paquets fileutils, shellutils, findutils, textutils, modutils,
grep, gzip, tar, etc. Il représente un environnement POSIX assez complet pour petits systèmes sous
systèmes embarqués.
Page | 165 © ISI 2018 Ridha Ghayoula
Ainsi il est facile d’inclure ou d’exclure des commandes à la compilation. Cela permet de l’adapter
facilement à chaque type de système embarqué. Sa taille plus petite est d’approximativement 200 Ko.

Figure 7.20. BusyBox

7.4.3 Génération du fichier image.dsu


Après avoir configuré le noyau et les applications, il est possible de compiler et de construire le
SnapGear LEON Linux distribution.
Pour cela, nous allons exécuter les commandes suivantes :

$ make dep : construction des dépendances


$ make clean : nettoie les fichiers inutiles utilisés pour construire les étapes précédentes
$ make : compilation du noyau

A la fin de la compilation, un fichier image.dsu sera générer sous le répertoire images.

7.5 Implémentation des fichiers


Dans cette étape, nous disposons de deux fichiers : leon3mini.sof qui contient la configuration
approprié à la carte cible et image.dsu contenant la configuration du noyau. Maintenant, nous allons
détailler l’implémentation de ces derniers fichiers sur la carte Hpe_mini en utilisant le logiciel
Quartus II et une liaison JTAG permettant de relier la carte à l’ordinateur.

7.5.1 Implémentation du fichier leon3mini.sof


Pour implémenter le fichier leon3mini.sof qui est généré après la compilation du fichier projet
leon3mini.qpf, nous suivrons les étapes suivantes : Dans l’onglet « File – Open » nous choisissons «
Programming File (*.cdf ; *.sof ; *.pof ; *.jam ; *.jbc ; *.jic ; *.jcf ; *.fcf) » dans le champ « Files of
type » et nous sélectionnons notre fichier leon3mini.sof.
Une fenêtre s’affiche, nous s’assurons que le mode sélectionné est JTAG et nous commençons
l’implémentation en appuyant sur le bouton « start ».

Page | 166 © ISI 2018 Ridha Ghayoula


Figure 7.21. Programmation du circuit FPGA

7.5.2 Implémentation du fichier image.dsu


Après avoir implémenté le fichier leon3mini.sof, nous passons à l’implémentation du fichier
image.dsu à l’aide du moniteur de débogage GRMON.

7.5.2.1 Moniteur de débogage GRMON


GRMON est un moniteur de débogage général pour le processeur LEON et pour les SOC basées
sur la bibliothèque GRLIB.

GRMON comprend les fonctions suivantes :


• Lecture / Ecriture sur tous les registres du système et la mémoire
• Haut-désassembleur et trace la gestion des tampons
• Téléchargement et exécution des applications
• point d’arrêt et point d’observation de la gestion
• Connexion à distance au débogueur GNU (GDB)
• Test automatique du matériel cible
• Prise en charge USB, JTAG, RS232, PCI, Ethernet et SpaceWire debugs Link.
Pour implémenter le fichier image.dsu nous allons suivre les étapes suivantes :

1. Sous le répertoire /grmon-eval/linux, nous exécutons la commande


./grmon-eval -eth -ip 192.168.1.50 -nb -u
Avec :

Page | 167 © ISI 2018 Ridha Ghayoula


-eth : se connecter en utilisant Ethernet. Nécessite le noyau EDCL d’être présents dans le système
cible.
-ip : se connecter à l’adresse ip de la carte qui a été spécifié pendant la configuration du grlib.
-nb : GRMON devrait être lancée avec cette option pour éviter d’aller en mode arrêt sur une page-
faute.
- u : Si GRMON est lancé avec cette option alors la sortie UART est bouclée sur son propre
récepteur et imprimée sur la console par GRMON

Figure 7.22. Composants activés dans le processeur


2. Une fois GRMON est lancé, nous chargeons notre image.dsu dans la mémoire cible avec la
commande
load image.dsu

Figure 7.23. Chargment du fichier image.dsu


3. Après avoir charger l’image dans la carte, il nous reste qu’à taper la commande
run
Enfin, nous visualisons notre système de fichiers en tapant la commande
ls

Page | 168 © ISI 2018 Ridha Ghayoula


Figure 7.24. Contenu du système de fichier

Nous avons détaillé les étapes de configuration et d’implémentation du processeur. D’abord, nous
avons configuré la bibliothèque GRLib dans le but d’avoir un fichier leon3mini.qpf qui va être
compilé à l’aide du logiciel Quartus pour avoir un fichier leon3mini.sof qui comporte la
configuration approprié à notre carte cible.
Ensuite, nous avons généré le noyau à l’aide du Snapgear. Enfin, nous avons implémenté le fichier
leon3mini.sof en utilisant Quartus et le fichier le noyau en utilisant le moniteur de débogage
GRMON.
• Câblage des matériels lors de l’implémentation des fichiers

Figure 7.25. Câblage du matériels

Page | 169 © ISI 2018 Ridha Ghayoula


Page | 170 © ISI 2018 Ridha Ghayoula
Exercices

Exercice 1 : Processeur softcore LEON3


A partir de l’architecture interne du processeur softcore LEON3 et ces périphériques (Figure.1).
a- Complétez les cases suivantes (1), (2), (3), (4) et (5).
b- Quelles sont les caractéristiques de Bus:
- Advanced High-performance Bus (AHB)
- Advanced Peripheral Bus (APB)

Figure 1. processeur softcore LEON3

1. Mapping de AHB.
a. AHB masters: 0xFFFFF000 - 0xFFFFF800
b. AHB slaves : 0xFFFFF800 - 0xFFFFFFFC
Déterminez le nombre de masters (a) et slaves (b) dans ces plages mémoires?

2. En général, Quelles sont Les composants hardware and software nécessaire pour
implémenter le processeur LEON3 en utilisant GRLIB IP library ?

3. La configuration du processeur LEON3 nous permet de modéliser notre processeur selon


notre choix donc a partir de ces quatre étapes (a,b,c et d) (Figure 2) , expliquez brièvement,
la configuration et l’implémentation d’un processeur LEON3 en utilisant la bibliothèque
Grlib et la carte FPGA –hpe-mini.

(a) Configuration du processeur LEON3

Page | 171 © ISI 2018 Ridha Ghayoula


(b)Implémentation du processeur LEON3

(d) : la carte FPGA-hpe-mini


(b) Quartus II

Figure 2. Configuration et implémentation processeur softcore LEON3

Page | 172 © ISI 2018 Ridha Ghayoula


8
Serveur Web Embarque

8.1. Introduction
Un serveur web embarqué est un « site web » intégré dans un module électronique, destiné à être mis
en place dans un équipement. Vous pouvez ensuite interagir avec l'équipement au moyen d'une
simple connexion réseau. C'est le premier pas vers les objets connectés.

Utilisateur
Le matériel
équipé d'un
serveur WEB
embarqué

Figure 8.1. Un serveur web embarqué

Ces modules électroniques peuvent être implantés sur tout type de matériel (domestiques,
industriels…) afin de les piloter depuis un poste informatique. Le serveur Web embarqué est un
moyen très simple d'ajouter une couche de services à vos produits, et de renforcer votre relation
client:
Le matériel dans
son Votre
environnement Client
operationnel

Vous

Figure 8.2. Sans serveur web embarqué

Page | 173 © ISI 2018 Ridha Ghayoula


Sans serveur web: Le matériel est dans son environnement opérationnel, il est difficile d’interagir
avec lui, pour votre client comme pour vous.

Le matériel dans
son Votre
environnement Client
operationnel

Vous

Figure 8.3. Avec un serveur web embarqué

Avec serveur web: Il devient très simple d'interagir avec le matériel. De nouvelles opportunités de
service s'ouvrent alors pour votre client et vous-même.
- Quelques cas d’emploi :
Améliorer votre politique SAV en étant au plus près de votre client : Vous êtes fabricant de machine.
Au travers de l’interface du serveur web vous pouvez avoir un regard permanent sur l’état de
fonctionnement de votre machine, et apporter à distance un support technique à votre client
(conseils à l’utilisation, opérations de maintenance…)

Mise à jour de firmware :


Votre service R&D fait du co-développement technique avec un partenaire lointain : Vous allez
pouvoir mettre à jour le logiciel de votre produit à distance, sans perte de temps. Vous allez donc
gagner en réactivité et en couts de fonctionnement.

Automatiser vos process :


Vous devez gérer un parc d’équipements : En créant des retours d’alertes automatiques, vous êtes
informé des disfonctionnements, uniquement quand c’est utile. Gain en volume et en qualité
d’information.

Management de la solution globale, administration et diagnostic à distance des produits :


Votre produit doit être réglé et ajusté en permanence pour répondre aux exigeantes opérationnelles
: Au travers de l’interface web embarquée, vous allez être en mesure d’agir sur votre produit, comme
si vous étiez devant !

Si l’utilisation des serveurs web embarqués est très simple, il est important de s’assurer que son
intégration dans votre système est correctement réalisée. Pour

cela, il faut prendre en compte 3 points sur lesquels nous pouvons vous accompagner :
 Choisir le serveur en fonction de la cible matérielle, de la mémoire nécessaire, et du besoin
attendu…

Page | 174 © ISI 2018 Ridha Ghayoula


 Intégrer le server dans le matériel. Cette action nécessite des compétences en électronique et en
logiciel embarqué
 Développer le site web embarqué. C’est le « portail d’accès » au travers duquel vous pourrez
prendre la main sur le matériel. Il permettra de gérer les configurations, les droits d’accès, les
alarmes, les informations… Ce site web embarqué pourra comporter des synoptiques, des zones de
leds à changement d’état, des affichages multilingues…

8.2. Serveurs web


Un serveur Web est un serveur informatique utilisé pour publier des sites web sur Internet ou
un intranet. L'expression « serveur Web » désigne également le logiciel utilisé sur le serveur pour
exécuter les requêtes HTTP, le protocole de communication employé sur le World Wide Web. Un
serveur web diffuse généralement des sites web, il peut contenir d'autres services liés comme l'envoi
d'e-mails, du streaming, le transfert de fichiers par FTP, etc.

8.3. Quelques exemples de serveurs web

XPort (serveur Ethernet embarqué) : Solution compacte et intégrée pour accès au web. En
incorporant ce composant à votre design, vous pouvez facilement et rapidement créer une
connectivité Série vers Ethernet. Votre matériel sera alors accessible et contrôlable par internet.

Figure 8.4. XPort (serveur Ethernet embarqué)

XPort-AR (serveur Ethernet embarqué programmable et sécurisé) :


De la taille de quelques morceaux de sucre, le XPORT AR et la solution qui permet d’ajouter une
connectivité Ethernet et d’embarquer un site internet dans votre produit. Le XPORT AR est
construit sur la base du XPORT, et intègre un processeur 16 bits, 120MHz.

Figure 8.5. XPort -AR


XPort-PRO (serveur embarqué sur base LINUX) :
Le XPORT PRO est le plus puissant module de la famille XPORT. Il intègre un processeur 32 bits,
et une capacité mémoire supérieure aux autres produits de la gamme.

Page | 175 © ISI 2018 Ridha Ghayoula


Figure 8.6. XPort -PRO

PREMIERWAVE (System-On-Module, processeur ARM9 400MHz 32 bits, OS LINUX):


Ce module est adapté aux applications M2M les plus exigeantes. Il intègre nativement des
connectivités Ethernet, série, USB, I2C, SPI et WIFI (protocoles de sécurité et d’authentification).
Sa base LINUX permet d’embarquer vos propres applications, pour rendre votre produit autonome,
intelligent et connecté. Il collecte les informations de votre produit, le pilote, pousse les informations
en dynamique vers des pages internet embarquée… En option : ce produit existe sans la fonction
WIFI

Figure 8.7. PremierWave EN Ethernet to Wi-Fi Gateway

"PremierWave EN is a high performance Industrial ready ARM 9 system on module suitable for IOT applications.
It is offered as a small removable module with integrated Flash, RAM and dual band 802.11 a/b/g/n capabilities.
The PremierWave EN is an ideal solution for embedded applications that require simple development, ease of use and
a proven robust high performing solution with network connectivity. Developers can save time and reduce the complexity
of developing subsystems with high speed memory, Ethernet and Wi-Fi networking that can be easily integrated into
real products."

8.4. Exemples d'applications


8.4.1 .La carte Raspberry Pi

Page | 176 © ISI 2018 Ridha Ghayoula


Figure 8.8. La carte Raspberry Pi

Voici leurs spécifications :

 Taille : 85.60 mm × 53.98 mm ;


 Poids : 45 g ;
 Processeur : 700 MHz ARM1176JZF-S core (ARM11) ;
 Système sur puce (Soc) : Broadcom BCM2835 ;
 Processeur graphique (GPU) : décodeur Broadcom VideoCore IV, API logicielle vidéo
OpenGL ES 2.0, MPEG-2 et VC-1, décodage vidéo 1080p30 h.264/MPEG-4 AVC ;

Page | 177 © ISI 2018 Ridha Ghayoula


 Mémoire (SDRAM) : 256 Mo [Modèle A] ou 512 Mo [Modèle B]] partagée avec le
processeur graphique ;
 Ports USB 2.0 : 1 [Modèle A] ou 2 [Modèle B]] ;
 Sortie vidéo : RCA Composite (PAL et NTSC) et HDMI (rev 1.3 & 1.4)
 Sortie audio : 3.5 mm jack, HDMI
 Unité de lecture-écriture de carte mémoire : SDHC / MMC / SDIO ;
 Réseau : 1 port réseau Fast Ethernet (10/100 Mbits/s) sur le [Modèle B]] uniquement ;
 Périphériques bas niveau : 8 × GPIO, UART, bus I²C, bus SPI ;
 Besoin en alimentation : 5 volt via MicroUSB ou GPIO ; 300 mA (1.5 W) [Modèle A] ou 700
mA (3.5 W) [Modèle B].

L’ordinateur Raspberry Pi est connecté en réseau par un connecteur Ethernet et/ou une liaison
WIFI. Il peut devenir un serveur WEB permettant le contrôle distant de processus ou la
transmission à distance de données à travers Internet. Ce TP montre comment créer un serveur
WEB affichant deux boutons ON et OFF sur lesquels l’utilisateur peut agir. Il existe plusieurs
bibliothèque de site WEB embarqué pour Raspberry Pi, l’ordinateur a cependant des ressources
limités, il est préférable d’utiliser un serveur peut gourmant en ressources processeur et éviter les
médias trop volumineux qui satureraient la mémoire flash. La bibliothèque retenue dans cet exemple
est webpy .

8.4.2. Serveur WEB


Il y a un exemple tres interessnt de monsieur Christian Dupaty dans la reference [13].

Procédure de création d’un site WEB avec webpy


Installation du serveur : http://webpy.org/install
ou (en français) https://itechnofrance.wordpress.com/2013/02/04/piloter-les-ports-gpio-partir-
dunnavigateur-internet/

Documentation web.py http://webpy.org/tutorial3.en


Télécharger le module http://webpy.org/static/web.py-0.37.tar.gz

Le transfert depuis un PC vers LINUX (dossier ~/python se fait avec WinSCP


tar –xzvf web.py-0.37.tar.gz (décompression)
cd web.py-0.37
python setup.py install

Création du dossier du serveur WEB


cd / (racine)
mkdir webpyserver (le dossier du serveur)
cd /webpyserver
mkdir templates (contiendra les pages html dont index.html
mkdir static (feuille de style CSS éventuelle)
Remarque : le port du serveur Web sera 8080

Réalisation du site WEB


Dans le dossier webpiserver, créér le fichier gpio4.py
Ce programme récupère les données des GPIO et gère l’interface homme-machine de la page Web.

Page | 178 © ISI 2018 Ridha Ghayoula


#!/usr/bin/env python
import web
import RPi.GPIO as GPIO
from web import form
# definit GPIO4 en sortie
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)
# definit la page de nom index pour le site web
urls = (‘/’, ‘index’)
dossier_web = web.template.render(‘templates’)
app = web.application(urls, globals())
# definit les boutons a afficher
ma_forme = form.Form (
form.Button("btn", id = "btnon", value = "on", html = "On", class_ = "bouton_on"),
form.Button("btn", id = "btnoff", value = "off", html = "Off", class_ = "bouton_off") )

# definit l action a effectuer quand la page index est appelee


class index:
# utilise quand la page est demandee
def GET(self):
forme = ma_forme()
return dossier_web.index(forme, "Raspberry Pi control GPIO4")

# utilise quand une forme web est soumise


def POST(self):
userdata = web.input()
if userdata.btn == "on":
GPIO.output(4,True) # Allume la LED
if userdata.btn == "off":
GPIO.output(4,False) # Eteind la LED
# recharge la page web
raise web.seeother(‘/’)
# programme
if __name__ == ‘__main__’:
app.run()

Dans le sous dossier templates créer le fichier index.html C’est la page html d’accueil du site Web,
elle est ici simplifiée au maximum. Il est possible de l’enrichir avec un éditeur html comme NVU ou
KOMPOSER ( www.nvu.com )
$def with (form, title)
<!doctype html>
<html>
<head>
<title>$title</title>
</head>

<body>

Page | 179 © ISI 2018 Ridha Ghayoula


<br />
<form class="form" method="post">
$:form.render()
</form>
</body>
</html>
$:form.render()

Lancer le programme gpio4.py et accéder au serveur de la Raspberry Pi depuis un PC en réseau à


l’adresse : ip : XXX.XXX.XXX.XXX :8080 ou plus simplement raspberrypi :8080

Résultat obtenu pour les deux boutons :

http://eduscol.education.fr/sti/sites/eduscol.education.fr.sti/files/ressources/pedagogiques/4346/4346-7-rpi-
serveur-web.pdf

Il y a une autre application Thermometre WEB dans le refernce [13]

8.4.3. Connexion à la Raspberry Pi sur un poste distant

À partir du moment où l'adresse IP de la Raspberry Pi est connue*, on peut s'y connecter à partir
d'un autre poste informatique du réseau pour y effectuer certaines opérations à distance, voire en
prendre le contrôle comme si vous travailliez sur la Raspberry Pi. L'écran, le clavier et la souris reliés
à la carte embarquée ne sont alors plus utiles.

*Note : attention, avec le DHCP, celle-ci est attribuée pour un temps limité et peut changer d'une session à l'autre, ce
qui oblige dans ce cas à brancher au moins un écran à chaque démarrage pour visualiser l'IP attribuée. Il existe bien
sûr des alternatives : - attribuer une IP fixe, à voir avec les services informatiques du lycée. Il vous faudra pour cela
modifier le fichier de configuration /etc/network/interfaces (voir par exemple Attribution d'un IP fixe ); - sinon, on
peut utiliser un logiciel qui scanne une plage d'adresse IP tel Advanced IP Scanner mais la recherche peut prendre du
temps.

Page | 180 © ISI 2018 Ridha Ghayoula


PC avce logiciels
clients9Putty,FileZi
lla,..)

Figure 8.9. Connexion à la Raspberry

Sur un poste distant sous Windows, une simple commande ping tapée dans une console d'exécution
permet de vérifier que la connexion est bien établie : Sur un poste distant sous Windows, une simple
commande ping tapée dans une console d'exécution permet de vérifier que la connexion est bien
établie :

a) Putty
Putty (http://www.putty.org/) est un logiciel Windows qui permet de prendre le contrôle à distance
du Raspberry Pi en utilisant le protocole SSH (Secure Shell). Si vous utilisez la distribution Linux
proposée avec la Pi-Lite, un client SSH est activé par défaut (voir dans l'utilitaire raspi-config). Le
dialogue s'effectue uniquement dans une console en mode texte. Il se présente sous la forme d'un
simple fichier exécutable (putty.exe). Cet outil peut être intéressant pour exécuter des commandes
Linux, exécuter des programmes Python, gérer des fichiers, etc. mais ne permet pas une prise de
contrôle avec l'environnement de bureau LXDE en mode graphique.

Page | 181 © ISI 2018 Ridha Ghayoula


Figure 8.10. Putty

b) FileZilla
FileZilla est un client FTP (File Transfer Protocol) libre qui permet de télécharger des fichiers sur un
serveur. Il propose une interface graphique à la façon d'un gestionnaire de fichiers et prend en
charge le protocole SSH. Site officiel : https://filezilla-project.org/, suivre les indications après avoir
cliqué sur le lien « Download FileZilla Client ». Rendez-vous dans le « Gestionnaire de Sites » pour
créer la connexion :

Page | 182 © ISI 2018 Ridha Ghayoula


Une fois connecté à la Raspberry Pi, vous pouvez y déposer vos fichiers par simple glisser-déposer à
la souris :

Sur un PC distant, l'élève peut préparer et mettre au point son programme Python avant de le
transférer sur la Raspberry grâce à FileZilla. Il peut ensuite lancer son exécution dans une console
Putty. Avec quelques précautions, il est possible d'ouvrir plusieurs sessions avec Putty et donc faire
travailler plusieurs élèves à distance sur une même carte Raspberry Pi.

Page | 183 © ISI 2018 Ridha Ghayoula


9
Les Applications Arduino

9.1. Introduction
Arduino est un circuit imprimé en matériel libre (les plans de la carte elle-même sont publiés
en licence libre, cependant, certains composants de la carte, comme le microcontrôleur par exemple,
ne sont pas en licence libre) sur lequel se trouve unmicrocontrôleur qui peut être programmé pour
analyser et produire des signaux électriques, de manière à effectuer des tâches très diverses comme
la domotique (le contrôle des appareils domestiques - éclairage, chauffage…), le pilotage
d'un robot, etc.C'est une plateforme basée sur une interface entrée/sortie simple. Il était destiné à
l'origine principalement mais pas exclusivement à la programmation multimédia interactive en vue
de spectacle ou d'animations artistiques. C'est une partie de l'explication de la descendance de son
interface de programmation de Processing, lui-même inspiré de l'environnement de
programmation Wiring.

Figure 9.1. Carte Arduino "Uno"

Vous apprendrez tout au long de la lecture, les bases de l'électronique et de la programmation. Sauf
que les notions électroniques abordées seront d'un bas niveau et ne vous permettrons que la mise en
oeuvre avec de la programmation. Vous ne pourrez donc pas créer tout seul des petits montages
n'utilisant que des composants électroniques sans avoir à programmer un microcontrôleur.
Cependant, il y aura deux grandes parties où l'on verra beaucoup d'électronique, il s'agit des moteurs
et des capteurs. On utilisera des petits systèmes électroniques (par exemple la commande de pilotage
d'un moteur à courant continu) associées à la programmation.

Page | 184 © ISI 2018 Ridha Ghayoula


9.2. Apprentissage des bases
9.2.1. Matériel
J’espère que vous disposez à présent du matériel requis pour continuer le cours car dans ce chapitre,
je vais vous montrer comment se présente votre carte, puis comment la tester pour vérifier son bon
fonctionnement.
Pour commencer notre découverte de la carte Arduino, je vais vous présenter la carte en elle-même.
Nous allons voir comment s'en servir et avec quoi. J'ai représenté en rouge sur cette photo les points
importants de la carte.

9.2.2. Le logiciel
a) Le logiciel va nous permettre de programmer la carte Arduino. Il nous offre une multitude de
fonctionnalités que nous verrons dans un chapitre dédié. Voilà à quoi il ressemble :

Figure 9.2. Logiciel Arduino


b)
Bouton 1 : Ce bouton permet de vérifier le programme, il actionne un module qui cherche les
erreurs dans votre programme
Bouton 2 : Créer un nouveau fichier
Bouton 3 : Sauvegarder le programme en cours
Bouton 4 : On n'y touche pas pour l'instant
Bouton 5 : Stoppe la vérification
Bouton 6 : Charger un programme existant
Bouton 7 : Compiler et envoyer le programme vers la carte
Enfin, on va pouvoir s'occuper du matériel que vous devriez tous posséder en ce moment même : la
carte Arduino !

Page | 185 © ISI 2018 Ridha Ghayoula


c)
Le cadre numéro 1 : ce sont les options de configuration du logiciel
Le cadre numéro 2 : il contient les boutons qui vont nous servir lorsque l'on va programmer nos
cartes
Le cadre numéro 3 : ce bloc va contenir le programme que nous allons créer
Le cadre numéro 4 : celui-ci est important, car il va nous aider à corriger les fautes dans notre
programme. C'est le débogueur.

Figure 9.3. Présentation des parties principales du logiciel

Approche et utilisation du logiciel


Attaquons-nous plus sérieusement à l'utilisation du logiciel. La barre des menus est entourée en
rouge et numérotée par le chiffre 1

Page | 186 © ISI 2018 Ridha Ghayoula


Figure 9.4. Contenu du menu "File"
New (nouveau) : va permettre de créer un nouveau programme. Quand on appuie sur ce bouton,
une nouvelle fenêtre, identique à celle-ci, s'affiche à l'écran
Open... (ouvrir) : avec cette commande, nous allons pouvoir ouvrir un programme existant
Save / Save as... (Enregistrer / enregistrer sous...) : enregistre le document en cours / demande où
enregistrer le document en cours
Examples (exemples) : ceci est important, toute une liste se déroule pour afficher les noms
d'exemples de programmes existants ; avec çà, vous pourrez vous aider pour créer vos propres
programmes.

Le reste des menus n'est pas intéressant pour l'instant, on y reviendra plus tard, avant de commencer
à programmer.

Page | 187 © ISI 2018 Ridha Ghayoula


Figure 9.5. Ouvrir le programme Blink
a) Clignoter un Groupe de LED

Figure 9.6. Carte Arduino

Page | 188 © ISI 2018 Ridha Ghayoula


// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
}
// the loop routine runs over and over again forever:
void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
Faire clignoter un groupe de LED
Vous avouerez facilement que ce n'était pas bien difficile d'arriver jusque-là. Alors, à présent,
accentuons la difficulté. Notre but : faire clignoter un groupe de LED.

Le programme est un peu plus long, car il ne s'agit plus d'allumer 1 seule LED, mais 6 ! Voilà
l'organigramme que va suivre notre programme :

R1
PIN9 LED1

R1
PIN10 LED2
USB

R1
PIN11 LED3

GROUND

Page | 189 © ISI 2018 Ridha Ghayoula


*/
void setup()
{
pinMode(9, OUTPUT); // sets digital pins as outputs
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
}
void loop()
{
digitalWrite(9, HIGH); // turns on red
digitalWrite(11, LOW); // turns off blue
delay(1000); // waits for 1 second
digitalWrite(10, HIGH); // turns on green
digitalWrite(9, LOW); // turns off red
delay(1000); // waits for 1 second
digitalWrite(11, HIGH); // turns on blue
digitalWrite(10, LOW); // turns off green
delay(1000); // waits for 1 second
}

9.3. Afficheurs 7 segments


Vous connaissez les afficheurs 7 segments ? Ou alors vous ne savez pas que ça s’appelle comme ça ?
Il s’agit des petites lumières qui forment le chiffre 8 et qui sont de couleur rouge ou verte, la plupart
du temps, mais peuvent aussi être bleus, blancs, etc. On en trouve beaucoup dans les radio-réveils,
car ils servent principalement à afficher l’heure. Autre particularité, non seulement de pouvoir
afficher des chiffres (0 à 9), ils peuvent également afficher certaines lettres de l’alphabet.
Pour cette partie, vous aurez besoin de :

Page | 190 © ISI 2018 Ridha Ghayoula


 Un (et plus) afficheur 7 segments (évidemment)
 8 résistances de 330Ω
 Un (ou deux) décodeurs BCD 7 segments
 Une carte Arduino ! Mais dans un premier temps on va d’abord bien saisir le truc avant de
faire du code
Nous allons commencer par une découverte de l’afficheur, comment il fonctionne et comment le
branche-t-on. Ensuite nous verrons comment l’utiliser avec la carte Arduino

Principe
Un afficheur 7 segments est le plus simple des afficheurs. On le retrouve très fréquemment lorsqu'il
s'agit d'afficher une information numérique. Il est constitué de 7 LED (+1 pour le point) reliées
ensemble par leur anode (il en existe aussi reliés par la cathode). On peut commander
individuellement. Classiquement les différentes LED (aussi appelées segments) sont nommées
conformément au schéma ci-dessous :

10 9 8 7 6

a
PIN2
USB
10
f b
PIN3 9
PIN4 7
g
PIN5 5
PIN6 4
PIN7 2
e c
PIN8 1
PIN9 6

d
GROUND
1 2 3 4 5

PIN2 10
PIN3 9
PIN4 7
PIN5 5
USB PIN6 4
PIN7 2
PIN8 1
PIN9 6

GROUND

Programme
Voici le programme qu'il faut éditer dans l'IDE Arduino, puis compiler et charger dans la carte
Arduino :

Page | 191 © ISI 2018 Ridha Ghayoula


/*
Ce programme met en oeuvre l'utilisation d'un afficheur 7 segments en
affichant les chiffres les uns après les autres
*/

//Déclaration des constantes


const int led_A = 2; // le segment A est branché sur la pin 2
const int led_B = 3;
const int led_C = 4;
const int led_D = 8;
const int led_E = 9;
const int led_F = 6;
const int led_G = 7;
const int led_DP = 5;

const int tableauSegment [] = {led_A, led_B, led_C, led_D, led_E, led_F,


led_G, led_DP};
const int nbSegment = 8;

inline void allumer(int led){


digitalWrite(led, LOW);
}

inline void eteindre(int led){


digitalWrite(led, HIGH);
}

inline void eteindreToutesLesLED(){


for(int i=0; i < nbSegment; i++){
int ledAEteindre = tableauSegment[i];
eteindre(ledAEteindre); // eteint la LED
}
}

inline void allumerEtEteindreLED(int led){


allumer(led);
delay(500); // attente de 1/2 seconde
eteindre(led);
}

void afficher(char chiffre){


eteindreToutesLesLED();
switch(chiffre)
{
case 0 :
allumer(led_A);
allumer(led_B);
allumer(led_C);
allumer(led_D);
allumer(led_E);
allumer(led_F);
break;
case 1 :
allumer(led_B);
allumer(led_C);
break;

Page | 192 © ISI 2018 Ridha Ghayoula


case 2 :
allumer(led_A);
allumer(led_B);
allumer(led_D);
allumer(led_E);
allumer(led_G);
break;
case 3 :
allumer(led_A);
allumer(led_B);
allumer(led_C);
allumer(led_D);
allumer(led_G);
break;
case 4 :
allumer(led_B);
allumer(led_C);
allumer(led_F);
allumer(led_G);
break;
case 5 :
allumer(led_A);
allumer(led_C);
allumer(led_D);
allumer(led_F);
allumer(led_G);
break;
case 6 :
allumer(led_A);
allumer(led_C);
allumer(led_D);
allumer(led_E);
allumer(led_F);
allumer(led_G);
break;
case 7 :
allumer(led_A);
allumer(led_B);
allumer(led_C);
break;
case 8 :
allumer(led_A);
allumer(led_B);
allumer(led_C);
allumer(led_D);
allumer(led_E);
allumer(led_F);
allumer(led_G);
break;
case 9 :
allumer(led_A);
allumer(led_B);
allumer(led_C);
allumer(led_D);
allumer(led_F);
allumer(led_G);
break;

Page | 193 © ISI 2018 Ridha Ghayoula


}
}
void setup() // setup est exécuté une seule fois après la remise à zéro
{
pinMode(led_A, OUTPUT); // la broche led_A (2) est initialisée en sortie
pinMode(led_B, OUTPUT);
pinMode(led_C, OUTPUT);
pinMode(led_D, OUTPUT);
pinMode(led_E, OUTPUT);
pinMode(led_F, OUTPUT);
pinMode(led_G, OUTPUT);
pinMode(led_DP, OUTPUT);
eteindreToutesLesLED();
}
void loop() // loop est exécuté indéfiniment
{
for(char i=0; i <=9; ++i){
afficher(i);
delay(500);
}
}

Ce programme peut être simplifié en stockant la matrice des configurations directement dans la
mémoire flash de l'arduino :
/*
/*
Ce programme met en oeuvre l'utilisation d'un afficheur 7 segments en
affichant les chiffres les uns après les autres
*/
//Déclaration des constantes
const int led_A = 2; // le segment A est branché sur la pin 2
const int led_B = 3;
const int led_C = 4;
const int led_D = 8;
const int led_E = 9;
const int led_F = 6;
const int led_G = 7;
const int led_DP = 5;

const int tableauSegment [] = {led_A, led_B, led_C, led_D, led_E, led_F,


led_G, led_DP};
const int nbSegment = 8;

const int tableauChiffre[][nbSegment] = {


{1, 1, 1, 1, 1, 1, 0, 0},
{0, 1, 1, 0, 0, 0, 0, 0},
{1, 1, 0, 1, 1, 0, 1, 0},
{1, 1, 1, 1, 0, 0, 1, 0},
{0, 1, 1, 0, 0, 1, 1, 0},
{1, 0, 1, 1, 0, 1, 1, 0},
{1, 0, 1, 1, 1, 1, 1, 0},
{1, 1, 1, 0, 0, 0, 0, 0},
{1, 1, 1, 1, 1, 1, 1, 0},
{1, 1, 1, 1, 0, 1, 1, 0},
{1, 1, 1, 0, 1, 1, 1, 0},

Page | 194 © ISI 2018 Ridha Ghayoula


{0, 0, 1, 1, 1, 1, 1, 0},

{1, 0, 0, 1, 1, 1, 0, 0},
{0, 1, 1, 1, 1, 0, 1, 0},
{1, 0, 0, 1, 1, 1, 1, 0},
{1, 0, 0, 0, 1, 1, 1, 0},
};

// Déclaration des variables globales


int indiceSegmentCourant = 0;

inline void allumer(int led){


digitalWrite(led, LOW);
}

inline void eteindre(int led){


digitalWrite(led, HIGH);
}

inline void eteindreToutesLesLED(){


for(int i=0; i < nbSegment; i++){
int ledAEteindre = tableauSegment[i];
eteindre(ledAEteindre); // eteint la LED
}
}

inline void allumerEtEteindreLED(int led){


allumer(led);
delay(500); // attente de 1/2 seconde
eteindre(led);
}

void afficher(char chiffre){


eteindreToutesLesLED();
for(int i = 0; i < nbSegment; ++i){
if(tableauChiffre[chiffre][i] == 1)
{
allumer(tableauSegment[i]);
}
}
}

void setup() // setup est exécuté une seule fois après la remise à zéro
{
pinMode(led_A, OUTPUT); // la broche led_A (2) est initialisée en sortie
pinMode(led_B, OUTPUT);
pinMode(led_C, OUTPUT);
pinMode(led_D, OUTPUT);
pinMode(led_E, OUTPUT);
pinMode(led_F, OUTPUT);
pinMode(led_G, OUTPUT);
pinMode(led_DP, OUTPUT);
eteindreToutesLesLED();
}

Page | 195 © ISI 2018 Ridha Ghayoula


void loop() // loop est exécuté indéfiniment
{
for(char i=0; i <=9; ++i){
afficher(i);
delay(500);
}
}

9.4. Réseau de LED 8x8 MAX7219


Composants utilisés
Un afficheur Max7219
Une carte Arduino Uno
Une breadboard
Fils de câblage

9.4.1. Principe
L'afficheur comporte 8 lignes et 8 colonnes de LED, contrôlables individuellement.
Il permet d'afficher avec ces 64 LED 256 x 256 motifs possibles = 65 536 combinaisons lumineuses.
Tous les caractères numériques, alphabétiques, ou caractères spéciaux sont donc affichables.
La brillance des leds peut être ajustée par logiciel.

9.4.2. Montage
L'afficheur MAX7219 Dot Matrix est fourni en kit simple à souder.

Souder la résistance et les deux condensateurs (l'électrolytique est polarisé, attention au sens)
Souder le support de circuit (placer l'encoche comme sur le schéma imprimé)
Souder les 2 connecteurs et les 2 supports d'afficheur.
Placer le circuit intégré et l'afficheur à cathode commune sur leurs supports.

9.4.3. Fonctionnement
Il suffit de 3 fils de commandes et 2 fils d'alimentation pour contrôler un ou plusieurs afficheurs.
Le pilotage est très simple depuis une carte Arduino.
Il se fait en mode série et utilise la persistance rétinienne en balayant les 8 colonnes rapidement.
Des modules identiques peuvent s'enchaîner en reliant Din et Dout d'un premier module au suivant.

Câblage 5 fils

PIN8 DIN
19
2
7
x
a
Max7219

PIN9 CS
PIN10 CLK
5V VCC
USB GND GND

Testing Steps

Page | 196 © ISI 2018 Ridha Ghayoula


1.Wiring Instructions
Connect Arduino pin8 to DIN on 8x8 LED Matrix
Connect Arduino pin9 to CS of 8x8 LED Matrix
Connect Arduino pin10 to CLK of 8x8 LED Matrix
Connect Arduino 5V to VCC of 8x8 LED Matrix
Connect Arduino GND to GND of 8x8 LED Matrix

/*
unsigned char i;
unsigned char j;
/*Port Definitions*/
int Max7219_pinCLK = 10;
int Max7219_pinCS = 9;
int Max7219_pinDIN = 8;

unsigned char disp1[38][8]={


{0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C},//0
{0x10,0x18,0x14,0x10,0x10,0x10,0x10,0x10},//1
{0x7E,0x2,0x2,0x7E,0x40,0x40,0x40,0x7E},//2
{0x3E,0x2,0x2,0x3E,0x2,0x2,0x3E,0x0},//3
{0x8,0x18,0x28,0x48,0xFE,0x8,0x8,0x8},//4
{0x3C,0x20,0x20,0x3C,0x4,0x4,0x3C,0x0},//5
{0x3C,0x20,0x20,0x3C,0x24,0x24,0x3C,0x0},//6
{0x3E,0x22,0x4,0x8,0x8,0x8,0x8,0x8},//7
{0x0,0x3E,0x22,0x22,0x3E,0x22,0x22,0x3E},//8
{0x3E,0x22,0x22,0x3E,0x2,0x2,0x2,0x3E},//9
{0x8,0x14,0x22,0x3E,0x22,0x22,0x22,0x22},//A
{0x3C,0x22,0x22,0x3E,0x22,0x22,0x3C,0x0},//B
{0x3C,0x40,0x40,0x40,0x40,0x40,0x3C,0x0},//C
{0x7C,0x42,0x42,0x42,0x42,0x42,0x7C,0x0},//D
{0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x7C},//E
{0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x40},//F
{0x3C,0x40,0x40,0x40,0x40,0x44,0x44,0x3C},//G
{0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44},//H
{0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x7C},//I
{0x3C,0x8,0x8,0x8,0x8,0x8,0x48,0x30},//J
{0x0,0x24,0x28,0x30,0x20,0x30,0x28,0x24},//K
{0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C},//L
{0x81,0xC3,0xA5,0x99,0x81,0x81,0x81,0x81},//M
{0x0,0x42,0x62,0x52,0x4A,0x46,0x42,0x0},//N
{0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C},//O
{0x3C,0x22,0x22,0x22,0x3C,0x20,0x20,0x20},//P
{0x1C,0x22,0x22,0x22,0x22,0x26,0x22,0x1D},//Q
{0x3C,0x22,0x22,0x22,0x3C,0x24,0x22,0x21},//R
{0x0,0x1E,0x20,0x20,0x3E,0x2,0x2,0x3C},//S
{0x0,0x3E,0x8,0x8,0x8,0x8,0x8,0x8},//T
{0x42,0x42,0x42,0x42,0x42,0x42,0x22,0x1C},//U
{0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18},//V
{0x0,0x49,0x49,0x49,0x49,0x2A,0x1C,0x0},//W
{0x0,0x41,0x22,0x14,0x8,0x14,0x22,0x41},//X
{0x41,0x22,0x14,0x8,0x8,0x8,0x8,0x8},//Y
{0x0,0x7F,0x2,0x4,0x8,0x10,0x20,0x7F},//Z
};

Page | 197 © ISI 2018 Ridha Ghayoula


void Write_Max7219_byte(unsigned char DATA)
{
unsigned char i;
digitalWrite(Max7219_pinCS,LOW);
for(i=8;i>=1;i--)
{
digitalWrite(Max7219_pinCLK,LOW);
digitalWrite(Max7219_pinDIN,DATA&0x80);// Extracting a bit data
DATA = DATA<<1;
digitalWrite(Max7219_pinCLK,HIGH);
}
}

void Write_Max7219(unsigned char address,unsigned char dat)


{
digitalWrite(Max7219_pinCS,LOW);
Write_Max7219_byte(address); //address,code of LED
Write_Max7219_byte(dat); //data,figure on LED
digitalWrite(Max7219_pinCS,HIGH);
}

void Init_MAX7219(void)
{
Write_Max7219(0x09, 0x00); //decoding :BCD
Write_Max7219(0x0a, 0x03); //brightness
Write_Max7219(0x0b, 0x07); //scanlimit;8 LEDs
Write_Max7219(0x0c, 0x01); //power-down mode:0,normal mode:1
Write_Max7219(0x0f, 0x00); //test display:1;EOT,display:0
}

void setup()
{

pinMode(Max7219_pinCLK,OUTPUT);
pinMode(Max7219_pinCS,OUTPUT);
pinMode(Max7219_pinDIN,OUTPUT);
delay(50);
Init_MAX7219();
}
void loop()
{
for(j=0;j<38;j++)
{
for(i=1;i<9;i++)
Write_Max7219(i,disp1[j][i-1]);
delay(500);
}
}

Page | 198 © ISI 2018 Ridha Ghayoula


9.4.4. Codage de nouveaux motifs et caractères
Il est facile de créer ses propres motifs personnalisés.
Dessiner un caractère sur une grille carrée 8 x 8. On le décompose ensuite ligne par ligne.

Rappel du codage binaire


Binaire Hex
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 8
1001 9
1010 A
1011 B
1100 C
1101 D
1110 E
1111 F

Exemple pour afficher "A" il suffit de définir ceci dans un tableau


{0x8,0x14,0x22,0x3E,0x22,0x22,0x22,0x22}, //A

C1 C2 Binaire Codage
L1 X 0000 1000 08
L2 X X 0001 0100 22
L3 X X 0010 0010 3E
L4 X X X X X 0011 1110 22
L5 X X 0010 0010 22
L6 X X 0010 0010 22
L7 X X 0010 0010 22
L8 X X 0010 0010 22
Pour afficher le "1"
{0x10,0x30,0x50,0x10,0x10,0x10,0x10,0x10},//1
C1 C2 Binaire Codage
L1 X 0001 0000 10
L2 X X 0011 0000 30
L3 X X 0101 0000 50
L4 X X 1001 0000 90
L5 X 0001 0000 10
L6 X 0001 0000 10
L7 X 0001 0000 10
L8 X 0001 0000 10

Pour afficher un damier alterné


{0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55},//damier

Page | 199 © ISI 2018 Ridha Ghayoula


C1 C2 Binaire Codage
L1 X X X X 1010 1010 AA
L2 X X X X 0101 0101 55
L3 X X X X 1010 1010 AA
L4 X X X X 0101 0101 55
L5 X X X X 1010 1010 AA
L6 X X X X 0101 0101 55
L7 X X X X 1010 1010 AA
L8 X X X X 0101 0101 55

9.5. Les Servo-Moteurs


Un servo-moteur est un type de moteur électrique. C'est un dispositif typiquement utilisé en
modélisme pour, par exemple, contrôler la direction d'une voiture télécommandée.

Figure 9.7. Servo-Moteur


Sur un servo-moteur, l'angle de de l'axe reste fixé dans une position et peu varier entre 0 et 180° en
fonction du signal envoyé. Un servo-moteur comprend :

 Un moteur électrique (continu), généralement assez petit.


 Des engrenages réducteur en sortie du ce moteur (pour avoir moins de vitesse et plus de
couple ou de force).
 Un capteur type "potentiomètre" raccordé sur la sortie.
 Il s'agit donc d'une résistance qui varie en fonction de l'angle, ce qui permet de
mesurer l'angle de rotation sur l'axe de sortie.
 Un asservissement électronique pour contrôler la position/rotation, de cet axe de
sortie pour le maintenir à la bonne position.
9.5.1. Commande électronique d'un servo-moteur
Le principe de base est assez simple. Il suffit d'envoyer une impulsion et c'est le temps que durera
cette impulsion qui déterminera l'angle du servo-moteur. Ce temps d'impulsion est de quelques de
quelques millisecondes et doit être répété à intervalle régulier (toutes les 20 ms à 50ms). Si le temps
d'impulsion varie d'un fabricant à l'autre, les valeurs suivantes sont assez standard:

 1.25 ms = 0 degré
 1.50 ms = 90 degrés
 1.75 ms = 180 degrés

Page | 200 © ISI 2018 Ridha Ghayoula


1.5ms

Centré

10 à 20ms
1 ms
-45 deg

10 à 20ms
2 ms

45 Deg

10 à 20ms

9.5.2. Raccordement d'un servo-moteur


Puisque l'interface de commande est assez simple, un servo-moteur se raccorde avec seulement 3 fils
(la masse, +5v et la commande d'impulsion). Les raccordements les plus standardisés sont:
Noir, Rouge, Blanc

 Noir: Raccordé à la Masse,


 Rouge: Alimentation moteur et logique de commande. Raccordé à VCC 5v,
 Blanc: Commande de la position du servo-moteur.
Marron, Rouge, Jaune

Page | 201 © ISI 2018 Ridha Ghayoula


USB

5V

GND
USB

9.5.3. La librairie Servo


C’est la librairie qui va nous permettre d’utiliser les servomoteurs. Vous pouvez consulter la page de
cette librairie sur le site officel.
Nous allons donc voir les fonctions de cette librairie et apprendre à les utiliser.
– Attach() : permet d’affecter notre servomoteur à une sortie de l’Arduino. Il faut indiquer la
sortie entre les parenthèses.
– Write() : vous permet de faire tourner votre servomoteur pour attendre le degré précisé entre les
parenthèses (on par toujours de 0 au début du programme).
– writeMicroseconds() :cette fonction est similaire à Write() sauf qu’on demande au servomoteur
de tourner pendant X millisecondes qu’on précise entre les parenthèses.
– read() : permet de connaître la position en degré du servomoteur par rapport au début du
programme.
– Attached() : permet simplement de vérifier si la sortie précisé entre parenthèse est affectée à un
servomoteur. Cette fonction est peu utile mais je préfère vous la donner.
– Detach() : donne l’effet inverse de la fonction Attach() et déconnecte donc votre servomoteur.
Il faut préciser entre parenthèse la sortie à vérifier.

Page | 202 © ISI 2018 Ridha Ghayoula


– Servo : pour déclarer une variable de type Servo.
Vous êtes toujours là ? Bon c’était tout pour les fonctions je vous rassure et on enchaîne à la
pratique.
Voilà un petit programme de démonstration que j’ai fait, testez votre servomoteur avec !
Exemple #1
#include <Servo.h> // inclusion de la librairie Servo

Servo monservo; // déclaration d'une variable de type Servo


int position = 0; //positionne le serveur a la valeur donnée (0= centré)
changez cette valeur pour tester

void setup()
{
monservo.attach(9); // attache la variable Servo à la broche 9
}

void loop() {
monservo.write(position);
}
Exemple #2

#include <Servo.h>
Servo moteur;
int commande = 9;

void setup()
{
moteur.attach( commande );
}

void loop()
{
moteur.write( 90 );
delay( 1000 );
moteur.write( 45 );
delay( 1000 );
}

Exemple #3

#include <Servo.h>
Servo monServo;
void setup(){
// Attacher la pin 9 à l'objet servo.
// ATTN: le code initialise l'angle à 90 degrés par défaut.
monServo.attach(9);
}
void loop(){
// Assigne un angle de 53 degrés
monServo.write( 53 );
delay( 2000 );

Page | 203 © ISI 2018 Ridha Ghayoula


// Passer de 0 a 180 degrés par angle de 10 degrés
for( int iAngle=0; iAngle<= 180; iAngle+=10 )
{
monServo.write(iAngle);
delay( 50 );
}
}

Voici le code de servo.pde, une version plus complète d'un programme contrôlant un servo-moteur.
Il démontre clairement la capacité d'Arduino à contrôler finement la position d'un servo-moteur.
Exemple #4

/*
* Commande d'un servo moteur en plusieurs séquences.
* Clignotement de la Led onBoar:
* - rapide en début de programme.
* - lente en entre les séquences.
* - fixe en fin de programme
*
* Commande servo à l'aide de servo.h et
* seulement sur les pin 9 ou pin 10.
*
*/
#include <Servo.h>

Servo monServo;
int pos = 0;

const int pinLed = 13; // Led sur le board


const long blinkTimeMs = 2000; // temps de clignotement de la led (2 sec)

const int FAST = 50; // interval entre deux clignotement (rapide)


const int SLOW = 150; // interval entre deux clignotement (lent)
const int FIXED = -1; // valeur spécial pour éclairage continu

void setup(){
pinMode( pinLed, OUTPUT );
// Attacher la pin 9 à l'objet servo.
// ATTN: le code initialise l'angle à 90 degrés par défaut.
monServo.attach(9);
// remettre l'angle à 0 degrés
monServo.write( 0 );

void loop(){
// Faire clignoter led 13 sur le board.
// Démarrage de séquence --> clignotement rapide
blinkBoardLed( FAST );

// Passer de 0 a 180° par angle de 10 degré


for( int iAngle=0; iAngle<= 180; iAngle+=10 )
{

Page | 204 © ISI 2018 Ridha Ghayoula


monServo.write(iAngle);
delay( 250 );
}

// Clignotement lent entre deux séquences


blinkBoardLed( SLOW );

// Angle décroissant progressif


for( int iAngle = 180; iAngle>=0; iAngle-- )
{
monServo.write( iAngle );
delay( 10 );
}

// Clignotement lent entre deux séquences


blinkBoardLed( SLOW );

// Angle arbitraire de 45 degrés


monServo.write( 45 );

// Find de séquence -> eclairage fixe


blinkBoardLed( FIXED );
}

/* Fait clignoter la led 13 sur le board pendant 2 secondes


*
* interval: Interval de clignotement. -1 pour fixe.
*/
void blinkBoardLed( int interval ){
long startMillis = millis();
// temps que pas 2 sec d'écoulée
while( (millis() - startMillis) < blinkTimeMs ) {

switch( interval ){
case -1 : // Cas spécial, allumage fixe
digitalWrite( pinLed, HIGH );
delay( blinkTimeMs ); // attendre le temps total
digitalWrite( pinLed, LOW );
break;
default:
// faire clignoter
digitalWrite( pinLed, HIGH );
delay( interval );
digitalWrite( pinLed, LOW );
delay( interval );

} // eof Case

} // eof While
}

Page | 205 © ISI 2018 Ridha Ghayoula


10
Universal Asynchronous Receiver Transmitter
UART

10.1. Introduction

Un UART, pour Universal Asynchronous Receiver Transmitter, est un émetteur-récepteur


asynchrone universel. En langage courant, c'est le composant utilisé pour faire la liaison entre
l'ordinateur et le port série . L'ordinateur envoie les données en parallèle (autant de fils que de bits de
données). Il faut donc transformer ces données pour les faire passer à travers une liaison série qui
utilise un seul fil pour faire passer tous les bits de données.

Un DUART (Dual Universal Asynchronous Receiver Transmitter) combine deux UART dans une
seule puce. Un USART (Universal Synchronous/Asynchronous Receiver Transmitter) peut
communiquer de façon synchrone.

Aujourd'hui, les UART sont généralement intégrés dans des composants comme des
microcontrôleurs. Ils ne sont dans ce cas plus un composant à proprement parler, mais une fonction
périphérique du composant.

L’objectif de ce chapitre est de réaliser une liaison série sur un FPGA. Egalement appelée UART
(Universal Asynchronous Receiver/Transmitter), cette liaison série est capable d’envoyer une
donnée parallèle bit par bit sur un bus. Elle est composée de deux modules principaux : le module
émission TX et le module réception RX

10.2. Réalisation du module TX


10.2. 1. Le protocole
Le module TX permet de transmettre une donnée sur 8 bits sur la liaison série suivant un protocole
imposé. Une trame série est composée d’un bit de start, un bit de stop, un bit de parité et des bits de
données. Le bit de parité permet d’effectuer un contrôle sur la donnée reçue. Dans notre cas, nous
ne l’utiliserons pas. Lorsque aucune donnée n’est envoyée, le bus reste à l’état haut.

Une trame UART est constituée des bits suivants :

Page | 206 © ISI 2018 Ridha Ghayoula


START D0 D1 D2 D3 D4 D5 D6 D7 STOP

Figure 10.1.Trame série


Constitution d'une trame UART

 un bit de start toujours à 0 : servant à la synchronisation du récepteur


 les données : la taille peut varier (généralement entre 5 et 9 bits)
 éventuellement un bit de parité paire ou impaire
 et un bit de stop toujours à 1 (la durée peut varier entre 1, 1,5 et 2 temps bit)

UART_RX UART_TX

Device Utilization Summary (estimated values)


Logic Utlization Used Available Utlization
Number of Slices 53 15552 0%
Numebr of Slice Flip Flops 47 31104 0%
LUTS 100 31104 0%
IOBS 7 408 1%
GCLKS 1 4 25%

10.3. Diagramme UART


Registre d'émission

TX
Registre a decalage

Générateur
d'horloge

RX
Registre a decalage
Clock
Registre de reception

Figure 10.2.Trame série

10.3.1. Niveaux de tension


Les niveaux de tension sont de type TTL soit 0 V pour le niveau logique bas et +5V pour le niveau
logique haut.

Page | 207 © ISI 2018 Ridha Ghayoula


10.3.2. Vitesse de transmission

Afin de faciliter l'interopérabilité entre périphériques (PC, microcontrôleur, modem, …) des vitesses
de transmission sont normalisées par multiples et sous-multiples de 9600 baud, l'unité baud
correspondant à un bit par seconde :

 110 baud
 300 baud
 1 200 baud
 2 400 baud
 4 800 baud
 9 600 baud
 19 200 baud
 38 400 baud
 57 600 baud
 115 200 baud
 230 400 baud (selon la fréquence d'oscillation employée)
 460 800 baud
 921 600 baud (« environ 1 mégabaud »)
 1 843 200 baud
 3 686 400 baud

10.4. VHDL Receiver (UART_RX.vhd)


-- This file contains the UART Receiver. This receiver is able to
-- receive 8 bits of serial data, one start bit, one stop bit,
-- and no parity bit. When receive is complete o_rx_dv will be
-- driven high for one clock cycle.
--

Page | 208 © ISI 2018 Ridha Ghayoula


-- Set Generic g_CLKS_PER_BIT as follows:
-- g_CLKS_PER_BIT = (Frequency of i_Clk)/(Frequency of UART)
-- Example: 10 MHz Clock, 115200 baud UART
-- (10000000)/(115200) = 87
--
library ieee;
use ieee.std_logic_1164.ALL;
use ieee.numeric_std.all;

entity UART_RX is
generic (
g_CLKS_PER_BIT : integer := 115 -- Needs to be set correctly
);
port (
i_Clk : in std_logic;
i_RX_Serial : in std_logic;
o_RX_DV : out std_logic;
o_RX_Byte : out std_logic_vector(7 downto 0)
);
end UART_RX;

architecture rtl of UART_RX is

type t_SM_Main is (s_Idle, s_RX_Start_Bit, s_RX_Data_Bits,


s_RX_Stop_Bit, s_Cleanup);
signal r_SM_Main : t_SM_Main := s_Idle;

signal r_RX_Data_R : std_logic := '0';


signal r_RX_Data : std_logic := '0';

signal r_Clk_Count : integer range 0 to g_CLKS_PER_BIT-1 := 0;


signal r_Bit_Index : integer range 0 to 7 := 0; -- 8 Bits Total
signal r_RX_Byte : std_logic_vector(7 downto 0) := (others => '0');
signal r_RX_DV : std_logic := '0';

begin

-- Purpose: Double-register the incoming data.


-- This allows it to be used in the UART RX Clock Domain.
-- (It removes problems caused by metastabiliy)
p_SAMPLE : process (i_Clk)
begin
if rising_edge(i_Clk) then
r_RX_Data_R <= i_RX_Serial;
r_RX_Data <= r_RX_Data_R;
end if;
end process p_SAMPLE;
-- Purpose: Control RX state machine
p_UART_RX : process (i_Clk)
begin
if rising_edge(i_Clk) then

case r_SM_Main is

when s_Idle =>


r_RX_DV <= '0';

Page | 209 © ISI 2018 Ridha Ghayoula


r_Clk_Count <= 0;
r_Bit_Index <= 0;

if r_RX_Data = '0' then -- Start bit detected


r_SM_Main <= s_RX_Start_Bit;
else
r_SM_Main <= s_Idle;
end if;
-- Check middle of start bit to make sure it's still low
when s_RX_Start_Bit =>
if r_Clk_Count = (g_CLKS_PER_BIT-1)/2 then
if r_RX_Data = '0' then
r_Clk_Count <= 0; -- reset counter since we found the middle
r_SM_Main <= s_RX_Data_Bits;
else
r_SM_Main <= s_Idle;
end if;
else
r_Clk_Count <= r_Clk_Count + 1;
r_SM_Main <= s_RX_Start_Bit;
end if;

-- Wait g_CLKS_PER_BIT-1 clock cycles to sample serial data


when s_RX_Data_Bits =>
if r_Clk_Count < g_CLKS_PER_BIT-1 then
r_Clk_Count <= r_Clk_Count + 1;
r_SM_Main <= s_RX_Data_Bits;
else
r_Clk_Count <= 0;
r_RX_Byte(r_Bit_Index) <= r_RX_Data;
-- Check if we have sent out all bits
if r_Bit_Index < 7 then
r_Bit_Index <= r_Bit_Index + 1;
r_SM_Main <= s_RX_Data_Bits;
else
r_Bit_Index <= 0;
r_SM_Main <= s_RX_Stop_Bit;
end if;
end if;

-- Receive Stop bit. Stop bit = 1


when s_RX_Stop_Bit =>
-- Wait g_CLKS_PER_BIT-1 clock cycles for Stop bit to finish
if r_Clk_Count < g_CLKS_PER_BIT-1 then
r_Clk_Count <= r_Clk_Count + 1;
r_SM_Main <= s_RX_Stop_Bit;
else
r_RX_DV <= '1';
r_Clk_Count <= 0;
r_SM_Main <= s_Cleanup;
end if;

-- Stay here 1 clock


when s_Cleanup =>
r_SM_Main <= s_Idle;
r_RX_DV <= '0';

Page | 210 © ISI 2018 Ridha Ghayoula


when others =>
r_SM_Main <= s_Idle;
end case;
end if;
end process p_UART_RX;

o_RX_DV <= r_RX_DV;


o_RX_Byte <= r_RX_Byte;

end rtl;

10.5. VHDL Transmitter (UART_TX.vhd):


----------------------------------------------------------------------
-- File Downloaded from http://www.nandland.com
----------------------------------------------------------------------
-- This file contains the UART Transmitter. This transmitter is able
-- to transmit 8 bits of serial data, one start bit, one stop bit,
-- and no parity bit. When transmit is complete o_TX_Done will be
-- driven high for one clock cycle.
--
-- Set Generic g_CLKS_PER_BIT as follows:
-- g_CLKS_PER_BIT = (Frequency of i_Clk)/(Frequency of UART)
-- Example: 10 MHz Clock, 115200 baud UART
-- (10000000)/(115200) = 87
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity UART_TX is
generic (
g_CLKS_PER_BIT : integer := 115 -- Needs to be set correctly
);
port (
i_Clk : in std_logic;
i_TX_DV : in std_logic;
i_TX_Byte : in std_logic_vector(7 downto 0);
o_TX_Active : out std_logic;
o_TX_Serial : out std_logic;
o_TX_Done : out std_logic
);
end UART_TX;

architecture RTL of UART_TX is

type t_SM_Main is (s_Idle, s_TX_Start_Bit, s_TX_Data_Bits,


s_TX_Stop_Bit, s_Cleanup);
signal r_SM_Main : t_SM_Main := s_Idle;

signal r_Clk_Count : integer range 0 to g_CLKS_PER_BIT-1 := 0;


signal r_Bit_Index : integer range 0 to 7 := 0; -- 8 Bits Total
signal r_TX_Data : std_logic_vector(7 downto 0) := (others => '0');
signal r_TX_Done : std_logic := '0';

begin

p_UART_TX : process (i_Clk)

Page | 211 © ISI 2018 Ridha Ghayoula


begin
if rising_edge(i_Clk) then

case r_SM_Main is

when s_Idle =>


o_TX_Active <= '0';
o_TX_Serial <= '1'; -- Drive Line High for Idle
r_TX_Done <= '0';
r_Clk_Count <= 0;
r_Bit_Index <= 0;

if i_TX_DV = '1' then


r_TX_Data <= i_TX_Byte;
r_SM_Main <= s_TX_Start_Bit;
else
r_SM_Main <= s_Idle;
end if;

-- Send out Start Bit. Start bit = 0


when s_TX_Start_Bit =>
o_TX_Active <= '1';
o_TX_Serial <= '0';

-- Wait g_CLKS_PER_BIT-1 clock cycles for start bit to finish


if r_Clk_Count < g_CLKS_PER_BIT-1 then
r_Clk_Count <= r_Clk_Count + 1;
r_SM_Main <= s_TX_Start_Bit;
else
r_Clk_Count <= 0;
r_SM_Main <= s_TX_Data_Bits;
end if;

-- Wait g_CLKS_PER_BIT-1 clock cycles for data bits to finish


when s_TX_Data_Bits =>
o_TX_Serial <= r_TX_Data(r_Bit_Index);

if r_Clk_Count < g_CLKS_PER_BIT-1 then


r_Clk_Count <= r_Clk_Count + 1;
r_SM_Main <= s_TX_Data_Bits;
else
r_Clk_Count <= 0;

-- Check if we have sent out all bits


if r_Bit_Index < 7 then
r_Bit_Index <= r_Bit_Index + 1;
r_SM_Main <= s_TX_Data_Bits;
else
r_Bit_Index <= 0;
r_SM_Main <= s_TX_Stop_Bit;
end if;
end if;

-- Send out Stop bit. Stop bit = 1


when s_TX_Stop_Bit =>
o_TX_Serial <= '1';

Page | 212 © ISI 2018 Ridha Ghayoula


-- Wait g_CLKS_PER_BIT-1 clock cycles for Stop bit to finish
if r_Clk_Count < g_CLKS_PER_BIT-1 then
r_Clk_Count <= r_Clk_Count + 1;
r_SM_Main <= s_TX_Stop_Bit;
else
r_TX_Done <= '1';
r_Clk_Count <= 0;
r_SM_Main <= s_Cleanup;
end if;

-- Stay here 1 clock


when s_Cleanup =>
o_TX_Active <= '0';
r_TX_Done <= '1';
r_SM_Main <= s_Idle;

when others =>


r_SM_Main <= s_Idle;

end case;
end if;
end process p_UART_TX;

o_TX_Done <= r_TX_Done;

end RTL;
10.4. VHDL Testbench (UART_TB.vhd):
----------------------------------------------------------------------
-- File Downloaded from http://www.nandland.com
----------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.ALL;
use ieee.numeric_std.all;

entity uart_tb is
end uart_tb;

architecture behave of uart_tb is

component uart_tx is
generic (
g_CLKS_PER_BIT : integer := 115 -- Needs to be set correctly
);
port (
i_clk : in std_logic;
i_tx_dv : in std_logic;
i_tx_byte : in std_logic_vector(7 downto 0);
o_tx_active : out std_logic;
o_tx_serial : out std_logic;
o_tx_done : out std_logic
);
end component uart_tx;

component uart_rx is
generic (
g_CLKS_PER_BIT : integer := 115 -- Needs to be set correctly

Page | 213 © ISI 2018 Ridha Ghayoula


);
port (
i_clk : in std_logic;
i_rx_serial : in std_logic;
o_rx_dv : out std_logic;
o_rx_byte : out std_logic_vector(7 downto 0)
);
end component uart_rx;

-- Test Bench uses a 10 MHz Clock


-- Want to interface to 115200 baud UART
-- 10000000 / 115200 = 87 Clocks Per Bit.
constant c_CLKS_PER_BIT : integer := 87;
constant c_BIT_PERIOD : time := 8680 ns;

signal r_CLOCK : std_logic := '0';


signal r_TX_DV : std_logic := '0';
signal r_TX_BYTE : std_logic_vector(7 downto 0) := (others => '0');
signal w_TX_SERIAL : std_logic;
signal w_TX_DONE : std_logic;
signal w_RX_DV : std_logic;
signal w_RX_BYTE : std_logic_vector(7 downto 0);
signal r_RX_SERIAL : std_logic := '1';

-- Low-level byte-write
procedure UART_WRITE_BYTE (
i_data_in : in std_logic_vector(7 downto 0);
signal o_serial : out std_logic) is
begin

-- Send Start Bit


o_serial <= '0';
wait for c_BIT_PERIOD;

-- Send Data Byte


for ii in 0 to 7 loop
o_serial <= i_data_in(ii);
wait for c_BIT_PERIOD;
end loop; -- ii

-- Send Stop Bit


o_serial <= '1';
wait for c_BIT_PERIOD;
end UART_WRITE_BYTE;

begin
-- Instantiate UART transmitter
UART_TX_INST : uart_tx
generic map (
g_CLKS_PER_BIT => c_CLKS_PER_BIT
)
port map (
i_clk => r_CLOCK,
i_tx_dv => r_TX_DV,
i_tx_byte => r_TX_BYTE,
o_tx_active => open,

Page | 214 © ISI 2018 Ridha Ghayoula


o_tx_serial => w_TX_SERIAL,
o_tx_done => w_TX_DONE
);

-- Instantiate UART Receiver


UART_RX_INST : uart_rx
generic map (
g_CLKS_PER_BIT => c_CLKS_PER_BIT
)
port map (
i_clk => r_CLOCK,
i_rx_serial => r_RX_SERIAL,
o_rx_dv => w_RX_DV,
o_rx_byte => w_RX_BYTE
);

r_CLOCK <= not r_CLOCK after 50 ns;

process is
begin

-- Tell the UART to send a command.


wait until rising_edge(r_CLOCK);

r_TX_DV <= '1';


r_TX_BYTE <= X"AB";
wait until rising_edge(r_CLOCK);
r_TX_DV <= '0';
wait until w_TX_DONE = '1';

-- Send a command to the UART


wait until rising_edge(r_CLOCK);
UART_WRITE_BYTE(X"3F", r_RX_SERIAL);
wait until rising_edge(r_CLOCK);

-- Check that the correct command was received


if w_RX_BYTE = X"3F" then
report "Test Passed - Correct Byte Received" severity note;
else
report "Test Failed - Incorrect Byte Received" severity note;
end if;
assert false report "Tests Complete" severity failure;
end process;
end behave;

Page | 215 © ISI 2018 Ridha Ghayoula


11
Wishbone dans les systemes embarqués

11.1. Introduction
Le bus Wishbone est un bus de matériel informatique libre destiné à permettre à différents circuits
intégrés de communiquer entre eux. L'objectif est de permettre une connexion de différents cœurs
entre eux dans un circuit. Un très grand nombre de conception open-source pour des CPUs, ou des
périphériques auxiliaires, ont été adaptés à l'interface Wishbone. Beaucoup peuvent être trouvés chez
OpenCores, une fondation qui essaie de rendre disponible le matériel open-source.

Wishbone a comme prétention d'être un "bus logique". Il ne spécifie donc pas d'information
électrique ou de topologie de bus. Ainsi, la spécification est écrite en termes de "signaux", cycles
d'horloge, et niveau logiques hauts et bas.

Cette ambigüité est intentionnelle. Wishbone est fait pour laisser les concepteurs combiner plusieurs
conceptions décrites en Verilog, VHDL ou un autre langage de description logique pour la
Conception assistée par ordinateur pour l'électronique. Wishbone fournit une façon standard pour
les concepteurs de combiner ces conceptions matérielles (appelées "cœurs" - core en anglais).
Wishbone est défini pour avoir des bus 8, 16, 32 bits. Tous les signaux sont synchrones à une
horloge unique mais les réponses des esclaves peuvent être générées de manière combinatoires pour
un maximum de performances. Wishbone permet l'addition d'un "tag bus" pour décrire les données.
Mais un reset, une simple lecture adressée ou son écriture, mouvement des blocs de données, et les
cycles indivisibles du bus cycles travaillent tous sans tags.

11.2. Topologies des bus Wishbone


Les bus Wishbone s'adaptent facilement aux topologies courantes comme le point-à-point,
plusieurs-à-plusieurs (i.e. le bus classique), hiérarchique, où même commutés. Pour des topologies
moins courantes, Wishbone requiert un contrôleur de bus ou arbitre, avec des composants gardant
la même interface.

Page | 216 © ISI 2018 Ridha Ghayoula


Figure 11.1 Interfaces maître et esclave du bus Wishbone

WISHBONE WISHBONE
MASTER SLAVE

RST_I: receives the reset output signal [RST_O] from the SYSCON.
CLK_I: receives the clock output signal [CLK_O] from the SYSCON.
ADR_I: receives the address from MASTER ADR_O: drives the address to the SLAVE
DAT_I: receives t he data
DAT_O: drives the data
WE_I, WE_O: Write Enable (active high)
STB_I, STB_O: Strobe (kind of chip select)
ACK_I, ACK_O: Acknowledge (active high)
CYC_I, CYC_O: Bus Cycle (active high)

Signaux de contrôle du bus Wishbone comparé aux autres bus standards pour System on Chip
Wishbone ⇒ Avalon
Wishbone Avalon Bus Description
cyc = !write_n or indique qu'un cycle valide du bus est en cours
!read_n
stb = chipselect indique un cycle de transfert de données valide
we = !write_n and indique si le bus courant local est un cycle d'écriture ou de lecture.
read_n Le signal estpositionné à 0 durant un cycle de lecture, et positionné
à 1 durant un cycle d'écriture.
ack = !waitrequest indique la terminaison d'un cycle normal de bus par l'esclave.

Page | 217 © ISI 2018 Ridha Ghayoula


Avalon ⇒ Wishbone
Avalon Bus Wishbone Description
chipselect = stb indique qu'un esclave est sélectionné.
write_n = !(cyc and we) indique que la requête du maître est pour une écriture dans un
esclave.
read_n = !(cyc indique que la requête du maitre est pour une lecture d'un esclave.
and !we)
waitrequest = !ack indique que le maître attend une requête de l'esclave.

Tag Types
Master Slave
Description TAG TYPE Associated with TAG TYPE Associated with
Address tag TGA_O() ADR_O TGA_I() ADR_I()
Data tag input TGD_I() DAT_I() TGD_I() DAT_I()
Data tag output TGD_O() DAT_O() TGD_O() DAT_O()
Cycle tag TGC_O() Bus Cycle TGC_I() Bus Cycle

 SINGLE READ cycle (Master Signals)  SINGLE WRITE cycle (Master Signals)

Le but de la FICHE TECHNIQUE WISHBONE est de promouvoir la réutilisation du design. Il


force l'expéditeur du noyau IP à documenter le fonctionnement de l'interface. Cela rend plus facile
pour une autre personne de réutiliser le noyau.
Table 11-1. WISHBONE DATASHEET for the 8-bit output port example.
Description Specification
General description: 8-bit SLAVE output port.
Supported cycles: SLAVE, READ/WRITE SLAVE, BLOCK
READ/WRITE SLAVE, RMW
Data port, size: 8-bit
Data port, granularity: 8-bit
Data port, maximum operand size: 8-bit
Data transfer ordering: Big endian and/or little endian
Data transfer sequencing: Undefined
Supported signal list and cross reference to equivalent Signal Name WISHBONE Equiv.
WISHBONE signals: ACK_O ACK_O
CLK_I CLK_I
DAT_I(7..0) DAT_I()
DAT_O(7..0) DAT_O()
RST_I RST_I
STB_I STB_I
WE_I WE_I

Page | 218 © ISI 2018 Ridha Ghayoula


8
WISHBONE INTERFACE

DAT_O(7..0)
8
DAT_I(7..0) D

PRT_O(7..0)
ACK_O

STB_I CE

WE_I
RST_I RESET
CLK_I

8-BIT D-TYPE REGISTER

Figure 11.2.Interface Wishbone

La Figure 11.3 montre un port de sortie WISHBONE SLAVE simple de 16 bits. Le Tableau A-2
montre la FICHE TECHNIQUE DE WISHBONE pour cette conception. Il est identique au port
8 bits illustré précédemment, sauf que le bus de données est plus large. En outre, ce port possède
une granularité 16 bits. Dans la section suivante, il sera comparé à un port de 16 bits avec une
granularité de 8 bits.
Table 11-1. WISHBONE DATASHEET for the 16-bit output port example.
Description Specification
General description: 16-bit SLAVE output port.
Supported cycles: SLAVE, READ/WRITE SLAVE, BLOCK
READ/WRITE SLAVE, RMW
Data port, size: 16-bit
Data port, granularity: 16-bit
Data port, maximum operand size: 16-bit
Data transfer ordering: Big endian and/or little endian
Data transfer sequencing: Undefined
Supported signal list and cross reference to equivalent Signal Name WISHBONE Equiv.
WISHBONE signals: ACK_O ACK_O
CLK_I CLK_I
DAT_I(15..0) DAT_I()

Page | 219 © ISI 2018 Ridha Ghayoula


DAT_O(15..0) DAT_O()
RST_I RST_I
STB_I STB_I
WE_I WE_I

16
WISHBONE INTERFACE

DAT_O(15..0)
16
DAT_I(15..0) D

PRT_O(15..0)
ACK_O

STB_I CE

WE_I
RST_I RESET
CLK_I

Figure 11.3. Port de sortie WISHBONE SLAVE 16 bits simple

 Port de sortie SLAVE 16 bits simple avec 8 bits


La Figure 11.4 montre un port de sortie WISHBONE SLAVE simple de 16 bits. Ce port a une
granularité de 8 bits, ce qui signifie que les données peuvent être transférées 8 ou 16 bits à la fois.

Page | 220 © ISI 2018 Ridha Ghayoula


16

WISHBONE INTERFACE

DAT_O(15..0)
15..8
DAT_I(15..0) D

ACK_O

STB_I CE
SEL_I(1)
WE_I
RST_I RESET
CLK_I

7..0
D
PRT_O(15..0)

CE

RESET

Figure 11.4. Port de sortie WISHBONE SLAVE 16 bits simple

Table 10.1. WISHBONE DATASHEET for the 8-bit


Description Specification
General description : 16-bit SLAVE output port.
Supported cycles : SLAVE, READ/WRITE SLAVE, BLOCK
READ/WRITE SLAVE, RMW
Data port, size: 16-bit
Data port, granularity: 8-bit
Data port, maximum operand size: 16-bit
Data transfer ordering: Big endian and/or little endian
Data transfer sequencing: Undefined
Signal Name WISHBONE Equiv.
ACK_O ACK_O
CLK_I CLK_I
Supported signal list and cross reference to equivalent DAT_I(15..0) DAT_I()
WISHBONE signals: DAT_O(15..0) DAT_O()
RST_I RST_I
STB_I STB_I
WE_I WE_I

Page | 221 © ISI 2018 Ridha Ghayoula


Page | 222 © ISI 2018 Ridha Ghayoula
16
WISHBONE INTERFACE

DAT_O(15..0)
16
DAT_I(15..0) D

PRT_O(15..0)
ACK_O

STB_I CE

WE_I
RST_I RESET
CLK_I

Figure 11.5. wishbone interface

11.3. Une conception simple avec le bus Wishbone


La fonctionnalité principale de ce composant est de permettre d'allumer une LED quand on appuie
sur un bouton. Lorsque le bouton est enfoncé, le bouton du composant envoie un signal
d'interruption à irq_mngr.
irq_mngr bascule un drapeau et envoie une interruption.
wishbone_wrapper, syscon et irq_mngr sont des standards ARMadeus-Wishbone qui viennent d'être
instanciés dans notre conception.
Le bouton et le led sont des composants esclaves simples que nous voulons intégrer dans le FPGA.
Tous ces composants sont connectés ensemble avec le composant intercon.

imx_addr(11..0)

Wb Wb
imx_data(15..0) led
wishbone
_wrapper led

imx_oe_n
imx_EB3_n intercon
imx_cs_n

Wb

button
gls_clk
ext_clk
rstgen_syscon

gls_reset Button
Wb

irq
TIN
irq_mnrg

Figure 11.6. conception simple avec le bus Wishbone (1)

Page | 223 © ISI 2018 Ridha Ghayoula


 Wishbone _wrapper

imx_addr(11..0)

Wb Wb
imx_data(15..0) led
wishbone
_wrapper led

imx_oe_n
imx_EB3_n intercon
imx_cs_n

Wb

gls_clk
button
ext_clk
rstgen_syscon

gls_reset Button
Wb

irq
TIN
irq_mnrg

Figure 11.7. conception simple avec le bus Wishbone (2)

Page | 224 © ISI 2018 Ridha Ghayoula


Page | 225 © ISI 2018 Ridha Ghayoula
 rstgen_syscon

Page | 226 © ISI 2018 Ridha Ghayoula


imx_addr(11..0)

Wb Wb
imx_data(15..0) led
wishbone
_wrapper led

imx_oe_n
imx_EB3_n intercon
imx_cs_n

Wb

gls_clk
button
ext_clk
rstgen_syscon

gls_reset Button
Wb

irq
TIN
irq_mnrg

Figure 11.8. conception simple avec le bus Wishbone(3)

Page | 227 © ISI 2018 Ridha Ghayoula


 intercon
L'intercon est un composant utilisé pour gérer les signaux entre les composants maître et
esclave Wishbone. Ce composant décode les adresses Wishbone-master et les envoie aux
composants Wishbone-Slave.

Page | 228 © ISI 2018 Ridha Ghayoula


imx_addr(11..0)

Wb Wb
imx_data(15..0) led
wishbone
_wrapper led

imx_oe_n
imx_EB3_n intercon
imx_cs_n

Wb

gls_clk
button
ext_clk
rstgen_syscon

gls_reset Button
Wb

irq
TIN
irq_mnrg

Figure 11.9. conception simple avec le bus Wishbone (4)

Page | 229 © ISI 2018 Ridha Ghayoula


architecture intercon_1 of intercon is
signal irq_mngr00_swb16_cs : std_logic := '0' ;
signal led0_swb16_cs : std_logic := '0' ;
signal button0_swb16_cs : std_logic := '0' ;
begin
-- Clock and Reset connection
irq_mngr00_gls_clk <= rstgen_syscon00_gls_clk;
irq_mngr00_gls_reset <= rstgen_syscon00_gls_reset;

led0_gls_reset <= rstgen_syscon00_gls_reset;


led0_gls_clk <= rstgen_syscon00_gls_clk;

button0_gls_reset <= rstgen_syscon00_gls_reset;


button0_gls_clk <= rstgen_syscon00_gls_clk;
wrapper_gls_reset <= rstgen_syscon00_gls_reset;
wrapper_gls_clk <= rstgen_syscon00_gls_clk;
-- Address decoding --

Page | 230 © ISI 2018 Ridha Ghayoula


-----------------------
irq_mngr00_wbs_s1_address <= wrapper_wbm_address(2 downto 1);
led0_wbs_add <= wrapper_wbm_address(1);
button0_wbs_add <= wrapper_wbm_address(1);
decodeproc : process(rstgen_syscon00_gls_clk,rstgen_syscon00_gls_reset)
begin
if rstgen_syscon00_gls_reset='1' then
irq_mngr00_swb16_cs <= '0';
led0_swb16_cs <= '0';
button0_swb16_cs <= '0';
elsif rising_edge(rstgen_syscon00_gls_clk) then
if wrapper_wbm_address(12 downto 3)="0000000000" and wrapper_wbm_strobe='1' then
irq_mngr00_swb16_cs <= '1';
else
irq_mngr00_swb16_cs <= '0';
end if;
if wrapper_wbm_address(12 downto 2)="00000000010" and wrapper_wbm_strobe='1' then
led0_swb16_cs <= '1';
else
led0_swb16_cs <= '0';
end if;
if wrapper_wbm_address(12 downto 2)="00000000011" and wrapper_wbm_strobe='1' then
button0_swb16_cs <= '1';
else
button0_swb16_cs <= '0';
end if;
end if;
end process decodeproc;
-----------------------------
-- Control signals to slave
-----------------------------
-- for irq_mngr00
irq_mngr00_wbs_s1_strobe <= (wrapper_wbm_strobe and irq_mngr00_swb16_cs );
irq_mngr00_wbs_s1_cycle <= (wrapper_wbm_cycle and irq_mngr00_swb16_cs );
irq_mngr00_wbs_s1_write <= (wrapper_wbm_write and irq_mngr00_swb16_cs );
irq_mngr00_wbs_s1_writedata <= wrapper_wbm_writedata when (wrapper_wbm_write and irq_mngr00_swb16_cs )
= '1' else (others => '0');
-- for led0
led0_wbs_strobe <= (wrapper_wbm_strobe and led0_swb16_cs );
led0_wbs_cycle <= (wrapper_wbm_cycle and led0_swb16_cs );
led0_wbs_write <= (wrapper_wbm_write and led0_swb16_cs );
led0_wbs_writedata <= wrapper_wbm_writedata
when (wrapper_wbm_write and led0_swb16_cs ) = '1'
else (others => '0');
-- for button0
button0_wbs_strobe <= (wrapper_wbm_strobe and button0_swb16_cs );

Page | 231 © ISI 2018 Ridha Ghayoula


button0_wbs_cycle <= (wrapper_wbm_cycle and button0_swb16_cs );
button0_wbs_write <= '0';
-------------------------------
-- Control signal for master --
-------------------------------
wrapper_wbm_readdata <= irq_mngr00_wbs_s1_readdata when irq_mngr00_swb16_cs='1' else led0_wbs_readdata
when led0_swb16_cs='1' else
button0_wbs_readdata when button0_swb16_cs='1' else
(others => '0');
wrapper_wbm_ack <= (irq_mngr00_wbs_s1_ack and irq_mngr00_swb16_cs) or (led0_wbs_ack and led0_swb16_cs)
or (button0_wbs_ack and button0_swb16_cs);

end architecture intercon_1;


 led
Ce composant est un simple port de sortie esclave Wishbone 16 bits
C'est un registre simple, qui peut être lu et écrit. La LED est contrôlée avec la broche de
registre 0.

Les deux registres sont:


registre Adresse Fonction
LED Ox00 Write '1' in LSB to shutdown LED
id Ox02 read identification number

imx_addr(11..0)

Wb Wb
imx_data(15..0) led
wishbone
_wrapper led

imx_oe_n
imx_EB3_n intercon
imx_cs_n

Wb

gls_clk
button
ext_clk
rstgen_syscon

gls_reset Button
Wb

irq
TIN
irq_mnrg

Page | 232 © ISI 2018 Ridha Ghayoula


Page | 233 © ISI 2018 Ridha Ghayoula
Page | 234 © ISI 2018 Ridha Ghayoula
 Button
Composant button, est comme LED mais en lecture seule et avec un détecteur de bord.

imx_addr(11..0)

Wb Wb
imx_data(15..0) led
wishbone
_wrapper led

imx_oe_n
imx_EB3_n intercon
imx_cs_n

Wb

button
gls_clk
ext_clk
rstgen_syscon

gls_reset Button
Wb

irq
TIN
irq_mnrg

Page | 235 © ISI 2018 Ridha Ghayoula


Page | 236 © ISI 2018 Ridha Ghayoula
 irq_mnrg
Certains composants génèrent des interruptions, irq_mnrg est utilisé pour multiplexer ces
interruptions. L'irq_mngr peut gérer jusqu'à 16 interruptions internes.

Le composant irq_mnrg a des registres d'arbre, un pour activer les interruptions, un pour
les alarmes drapeaux / acquittement et un registre d’identification :

Page | 237 © ISI 2018 Ridha Ghayoula


imx_addr(11..0)

Wb Wb
imx_data(15..0) led
wishbone
_wrapper led

imx_oe_n
imx_EB3_n intercon
imx_cs_n

Wb

gls_clk
button
ext_clk
rstgen_syscon

gls_reset
Button
Wb

irq
TIN
irq_mnrg

Page | 238 © ISI 2018 Ridha Ghayoula


Page | 239 © ISI 2018 Ridha Ghayoula
Page | 240 © ISI 2018 Ridha Ghayoula
Page | 241 © ISI 2018 Ridha Ghayoula
12 Le Bus Serial Port Interface SPI
12.1. Introduction
La sophistication et la complexité des appareils grand public ne permet plus l'échange entre
composants électroniques par liaisons parallèles, ces liaisons devenaient de plus en plus nombreuses
et encombrantes. Dans ces systèmes à base de microcontrôleurs (téléphones mobiles...), les échanges
de données entre les composants se font maintenant avec des bus série. Dans le but de minimiser
ces liaisons, et par conséquent d’en augmenter la fiabilité, a été créé le bus série SPI (Synchronous
Peripheral Interface), initialement développé par Motorola.
D’autres fabricants (Microchip, Atmel, Texas Instrument...) ont adopté pour ce type de liaison et de
nombreux composants sont apparus (mémoires, capteurs, microcontrôleurs ...)
Une liaison SPI s’établit entre un maître, Master (habituellement un microcontrôleur) et un esclave,
Slave (convertisseur, registre à décalage, mémoire, microcontrôleur...) et permet l’échange, en série,
de données. L’échange de données peut s’effectuer dans les deux sens (Full duplex). Cette liaison,
synchrone, s’effectue par l’intermédiaire de trois fils notés MOSI (Master Output Slave Input),
MISO (Master Input Slave Output) et SCK (SPI Serial Clock).
La fréquence de l’horloge SCK est fixé par le maître et est programmable
Une liaison SPI (pour Serial Peripheral Interface) est un bus de données série synchrone baptisé ainsi
par Motorola, qui opère en mode full-duplex. Les circuits communiquent selon un schéma maître-
esclaves, où le maître contrôle la communication. Plusieurs esclaves peuvent coexister sur un même
bus, dans ce cas, la sélection du destinataire se fait par une ligne dédiée entre le maître et l'esclave
appelée Slave Select (SS).

SCLK SCLK

SPI MOSI MOSI SPI


Master MISI MISI Slave
SS SS

Figure 12.1. Liaison SPI: un maître et un esclave

Page | 242 © ISI 2018 Ridha Ghayoula


SPI SCLK SCLK
SPI
Master Slave
MOSI MOSI

MISI MISI

7 0 SS SS 7 0

Figure 12.2. Liaison SPI: un maître et un esclave

Initialement développé par Bus synchrone série à haut


MOTOROLA pour débit, multipoint ( 1 maître / 1
les microcontrôleurs 68xx ou plusieurs esclaves)

Pas de contrôle Transmission en "FULL


physique de données
Bus SPI DUPLEX"

Protocole simple Lignes de communication


. Pas d’adressage (sélection unidirectionnelles
de l’esclave). Transmission à courte distance.

Figure 12.3. La philosophie du bus SPI

12.2. Interface
Les données échangées sont des octets. La transmission s’effectue sur 2 fils monodirectionnels
(nommés MOSI, MISO). Une horloge indépendante fixée par le maître synchroniseles échanges (en
général sur front).
La fréquence de l’horloge de transmission est comprise entre 1Mhz et 20Mhz (selon les
performances des circuits reliés au bus). Il n’y a pas d’adressage des esclaves (comme sur un bus i2C
par exemple). L’esclavedevient actif au moyen d’une ligne de sélection de boîtierdédiée
(généralement active à l'état bas). La ligne est constituée de 3fils auxquels il faut ajouter les fils de
sélection d'esclave.

Liaison SPI avec un maître et trois esclaves

Le bus SPI utilise quatre signaux logiques :

 SCLK — Serial Clock, Horloge (généré par le maître)


 MOSI — Master Output, Slave Input (généré par le maître)
 MISO — Master Input, Slave Output (généré par l'esclave)
 SS — Slave Select, Actif à l'état bas (généré par le maître)

Page | 243 © ISI 2018 Ridha Ghayoula


Il existe d'autres noms qui sont souvent utilisés :

 SCK — Horloge (généré par le maître)


 SDI, DI, SI — Serial Data IN, MOSI
 SDO, DO, SO — Serial Data OUT, MISO
 nCS, CS, nSS, STE, CSN— SS

Dans le cas de la convention de nommage SDI/SDO, le SDO du maître doit-être relié au SDI de
l'esclave et vice versa. Pour éviter les confusions au moment du câblage, il est donc souvent
recommandé d'utiliser les dénominations MISO-MOSI qui évitent une certaine ambiguïté.

SCLK SCLK

SPI MOSI MOSI SPI


Master MISI MISI Slave
SS SS

SCLK

MOSI SPI
MISI Slave
SS

SCLK

MOSI SPI
MISI Slave
SS

Figure 12.4. Liaison SPI: un maître et trois esclaves

12.3. Fonctionnement
Suivant CPOL (ClockPolarity) et CPHA (ClockPhase). Il existe donc 4 modesde transmission
différents (voir tableau ci-dessous). Pour une transmission correcte il faut que ces paramètres soient
réglés de la même manière pour tous les composants reliés au bus.

Mode SPI CPOL CPHA


0 0 0
1 0 1
2 1 0
3 1 1
Le CPOL détermine si au repos l’horloge est au niveau BAS (CPOL=0) ou HAUT (CPOL=1).
Le CPHA détermine à quel front de l’horloge les données sont transmises. CPHA=0 les données
sont valides au premier front d’horloge, CPHA=1 elles sont valides au deuxième front.

Page | 244 © ISI 2018 Ridha Ghayoula


Pour CPOL=1, au repos, l’horloge est sur le niveau HAUT; le premier front est donc un front
descendant.
La polarité de l’horloge n’ayant pas d’influence sur le moment où le premier bit de données est
valide elle n’a pas d’effet sur le format du transfert de données (voir figure ci-dessous).

Lorsque CPHA =1, les données sont réceptionnées avec le deuxième front du signal d’horloge.
Pour CPOL=0, au repos, l’horloge est auniveau BAS et monte au niveau HAUT après le premier
front, le deuxième front est donc un front descendant.
Pour CPOL=1, au repos, l’horloge est au niveau HAUT et descend au niveau BAS après le premier
front; le deuxième front est donc un front montant.

Page | 245 © ISI 2018 Ridha Ghayoula


Figure 12.5. Oscillogrammes des signaux électriquesSPI

Avantages et Inconvénients du bus SPI


Avantages Inconvénients
Communication en Full Duplex Pas d'adressage possible
"Indépendant" du nombre de bits à transmettre Utilisation sur très courte distance (même carte)
Pas de collision possible Nécessite plus de fils que I²C
Les esclaves utilisent l'horloge du maître pas de Pas d'acquittement (le maître ne sait pas s’il est
problème de précision de quartz écouté)
Beaucoup plus rapide que I²C en mode standard ---
Possibilité de configuration à plusieurs maîtres ---

12.3. Synthese VHDL d'un Bus Serial Port Interface SPI


 FSM_SPI.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.std_logic_unsigned.ALL;
entity fsm_spi is
Port ( clk : in STD_LOGIC;
clr : in std_logic;
data : in STD_LOGIC_VECTOR(7 downto 0);
start : in STD_LOGIC;
done : out STD_LOGIC;
ss : out STD_LOGIC;
mosi : out STD_LOGIC;
sck : out STD_LOGIC);
end fsm_spi;
architecture fsm_spi of fsm_spi is
signal counter: STD_LOGIC_VECTOR (3 downto 0);

Page | 246 © ISI 2018 Ridha Ghayoula


signal sclk: std_logic;
signal temp: std_logic_vector(7 downto 0);
type state_type is (initial, copy,clk_gen,shifting,completed);
signal state: state_type;
attribute INIT: STRING;
attribute INIT
OF state: SIGNAL IS "initial";
begin
process (clk, clr)
begin
if clr = '1' then
done <= '0';
ss <= '1';
mosi <= '0';
sck <= '1';
counter <= "0000";
state <= initial;
elsif clk'event and clk = '1' then
case state is
when initial =>
if start = '0' then
state <= completed;
else
counter <= "0000";
state <= copy;
ss <= '0';
end if;
sclk <= '1';
done <= '0';
when copy =>
temp <= data;
state <= clk_gen;
when clk_gen =>
sclk <= not sclk;
state <= shifting;
when shifting =>
if counter = "1000" then
done <= '1';
state <= completed;
else
counter <= counter + '1';
state <= clk_gen;
end if;

mosi <= temp (7);


temp <= (temp (6 downto 0) & '0');
sclk <= not sclk;

when completed =>


ss <= '1';
state <= initial;

when others =>


state <= initial;
end case;
sck <= sclk;
end if;

Page | 247 © ISI 2018 Ridha Ghayoula


end process;
end fsm_spi;

Figure 12.6. Simulatations


 FSM_CTRL.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.std_logic_unsigned.ALL;
entity fsm_ctrl is
Port ( clr : in STD_LOGIC;
clk : in STD_LOGIC;
address : buffer STD_LOGIC_vector(10 downto 0);
data : in STD_LOGIC_vector(7 downto 0);
start : out STD_LOGIC;
done : in STD_LOGIC
);
end fsm_ctrl;
architecture fsm_ctrl of fsm_ctrl is
signal q : std_logic_vector(14 downto 0);
type state_type is (initial,checking,send,delay,command,parameters,completed);
signal state: state_type;
attribute INIT: STRING;
attribute INIT OF state:
SIGNAL IS "initial";
begin
process (clk, clr)
begin
if clr = '1' then
start <= '0';
address <= (others => '0');
state <= initial;
q <= (others => '0');
elsif clk'event and clk = '1' then
case state is

when initial =>


address <= (others => '0');
start <= '0';
state <= checking;
when checking =>
if data = X"00" then --data is checking.
start <= '0';
address <= (others =>'0');
--if address‟s value won‟t be „0‟, when data‟s

Page | 248 © ISI 2018 Ridha Ghayoula


--value "00" system will wait for reset signal
-- to restart.
state <= checking;
elsif data = X"1B" then -- escape squence checking.
state <= command;
else
start <= '1';
state <= send;
end if;
when send =>
if done = '1' then
start <= '0';
address <= address + '1';
q<= (others => '0'); --if delay is not necessary, state should return
--to state “checking”at here.
state <= delay;
else
state <= send;
end if;
when delay => --delay state for characters send.
if q = "111111111111111" then
state <= checking;
else
q <= q + '1';
state <= delay;
end if;
when command =>
start <= '1';
case data is--commands list for understand the escape squence ending.
When X"48" => state <= completed;-- H command
When X"73" => state <= completed; --s command
When X"75" => state <= completed; -- u command
When X"6A" => state <= completed; -- j command
When X"4B" => state <= completed; -- K command
When X"4E" => state <= completed; -- N command
When X"40" => state <= completed ; -- @ command
When X"41" => state <= completed; -- A command
When X"2A" => state <= completed; -- * command
When X"65" => state <= completed; -- e command
When X"68" => state <= completed; -- h command
When X"63" => state <= completed; -- c command
When X"61" => state <= completed; -- a command
When X"62" => state <= completed; -- b command
When X"70" => state <= completed; -- p command
When X"74" => state <= completed; -- t command
When X"6C" => state <= completed; -- l command
When X"64" => state <= completed; -- d command
When X"6D" => state <= completed; -- m command
When X"77" => state <= completed; -- w command
When X"6E" => state <= completed; -- n command
When X"6F" => state <= completed; -- o command
When
others =>
state <= parameters; -- while command co mes, continue to read and write
-- escape squences
end case;
when parameters =>

Page | 249 © ISI 2018 Ridha Ghayoula


if done = '1' then
start <= '0';
address <= address + '1';
state <= command;
else
state <= parameters;
end
if;
when completed =>
if done = '1' then
start <= '0';
address <= address + '1';
state <= checking;
else
state <= completed;
end if;
when others =>
state <= initial;
end case;
end if;
end process;
end fsm_ctrl;

Figure 12.7. Simulation of FSM_CTRL module character sending followed by escape sequences

Figure 12.8. Simulation of FSM_CTRL module invalid character


 ROM_Memory.v
`timescale 1ns / 1ps
module ROM_Memory(data,address);
input [10:0] address;
output [7:0] data;
reg [7:0] ROM [0:1034];
initial begin
$readmemh("ROM.txt",ROM);

Page | 250 © ISI 2018 Ridha Ghayoula


end
assign data = ROM[address];
endmodule

 CLOCK_DIV.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.std_logic_unsigned.ALL;
entity clock_div is
Port ( clr : in STD_LOGIC;
mclk : in STD_LOGIC;
clk_out : out STD_LOGIC);
end clock_div;

architecture clock_div of clock_div is


signal q: std_logic_vector(7 downto 0);
begin
process(mclk, clr)
begin
if clr = '1' then
q <= (others => '0');
clk_out <= '0';
elsif mclk'event and mclk = '1' then
if q = "11111111" then
q <= (others => '0');
else
q <= q + '1';
end if;
clk_out <= q(7);
end
if;
end process;
end clock_div;

Page | 251 © ISI 2018 Ridha Ghayoula


13
Le Bus I2C Inter Integrated Circuit
13.1. Introduction

Le bus I2C (Inter Integrated Circuit Bus) est le bus historique, développé par Philips pour les
applications de domotique et d'électronique domestique au début des années 80, notamment pour
permettre de relier facilement à un microprocesseur les différents circuits d'un téléviseur moderne.

C'est le bus qui a émergé de la guerre des standards lancée par tous les acteurs du monde
électronique. Ainsi, dans votre téléviseur, tous les ensembles sont sur un bus I2C (Récepteur
télécommande, réglages ampli BF, tuner, horloge, gestion péritel…)

Il existe d'innombrables périphériques exploitant ce bus, il est même implantable par logiciel dans
n'importe lequel des microcontrôleurs. Le poids de l'industrie de l'électronique grand public a
imposé des prix très bas aux nombreux composants.

13. 2. Caractéristiques
Le bus I2C permet de faire communiquer entre eux des composants électroniques très divers grâce à
seulement trois fils :

 Un signal de donnée (SDA),


 Un signal d'horloge (SCL),
 Un signal de référence électrique (Masse).

Ceci permet de réaliser des équipements ayants des fonctionnalités très puissantes (En apportant
toute la puissance des systèmes microprogrammés) et conservant un circuit imprimé très simple, par
rapport un schéma classique (8 bits de données, 16 bits d'adresse + les bits de contrôle).

Les données sont transmises en série à 100Kbits/s en mode standard et jusqu'à 400Kbits/s en
mode rapide. Ce qui ouvre la porte de cette technologie à toutes les applications où la vitesse n'est
pas primordiale.

De nombreux fabricants ayant adopté le système, la variété des circuits disponibles disposant d'un
port I2C est énorme : Ports d'E/S bidirectionnels, Convertisseurs A/N et N/A, mémoires (RAM,
EPREM, EEPROM, etc.…), Circuits Audio (Egaliseur, Contrôle de volume, ...) et autre drivers
(LED , LCD , ...).

Page | 252 © ISI 2018 Ridha Ghayoula


Le nombre de composants qu'il est ainsi possible de relier est essentiellement limité par la charge
capacitive des lignes SDA et SCL : 400 pF

OxXX Ox2E Oxb8

+5v

Master_01 Slave_02 Slave_03

I2C
SDA

BUS SCL

Slave_01 Master_02

Ox34 OxXX

Figure 13.1. Bus I2C

13.3. Le protocole I2C


Le protocole I2C définit la succession des états logiques possibles sur SDA et SCL, et la façon
dont doivent réagir les circuits en cas de conflits.

13.3.1. La prise de contrôle du bus

Pour prendre le contrôle du bus, il faut que celui-ci soit au repos (SDA et SCL à '1'). Pour
transmettre des données sur le bus, il faut donc surveiller deux conditions particulières :

 La condition de départ. (SDA passe à '0' alors que SCL reste à '1’)
 La condition d'arrêt. (SDA passe à '1' alors que SCL reste à '1’)

Lorsqu'un circuit, après avoir vérifié que le bus est libre, prend le contrôle de celui-ci, il en devient le
maître. C'est lui qui génère le signal d'horloge.

Arret
Départ
SDA
D7 D6 D5 D4 D3 D2 D1 D0 ACK

SCL

Figure 13.2. La prise de contrôle du bus

Page | 253 © ISI 2018 Ridha Ghayoula


13.3.2. La transmission d'un octet

 Après avoir imposé la condition de départ, le maître applique sur SDA le bit de poids fort
D7.
 Il valide ensuite la donnée en appliquant pendant un instant un niveau '1' sur la ligne SCL.
 Lorsque SCL revient à '0', il recommence l'opération jusqu'à ce que l'octet complet soit
transmis.
 Il envoie alors un bit ACK à '1' tout en scrutant l'état réel de SDA.
 L'esclave doit alors imposer un niveau '0' pour signaler au maître que la transmission s'est
effectuée correctement.
 Les sorties de chacun étant à collecteurs ouverts, le maître voie le '0' et peut alors passer à la
suite.

SCL

SDA

D7 D6 D5 D4 D3 D2 D1 D0 ACK

SDAE
ACK

SDAR

D7 D6FigureD5
13.3. D4 D3 d'un D2
Transmission octet D1 D0 ACK

Dans cet exemple :

 SCL : Horloge imposée par le maître.


 SDAM : Niveaux de SDA imposés par le maître.
 SDAE : Niveaux de SDA imposés par l'esclave.
 SDAR : Niveaux de SDA réels résultants.

13.3.3. La transmission d'une adresse

Le nombre de composants qu'il est possible de connecter sur un bus I2C étant largement supérieur à
deux, il est nécessaire de définir pour chacun une adresse unique.

L'adresse d'un circuit, codée sur sept bits, est défini d'une part par son type et d'autre part par l'état
appliqué à un certain nombre de ces broches. Cette adresse est transmise sous la forme d'un octet au
format particulier.

SDA

A6 A5 A4 A3 A2 A0 R/W ACK

Page | 254 © ISI 2018 Ridha Ghayoula


Figure 13.4. Transmission d'une adresse

On remarque ici que les bits D7 à D1 représentent les adresse A6 à A0, et que le bit D0 et remplacé
par le bit de R/W qui permet au maître de signaler s'il veut lire ou écrire une donnée. Le bit
d'acquittement ACK fonctionne comme pour une donnée, ceci permet au maître de vérifier si
l'esclave est disponible.

Note 1: Cas particulier des mémoires :

L'espace adressable d'un circuit de mémoire étant sensiblement plus grand que la plupart des
autres types de circuits, l'adresse d'une information y est codée sur deux octets ou plus. Le premier
représente toujours l'adresse du circuit, et les suivants l'adresse interne de la mémoire.

Note 2: Les adresses réservées.

Les adresses 00000XXX et 111111XX sont réservés à des modes de fonctionnement


particuliers.

13.3.4. Ecriture d'une donnée

L'écriture d'une donnée par le maître ne pose pas de problème particulier :

SCL

SDAM
A6 A5 A4 A3 A2 A1 A0 A D7 D6 D5 D4 D3 D2 D1 D0 A
R/W C C
K K

SDAE ACK ACK

SDAR
A6 A5 A4 A3 A2 A1 A0 A D7 D6 D5 D4 D3 D2 D1 D0 A
R/W C C
K K

Figure 13.5. Ecriture d'une donnée

Note : Cas particulier d'utilisation d'ACK :

L'écriture d'un octet dans certains composants (Mémoires, microcontrôleur, ... ) peut prendre un
certain temps. Il est donc possible que le maître soit obligé d'attendre l'acquittement ACK avant de
passer à la suite.

Page | 255 © ISI 2018 Ridha Ghayoula


13.3.5. Lecture d'une donnée

La lecture d'une donnée par le maître se caractérise par l'utilisation spéciale qui faite du bit ACK.
Après la lecture d'un octet, le maître positionne ACK à '0' s'il veut lire la donnée suivante ( cas d'une
mémoire par exemple ) ou à '1' la cas échéant. Il envoie alors la condition d'arrêt

SCL

SDAM
A6 A5 A4 A3 A2 A1 A0 A A
R/W C C
K K

SDAE ACK ACK


D7 D6 D5 D4 D3 D2 D1 D0

SDAR
A6 A5 A4 A3 A2 A1 A0 A D7 D6 D5 D4 D3 D2 D1 D0 A
R/W C C
K K

Figure 13.5. Lecture d'une donnée

13.4. La gestion des conflits


13.4.1. Mise en situation

La structure même du bus I2C a été conçu pour pouvoir y accueillir plusieurs maîtres. Se pose alors
le problème commun à tous les réseaux utilisant un canal de communication unique : la prise de parole.

En effet, chaque maître pouvant prendre possession du bus dès que celui-ci est libre, il existe la
possibilité de que deux maîtres prennent la parole en même temps. Si cela ne pose pas de problème
sur le plan électrique grâce à l'utilisation de collecteurs ouverts, il faut pouvoir détecter cet état de
fait pour éviter la corruption des données transmises.

13.4.2. Principe

Comme nous l'avons vu précédemment, pour prendre le contrôle du bus, un maître potentiel doit
d'abord vérifier que celui-ci soit libre, et qu'une condition d'arrêt ait bien été envoyée depuis au
moins 4.7 µs. Mais il reste la possibilité que plusieurs maîtres prennent le contrôle du bus
simultanément.

Chaque circuit vérifie en permanence l'état des lignes SDA et SCL, y compris lorsqu'ils sont eux
même en train d'envoyer des données. On distingue alors plusieurs cas :

(1) Les différents maîtres envoient les mêmes données au même moment :

 Les données ne sont pas corrompues, la transmission s'effectue normalement, comme si un


seul maître avait parlé. Ce cas est rare.

Page | 256 © ISI 2018 Ridha Ghayoula


(2) Un maître impose un '0' sur le bus :

 Il relira forcément '0' et continuera à transmettre. Il ne peut pas alors détecter un éventuel
conflit.

(3) Un maître cherche à appliquer un '1' sur le bus :

 S’il ne relit pas un niveau '1', c'est qu'un autre maître a pris la parole en même temps. Le
premier perd alors immédiatement le contrôle du bus, pour ne pas perturber la transmission
du second. Il continue néanmoins à lire les données au cas celles-ci lui auraient été destinées.

13.4.3. Analyse :
Le premier octet est transmis normalement car les deux maîtres imposent les mêmes données. (Cas
n°1). Le bit ACK est mis à '0' par l'esclave.

Lors du deuxième octet, le maître n°2 cherche à imposer un '1' (SDA2), mais relit un '0' (SDAR), il
perd alors le contrôle du bus et devient esclave (Cas n°3). Il reprendra le contrôle du bus, lorsque
celui-ci sera de nouveau libre.

Le maître n°1 ne voit pas le conflit et continue à transmettre normalement. (Cas n°2)

Au total, l'esclave à reçu les données du maître n°1 sans erreurs et le conflit est passé inaperçu.

13.4.4. Les nouvelles caractéristiques

Afin de compenser quelques lacunes des premières spécifications du bus I2C (qui datent de 1982),
quelques nouvelles améliorations ont été apportées à partir de 1993 :

 Le mode rapide : Le bus à désormais la capacité de transmettre des données jusqu'à une
vitesse de 400 Kbit/s.
 Des entrées à triggers de Schmitt : Afin de limiter la sensibilité au bruit.
 La mise en haute impédance d'un circuit non alimenté : Ceci évite de bloquer le bus si
un périphérique n'est pas alimenté.
 Extension à 10 bits de l'adressage des circuits répartis sur 2 octets de la manière
suivante :

SDA
1 1 1 1 1 A9 A8 A A7 A6 A5 A4 A3 A2 A1 A0 A
R/W C C
K K

Remarque :

En 1998, le mode haut débit porte la vitesse maximum du bus I2C à 3.4 Mb/s. Les marges
de bruit ont aussi été modifiées pour permettre de relier des circuits faible consommation
(alimentation 2V)

Page | 257 © ISI 2018 Ridha Ghayoula


13.5. Les adresses réservées

Les adresses 0000 0xxx ne sont pas utilisées pour l'adressage de composants. Elles ont été réservées
par Philips pour effectuer certaines fonctions spéciales.

13.5.1. Adresses d'appel général

Adresse: 0000 0000.

Après l'émission d'un appel général, les circuits ayant la capacité de traiter ce genre d'appel émettent
un acquittement.

Le deuxième octet permet de définir le contenu de l'appel :

 0000 0110 : RESET. Remet tout les registres de circuits connectés dans leur état initial (Mise
sous tension ). Les circuits qui le permettent rechargent leur adresse d'esclave.
 0000 0010 : Les circuits qui le permettent rechargent leur adresse d'esclave.
 0000 0100 : Les circuits définissant leur adresse de façon matériel réinitialisent leur adresse
d'esclave.
 0000 0000 : Interdit
 xxxx xxx1 : Cette commande joue le rôle d'interruption. xxxx xxx peut être l'adresse du
circuit qui a généré l'interruption.

13.5.2. Octet de START

Adresse : 0000 0001.

Cet octet est utilisé pour synchroniser les périphériques lents avec les périphériques rapides.
13.5.3. Début d'adresse CBUS
Adresse : 0000 001x.

L'émission de cet octet permet de rendre sourd tout les circuits I2C présents sur le bus. A partir de
ce moment, on peut transmettre ce que l'on désire sur le bus, en utilisant par exemple un autre
protocole. Le bus repasse en mode normal lors de la réception d'une condition d'arrêt.

13.5.4. Autres

Adresses : 0000 0110 à 0000 1111.

Ces octets ne sont pas définis et sont ignoré par les circuits I2C. Ils peuvent être utilisé pour
débugger un réseau multimaster.

Page | 258 © ISI 2018 Ridha Ghayoula


13.6. Exemples

program Eeprom_Test;
var EE_adr, EE_data, k : byte;
jj : word;
begin
I2C_Init(100000); // Initialize full master mode
TRISD := 0; // PORTD is output
PORTD := $FF; // Initialize PORTD
I2C_Start; // Issue I2C start signal
I2C_Wr($A2); // Send byte via I2C(command to 24cO2)
EE_adr := 2;
I2C_Wr(EE_adr); // Send byte(address for EEPROM)
EE_data := $AA;
I2C_Wr(EE_data); // Send data(data that will be written)
I2C_Stop; // Issue I2C stop signal
for jj := 0 to 65500 do nop; // Pause while EEPROM writes data
I2C_Start; // Issue I2C start signal
I2C_Wr($A2); // Send byte via I2C
EE_adr := 2;
I2C_Wr(EE_adr); // Send byte(address for EEPROM)
I2C_Repeated_Start; // Issue I2C signal repeated start
I2C_Wr($A3); // Send byte (request data from EEPROM)
k := I2C_Rd(1); // Read the data
I2C_Stop; // Issue I2C stop signal
PORTD := k; // Show data on PORTD

Page | 259 © ISI 2018 Ridha Ghayoula


while true do nop; // Endless loop

end.

-- Simple I2C controller


--
-- 1) No multimaster
-- 2) No slave mode
-- 3) No fifo's
-- notes:
-- Every command is acknowledged. Do not set a new command before previous is acknowledged.
-- Dout is available 1 clock cycle later as cmd_ack
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
package I2C is
component simple_i2c is
port (
clk : in std_logic;
ena : in std_logic;
nReset : in std_logic;

clk_cnt : in unsigned(7 downto 0); -- 4x SCL

-- input signals
start,
stop,
read,
write,
ack_in : std_logic;
Din : in std_logic_vector(7 downto 0);

-- output signals
cmd_ack : out std_logic;
ack_out : out std_logic;
Dout : out std_logic_vector(7 downto 0);
-- i2c signals
SCL : inout std_logic;
SDA : inout std_logic
);
end component simple_i2c;
end package I2C;

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity simple_i2c is
port (
clk : in std_logic;
ena : in std_logic;
nReset : in std_logic;

clk_cnt : in unsigned(7 downto 0); -- 4x SCL

-- input signals
start,

Page | 260 © ISI 2018 Ridha Ghayoula


stop,
read,
write,
ack_in : std_logic;
Din : in std_logic_vector(7 downto 0);
-- output signals
cmd_ack : out std_logic;
ack_out : out std_logic;
Dout : out std_logic_vector(7 downto 0);
-- i2c signals
SCL : inout std_logic;
SDA : inout std_logic
);
End entity simple_i2c;

architecture structural of simple_i2c is


component i2c_core is
port (
clk : in std_logic;
nReset : in std_logic;
clk_cnt : in unsigned(7 downto 0);
cmd : in std_logic_vector(2 downto 0);
cmd_ack : out std_logic;
busy : out std_logic;
Din : in std_logic;
Dout : out std_logic;
SCL : inout std_logic;
SDA : inout std_logic
);
end component i2c_core;
-- commands for i2c_core
constant CMD_NOP : std_logic_vector(2 downto 0) := "000";
constant CMD_START : std_logic_vector(2 downto 0) := "010";
constant CMD_STOP : std_logic_vector(2 downto 0) := "011";
constant CMD_READ : std_logic_vector(2 downto 0) := "100";
constant CMD_WRITE : std_logic_vector(2 downto 0) := "101";
-- signals for i2c_core
signal core_cmd : std_logic_vector(2 downto 0);
signal core_ack, core_busy, core_txd, core_rxd : std_logic;
-- signals for shift register
signal sr : std_logic_vector(7 downto 0); -- 8bit shift register
signal shift, ld : std_logic;
-- signals for state machine
signal go, host_ack : std_logic;
begin
-- hookup i2c core
u1: i2c_core port map (clk, nReset, clk_cnt, core_cmd, core_ack, core_busy, core_txd, core_rxd, SCL, SDA);
-- generate host-command-acknowledge
cmd_ack <= host_ack;
-- generate go-signal
go <= (read or write) and not host_ack;
-- assign Dout output to shift-register
Dout <= sr;
-- assign ack_out output to core_rxd (contains last received bit)
ack_out <= core_rxd;
-- generate shift register
shift_register: process(clk)

Page | 261 © ISI 2018 Ridha Ghayoula


begin
if (clk'event and clk = '1') then
if (ld = '1') then
sr <= din;
elsif (shift = '1') then
sr <= (sr(6 downto 0) & core_rxd);
end if;
end if;
end process shift_register;
-- state machine
statemachine : block
type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop);
signal state : states;
signal dcnt : unsigned(2 downto 0);
begin
--
-- command interpreter, translate complex commands into simpler I2C commands
--
nxt_state_decoder: process(clk, nReset, state)
variable nxt_state : states;
variable idcnt : unsigned(2 downto 0);
variable ihost_ack : std_logic;
variable icore_cmd : std_logic_vector(2 downto 0);
variable icore_txd : std_logic;
variable ishift, iload : std_logic;
begin
-- 8 databits (1byte) of data to shift-in/out
idcnt := dcnt;
-- no acknowledge (until command complete)
ihost_ack := '0';
icore_txd := core_txd;
-- keep current command to i2c_core
icore_cmd := core_cmd;
-- no shifting or loading of shift-register
ishift := '0';
iload := '0';
-- keep current state;
nxt_state := state;
case state is
when st_idle =>
if (go = '1') then
if (start = '1') then
nxt_state := st_start;
icore_cmd := CMD_START;
elsif (read = '1') then
nxt_state := st_read;
icore_cmd := CMD_READ;
idcnt := "111";
else
nxt_state := st_write;
icore_cmd := CMD_WRITE;
idcnt := "111";
iload := '1';
end if;
end if;

when st_start =>

Page | 262 © ISI 2018 Ridha Ghayoula


if (core_ack = '1') then
if (read = '1') then
nxt_state := st_read;
icore_cmd := CMD_READ;
idcnt := "111";
else
nxt_state := st_write;
icore_cmd := CMD_WRITE;
idcnt := "111";
iload := '1';
end if;
end if;
when st_write =>
if (core_ack = '1') then
idcnt := dcnt -1; -- count down Data_counter
icore_txd := sr(7);
if (dcnt = 0) then
nxt_state := st_ack;
icore_cmd := CMD_READ;
else
ishift := '1';
-- icore_txd := sr(7);
end if;
end if;

when st_read =>


if (core_ack = '1') then
idcnt := dcnt -1; -- count down Data_counter
ishift := '1';
if (dcnt = 0) then
nxt_state := st_ack;
icore_cmd := CMD_WRITE;
icore_txd := ack_in;
end if;
end if;

when st_ack =>


if (core_ack = '1') then
-- generate command acknowledge signal
ihost_ack := '1';
-- Perform an additional shift, needed for 'read' (store last received bit in shift register)
ishift := '1';
-- check for stop; Should a STOP command be generated ?
if (stop = '1') then
nxt_state := st_stop;
icore_cmd := CMD_STOP;
else
nxt_state := st_idle;
icore_cmd := CMD_NOP;
end if;
end if;
when st_stop =>
if (core_ack = '1') then
nxt_state := st_idle;
icore_cmd := CMD_NOP;
end if;

Page | 263 © ISI 2018 Ridha Ghayoula


when others => -- illegal states
nxt_state := st_idle;
icore_cmd := CMD_NOP;
end case;
-- generate registers
if (nReset = '0') then
core_cmd <= CMD_NOP;
core_txd <= '0';
shift <= '0';
ld <= '0';
dcnt <= "111";
host_ack <= '0';
state <= st_idle;
elsif (clk'event and clk = '1') then
if (ena = '1') then
state <= nxt_state;
dcnt <= idcnt;
shift <= ishift;
ld <= iload;
core_cmd <= icore_cmd;
core_txd <= icore_txd;
host_ack <= ihost_ack;
end if;
end if;
end process nxt_state_decoder;
end block statemachine;
end architecture structural;

-- I2C Core
-- Translate simple commands into SCL/SDA transitions
-- Each command has 5 states, A/B/C/D/idle
-- start: SCL ~~~~~~~~~~\____
-- SDA ~~~~~~~~\______
-- x|A|B|C|D|i
--
-- repstart SCL ____/~~~~\___
-- SDA __/~~~\______
-- x|A|B|C|D|i
--
-- stop SCL ____/~~~~~~~~
-- SDA ==\____/~~~~~
-- x|A|B|C|D|i
--
--- write SCL ____/~~~~\____
-- SDA ==X=========X=
-- x|A|B|C|D|i
--
--- read SCL ____/~~~~\____
-- SDA XXXX=====XXXX
-- x|A|B|C|D|i
--

-- Timing: Normal mode Fast mode


-----------------------------------------------------------------
-- Fscl 100KHz 400KHz
-- Th_scl 4.0us 0.6us High period of SCL
-- Tl_scl 4.7us 1.3us Low period of SCL

Page | 264 © ISI 2018 Ridha Ghayoula


-- Tsu:sta 4.7us 0.6us setup time for a repeated start condition
-- Tsu:sto 4.0us 0.6us setup time for a stop conditon
-- Tbuf 4.7us 1.3us Bus free time between a stop and start condition
--
i2c_core is
port (
clk : in std_logic;
nReset : in std_logic;
clk_cnt : in unsigned(7 downto 0);
cmd : in std_logic_vector(2 downto 0);
cmd_ack :out std_logic;
busy : out std_logic;
Din : in std_logic;
Dout : out std_logic;
SCL : inout std_logic;
SDA : inout std_logic
);
end entity i2c_core;
architecture structural of i2c_core is
constant CMD_NOP : std_logic_vector(2 downto 0) := "000";
constant CMD_START : std_logic_vector(2 downto 0) := "010";
constant CMD_STOP : std_logic_vector(2 downto 0) := "011";
constant CMD_READ : std_logic_vector(2 downto 0) := "100";
constant CMD_WRITE : std_logic_vector(2 downto 0) := "101";
type cmds is (idle, start_a, start_b, start_c, start_d, stop_a, stop_b, stop_c, rd_a, rd_b, rd_c, rd_d, wr_a, wr_b,
wr_c, wr_d);
signal state : cmds;
signal SDAo, SCLo : std_logic;
signal txd : std_logic;
signal clk_en, slave_wait :std_logic;
signal cnt : unsigned(7 downto 0) := clk_cnt;
begin
-- whenever the slave is not ready it can delay the cycle by pulling SCL low
slave_wait <= '1' when ((SCLo = '1') and (SCL = '0')) else '0';
-- generate clk enable signal
gen_clken: process(clk, nReset)
begin
if (nReset = '0') then
cnt <= (others => '0');
clk_en <= '1'; --'0';
elsif (clk'event and clk = '1') then
if (cnt = 0) then
clk_en <= '1';
cnt <= clk_cnt;
else
if (slave_wait = '0') then
cnt <= cnt -1;
end if;
clk_en <= '0';
end if;
end if;
end process gen_clken;
-- generate statemachine
nxt_state_decoder : process (clk, nReset, state, cmd, SDA)
variable nxt_state : cmds;
variable icmd_ack, ibusy, store_sda : std_logic;
variable itxd : std_logic;

Page | 265 © ISI 2018 Ridha Ghayoula


begin
nxt_state := state;
icmd_ack := '0'; -- default no acknowledge
ibusy := '1'; -- default busy
store_sda := '0';
itxd := txd;

case (state) is
-- idle
when idle =>
case cmd is
when CMD_START =>
nxt_state := start_a;
icmd_ack := '1'; -- command completed

when CMD_STOP =>


nxt_state := stop_a;
icmd_ack := '1'; -- command completed

when CMD_WRITE =>


nxt_state := wr_a;
icmd_ack := '1'; -- command completed
itxd := Din;

when CMD_READ =>


nxt_state := rd_a;
icmd_ack := '1'; -- command completed

when others =>


nxt_state := idle;
-- don't acknowledge NOP command icmd_ack := '1'; -- command completed
ibusy := '0';
end case;
-- start
when start_a =>
nxt_state := start_b;
when start_b =>
nxt_state := start_c;
when start_c =>
nxt_state := start_d;
when start_d =>
nxt_state := idle;
ibusy := '0'; -- not busy when idle
-- stop
when stop_a =>
nxt_state := stop_b;
when stop_b =>
nxt_state := stop_c;

when stop_c =>


-- nxt_state := stop_d;

-- when stop_d =>


nxt_state := idle;
ibusy := '0'; -- not busy when idle
-- read
when rd_a =>

Page | 266 © ISI 2018 Ridha Ghayoula


nxt_state := rd_b;
when rd_b =>
nxt_state := rd_c;
when rd_c =>
nxt_state := rd_d;
store_sda := '1';
when rd_d =>
nxt_state := idle;
ibusy := '0'; -- not busy when idle
-- write
when wr_a =>
nxt_state := wr_b;
when wr_b =>
nxt_state := wr_c;
when wr_c =>
nxt_state := wr_d;
when wr_d =>
nxt_state := idle;
ibusy := '0'; -- not busy when idle
end case;
-- generate regs
if (nReset = '0') then
state <= idle;
cmd_ack <= '0';
busy <= '0';
txd <= '0';
Dout <= '0';
elsif (clk'event and clk = '1') then
if (clk_en = '1') then
state <= nxt_state;
busy <= ibusy;
txd <= itxd;
if (store_sda = '1') then
Dout <= SDA;
end if;
end if;
cmd_ack <= icmd_ack and clk_en;
end if;
end process nxt_state_decoder;
-- convert states to SCL and SDA signals
output_decoder: process (clk, nReset, state)
variable iscl, isda : std_logic;
begin
case (state) is
when idle =>
iscl := SCLo; -- keep SCL in same state
isda := SDA; -- keep SDA in same state
-- start
when start_a =>
iscl := SCLo; -- keep SCL in same state (for repeated start)
isda := '1'; -- set SDA high
when start_b =>
iscl := '1'; -- set SCL high
isda := '1'; -- keep SDA high
when start_c =>
iscl := '1'; -- keep SCL high
isda := '0'; -- sel SDA low

Page | 267 © ISI 2018 Ridha Ghayoula


when start_d =>
iscl := '0'; -- set SCL low
isda := '0'; -- keep SDA low
-- stop
when stop_a =>
iscl := '0'; -- keep SCL disabled
isda := '0'; -- set SDA low

when stop_b =>


iscl := '1'; -- set SCL high
isda := '0'; -- keep SDA low

when stop_c =>


iscl := '1'; -- keep SCL high
isda := '1'; -- set SDA high
-- write
when wr_a =>
iscl := '0'; -- keep SCL low
-- isda := txd; -- set SDA
isda := Din;

when wr_b =>


iscl := '1'; -- set SCL high
-- isda := txd; -- set SDA
isda := Din;
when wr_c =>
iscl := '1'; -- keep SCL high
-- isda := txd; -- set SDA
isda := Din;
when wr_d =>
iscl := '0'; -- set SCL low
-- isda := txd; -- set SDA
isda := Din;
-- read
when rd_a =>
iscl := '0'; -- keep SCL low
isda := '1'; -- tri-state SDA
when rd_b =>
iscl := '1'; -- set SCL high
isda := '1'; -- tri-state SDA
when rd_c =>
iscl := '1'; -- keep SCL high
isda := '1'; -- tri-state SDA

when rd_d =>


iscl := '0'; -- set SCL low
isda := '1'; -- tri-state SDA
end case;
-- generate registers
if (nReset = '0') then
SCLo <= '1';
SDAo <= '1';
elsif (clk'event and clk = '1') then
if (clk_en = '1') then
SCLo <= iscl;
SDAo <= isda;
end if;

Page | 268 © ISI 2018 Ridha Ghayoula


end if;
end process output_decoder;
SCL <= '0' when (SCLo = '0') else 'Z'; -- since SCL is externally pulled-up convert a '1' to a 'Z'(tri-state)
SDA <= '0' when (SDAo = '0') else 'Z'; -- since SDA is externally pulled-up convert a '1' to a 'Z'(tri-state)
-- SCL <= SCLo;
-- SDA <= SDAo;
end architecture structural;

---------------------------------------------------------------------
---- ----
---- WISHBONE revB2 I2C Master Core; bit-controller ----
---- ----
---- ----
---- Author: Richard Herveille ----
---- richard@asics.ws ----
---- www.asics.ws ----
---- ----
---- Downloaded from: http://www.opencores.org/projects/i2c/ ----
--
-------------------------------------
-- Bit controller section
------------------------------------
--
-- Translate simple commands into SCL/SDA transitions
-- Each command has 5 states, A/B/C/D/idle
--
-- start: SCL ~~~~~~~~~~~~~~\____
-- SDA XX/~~~~~~~\______
-- x|A|B|C|D|i
--
-- repstart SCL ______/~~~~~~~\___
-- SDA __/~~~~~~~\______
-- x|A|B|C|D|i
--
-- stop SCL _______/~~~~~~~~~~~
-- SDA ==\___________/~~~~~
-- x|A|B|C|D|i
--
--- write SCL ______/~~~~~~~\____
-- SDA XXX===============XX
-- x|A|B|C|D|i
--
--- read SCL ______/~~~~~~~\____
-- SDA XXXXXXX=XXXXXXXXXXX
-- x|A|B|C|D|i
--

-- Timing: Normal mode Fast mode


-----------------------------------------------------------------
-- Fscl 100KHz 400KHz
-- Th_scl 4.0us 0.6us High period of SCL
-- Tl_scl 4.7us 1.3us Low period of SCL
-- Tsu:sta 4.7us 0.6us setup time for a repeated start condition
-- Tsu:sto 4.0us 0.6us setup time for a stop conditon
-- Tbuf 4.7us 1.3us Bus free time between a stop and start condition
--

Page | 269 © ISI 2018 Ridha Ghayoula


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity i2c_master_bit_ctrl is
port (
clk : in std_logic;
rst : in std_logic;
nReset : in std_logic;
ena : in std_logic; -- core enable signal

clk_cnt : in unsigned(15 downto 0); -- clock prescale value


cmd : in std_logic_vector(3 downto 0);
cmd_ack : out std_logic; -- command completed
busy : out std_logic; -- i2c bus busy
al : out std_logic; -- arbitration lost
din : in std_logic;
dout : out std_logic;
-- i2c lines
scl_i : in std_logic; -- i2c clock line input
scl_o : out std_logic; -- i2c clock line output
scl_oen : out std_logic; -- i2c clock line output enable, active low
sda_i : in std_logic; -- i2c data line input
sda_o : out std_logic; -- i2c data line output
sda_oen : out std_logic -- i2c data line output enable, active low
);
end entity i2c_master_bit_ctrl;

architecture structural of i2c_master_bit_ctrl is


constant I2C_CMD_NOP : std_logic_vector(3 downto 0) := "0000";
constant I2C_CMD_START : std_logic_vector(3 downto 0) := "0001";
constant I2C_CMD_STOP : std_logic_vector(3 downto 0) := "0010";
constant I2C_CMD_READ : std_logic_vector(3 downto 0) := "0100";
constant I2C_CMD_WRITE : std_logic_vector(3 downto 0) := "1000";

type states is (idle, start_a, start_b, start_c, start_d, start_e,


stop_a, stop_b, stop_c, stop_d, rd_a, rd_b, rd_c, rd_d, wr_a, wr_b, wr_c, wr_d);
signal c_state : states;

signal iscl_oen, isda_oen : std_logic; -- internal I2C lines


signal sda_chk : std_logic; -- check SDA status (multi-master arbitration)
signal dscl_oen : std_logic; -- delayed scl_oen signals
signal sSCL, sSDA : std_logic; -- synchronized SCL and SDA inputs
signal dSCL, dSDA : std_logic; -- delayed versions ofsSCL and sSDA
signal clk_en : std_logic; -- statemachine clock enable
signal scl_sync, slave_wait : std_logic; -- clock generation signals
signal ial : std_logic; -- internal arbitration lost signal
signal cnt : unsigned(15 downto 0); -- clock divider counter (synthesis)
begin
-- whenever the slave is not ready it can delay the cycle by pulling SCL low
-- delay scl_oen
process (clk, nReset)
begin
if (nReset = '0') then
dscl_oen <= '0';
elsif (clk'event and clk = '1') then

Page | 270 © ISI 2018 Ridha Ghayoula


dscl_oen <= iscl_oen;
end if;
end process;
-- slave_wait is asserted when master wants to drive SCL high, but the slave pulls it low
-- slave_wait remains asserted until the slave releases SCL
process (clk, nReset)
begin
if (nReset = '0') then
slave_wait <= '0';
elsif (clk'event and clk = '1') then
slave_wait <= (iscl_oen and not dscl_oen and not sSCL) or (slave_wait and not sSCL);
end if;
end process;

-- master drives SCL high, but another master pulls it low


-- master start counting down its low cycle now (clock synchronization)
scl_sync <= dSCL and not sSCL and iscl_oen;

-- generate clk enable signal


gen_clken: process(clk, nReset)
begin
if (nReset = '0') then
cnt <= (others => '0');
clk_en <= '1';
elsif (clk'event and clk = '1') then
if ((rst = '1') or (cnt = 0) or (ena = '0') or (scl_sync = '1')) then
cnt <= clk_cnt;
clk_en <= '1';
elsif (slave_wait = '1') then
cnt <= cnt;
clk_en <= '0';
else
cnt <= cnt -1;
clk_en <= '0';
end if;
end if;
end process gen_clken;
-- generate bus status controller
bus_status_ctrl: block
signal cSCL, cSDA : std_logic_vector( 1 downto 0); -- capture SDA and SCL
signal fSCL, fSDA : std_logic_vector( 2 downto 0); -- filter inputs for SCL and SDA
signal filter_cnt : unsigned(13 downto 0); -- clock divider for filter
signal sta_condition : std_logic; -- start detected
signal sto_condition : std_logic; -- stop detected
signal cmd_stop : std_logic; -- STOP command
signal ibusy : std_logic; -- internal busy signal
begin
-- capture SCL and SDA
capture_scl_sda: process(clk, nReset)
begin
if (nReset = '0') then
cSCL <= "00";
cSDA <= "00";
elsif (clk'event and clk = '1') then
if (rst = '1') then
cSCL <= "00";
cSDA <= "00";

Page | 271 © ISI 2018 Ridha Ghayoula


else
cSCL <= (cSCL(0) & scl_i);
cSDA <= (cSDA(0) & sda_i);
end if;
end if;
end process capture_scl_sda;
-- filter SCL and SDA; (attempt to) remove glitches
filter_divider: process(clk, nReset)
begin
if (nReset = '0') then
filter_cnt <= (others => '0');
elsif (clk'event and clk = '1') then
if ( (rst = '1') or (ena = '0') ) then
filter_cnt <= (others => '0');
elsif (filter_cnt = 0) then
filter_cnt <= clk_cnt(15 downto 2);
else
filter_cnt <= filter_cnt -1;
end if;
end if;
end process filter_divider;
filter_scl_sda: process(clk, nReset)
begin
if (nReset = '0') then
fSCL <= (others => '1');
fSDA <= (others => '1');
elsif (clk'event and clk = '1') then
if (rst = '1') then
fSCL <= (others => '1');
fSDA <= (others => '1');
elsif (filter_cnt = 0) then
fSCL <= (fSCL(1 downto 0) & cSCL(1));
fSDA <= (fSDA(1 downto 0) & cSDA(1));
end if;
end if;
end process filter_scl_sda;
-- generate filtered SCL and SDA signals
scl_sda: process(clk, nReset)
begin
if (nReset = '0') then
sSCL <= '1';
sSDA <= '1';
dSCL <= '1';
dSDA <= '1';
elsif (clk'event and clk = '1') then
if (rst = '1') then
sSCL <= '1';
sSDA <= '1';
dSCL <= '1';
dSDA <= '1';
else
sSCL <= (fSCL(2) and fSCL(1)) or
(fSCL(2) and fSCL(0)) or
(fSCL(1) and fSCL(0));
sSDA <= (fSDA(2) and fSDA(1)) or
(fSDA(2) and fSDA(0)) or
(fSDA(1) and fSDA(0));

Page | 272 © ISI 2018 Ridha Ghayoula


dSCL <= sSCL;
dSDA <= sSDA;
end if;
end if;
end process scl_sda;
-- detect start condition => detect falling edge on SDA while SCL is high
-- detect stop condition => detect rising edge on SDA while SCL is high
detect_sta_sto: process(clk, nReset)
begin
if (nReset = '0') then
sta_condition <= '0';
sto_condition <= '0';
elsif (clk'event and clk = '1') then
if (rst = '1') then
sta_condition <= '0';
sto_condition <= '0';
else
sta_condition <= (not sSDA and dSDA) and sSCL;
sto_condition <= (sSDA and not dSDA) and sSCL;
end if;
end if;
end process detect_sta_sto;
-- generate i2c-bus busy signal
gen_busy: process(clk, nReset)
begin
if (nReset = '0') then
ibusy <= '0';
elsif (clk'event and clk = '1') then
if (rst = '1') then
ibusy <= '0';
else
ibusy <= (sta_condition or ibusy) and not sto_condition;
end if;
end if;
end process gen_busy;
busy <= ibusy;
-- generate arbitration lost signal
-- aribitration lost when:
-- 1) master drives SDA high, but the i2c bus is low
-- 2) stop detected while not requested (detect during 'idle' state)
gen_al: process(clk, nReset)
begin
if (nReset = '0') then
cmd_stop <= '0';
ial <= '0';
elsif (clk'event and clk = '1') then
if (rst = '1') then
cmd_stop <= '0';
ial <= '0';
else
if (clk_en = '1') then
if (cmd = I2C_CMD_STOP) then
cmd_stop <= '1';
else
cmd_stop <= '0';
end if;
end if;

Page | 273 © ISI 2018 Ridha Ghayoula


if (c_state = idle) then
ial <= (sda_chk and not sSDA and isda_oen) or (sto_condition and not cmd_stop);
else
ial <= (sda_chk and not sSDA and isda_oen);
end if;
end if;
end if;
end process gen_al;
al <= ial;
-- generate dout signal, store dout on rising edge of SCL
gen_dout: process(clk, nReset)
begin
if (nReset = '0') then
dout <= '0';
elsif (clk'event and clk = '1') then
if (sSCL = '1' and dSCL = '0') then
dout <= sSDA;
end if;
end if;
end process gen_dout;
end block bus_status_ctrl;
-- generate statemachine
nxt_state_decoder : process (clk, nReset)
begin
if (nReset = '0') then
c_state <= idle;
cmd_ack <= '0';
iscl_oen <= '1';
isda_oen <= '1';
sda_chk <= '0';
elsif (clk'event and clk = '1') then
if (rst = '1' or ial = '1') then
c_state <= idle;
cmd_ack <= '0';
iscl_oen <= '1';
isda_oen <= '1';
sda_chk <= '0';
else
cmd_ack <= '0'; -- default no acknowledge
if (clk_en = '1') then
case (c_state) is
-- idle
when idle =>
case cmd is
when I2C_CMD_START => c_state <= start_a;
when I2C_CMD_STOP => c_state <= stop_a;
when I2C_CMD_WRITE => c_state <= wr_a;
when I2C_CMD_READ => c_state <= rd_a;
when others => c_state <= idle; -- NOP command
end case;
iscl_oen <= iscl_oen; -- keep SCL in same state
isda_oen <= isda_oen; -- keep SDA in same state
sda_chk <= '0'; -- don't check SDA
-- start
when start_a =>
c_state <= start_b;
iscl_oen <= iscl_oen; -- keep SCL in same state (for repeated start)

Page | 274 © ISI 2018 Ridha Ghayoula


isda_oen <= '1'; -- set SDA high
sda_chk <= '0'; -- don't check SDA
when start_b =>
c_state <= start_c;
iscl_oen <= '1'; -- set SCL high
isda_oen <= '1'; -- keep SDA high
sda_chk <= '0'; -- don't check SDA
when start_c =>
c_state <= start_d;
iscl_oen <= '1'; -- keep SCL high
isda_oen <= '0'; -- set SDA low
sda_chk <= '0'; -- don't check SDA
when start_d =>
c_state <= start_e;
iscl_oen <= '1'; -- keep SCL high
isda_oen <= '0'; -- keep SDA low
sda_chk <= '0'; -- don't check SDA
when start_e =>
c_state <= idle;
cmd_ack <= '1'; -- command completed
iscl_oen <= '0'; -- set SCL low
isda_oen <= '0'; -- keep SDA low
sda_chk <= '0'; -- don't check SDA
-- stop
when stop_a =>
c_state <= stop_b;
iscl_oen <= '0'; -- keep SCL low
isda_oen <= '0'; -- set SDA low
sda_chk <= '0'; -- don't check SDA
when stop_b =>
c_state <= stop_c;
iscl_oen <= '1'; -- set SCL high
isda_oen <= '0'; -- keep SDA low
sda_chk <= '0'; -- don't check SDA
when stop_c =>
c_state <= stop_d;
iscl_oen <= '1'; -- keep SCL high
isda_oen <= '0'; -- keep SDA low
sda_chk <= '0'; -- don't check SDA
when stop_d =>
c_state <= idle;
cmd_ack <= '1'; -- command completed
iscl_oen <= '1'; -- keep SCL high
isda_oen <= '1'; -- set SDA high
sda_chk <= '0'; -- don't check SDA
-- read
when rd_a =>
c_state <= rd_b;
iscl_oen <= '0'; -- keep SCL low
isda_oen <= '1'; -- tri-state SDA
sda_chk <= '0'; -- don't check SDA
when rd_b =>
c_state <= rd_c;
iscl_oen <= '1'; -- set SCL high
isda_oen <= '1'; -- tri-state SDA
sda_chk <= '0'; -- don't check SDA
when rd_c =>

Page | 275 © ISI 2018 Ridha Ghayoula


c_state <= rd_d;
iscl_oen <= '1'; -- keep SCL high
isda_oen <= '1'; -- tri-state SDA
sda_chk <= '0'; -- don't check SDA
when rd_d =>
c_state <= idle;
cmd_ack <= '1'; -- command completed
iscl_oen <= '0'; -- set SCL low
isda_oen <= '1'; -- tri-state SDA
sda_chk <= '0'; -- don't check SDA
-- write
when wr_a =>
c_state <= wr_b;
iscl_oen <= '0'; -- keep SCL low
isda_oen <= din; -- set SDA
sda_chk <= '0'; -- don't check SDA (SCL low)
when wr_b =>
c_state <= wr_c;
iscl_oen <= '1'; -- set SCL high
isda_oen <= din; -- keep SDA
sda_chk <= '0'; -- don't check SDA yet
-- Allow some more time for SDA and SCL to settle
when wr_c =>
c_state <= wr_d;
iscl_oen <= '1'; -- keep SCL high
isda_oen <= din; -- keep SDA
sda_chk <= '1'; -- check SDA
when wr_d =>
c_state <= idle;
cmd_ack <= '1'; -- command completed
iscl_oen <= '0'; -- set SCL low
isda_oen <= din; -- keep SDA
sda_chk <= '0'; -- don't check SDA (SCL low)
when others =>
end case;
end if;
end if;
end if;
end process nxt_state_decoder;
-- assign outputs
scl_o <= '0';
scl_oen <= iscl_oen;
sda_o <= '0';
sda_oen <= isda_oen;
end architecture structural;

--------------------------------------------------------------------- ----
---- WISHBONE revB2 compl. I2C Master Core; byte-controller ----
---- Downloaded from: http://www.opencores.org/projects/i2c/ ----
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity i2c_master_byte_ctrl is
port (
clk : in std_logic;
rst : in std_logic; -- synchronous active high reset (WISHBONE compatible)

Page | 276 © ISI 2018 Ridha Ghayoula


nReset : in std_logic; -- asynchornous active low reset (FPGA compatible)
ena : in std_logic; -- core enable signal
clk_cnt : in unsigned(15 downto 0); -- 4x SCL
-- input signals start,
stop, read,write, ack_in : std_logic;
din : in std_logic_vector(7 downto 0);
-- output signals
cmd_ack : out std_logic; -- command done
ack_out : out std_logic;
i2c_busy : out std_logic; -- arbitration lost
i2c_al : out std_logic; -- i2c bus busy
dout : out std_logic_vector(7 downto 0);
-- i2c lines
scl_i : in std_logic; -- i2c clock line input
scl_o : out std_logic; -- i2c clock line output
scl_oen : out std_logic; -- i2c clock line output enable, active low
sda_i : in std_logic; -- i2c data line input
sda_o : out std_logic; -- i2c data line output
sda_oen : out std_logic -- i2c data line output enable, active low
);
end entity i2c_master_byte_ctrl;
architecture structural of i2c_master_byte_ctrl is
component i2c_master_bit_ctrl is
port (
clk : in std_logic;
rst : in std_logic;
nReset : in std_logic;
ena : in std_logic; -- core enable signal
clk_cnt : in unsigned(15 downto 0); -- clock prescale value
cmd : in std_logic_vector(3 downto 0);
cmd_ack : out std_logic; -- command done
busy : out std_logic; -- i2c bus busy
al : out std_logic; -- arbitration lost

din : in std_logic;
dout : out std_logic;

-- i2c lines
scl_i : in std_logic; -- i2c clock line input
scl_o : out std_logic; -- i2c clock line output
scl_oen : out std_logic; -- i2c clock line output enable, active low
sda_i : in std_logic; -- i2c data line input
sda_o : out std_logic; -- i2c data line output
sda_oen : out std_logic -- i2c data line output enable, active low
);
end component i2c_master_bit_ctrl;

-- commands for bit_controller block


constant I2C_CMD_NOP : std_logic_vector(3 downto 0) := "0000";
constant I2C_CMD_START : std_logic_vector(3 downto 0) := "0001";
constant I2C_CMD_STOP : std_logic_vector(3 downto 0) := "0010";
constant I2C_CMD_READ : std_logic_vector(3 downto 0) := "0100";
constant I2C_CMD_WRITE : std_logic_vector(3 downto 0) := "1000";
-- signals for bit_controller
signal core_cmd : std_logic_vector(3 downto 0);
signal core_ack, core_txd, core_rxd : std_logic;
signal al : std_logic;

Page | 277 © ISI 2018 Ridha Ghayoula


-- signals for shift register
signal sr : std_logic_vector(7 downto 0); -- 8bit shift register
signal shift, ld : std_logic;
-- signals for state machine
signal go, host_ack : std_logic;
signal dcnt : unsigned(2 downto 0); -- data counter
signal cnt_done : std_logic;
begin
-- hookup bit_controller
bit_ctrl: i2c_master_bit_ctrl port map(
clk => clk,
rst => rst,
nReset => nReset,
ena => ena,
clk_cnt => clk_cnt,
cmd => core_cmd,
cmd_ack => core_ack,
busy => i2c_busy,
al => al,
din => core_txd,
dout => core_rxd,
scl_i => scl_i,
scl_o => scl_o,
scl_oen => scl_oen,
sda_i => sda_i,
sda_o => sda_o,
sda_oen => sda_oen
);
i2c_al <= al;
-- generate host-command-acknowledge
cmd_ack <= host_ack;
-- generate go-signal
go <= (read or write or stop) and not host_ack;
-- assign Dout output to shift-register
dout <= sr;
-- generate shift register
shift_register: process(clk, nReset)
begin
if (nReset = '0') then
sr <= (others => '0');
elsif (clk'event and clk = '1') then
if (rst = '1') then
sr <= (others => '0');
elsif (ld = '1') then
sr <= din;
elsif (shift = '1') then
sr <= (sr(6 downto 0) & core_rxd);
end if;
end if;
end process shift_register;
-- generate data-counter
data_cnt: process(clk, nReset)
begin
if (nReset = '0') then
dcnt <= (others => '0');
elsif (clk'event and clk = '1') then
if (rst = '1') then

Page | 278 © ISI 2018 Ridha Ghayoula


dcnt <= (others => '0');
elsif (ld = '1') then
dcnt <= (others => '1'); -- load counter with 7
elsif (shift = '1') then
dcnt <= dcnt -1;
end if;
end if;
end process data_cnt;
cnt_done <= '1' when (dcnt = 0) else '0';
-- state machine
--
statemachine : block
type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop);
signal c_state : states;
begin
--
-- command interpreter, translate complex commands into simpler I2C commands
--
nxt_state_decoder: process(clk, nReset)
begin
if (nReset = '0') then
core_cmd <= I2C_CMD_NOP;
core_txd <= '0';
shift <= '0';
ld <= '0';
host_ack <= '0';
c_state <= st_idle;
ack_out <= '0';
elsif (clk'event and clk = '1') then
if (rst = '1' or al = '1') then
core_cmd <= I2C_CMD_NOP;
core_txd <= '0';
shift <= '0';
ld <= '0';
host_ack <= '0';
c_state <= st_idle;
ack_out <= '0';
else
-- initialy reset all signal
core_txd <= sr(7);
shift <= '0';
ld <= '0';
host_ack <= '0';

case c_state is
when st_idle =>
if (go = '1') then
if (start = '1') then
c_state <= st_start;
core_cmd <= I2C_CMD_START;
elsif (read = '1') then
c_state <= st_read;
core_cmd <= I2C_CMD_READ;
elsif (write = '1') then
c_state <= st_write;
core_cmd <= I2C_CMD_WRITE;
else -- stop

Page | 279 © ISI 2018 Ridha Ghayoula


c_state <= st_stop;
core_cmd <= I2C_CMD_STOP;
end if;
ld <= '1';
end if;
when st_start =>
if (core_ack = '1') then
if (read = '1') then
c_state <= st_read;
core_cmd <= I2C_CMD_READ;
else
c_state <= st_write;
core_cmd <= I2C_CMD_WRITE;
end if;
ld <= '1';
end if;
when st_write =>
if (core_ack = '1') then
if (cnt_done = '1') then
c_state <= st_ack;
core_cmd <= I2C_CMD_READ;
else
c_state <= st_write; -- stay in same state
core_cmd <= I2C_CMD_WRITE; -- write next bit
shift <= '1';
end if;
end if;
when st_read =>
if (core_ack = '1') then
if (cnt_done = '1') then
c_state <= st_ack;
core_cmd <= I2C_CMD_WRITE;
else
c_state <= st_read; -- stay in same state
core_cmd <= I2C_CMD_READ; -- read next bit
end if;
shift <= '1';
core_txd <= ack_in;
end if;
when st_ack =>
if (core_ack = '1') then
-- check for stop; Should a STOP command be generated ?
if (stop = '1') then
c_state <= st_stop;
core_cmd <= I2C_CMD_STOP;
else
c_state <= st_idle;
core_cmd <= I2C_CMD_NOP;
-- generate command acknowledge signal
host_ack <= '1';
end if;
-- assign ack_out output to core_rxd (contains last received bit)
ack_out <= core_rxd;
core_txd <= '1';
else
core_txd <= ack_in;
end if;

Page | 280 © ISI 2018 Ridha Ghayoula


when st_stop =>
if (core_ack = '1') then
c_state <= st_idle;
core_cmd <= I2C_CMD_NOP;

-- generate command acknowledge signal


host_ack <= '1';
end if;

when others => -- illegal states


c_state <= st_idle;
core_cmd <= I2C_CMD_NOP;
report ("Byte controller entered illegal state.");
end case;
end if;
end if;
end process nxt_state_decoder;
end block statemachine;
end architecture structural;

--------------------------------------------------------------------
---- ----
---- WISHBONE revB2 compl. I2C Master Core; top level ----
----
---- www.asics.ws ----
library ieee;
use ieee.std_logic_1164.all;
entity i2c_master_top is
generic(
ARST_LVL : std_logic := '0' -- asynchronous reset level
);
port (
-- wishbone signals
wb_clk_i : in std_logic; -- master clock input
wb_rst_i : in std_logic := '0'; -- synchronous active high reset
arst_i : in std_logic := not ARST_LVL; -- asynchronous reset
wb_adr_i : in std_logic_vector(2 downto 0); -- lower address bits
wb_dat_i : in std_logic_vector(7 downto 0); -- Databus input
wb_dat_o : out std_logic_vector(7 downto 0); -- Databus output
wb_we_i : in std_logic; -- Write enable input
wb_stb_i : in std_logic; -- Strobe signals / core select signal
wb_cyc_i : in std_logic; -- Valid bus cycle input
wb_ack_o : out std_logic; -- Bus cycle acknowledge output
wb_inta_o : out std_logic; -- interrupt request output signal

-- i2c lines
scl_pad_i : in std_logic; -- i2c clock line input
scl_pad_o : out std_logic; -- i2c clock line output
scl_padoen_o : out std_logic; -- i2c clock line output enable, active low
sda_pad_i : in std_logic; -- i2c data line input
sda_pad_o : out std_logic; -- i2c data line output
sda_padoen_o : out std_logic -- i2c data line output enable, active low
);

Page | 281 © ISI 2018 Ridha Ghayoula


end entity i2c_master_top;

architecture structural of i2c_master_top is


component i2c_master_byte_ctrl is
port (
clk : in std_logic;
rst : in std_logic; -- synchronous active high reset (WISHBONE compatible)
nReset : in std_logic; -- asynchornous active low reset (FPGA compatible)
ena : in std_logic; -- core enable signal
clk_cnt : in unsigned(15 downto 0); -- 4x SCL
-- input signals
start,stop,read,write, ack_in : std_logic;
din : in std_logic_vector(7 downto 0);
-- output signals
cmd_ack : out std_logic;
ack_out : out std_logic;
i2c_busy : out std_logic;
i2c_al : out std_logic;
dout : out std_logic_vector(7 downto 0);
-- i2c lines
scl_i : in std_logic; -- i2c clock line input
scl_o : out std_logic; -- i2c clock line output
scl_oen : out std_logic; -- i2c clock line output enable, active low
sda_i : in std_logic; -- i2c data line input
sda_o : out std_logic; -- i2c data line output
sda_oen : out std_logic -- i2c data line output enable, active low
);
end component i2c_master_byte_ctrl;
-- registers
signal prer : unsigned(15 downto 0); -- clock prescale register
signal ctr : std_logic_vector(7 downto 0); -- control register
signal txr : std_logic_vector(7 downto 0); -- transmit register
signal rxr : std_logic_vector(7 downto 0); -- receive register
signal cr : std_logic_vector(7 downto 0); -- command register
signal sr : std_logic_vector(7 downto 0); -- status register
-- internal reset signal
signal rst_i : std_logic;
-- wishbone write access
signal wb_wacc : std_logic;
-- internal acknowledge signal
signal iack_o : std_logic;
-- done signal: command completed, clear command register
signal done : std_logic;
-- command register signals
signal sta, sto, rd, wr, ack, iack : std_logic;
signal core_en : std_logic; -- core enable signal
signal ien : std_logic; -- interrupt enable signal
-- status register signals
signal irxack, rxack : std_logic; -- received aknowledge from slave
signal tip : std_logic; -- transfer in progress
signal irq_flag : std_logic; -- interrupt pending flag
signal i2c_busy : std_logic; -- i2c bus busy (start signal detected)
signal i2c_al, al : std_logic; -- arbitration lost

begin
-- generate internal reset signal
rst_i <= arst_i xor ARST_LVL;

Page | 282 © ISI 2018 Ridha Ghayoula


-- generate acknowledge output signal
gen_ack_o : process(wb_clk_i)
begin
if (wb_clk_i'event and wb_clk_i = '1') then
iack_o <= wb_cyc_i and wb_stb_i and not iack_o; -- because timing is always honored
end if;
end process gen_ack_o;
wb_ack_o <= iack_o;
-- generate wishbone write access signal
wb_wacc <= wb_we_i and iack_o;
-- assign wb_dat_o
assign_dato : process(wb_clk_i)
begin
if (wb_clk_i'event and wb_clk_i = '1') then
case wb_adr_i is
when "000" => wb_dat_o <= std_logic_vector(prer( 7 downto 0));
when "001" => wb_dat_o <= std_logic_vector(prer(15 downto 8));
when "010" => wb_dat_o <= ctr;
when "011" => wb_dat_o <= rxr; -- write is transmit register TxR
when "100" => wb_dat_o <= sr; -- write is command register CR
-- Debugging registers:
-- These registers are not documented.
-- Functionality could change in future releases
when "101" => wb_dat_o <= txr;
when "110" => wb_dat_o <= cr;
when "111" => wb_dat_o <= (others => '0');
when others => wb_dat_o <= (others => 'X'); -- for simulation only
end case;
end if;
end process assign_dato;
-- generate registers (CR, SR see below)
gen_regs: process(rst_i, wb_clk_i)
begin
if (rst_i = '0') then
prer <= (others => '1');
ctr <= (others => '0');
txr <= (others => '0');
elsif (wb_clk_i'event and wb_clk_i = '1') then
if (wb_rst_i = '1') then
prer <= (others => '1');
ctr <= (others => '0');
txr <= (others => '0');
elsif (wb_wacc = '1') then
case wb_adr_i is
when "000" => prer( 7 downto 0) <= unsigned(wb_dat_i);
when "001" => prer(15 downto 8) <= unsigned(wb_dat_i);
when "010" => ctr <= wb_dat_i;
when "011" => txr <= wb_dat_i;
when "100" => null; --write to CR, avoid executing the others clause
-- illegal cases, for simulation only
when others =>
report ("Illegal write address, setting all registers to unknown.");
prer <= (others => 'X');
ctr <= (others => 'X');
txr <= (others => 'X');
end case;
end if;

Page | 283 © ISI 2018 Ridha Ghayoula


end if;
end process gen_regs;
-- generate command register
gen_cr: process(rst_i, wb_clk_i)
begin
if (rst_i = '0') then
cr <= (others => '0');
elsif (wb_clk_i'event and wb_clk_i = '1') then
if (wb_rst_i = '1') then
cr <= (others => '0');
elsif (wb_wacc = '1') then
if ( (core_en = '1') and (wb_adr_i = "100") ) then
-- only take new commands when i2c core enabled
-- pending commands are finished
cr <= wb_dat_i;
end if;
else
if (done = '1' or i2c_al = '1') then
cr(7 downto 4) <= (others => '0'); -- clear command bits when command done or arbitration lost
end if;
cr(2 downto 1) <= (others => '0'); -- reserved bits, always '0'
cr(0) <= '0'; -- clear IRQ_ACK bit
end if;
end if;
end process gen_cr;
-- decode command register
sta <= cr(7);
sto <= cr(6);
rd <= cr(5);
wr <= cr(4);
ack <= cr(3);
iack <= cr(0);
-- decode control register
core_en <= ctr(7);
ien <= ctr(6);
-- hookup byte controller block
byte_ctrl: i2c_master_byte_ctrl
port map (
clk => wb_clk_i,
rst => wb_rst_i,
nReset => rst_i,
ena => core_en,
clk_cnt => prer,
start => sta,
stop => sto,
read => rd,
write => wr,
ack_in => ack,
i2c_busy => i2c_busy,
i2c_al => i2c_al,
din => txr,
cmd_ack => done,
ack_out => irxack,
dout => rxr,
scl_i => scl_pad_i,
scl_o => scl_pad_o,
scl_oen => scl_padoen_o,

Page | 284 © ISI 2018 Ridha Ghayoula


sda_i => sda_pad_i,
sda_o => sda_pad_o,
sda_oen => sda_padoen_o
);
-- status register block + interrupt request signal
st_irq_block : block
begin
-- generate status register bits
gen_sr_bits: process (wb_clk_i, rst_i)
begin
if (rst_i = '0') then
al <= '0';
rxack <= '0';
tip <= '0';
irq_flag <= '0';
elsif (wb_clk_i'event and wb_clk_i = '1') then
if (wb_rst_i = '1') then
al <= '0';
rxack <= '0';
tip <= '0';
irq_flag <= '0';
else
al <= i2c_al or (al and not sta);
rxack <= irxack;
tip <= (rd or wr);
-- interrupt request flag is always generated
irq_flag <= (done or i2c_al or irq_flag) and not iack;
end if;
end if;
end process gen_sr_bits;
-- generate interrupt request signals
gen_irq: process (wb_clk_i, rst_i)
begin
if (rst_i = '0') then
wb_inta_o <= '0';
elsif (wb_clk_i'event and wb_clk_i = '1') then
if (wb_rst_i = '1') then
wb_inta_o <= '0';
else
-- interrupt signal is only generated when IEN (interrupt enable bit) is set
wb_inta_o <= irq_flag and ien;
end if;
end if;
end process gen_irq;
-- assign status register bits
sr(7) <= rxack;
sr(6) <= i2c_busy;
sr(5) <= al;
sr(4 downto 2) <= (others => '0'); -- reserved
sr(1) <= tip;
sr(0) <= irq_flag;
end block;
end architecture structural;

The i2c_master core consists of three files:

Page | 285 © ISI 2018 Ridha Ghayoula


- i2c_master_top -- top level
- i2c_master_byte_ctrl -- byte controller
- i2c_master_bit_ctrl -- bit controller

-- State machine for reading data from Dallas 1621


-- Testsystem for i2c controller
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.i2c.all;
entity DS1621_interface is
port (
clk : in std_logic;
nReset : in std_logic;

Dout : out std_logic_vector(7 downto 0); -- data read from ds1621

error : out std_logic; -- no correct ack received

SCL : inout std_logic;


SDA : inout std_logic
);
end entity DS1621_interface;
architecture structural of DS1621_interface is
constant SLAVE_ADDR : std_logic_vector(6 downto 0) := "1001000";
constant CLK_CNT : unsigned(7 downto 0) := conv_unsigned(20, 8);

signal cmd_ack : std_logic;


signal D : std_logic_vector(7 downto 0);
signal lack, store_dout : std_logic;

signal start, read, write, ack, stop : std_logic;


signal i2c_dout : std_logic_vector(7 downto 0);

begin
-- hookup I2C controller
u1: simple_i2c port map (clk => clk, ena => '1', clk_cnt => clk_cnt, nReset => nReset,
read => read, write => write, start => start, stop => stop, ack_in => ack, cmd_ack =>
cmd_ack,
Din => D, Dout => i2c_dout, ack_out => lack, SCL => SCL, SDA => SDA);

init_statemachine : block
type states is (i1, i2, i3, i4, i5, t1, t2, t3, t4, t5);
signal state : states;
begin
nxt_state_decoder: process(clk, nReset, state)
variable nxt_state : states;
variable iD : std_logic_vector(7 downto 0);
variable ierr : std_logic;
variable istart, iread, iwrite, iack, istop : std_logic;
variable istore_dout : std_logic;
begin
nxt_state := state;
ierr := '0';
istore_dout := '0';
istart := start;

Page | 286 © ISI 2018 Ridha Ghayoula


iread := read;
iwrite := write;
iack := ack;
istop := stop;
iD := D;

case (state) is
-- init DS1621
-- 1) send start condition
-- 2) send slave address + write
-- 3) check ack
-- 4) send "access config" command (0xAC)
-- 5) check ack
-- 6) send config register data (0x00)
-- 7) check ack
-- 8) send stop condition
-- 9) send start condition
-- 10) send slave address + write
-- 11) check ack
-- 12) send "start conversion" command (0xEE)
-- 13) check ack
-- 14) send stop condition

when i1 => -- send start condition, sent slave address + write


nxt_state := i2;
istart := '1';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := (slave_addr & '0'); -- write to slave (R/W = '0')

when i2 => -- send "access config" command


if (cmd_ack = '1') then
nxt_state := i3;
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;

istart := '0';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := x"AC";
end if;

when i3 => -- send config register data, sent stop condition


if (cmd_ack = '1') then
nxt_state := i4;
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;

istart := '0';

Page | 287 © ISI 2018 Ridha Ghayoula


iread := '0';
iwrite := '1';
iack := '0';
istop := '1';
iD := x"00";
end if;

when i4 => -- send start condition, sent slave address + write


if (cmd_ack = '1') then
nxt_state := i5;

istart := '1';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := (slave_addr & '0'); -- write to slave (R/W = '0')
end if;

when i5 => -- send "start conversion" command + stop condition


if (cmd_ack = '1') then
nxt_state := t1;
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;

istart := '0';
iread := '0';
iwrite := '1';
iack := '0';
istop := '1';
iD := x"EE";
end if;
-- read temperature
-- 1) sent start condition
-- 2) sent slave address + write
-- 3) check ack
-- 4) sent "read temperature" command (0xAA)
-- 5) check ack
-- 6) sent start condition
-- 7) sent slave address + read
-- 8) check ack
-- 9) read msb
-- 10) send ack
-- 11) read lsb
-- 12) send nack
-- 13) send stop condition

when t1 => -- send start condition, sent slave address + write


if (cmd_ack = '1') then
nxt_state := t2;
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;

Page | 288 © ISI 2018 Ridha Ghayoula


istart := '1';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := (slave_addr & '0'); -- write to slave (R/W = '0')
end if;

when t2 => -- send read temperature command


if (cmd_ack = '1') then
nxt_state := t3;
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;

istart := '0';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := x"AA";
end if;

when t3 => -- send (repeated) start condition, send slave address + read
if (cmd_ack = '1') then
nxt_state := t4;
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received, expected ACK
end if;

istart := '1';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := (slave_addr & '1'); -- read from slave (R/W = '1')
end if;

when t4 => -- read MSB (hi-byte), send acknowledge


if (cmd_ack = '1') then
nxt_state := t5;
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;

istart := '0';
iread := '1';
iwrite := '0';
iack := '0'; --ACK
istop := '0';
end if;

when t5 => -- read LSB (lo-byte), send acknowledge, sent stop


if (cmd_ack = '1') then

Page | 289 © ISI 2018 Ridha Ghayoula


nxt_state := t1;
istart := '0';
iread := '1';
iwrite := '0';
iack := '1'; --NACK
istop := '1';
istore_dout := '1';
end if;
end case;

-- genregs
if (nReset = '0') then
state <= i1;
error <= '0';
store_dout <= '0';
start <= '0';
read <= '0';
write <= '0';
ack <= '0';
stop <= '0';
D <= (others => '0');
elsif (clk'event and clk = '1') then
state <= nxt_state;
error <= ierr;
store_dout <= istore_dout;

start <= istart;


read <= iread;
write <= iwrite;
ack <= iack;
stop <= istop;
D <= iD;
end if;
end process nxt_state_decoder;
end block init_statemachine;

-- store temp
gen_dout : process(clk)
begin
if (clk'event and clk = '1') then
if (store_dout = '1') then
Dout <= i2c_dout;
end if;
end if;
end process gen_dout;
end architecture structural;
-- State machine for reading data from Dallas 1621
-- Testsystem for i2c controlle
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.i2c.all;
entity DS1621_interface is
port (
clk : in std_logic;
nReset : in std_logic;

Page | 290 © ISI 2018 Ridha Ghayoula


Dout : out std_logic_vector(7 downto 0); -- data read from ds1621
error : out std_logic; -- no correct ack received
SCL : inout std_logic;
SDA : inout std_logic
);
end entity DS1621_interface;

architecture structural of DS1621_interface is


constant SLAVE_ADDR : std_logic_vector(6 downto 0) := "1001000";
constant CLK_CNT : unsigned(7 downto 0) := conv_unsigned(20, 8);
signal cmd_ack : std_logic;
signal D : std_logic_vector(7 downto 0);
signal lack, store_dout : std_logic;

signal start, read, write, ack, stop : std_logic;


signal i2c_dout : std_logic_vector(7 downto 0);

begin
-- hookup I2C controller
u1: simple_i2c port map (clk => clk, ena => '1', clk_cnt => clk_cnt, nReset => nReset,
read => read, write => write, start => start, stop => stop, ack_in => ack, cmd_ack => cmd_ack,
Din => D, Dout => i2c_dout, ack_out => lack, SCL => SCL, SDA => SDA);

init_statemachine : block
type states is (i1, i2, i3, i4, i5, t1, t2, t3, t4, t5);
signal state : states;
begin
nxt_state_decoder: process(clk, nReset, state)
variable nxt_state : states;
variable iD : std_logic_vector(7 downto 0);
variable ierr : std_logic;
variable istart, iread, iwrite, iack, istop : std_logic;
variable istore_dout : std_logic;
begin
nxt_state := state;
ierr := '0';
istore_dout := '0';
istart := start;
iread := read;
iwrite := write;
iack := ack;
istop := stop;
iD := D;
case (state) is
-- init DS1621
-- 1) send start condition
-- 2) send slave address + write
-- 3) check ack
-- 4) send "access config" command (0xAC)
-- 5) check ack
-- 6) send config register data (0x00)
-- 7) check ack
-- 8) send stop condition
-- 9) send start condition
-- 10) send slave address + write
-- 11) check ack
-- 12) send "start conversion" command (0xEE)

Page | 291 © ISI 2018 Ridha Ghayoula


-- 13) check ack
-- 14) send stop condition

when i1 => -- send start condition, sent slave address + write


nxt_state := i2;
istart := '1';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := (slave_addr & '0'); -- write to slave (R/W = '0')

when i2 => -- send "access config" command


if (cmd_ack = '1') then
nxt_state := i3;
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;
istart := '0';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := x"AC";
end if;

when i3 => -- send config register data, sent stop condition


if (cmd_ack = '1') then
nxt_state := i4;
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;
istart := '0';
iread := '0';
iwrite := '1';
iack := '0';
istop := '1';
iD := x"00";
end if;

when i4 => -- send start condition, sent slave address + write


if (cmd_ack = '1') then
nxt_state := i5;
istart := '1';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := (slave_addr & '0'); -- write to slave (R/W = '0')
end if;

when i5 => -- send "start conversion" command + stop condition


if (cmd_ack = '1') then
nxt_state := t1;
-- check aknowledge bit

Page | 292 © ISI 2018 Ridha Ghayoula


if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;

istart := '0';
iread := '0';
iwrite := '1';
iack := '0';
istop := '1';
iD := x"EE";
end if;
-- read temperature
-- 1) sent start condition
-- 2) sent slave address + write
-- 3) check ack
-- 4) sent "read temperature" command (0xAA)
-- 5) check ack
-- 6) sent start condition
-- 7) sent slave address + read
-- 8) check ack
-- 9) read msb
-- 10) send ack
-- 11) read lsb
-- 12) send nack
-- 13) send stop condition

when t1 => -- send start condition, sent slave address + write


if (cmd_ack = '1') then
nxt_state := t2;
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;

istart := '1';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := (slave_addr & '0'); -- write to slave (R/W = '0')
end if;
when t2 => -- send read temperature command
if (cmd_ack = '1') then
nxt_state := t3;
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;
istart := '0';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := x"AA";
end if;

when t3 => -- send (repeated) start condition, send slave address + read

Page | 293 © ISI 2018 Ridha Ghayoula


if (cmd_ack = '1') then
nxt_state := t4;
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received, expected ACK
end if;
istart := '1';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := (slave_addr & '1'); -- read from slave (R/W = '1')
end if;

when t4 => -- read MSB (hi-byte), send acknowledge


if (cmd_ack = '1') then
nxt_state := t5;
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;

istart := '0';
iread := '1';
iwrite := '0';
iack := '0'; --ACK
istop := '0';
end if;

when t5 => -- read LSB (lo-byte), send acknowledge, sent stop


if (cmd_ack = '1') then
nxt_state := t1;

istart := '0';
iread := '1';
iwrite := '0';
iack := '1'; --NACK
istop := '1';
istore_dout := '1';
end if;
end case;
-- genregs
if (nReset = '0') then
state <= i1;
error <= '0';
store_dout <= '0';
start <= '0';
read <= '0';
write <= '0';
ack <= '0';
stop <= '0';
D <= (others => '0');
elsif (clk'event and clk = '1') then
state <= nxt_state;
error <= ierr;
store_dout <= istore_dout;
start <= istart;

Page | 294 © ISI 2018 Ridha Ghayoula


read <= iread;
write <= iwrite;
ack <= iack;
stop <= istop;
D <= iD;
end if;
end process nxt_state_decoder;
end block init_statemachine;
-- store temp
gen_dout : process(clk)
begin
if (clk'event and clk = '1') then
if (store_dout = '1') then
Dout <= i2c_dout;
end if;
end if;
end process gen_dout;
end architecture structural;

Page | 295 © ISI 2018 Ridha Ghayoula


14
Synthese d'un filtre FIR passe-bas pour les
Signaux ECG
14.1. Introduction
L'électrocardiogramme (ECG) est un signal qui représente l'activité électrique du coeur. L'ECG est un
élément essentiel que ce soit dans la surveillance des patients ou dans le diagnostic des maladies
cardiovasculaires. Les bases théoriques et pratiques de l’enregistrement de l'activité électrique cardiaque
ont été énoncées par Einthoven en 1901 et, même si les postulats proposés sont très discutables, ils sont
encore utilisés dans l’électrocardiographie. Dans les paragraphes qui suivent, nous décrivons brièvement
l'onde d'activation du coeur, les modes d'enregistrement de cette activité électrique et les principales
caractéristiques fréquentielles présentées par l'ECG.

14.2. ECG
Il est évident que l'une des étapes les plus critiques dans le traitement du signal numérique ECG est
le filtrage du bruit car les signaux ECG sont bruyamment affectés par de nombreuses sources
différentes telles que Baseline Wander, EMG et bruit de ligne électrique. Ces bruits peuvent être
réduits par de nombreux filtres, comme indiqué sur la figure ci-dessus. Ce projet consiste à mettre en
œuvre un filtre FIR passe-bas dans VHDL pour réduire le bruit de haute fréquence et les
interférences de ligne de puissance
La spécification du filtre est la suivante :

Commande : 10
Tap: 11
Les coefficients entiers signés de 8 bits sont les suivants:
Coefficient b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10
8 bits Interger -15 -13 7 38 66 78 66 38 7 -13 -15
Hexadecimal F1 F3 07 26 42 4E 42 26 07 F3 F1

Dans ce chapitre, la mise en œuvre régulière du filtre FIR comme indiqué dans la figure suivante est
implémentée dans VHDL.

Page | 296 © ISI 2018 Ridha Ghayoula


x[n] Z-1 Z-1 Z-1

b0 b1 b2 bN

y[n]
∑ ∑ ∑

Figure 14.1. Filtre

14.2. Filtre à réponse impulsionnelle finie


En traitement du signal, un filtre à réponse impulsionnelle finie ou filtre RIF (en anglais Finite Impulse
Response filter ou FIR filter) est un filtre dont la réponse impulsionnelle est de durée finie.

On parle le plus souvent de filtre RIF pour des filtres à temps discret. Un filtre numérique RIF est
caractérisé par une réponse uniquement basée sur un nombre fini de valeurs du signal d'entrée. Par
conséquent, quel que soit le filtre, sa réponse impulsionnelle sera stable et de durée finie, dépendante du
nombre de coefficients du filtre. Les termes de filtre non récursif ou de filtre à moyenne mobile sont
parfois employés pour nommer la même classe de filtres, bien que l'expression de filtre à moyenne
mobile désigne en premier lieu les filtres passe-bas.

Parmi les filtres linéaires, les filtres à réponse impulsionnelle finie sont opposés aux filtres à réponse
impulsionnelle infinie (filtre RII) qui ne peuvent être réalisés que par une implémentation récursive.

De façon générale le filtre à réponse impulsionnelle finie est décrit par la combinaison linéaire
suivante où xi 1in représente les valeurs du signal d'entrée et yi 1in les valeurs du signal de sortie.

yn  b0 .xn  b1.xn  1  b2 .xn  2  ...  bN .xn  N 

En utilisant le symbole de sommation, l'équation peut être réécrite de la façon suivante :


N
yn   bk .xn  k  .
k 0
Puisque la réponse est une somme d'un nombre fini de valeurs, le filtre RIF est naturellement stable
d'après le critère Entrée Bornée/Sortie Bornée.

Les filtres numériques peuvent être réalisés à l'aide de trois éléments ou opérations de base. Soit
l'élément gain, l'élément de sommation et le retard unitaire. Ces éléments sont suffisants pour
réaliser tous les filtres numériques linéaires possibles. La réalisation présentée dans la figure ci-contre
est une réalisation directe de type 1 du filtre RIF.

Des logiciels comme MATLAB ou GNU Octave proposent des fonctions pour la conception de ce
genre de filtres

Page | 297 © ISI 2018 Ridha Ghayoula


x[n] Z-1 Z-1 Z-1

b0 b1 b2 bN

y[n]
∑ ∑ ∑

Figure 14.2. Filtre à réponse impulsionnelle finie

Le filtre FIR est fondamentalement mis en œuvre en utilisant des D-Flip-Flops, des multiplicateurs
signés et des additionneurs. Un bloc de base comprend un registre N-bit, un multiplicateur et un
additionneur. L'instruction de génération VHDL est utilisée pour générer la conception complète à
l'aide du bloc de base.
Code VHDL pour le filtre FIR passe-bas:
Library IEEE;
USE IEEE.Std_logic_1164.all;
USE IEEE.Std_logic_signed.all;

entity FIR_RI is -- VHDL projects


generic (
input_width : integer :=8 ;-- set input width by user
output_width : integer :=16 ;-- set output width by user
coef_width : integer :=8 ;-- set coefficient width by user
tap : integer :=11 ;-- set filter order
guard : integer :=0) ;-- log2(tap)+1
port(
Din : in std_logic_vector(input_width-1 downto 0) ;-- input data
Clk : in std_logic ;-- input clk
reset : in std_logic ;-- input reset
Dout : out std_logic_vector(output_width-1 downto 0)) ;-- output data
end FIR_RI;
architecture behaivioral of FIR_RI is
-- N bit Register
component N_bit_Reg
generic (
input_width : integer :=8
);
port(
Q :out std_logic_vector(input_width-1 downto 0);
Clk :in std_logic;
reset :in std_logic;
D :in std_logic_vector(input_width-1 downto 0)
);

Page | 298 © ISI 2018 Ridha Ghayoula


end component;
type Coeficient_type is array (1 to tap) of std_logic_vector(coef_width-1 downto 0);
-----------------------------------FIR filter coefficients-------------------------------------------------------------
constant coeficient: coeficient_type :=
( X"F1",
X"F3",
X"07",
X"26",
X"42",
X"4E",
X"42",
X"26",
X"07",
X"F3",
X"F1"
);
----------------------------------------------------------------------------------------------
type shift_reg_type is array (0 to tap-1) of std_logic_vector(input_width-1 downto 0);
signal shift_reg : shift_reg_type;
type mult_type is array (0 to tap-1) of std_logic_vector(input_width+coef_width-1 downto 0);
signal mult : mult_type;
type ADD_type is array (0 to tap-1) of std_logic_vector(input_width+coef_width-1 downto 0);
signal ADD: ADD_type;
begin
-- fpga4student.com: FPGA projects, VHDL projects, Verilog projects
shift_reg(0) <= Din;
mult(0)<= Din*coeficient(1);
ADD(0)<= Din*coeficient(1);
GEN_FIR:
for i in 0 to tap-2 generate
begin
-- N-bit reg unit
N_bit_Reg_unit : N_bit_Reg generic map (input_width => 8)
port map ( Clk => Clk,
reset => reset,
D => shift_reg(i),
Q => shift_reg(i+1)
);
-- filter multiplication
mult(i+1)<= shift_reg(i+1)*coeficient(i+2);
-- filter conbinational addition
ADD(i+1)<=ADD(i)+mult(i+1);
end generate GEN_FIR;
Dout <= ADD(tap-1);
end Architecture;
Library IEEE;

Page | 299 © ISI 2018 Ridha Ghayoula


USE IEEE.Std_logic_1164.all;
-- LOW pass FIR filter for ECG Denoising
-- VHDL project: VHDL code for FIR filter
-- N-bit Register in VHDL
entity N_bit_Reg is
generic (
input_width : integer :=8
);
port(
Q : out std_logic_vector(input_width-1 downto 0);
Clk :in std_logic;
reset :in std_logic;
D :in std_logic_vector(input_width-1 downto 0)
);
end N_bit_Reg;

architecture Behavioral of N_bit_Reg is


begin
process(Clk,reset)
begin
if (reset = '1') then
Q <= (others => '0');
elsif ( rising_edge(Clk) ) then
Q <= D;
end if;
end process;
end Behavioral;

Code VHDL Testbench pour le filtre FIR:


Library IEEE;
USE IEEE.Std_logic_1164.all;
USE IEEE.numeric_std.all;
Use STD.TEXTIO.all;
-- Testbench VHDL code for FIR Filter
entity TB_FIR is
end TB_FIR;
architecture behaivioral of TB_FIR is
Component FIR_RI is
generic (
input_width : integer :=8 ; -- set input width by user
output_width : integer :=16 ; -- set output width by user
coef_width : integer :=8 ; -- set coefficient width by user
tap : integer :=11 ; -- set filter order
guard : integer :=4) ; -- log2(tap)+1
port(
Din : in std_logic_vector(input_width-1 downto 0) ; -- input data

Page | 300 © ISI 2018 Ridha Ghayoula


Clk : in std_logic ; -- input clk
reset : in std_logic ; -- input reset
Dout : out std_logic_vector(output_width-1 downto 0)) ;-- output data
end Component;
signal Din : std_logic_vector(7 downto 0) ;
signal Clk : std_logic:='0' ;
signal reset : std_logic:='1' ;
signal output_ready : std_logic:='0';
signal Dout : std_logic_vector(15 downto 0) ;
signal input : std_logic_vector(7 downto 0);
file my_input : TEXT open READ_MODE is "input101.txt";
file my_output : TEXT open WRITE_MODE is "output101_functional_sim.txt";
begin
FIR_int : FIR_RI
generic map(
input_width => 8,
output_width => 16,
coef_width => 8,
tap => 11,
guard => 0)
port map (
Din => Din,
Clk => Clk,
reset => reset,
Dout => Dout
);
process(clk)
begin
Clk <= not Clk after 10 ns;
end process;
reset <= '1', '1' after 100 ns, '0' after 503 ns;
-- Writing output result to output file
process(clk)
variable my_input_line : LINE;
variable input1: integer;
begin
if reset ='1' then
Din <= (others=> '0');
input <= (others=> '0');
output_ready <= '0';
elsif rising_edge(clk) then
readline(my_input, my_input_line);
read(my_input_line,input1);
Din <= std_logic_vector(to_signed(input1, 8));
--Din<=input(7 downto 0);
output_ready <= '1';

Page | 301 © ISI 2018 Ridha Ghayoula


end if;
end process;
process(clk)
variable my_output_line : LINE;
variable input1: integer;
begin
if falling_edge(clk) then
if output_ready ='1' then
write(my_output_line, to_integer(signed(Dout)));
writeline(my_output,my_output_line);
end if;
end if;
end process;
end Architecture;

Page | 302 © ISI 2018 Ridha Ghayoula


15
Programmation des microcontrôleurs PIC en
langage C
15.1. Introduction

Ce chapitre est une initiation au développement en Langage C sur les systèmes embarqués. Ce
chapitre s’appuie sur le microcontrôleur PIC. On présente brièvement l'environnement système, les
chaînes de développement, le Langage C et on illustre les applications classiques de ces systèmes
spécialisés.
Ce document essaie d'illustrer les différences entre les deux contextes d'utilisation avec et sans noyau
de système d'exploitation. Le maximum d'exemples de programmes sont présentés dans ce chapitre.

15.2. Organisation générale d’un compilateur C

Figure 15.1. Organisation générale d’un compilateur C

Page | 303 © ISI 2018 Ridha Ghayoula


Le langage C est un langage de programmation évolué, typé, modulaire et structuré :
•Evolué : Le code est indépendant du processeur utilisé
•Typé : Un type est l’ensemble des valeurs que peut prendre une variable
•Entiers, réels, caractères etc ... ou à définir par le programmeur
•Modulaire et structuré : Tout programme est décomposable en tâches simples (3 structures
algorithmiques de base) qui seront regroupées sous forme de modules (fonctions) qui eux même
regroupés de façon cohérente en tâches plus complexes (structurés) formeront le programme.

15.3. La Syntaxe du C : le premier programme

Main : fonction principale et point d’entrée du programme.


Void : indique qu’il n’y pas de paramètre d’entrée.
15.4. Variables.équivalences et constantes.
Types Longueur Domaine de valeurs
Char 8 bits -128 à 127
Unsigned char 8 bits 0 à 255
Int 16 bits -32768 à 32767
Unsigned int 16 bits 0 à 65535
long 32 bits -2,147,483,648 à 2,147,483,647
Unsigned long 32 bits 0 à 4,294,967,295
float 32 bits 3.4 * (10**-38) à 3.4 * (10**+38)
double 64 bits 1.7 * (10**-308) à 1.7 * (10**+308)
Exemple de déclaration
char a,b,c ; /* trois caractères*/
 les données peuvent être regroupées en tableaux :
int table[100] ; /*tableau de 100 entiers*/

Page | 304 © ISI 2018 Ridha Ghayoula


char tableau[]={10,0x1c,’A’,55,4}; /* tableau de 5 caractères*/
char *chaine= “bonjour” ; /*chaîne de 8 caractères (finie par 0)*/
le symbole * désigne un pointeur sur un type défini
char *p ; /* p est un pointeur sur des caractères*/

Equivalences : déclarées après la directive #define elles sont remplacées par leur valeur lors de la
compilation
#define pi 3.14
#define fruit pomme
!Attention il n’y a pas de ; après une directive #define

Constantes : elles sont rangées dans la ROM (dans la RAM en lecture seule sur un PC) et ne sont
donc pas modifiables.
Const int i=16569, char c=0x4c ;

Variables: elles sont rangées dans la RAM soit à une adresse fixe (statique) soit dans une pile
LIFO (dynamique)
char a,b=28,c=’A’ ;/* trois caractères dont 2 initialisés*/

auto est le contraire de static pour une variable locale. C’est une variable crée et détruite
automatiquement (attribut par défaut).
near indique une adresse sur 16 bits au contraire de far sur 21 bits
volatile indique une variable modifiable par l’environnement (un PORT par exemple) const qui
indique une constante (ROM). La distinction ROM/RAM n’est pas possible sur tous les systèmes
(ex les PC) .
Variables Accès Visibilité Exemple
Globale Adresse fixe Déclarée en dehors d'une fonction,visible Char c;
partout
locale Pile (perdre à la sortie ) Déclarée et visible dans une fonction Void fonction (void) {char
c;,...}
Statique Adresse fixe Déclarée et visible dans une fonction Void fonction (void)
{static char c;,...}
Externe Déclarée initialisée dans une bibliothèque extern char c;
externe

15.5. Les opérateurs

Page | 305 © ISI 2018 Ridha Ghayoula


15.6. Les boucles
 For est utilisé lorsque l’on connaît à l’avance le nombre d’itérations d’une boucle.

Dans cet exemple les accolades sont superflues, il n’y a qu’une instruction dans la boucle)

Page | 306 © ISI 2018 Ridha Ghayoula


 While (expression)
{instructions}, tant que l’expression est vraie (! =0) la boucle est effectuée , la boucle peut ne jamais
être effectuée

Tant que « condition de continuation » faire « traitement »

 Do {instructions} while (expression), comme while mais la boucle est effectuée au moins
une fois

15.7. Branchements conditionnels :


 if else Une fonction qui est “vraie” si son paramètre est une voyelle

Si « condition » alors« action 1 » sinon « action 2 »


 switch case
Le même fonction

Page | 307 © ISI 2018 Ridha Ghayoula


Selon cas faire :
Cas1 : « traitement 1 »
Cas2 : « traitement 2 »
Cas3 : « traitement 3 »
etc..

L’instruction break permet de sortir de la boucle en cours (for, while, do while, switch l’instruction
continue permet de sauter directement à l’itération suivante d’une boucle
for(i=0 ;i<100 ;i++) { if (i<50) continue else putchar(i);}
exit permet de quitter directement le programme (inutile sur micro contrôleur)

15.8. Les pointeurs


 Ce sont des variables particulières qui contiennent l’adresse d’une variable, elles ont
toujours le même format, sur PIC18 ( par exemple) un pointeur est une valeur sur 16bits ou
20 bits.
 Un pointeur est déclaré par une * précédée du type de donnée pointée
 Le signe & devant une donnée indique l’adresse de celle ci et sa valeur
 char *p ; déclare un pointeur p sur un caractère
 float *f ; déclare une pointeur sur un réel.
 char *fonction(void) déclare une fonction qui retourne un pointeur sur un caractère
 Void (*fonction) (void) déclare un pointeur sur une fonction
 void (*fonction) (void) = 0x8000 crée un pointeur sur une fonction en 8000

Exemples de manipulation de pointeurs


int a=1,b=2,c ; /*trois entiers dont deux initialisés*/
int *p1,*p2 ;/*deux pointeurs sur des entiers*/
p1=&a ; /*p1 contient l’adresse de la variable a*/
p2=p1 ; /*p2 contient maintenant aussi l’adresse de a*/
c=*p1 ; /*c égale le contenue de l’adresse pointé par p1 donc c=a*/
p2=&b ; /*p2 pointe b*/
*p2=*p1 /*la donnée à l’adresse pointé par p2 est placée dans l’adresse
pointé par p1, cela revient à donc recopier a dans b*/

Page | 308 © ISI 2018 Ridha Ghayoula


Lors de l’appelle par echange (x, y), les variables i,j,k sont localement crées dans la pile, i=x, j=y. i
et j sont échangé mais pas x et y

La fonction echange qui fonctionne s’écrit comme cela :

i et j représente maintenant les adresses de x et y. k prend bien la valeur de x, i celle de j puis j celle
de k. Les valeur x et y ont alors été échangées.

15.9. Les Tableaux


Un tableau est un regroupement dans une même variable de variables de même type
int chiffres[ ]={10,11,12,13,14,15,16,17,18,19} /* un tableau de 10 entiers*/
chiffre[0]=10, et chiffre[3]=13
int TAB[20]={1,12,13} /* les 17 autres sont initialisés à 0*/
TAB correspond à l’adresse de début du tableau, donc
 TAB représente &TAB[0]
 TAB[0] représente *TAB

TAB+1 pointera la donnée suivante et non l’adresse suivante


TAB+i = &TAB[i]
Un tableau peut avoir n dimensions
char TAB[2][3]={{1,2,3},{4,5,6}} représente une matrice 2x3 initialisée,
1 2 3
4 5 6
TAB[1][1]=5
Les chaînes de caractères sont des tableaux de caractères finissant par 0,
une chaîne est entourée de " et est automatiquement terminée par \0
char message[]= "bonjour"; est la même chose que
char message[]={‘b’,’o’,’n’,’j’,’o’,’u’,’r’,\0} ;
on peut utiliser un pointeur pour traiter les chaînes de caractères
char *p= " bonjour " ;
while (*p !=0) putchar(*p++) ; /*équivalent à puts*/
 Conversions de types : CAST

Page | 309 © ISI 2018 Ridha Ghayoula


Lors d’un calcul les char sont automatiquement transformés en int.
Si nécessaire les transformations de type s’effectuent dans l’ordre
char -> int -> long -> float -> double
signed -> unsigned
Une transformation peut être forcée par un cast
float x ; int a=5 ; x=(float)a ; /* x vaudra 5.0 */
float x=5.6 ; int a ; a=(int)x ; /* a vaudra 5*/

 Initialisation d’un pointeur à une adresse absolue


#define PORTA *(unsigned char *)(0xF80) ex: var=PORTA
la valeur 0xF80 est transformée en un pointeur sur un char. PORTA est équivalent au contenu de
ce pointeur, donc au contenu de l’adresse 0xF80

15.10.Utilisation des pointeurs


Soit deux chaînes de caractères : char s [ ],t[ ] ;
La fonction strcpy(s,t) recopie la chaîne s dans la chaîne t

L’utilisation de pointeurs simplifie l’écriture

On préfèrera écrire

La proposition de la boucle tant que étant fausse si égale à zéro on peut écrire :

15.11. Structures
Une structure est un tableau dans lequel les variables peuvent être de types différents

Page | 310 © ISI 2018 Ridha Ghayoula


15.12. Champs de bits
On peut créer une structure « champ de bits ». Le premier élément est le bit 0. Le nom de l’élément
est suivi du nombre de bits utilisés.

Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0


RB7 GROUPE RB3 RB2 RB1 RB0

15.13. Union
Dans une UNION les champs partagent les mêmes adresses.

Page | 311 © ISI 2018 Ridha Ghayoula


15.14. Bibliothèque standard stdio.h
 puts(chaîne) ; affiche une chaîne de caractères
 char *gets(chaîne) ; saisie une chaîne de caractère au clavier finie par un RC et retourne un
pointeur sue le premier caractère de cette chaîne
 scanf(format, liste d’adresses) permet de saisir les données au clavier
 Ex scanf("%d%d%f " ,&a,&b,&c) ;
 attend la saisie de deux entiers puis d’un réel puis d’un RC. Le passage d’argument
par adresse est ici indispensable.
 printf(format, liste de valeurs) affiche la liste de valeur dans un format choisi
Exemple :

Formats des types sur printf et scanf


 %c (char)
 %s (chaîne de caractères, jusqu'au \0)
 %d (int)
 %u (entier non signé)
 %x ou X (entier affiché en hexadécimal)
 %f (réel en virgule fixe)
 %p (pointeur)
 % (pour afficher le signe %).
Page | 312 © ISI 2018 Ridha Ghayoula
 \ n nouvelle ligne
 \ t tabulation
 \ b backspace
 \ r retour chariot (même ligne)
 \ f form feed (nouvelle page)
 \ ' apostrophe
 \ \ antislash
 \ " double quote
 \ 0 nul
 char getchar(void) comme getch mais sur l’entrée standard
 int putchar(char) comme putch mais sur la sortie standard

Important : les fonctions puts, gets, printf, scanf etc.. utilisent pour acquérir ou envoyer un
caractère getchar et putchar. Ce principe rend le C très universel, seules getchar et putchar diffèrent
d’un système à l’autre. (l’écran peut être un tube cathodique ou des cristaux liquides, le clavier peut
être à 16 ou 120 touches ...)
Ctype.h test pour détecter des types ex: isdigit (chiffre) ou islower (minuscule)
Limits.h indique les limites des types
String.h traitement des chaînes, copie, concatène, recherche de sous chaîne etc.
Math.h fonctions mathématiques
stdlib.h conversion ascii vers nombre (atoi atof) génération d’un nombre aléatoire (rand,
srand) allocation dynamique de mémoire (malloc, calloc), tri (qsort)
time.h toutes les fonctions liée à l’heure et à la génération de nombre aléatoires

15.15. La récursivité en langage C


L’agorithme de tri QuickSort a été inventé par C.A.R Hoare en 1960. Il consiste à trier une partie
d’un tableau, délimitée par les indices gauches et droite. On choisit une valeur quelconque de ce sous
tableau. On recherche ensuite la position définitive de cette valeur, en plaçant toutes les valeurs
inférieures d’un coté et toutes les valeurs supérieures de l’autre sans les classer. On appelle trie
ensuite de manière récursive le coté des plus petits et celui des plus grands et cela jusqu’à ce que les
cotés traités soient réduits à un seul élément.

Page | 313 © ISI 2018 Ridha Ghayoula


 Les réels
 Représentation en virgule fixe

On affecte à la partie entière et à la partie décimale un certain nombre de bits. Le poids des bits est
positif pour la partie entière et négatif pour la partie décimale.

L’erreur absolue sur un réel représenté en virgule fixe est toujours inférieure à 2-m
Exemple : pour représenter le réel 5,635 sur 8 bits (4 pour la partie entière et 4 pour la partie
décimale) max 15,9375.
on obtient :
4+1+0.5+0.125 = 5.625 nombre le plus proche

23 22 21 20 2-1 2-2 2-3 2-4


0 1 0 1 1 0 1 0

Soit 0x5A
Un bit supplémentaire est nécessaire pour indiquer le signe (+/-)

Page | 314 © ISI 2018 Ridha Ghayoula


2n ....
27 128
26 64
25 32
24 16
23 8
22 4
21 2
20 1
2-1 0.5
2-2 0.25
2-3 0.125
2-4 0.0625
2-5 0.03125
2-6 0.015625
2-7 0.0078125
2-m ....

 Représentation en virgule flottante


r = Sm.M.10Se.E
r : réel à coder
Sm : signe de la matrice (0 = positif, 1 = négatif)
M : matrice
Se : signe de l’exposant
E : exposant
Un nombre réel codé en virgule flottante a cette aspect :

Sm se En E0 Mm M0

16, 32, 64 ou128 bits suivant les processeurs


et les compilateurs
Nb bits Exposant N Mantisse M
16 4 10
32 8 22
64 14 48
La mantisse représente les chiffres significatifs d’un réel inférieur à 0 codé en 2-n
Par exemple 245,36 a une mantisse égale à +24536 et un exposant égal à +3 : 245,36=0.24536. 103
Exemple de codage en virgule flottante :
-5,635 = -0,5635. 101 et 2-1+2-4+2-10=0.5634765
Sm Se E3 E2 E1 E0 M9 M8 M7 M6 M5 M4 M3 M2 M1 M0
1 0 0 0 0 1 1 0 0 1 0 0 0 0 0 1
1 0.5634765

Page | 315 © ISI 2018 Ridha Ghayoula


15.16. Installation des Programmes et Premiers simulations
Le but de cette partie est de se familiariser avec la suite logicielle « MPLAB Integrated Development
Environment » (v7.0) de Microchip afin de pouvoir utiliser les fonctions de bases de cet outil
développement à savoir : créer un projet, éditer et compiler un programme en assembleur, simuler
son fonctionnement et enfin programmer le microcontrôleur (μC). Les différentes fonctions sont
expliquées à travers deux programmes qui vous sont donnés.
Les microcontrôleurs PIC sont des microcontrôleurs fabriqués par la société Microchip qui fournit
par ailleurs gratuitement la plate-forme logiciel de développement MPLAB IDE.
a) Les outils pour réaliser une application.
Pour développer une application fonctionnant à l’aide d’un microcontrôleur, il faut disposer d’un
éditeur de programme, d’un compilateuret d’un programmateur

Compilateur: Programmateur
Fabriqué le programme Transfert le programme
du PC au PIC (hard+soft)

Editeur: Compilateur: Simulateur débuggeur:


écriture du programme en Transforme l'assembleur Vérification,mise au
assembleur en langage machine point,simulation

MPLAB IDE
 L’éditeur de programme est un logiciel permettant d’écrire le programme dans un langage de
programmation. Nous utiliserons le logiciel MPLAB IDE. Le fabricant Microchip fournit
gratuitement ce logiciel téléchargeable sur le site www.microchip.com.
 Le compilateur est un logiciel traduisant un programme écrit dans un langage donné (C,
basic, assembleur) en langage machine. Ce logiciel peut aussi comporter un « debugger »
permettant la mise au point du programme, et un simulateur permettant de vérifier son
fonctionnement. On utilisera le compilateur CC5X dans sa version gratuite téléchargeable
sur www.bknd.com . Cette version gratuite permet d'écrire environ 1ko de programme. On
peut alors intégrer CC5X dans l'environnement MPLAB. Ainsi CC5X devient un outil de
MPLAB dans lequel l'écriture, la simulation et le debugging du programme en C devient
alors possible.
 Le programmateur permet de transférer le programme compilé (langage machine) dans la
mémoire du microcontrôleur. Il est constitué d’un circuit branché sur le port COM ou USB
du PC, sur lequel on implante le PIC, et d’un logiciel permettant d’assurer le transfert. Il
existe différents logiciels, nous utiliserons Icprog ou WinPic800. De nos jours, il existe des
PIC programmable sur site. Les mises à jour du logiciel Icprog sont téléchargeables sur
www.seeit.fr.

b) Déclaration du compilateur CC5X dans MPLAB.


La déclaration du compilateur s'effectue une seule fois :
Lancez MPLAB IDE; ouvrez la fenêtre Projet > Set Language Tool Locations...

Page | 316 © ISI 2018 Ridha Ghayoula


Déclarer également le chemin de MPASM et MPLINK :

c) Création d'un nouveau projet.


Définition du projet avec l'assistant

Dans le menu Project, sélectionner Project Wizard. Cela lance un assistant permettant de
Définir certaines options du projet.

Page | 317 © ISI 2018 Ridha Ghayoula


Sélectionner un microcontrôleur

Page | 318 © ISI 2018 Ridha Ghayoula


Si la déclaration du compilateur n’a pas été faite, il convient de le faire.

Définir un chemin (browse...) pour la sauvegarde du projet.

15.16. PIC Carte Système/PIC16F877A


Une carte de developpement est un ensemble de circuit integrés précablés entre eux qui permet de
realiser des montages à diverses fins (pédagogiques, test...) sans devoir concevoir un circuit
exterieur. La carte que vous utiliserez dans ce laboratoire (representée par la Figure suivante) est
constituée des éléments suivants :

Page | 319 © ISI 2018 Ridha Ghayoula


Figure 15.2.PIC Carte Système/PIC16F877A

 Peut être un externe 12 V alimentation; peut également USB alimentation;


 À Bord puce MAX3232, ne série communication des expériences;
 le conseil peut fournir 5 V et 3.3 V tension;
 8-peu d'eau lampe expérience;
 Avec 12864 LCD interface;
 Avec 1602 LCD interface;
 Avec deux DS18B20 capteur de température interface ;
 Avec un récepteur infrarouge intégré tête, ne expérience de contrôle à distance ;
 Laissant la FAI télécharger port ;
 À Bord 4 M cristal ;
 CPU tous les IO port et alimentation VCC, 3.3 V, GND sont cités à l'extérieur pour faciliter
les différentes expériences fonctionnelles ;
 Avec quatre touches indépendantes, faites interruption et les expériences clés ;
 À Bord avec circuit de réinitialisation, peut être réinitialisé manuellement ;
 conseil de développement standard:

Un PC est relié via USB à une carte de développement appelée PIC16F877A.

MPLAB - Plate forme de développement


Pour écrire un programme PIC il vous faut :
 un éditeur de texte
 un assembleur
 un compilateur
 un simulateur pour tester le programme sur le micro
Tout cela est mis gracieusement à votre disposition par Microchip. Cela s'appelle MPLAB,
téléchargez-le et installez-le sur votre micro

Page | 320 © ISI 2018 Ridha Ghayoula


 A partir de 'Projects' tab, selectionnez l'option 'Project Wizard'

 Click sur 'Next' in the welcome window that appears

Page | 321 © ISI 2018 Ridha Ghayoula


 Sélectionnez le PIC désiré sur lequel vous voulez programmer ou construire votre projet et
cliquez sur 'Suivant'

Le HI-TECH C Compiler pour PIC10 / 12/16 unités MCU est en position libre, l' optimisation
de compilateur ANSI C. Il prend en charge tous les PIC10, PIC12 et dispositifs série PIC16, ainsi
que le dispositif de PIC14000 et l'amélioration de l' architecture MCU Mid-Range PIC®.
Le compilateur est disponible pour plusieurs systèmes d'exploitation, y compris 32 et 64 bits
de Windows, Linux et Apple OS X.

Page | 322 © ISI 2018 Ridha Ghayoula


Sélectionnez la suite d'outils active dont vous avez besoin; parmi la liste des suites d'outils données
(Habituellement, la suite d'outils HI-TECH Universal est préférée, si elle est installée)

Vérifiez si le contenu de ToolSuite répertorié contient un compilateur adapté à vos besoins de


programmation ("Compilateur C HI-TECH ANSI" dans le cas d'une suite d'outils HI-TECH
Universal) et cliquez sur "Suivant"

Page | 323 © ISI 2018 Ridha Ghayoula


Créez un nouveau fichier de projet à l'emplacement souhaité dans le nom souhaité.
Veillez à ce que le fichier de projet soit enregistré au format '* .mcp' et cliquez sur 'Suivant'

Dans la fenêtre suivante, ajoutez les fichiers que vous souhaitez ajouter à votre nouveau projet, si
nécessaire. Sinon, passez simplement cette étape en cliquant sur "Suivant".

Page | 324 © ISI 2018 Ridha Ghayoula


Maintenant, cliquez sur 'terminer' et votre nouveau projet est créé.

Maintenant, sélectionnez l'option 'Nouveau' dans l'onglet 'Fichier'.

Page | 325 © ISI 2018 Ridha Ghayoula


Sélectionnez l'option « Enregistrer sous » dans l'onglet « Fichier » et enregistrez le nouveau fichier
dans le même dossier que celui dans lequel vous avez créé le projet en sélectionnant une option
appropriée dans « enregistrer en tant que type » (en fonction du type de programme )
Exemple: C Fichiers source si vous faites de la programmation en C
Assembly Source Files si vous faites de la programmation dans la langue d'ASSEMBLAGE etc ...

Accédez à l'onglet "Projet" et sélectionnez l'option "Ajouter des fichiers au projet" et ajoutez le
fichier enregistré à l'étape précédente.

Page | 326 © ISI 2018 Ridha Ghayoula


 Le programmateur
Une fois le programme compilé, il faut le transférer dans la mémoire du microcontrôleur. Pour cela
il vous faut : Une petite interface matérielle

Figure 15.3. Interface de programmation par le port USB

Vous pouvez suivre une video ou les étapes sont détaillés [41].

 Un logiciel
Un logiciel qui assure le transfert des données entre le PC et le microcontrôleur (il est fourni avec le
programmateur) ou bien il se trouve sur le Web.
Je vous conseille de loin ICPROG , c'est le meilleur logiciel de programmation de PIC à l'heure
actuelle, et il a l'avantage d'être disponible en freeware.

15.17. Liaison Bluetooth entre un Microcontrôleur et Android


Voici une méthode pour faire communiquer un microcontrôleur avec un smartphone Android.
La liaison Bluetooth se fait par le profil Bluetooth SPP (Serial Port Profile), qui permet d'émuler une
connexion série. Cette méthode est donc compatible avec n'importe quel microcontrôleur ayant une
interface série (PIC, MSP430, Atmel AVR (Arduino), ...).

Page | 327 © ISI 2018 Ridha Ghayoula


15.17.1. Matériel
Votre smartphone (ou tout autre dispositif sous Android) doit avoir le bluetooth bien évidement et
doit tourner sur Android 2.0 minimum : les fonctions pour l'utilisation bluetooth ne sont présente
dans le SDK qu'à partir de l'API Level 5.
Le microcontrôleur doit pouvoir communiquer par une liaison série, aussi appelée RS232, ou
UART. Quelques exemples de microcontrôleur : PIC18F2550, PIC18F14K50, PIC18F1320,
PIC16F886, ... ou bien chez TI : MSP430G2231, MSP430G2452, ...

Enfin, il vous faut un transmetteur Bluetooth, qui sera connecté au microcontrôleur. Vous devez
choisir un transmetteur prenant en charge le profil SPP et compatible avec une liaison série. Il existe
de nombreux modules, avec une connexion DB9, DIP ou CMS.

Attention, selon votre microcontrôleur et le module que vous choisissez, vous aurez peut être besoin
d'une interface du type MAX232 afin de rendre les tensions compatibles entre elles. Le schéma de
droite est un exemple pour interfacer un module bluetooth prévu pour une connexion série sur un
PC (prise DB9) qui envoie un signal entre -10V et 10V et un PIC (signaux 0-5V).

Page | 328 © ISI 2018 Ridha Ghayoula


a) Microcontrôleur

Tout d'abord il faut relier le microcontrôleur au module, n'oubliez pas, le câblage est croisé : il faut
relier la pin TX du microcontrôleur à la pin RX du module bluetooth et inversement la pin RX avec
la TX du module. Il faut ensuite configurer le microcontrôleur et/ou le module bluetooth afin qu'ils
utilisent la même vitesse de connexion, le même baud rate.
Cette vitesse n'intervient pas pour la suite (pour Android) car la liaison bluetooth entre le module et
Android se fait par le protocole RFCOMM, qui va beaucoup plus vite que la liaison série. Le module
bluetooth se charge de faire la 'conversion' entre ces deux protocoles. Vous pouvez donc choisir le
baud rate que vous voulez.
Il n'y a pas de règle spéciale / de protocole pour l'envoi ou la réception des données pour le
microcontrôleur, il suffit d'envoyer les données simplement, comme pour une liaison série.

b) Le programme Android

Page | 329 © ISI 2018 Ridha Ghayoula


Nous allons créer une classe BtInterface qui regrouperas les fonctions pour envoyer, recevoir, ouvrir
et fermer la connexion, ... Pour simplifier la programmation, nous n'allons pas gérer l'association du
périphérique dans cette classe, ni l'activation du bluetooth. Il faudra donc passer par les
paramètresbluetooth pour associer le périphérique avec Android (Paramètres -> Sans fil et
réseaux -> Paramètres Bluetooth -> Rechercher des appareils), et ne pas oubliez d'activer le
bluetooth.

 Prérequis
Il vous faudra ajouter les permissions BLUETOOTH et BLUETOOTH_ADMIN afin de pouvoir
utiliser le bluetooth dans votre application. BLUETOOTH_ADMIN n'est nécessaire que pour la
découverte, l'association de périphériques et l'activation/désactivation du bluetooth.
Ajoutez ceci dans l'AndroidManifest.xml :

Ajoutez ceci dans l'AndroidManifest.xml :

3 classes spécifiques du SDK sont nécessaires :

 BluetoothDevice : Classe qui représente un périphérique bluetooth


 BluetoothAdapter : Classe qui représente le module bluetooth de votre Android, elle
permet de scanner les périphériques présents, d'activer / désactiver le bluetooth, ...
 BluetoothSocket : Classe qui permet d'obtenir les canaux d'écriture (émission) et de lecture
(réception) du périphérique

Pour pouvoir utiliser ces classes, il faut donc les importer :

La classe va donc contenir le 'périphérique', sa 'connexion', et ses canaux d'entrée et sortie :

Première étape : récupérer le BluetoothDevice de notre périphérique, pour cela, on utilise la


fonction getBondedDevices() de BluetoothAdapter qui permet d'obtenir la liste des
périphériques associés à Android. On récupère le module bluetooth par défaut d'Android avec la
fonction BluetoothAdapter.getDefaultAdapter().
Il suffit de chercher dans cette liste notre périphérique. On récupère ensuite le BluetoothSocket de
notre périphérique avec la fonction createRfcommSocketToServiceRecord(UUID uuid); Cette
fonction prend en paramètre un UUID, on utilise ici l'UUID 00001101-0000-1000-8000-
00805F9B34FB, qui indique une connexion 'port série'.
Les canaux d'émission/réception sont ensuite récupérés avec les fonctions getInputStream et
getOutputStream.

Page | 330 © ISI 2018 Ridha Ghayoula


Le module bluetooth n'a pas besoin d'être sous tension pour utiliser ces fonctions, les canaux seront
seulement invalides tant que celui-ci n'est pas connecté.

 Connexion
Pour se connecter, on utilise la fonction connect(); de BluetoothSocket. La connexion pouvant
prendre du temps, il est nécessaire de la lancer dans un autre thread pour éviter de bloquer
l'application.

 Envoi de données
Pour envoyer des données, on va tout simplement utiliser les fonctions write(...) de OutputStream

Page | 331 © ISI 2018 Ridha Ghayoula


 Réception de données
Pour recevoir des données, le plus simple est de faire un Thread qui va vérifier l'arrivé de données en
permanence. On utilise les fonctions read(...) et available() de InputStream pour lire ces données
et vérifier si de nouvelles sont disponibles.
Problème : on ne peut afficher les données depuis ce nouveau thread : Android impose de les
envoyer dans le thread de l'UI. On utilise donc la classe Handler. On doit alors modifier le
constructeur pour récupérer un Handler du thread de l'UI.

Page | 332 © ISI 2018 Ridha Ghayoula


Et dans le thread de l'UI, il suffit de créer un Handler et de le faire passer dans le constructeur de
notre classe.

 Déconnexion
Enfin, pour fermer la connexion, il y a la fonction close() de BluetoothSocket :

Page | 333 © ISI 2018 Ridha Ghayoula


16
Programmation des microcontrôleurs STM32

16.1. Introduction
Le microcontrôleur est un petit ordinateur qu’on peut trouver dans de nombreux appareils, comme
les téléphones mobiles et les machines à laver. En cas de dysfonctionnement, déboguer un
microcontrôleur reste une tache difficile à faire. Cette diffculté est liée principalement `a l’absence
d’un historique du fonctionnement du microcontrôleur.
Afin de répondre au besoin de pouvoir faire du débogage, les microcontrôleurs récents permettent
d’avoir des traces d’exécution. Un grand nombre de programmes embarqués sur les
microcontrôleurs s’appuient sur une boucle principale qui est parcourue indéfiniment, pour par
exemple lire les valeurs des capteurs. Par conséquent, à cause de cet aspect cyclique des programmes
embarqués, les traces contiennent une quantité importante d’information. De plus, l’absence de
données d’entrées et de sorties, ainsi que les optimisations du compilateur rendent l’analyse de ces
traces encore plus difficile. Les microcontrôleurs STMicroelectronics STM32 32 bits ARM Cortex-M
sont basés sur le processeur ARM® Cortex®-M et offrent une plus grande liberté aux utilisateurs de
MCU. C'est une gamme complète de produits 32 bits qui combine haute performance, capacités en
temps réel, traitement du signal numérique, faible consommation et basse tension, tout en assurant
intégration complète et facilité de développement. La vaste gamme inégalée de dispositifs STM32,
basée sur un cœur standard et accompagnée d'un large choix d'outils et de logiciels, est un choix
idéal pour les petits projets et pour toutes les décisions de plate-forme.

Page | 334 © ISI 2018 Ridha Ghayoula


16.2. Architecture

Figure 16.1. STM32F105xx and STM32F107xx connectivity line block diagram

Page | 335 © ISI 2018 Ridha Ghayoula


Figure 16.2. STM32F105xx and STM32F107xx connectivity line LQFP100 pinout

16.3. Les cartes d'évaluation STM32

Les microcontrôleurs STM32 sont pris en charge par une gamme complète d'outils d'évaluation,
allant des kits très abordables aux cartes de développement entièrement équipées pour les
applications haut de gamme. Ils permettent de mettre en œuvre la gamme complète de périphériques
et de fonctionnalités de chaque gamme de produits. Les outils d'évaluation sont également fournis
avec des solutions tierces qui utilisent un environnement de développement intégré et un
programmateur/débogueur intégré au circuit.

 Les cartes Nucleo STM32 permettent aux ingénieurs de conception d'essayer de nouvelles
idées et de créer rapidement des prototypes avec n'importe quel microcontrôleur STM32.
Toutes les cartes Nucleo sont fournies avec des connecteurs Arduino™ et les connecteurs
Morpho de STMicroelectronics pour des extensions matérielles simplifiées. Les utilisateurs
de cartes Nucleo STM32 ont libre accès au compilateur en ligne mbed, au kit de
développement logiciel (SDK) C/C++ en ligne mbed et à la communauté de développeurs
sur mbed.org. Développez une application complète en seulement quelques minutes.

Figure 16.3. Carte Nucleo STM32

Page | 336 © ISI 2018 Ridha Ghayoula


Figure 16.4. Carte Nucleo STM32

 Les kits de découverte STM32 constituent une approche complète et abordable pour
évaluer les exceptionnelles capacités des microcontrôleurs STM32. Ils incluent les
composants nécessaires, tels que des microphones MEMS, des capteurs et des écrans LCD
pour démontrer des fonctionnalités de dispositif spécifiques. Avec une bibliothèque HAL,
plusieurs exemples de logiciels et le programmateur/débogueur intégré, les kits de
découverte sont parfaits pour le prototypage.

Figure 16.5. STM32F0 Discovery Kit

 Les cartes d'évaluation STM32 incluent l'ensemble du matériel externe requis,


indispensable à l'utilisation de l'ensemble des fonctionnalités d'un microcontrôleur STM32.
Les cartes d'évaluation STM32 offrent un accès à toutes les broches du microcontrôleur, ce
qui permet de les considérer comme une conception de référence pour le développement
d'applications.

Page | 337 © ISI 2018 Ridha Ghayoula


Figure 16.6. STM32 VL Discovery Board

Le microcontroleur équipant cette carte est le bas de gamme de la serie STM32 mais le cœur ARM
Cortex-M3 est compatible avec toute la gamme de ce fabriquant. En particulier, les caractéristiques
de cette carte sont :
— processeur STM32F100RB, cœur Cortex-M3 cadencé à 24 MHz, 128 KB flash,
8 KB RAM,
— 7 canaux DMA, 3 USARTs, 2 SPIs, 2 I2C, ADC, DAC, RTC, horloges, deux chiens de garde,
— interface ST-Link par USB pour d everminer/programmer,
— résonateur externe rapide (HSE) 8 MHz,
— résonateur externe lent (LSE) 32768 Hz.
— deux LEDs (vert, bleu) connectées au port C (broches 8 et 9 ).

16.4. Contrôleur d'horloges et de resets (RCC)


Les périphériques du microcontrôleur sont pilotés par des horloges programmables. Au reset ces
horloges ne sont pas envoyées aux périphériques. Avant d'utiliser un périphérique il faut donc en
activer l'horloge. Il est également possible de faire un reset d'un périphérique par programme pour le
remettre dans son état initial (celui qu'il a après un reset physique).

16.4.1. Activation des horloges


Deux fonctions (selon le périphérique) permettent d'activer ou de désactiver l'horloge d’un
périphérique.

 Le premier paramètre désigne le périphérique dont on veut activer ou désactiver l'horloge. Il


peut prendre les valeurs décrites dans le tableau suivant :
RCC_APB2Periph_AFIO Horloge pour le contrôle des fonctions alternatives
des lignes (mémorisation d'états, génération
d'interruptions et redirection des lignes)
RCC_APB2Periph_GPIOA Horloge pour GPIOA
RCC_APB2Periph_GPIOB Horloge pour GPIOB
RCC_APB2Periph_GPIOC Horloge pour GPIOC
RCC_APB2Periph_GPIOD Horloge pour GPIOD
RCC_APB2Periph_GPIOE Horloge pour GPIOE
RCC_APB2Periph_ADC1 Horloge pour convertisseur analogique/numérique 1
RCC_APB2Periph_ADC2 Horloge pour convertisseur analogique/numérique 2
RCC_APB2Periph_TIM1 Horloge pour timer1
 Le second paramètre indique si l'horloge de ce périphérique est activée ou désactivée.
Il peut prendre les valeurs :ENABLE ou DISABLE

Page | 338 © ISI 2018 Ridha Ghayoula


 Le premier paramètre désigne le périphérique dont on veut activer ou désactiver l'horloge. Il
peut prendre les valeurs décrites dans le tableau suivant :
RCC_APB1Periph_TIM2 Horloge pour timer2
RCC_APB1Periph_TIM3 Horloge pour timer3
RCC_APB1Periph_TIM4 Horloge pour timer4
RCC_APB1Periph_TIM5 Horloge pour timer5
RCC_APB1Periph_TIM6 Horloge pour timer6
RCC_APB1Periph_TIM7 Horloge pour timer7
RCC_APB1Periph_DAC Horloge pour convertisseurs numérique/analogique
 Le second paramètre indique si l'horloge de ce périphérique est activée ou désactivée.
Il peut prendre les valeurs : ENABLE ou DISABLE

16.4.2. Reset des périphériques


Deux fonctions (selon le périphérique) permettent de mettre ou de sortir un périphérique en
mode reset.

 Le premier paramètre désigne le périphérique que l'on veut mettre en mode reset. Il peut
prendre mêmes valeurs que le 1er paramètre de la fonction RCC_APB2PeriphClockCmd
 Le second paramètre indique si le périphérique est mis en mode reset ou sorti du mode reset.
Il peut prendre les valeurs ENABLE ou DISABLE

 Le premier paramètre désigne le périphérique dont on veut faire un reset. Il peut prendre
les mêmes valeurs que le premier paramètre de la fonction RCC_APB1PeriphClockCmd
 Le second paramètre indique si le périphérique est mis en mode reset ou sorti du mode
reset. Il peut prendre les valeurs ENABLE ou DISABLE

16.5. Lignes d'entrée / sortie (GPIO)


Le STM32F107VC dispose de 80 lignes d'entrée/sortie constituées en 5 ports de 16 bits chacun.
Chaque ligne peut être indépendamment programmée comme entrée ou comme sortie numérique
ou analogique. De plus, la plupart des lignes sont connectées en interne à des contrôleurs de
périphériques du microcontrôleur qui les utilisent, selon le cas, comme entrée ou comme sortie. La
plupart des lignes d'entrée/sortie des périphériques internes peuvent être redirigées vers deux lignes
physiques au choix (fonction alternative directe ou redirigée).

16.5.1. Remise à l'état initial d'un port


La fonction GPIO_DeInit permet de mettre un port dans son état initial (comme après un reset)
Sa définition est la suivante:

Le paramètre désigne le port à réinitialiser. Il peut prendre les valeurs : GPIOA , GPIOB , GPIOC ,
GPIOD ou GPIOE

Page | 339 © ISI 2018 Ridha Ghayoula


16.5.2. Initialisation du fonctionnement des lignes d'un port
La fonction GPIO_Init permet d'initialiser les lignes d'un port. Elle utilise comme paramètre une
structure de données de type GPIO_InitTypeDef dont les champs sont les suivants :

Avant d'être utilisée par GPIO_Init cette structure doit être initialisée par la fonction
GPIO_StructInit définie comme suit :

 Le paramètre est un pointeur sur la structure de type GPIO_InitTypeDef à initialiser.

Avant d'utiliser la fonction pour initialiser les lignes il faut remplir les champs de cette structure en
utilisant valeurs suivantes :

Champ GPIO_Pin , il désigne la ou les lignes du port à programmer. Les valeurs possibles pour ce
champ sont : GPIO_Pin_0 à GPIO_Pin_15 ou GPIO_Pin_All, on peut également programmer
plusieurs lignes de la même façon en une seule fois en indiquant dans ce paramètre plusieurs valeurs
séparées par +

Champ GPIO_Mode , il suivantes :indique le mode de fonctionnement désiré pour cette ou ces
lignes. Il peut prendre les valeurs
Analogique GPIO_Mode_AIN Ligne en entrée analogique
GPIO_Mode_Out_OD Ligne en sortie analogique
Numérique GPIO_Mode_IN_FLOATING Ligne en entrée numérique sans état défini si elle n'est pas
connectée
GPIO_Mode_IPD Ligne en entrée numérique à 0 si elle n'est pasconnectée
GPIO_Mode_IPU Ligne en entrée numérique à 1 si elle n'est pas connectée
GPIO_Mode_Out_PP Ligne en sortie numérique (0 ou 1)
alternative GPIO_Mode_IN_FLOATING Ligne utilisée en entrée numérique pour sa fonction alternative.
GPIO_Mode_AF_PP Ligne utilisée en sortie numérique pour sa fonction alternative
La fonction GPIO_Init est définie comme suit :

 Le premier paramètre désigne le port à initialiser. Il peut prendre les valeurs : GPIOA ,
GPIOB , GPIOC , GPIOD ou GPIOE
 Le second paramètre est un pointeur sur une structure de type GPIO_InitTypeDef préparée
par la fonction GPIO_StructInit puis dont les champs ont été remplis en fonction du
fonctionnement désiré.

16.5.3. Lecture d'un port


La fonction GPIO_ReadInputData renvoie un entier sur 16 bits constitué par l'état des lignes en
entrée de ce port (le ième bit de cet entier vaut 0 ou 1 selon l'état de la ième ligne de ce port), sa
définition est la suivante :

 Le paramètre désigne le port à lire. Il peut prendre les valeurs : GPIOA , GPIOB , GPIOC ,
GPIOD ou GPIOE

Page | 340 © ISI 2018 Ridha Ghayoula


La fonction GPIO_ReadOutputData renvoie un entier sur 16 bits constitué par l'état des lignes en
sortie de ce port (le ième bit de cet entier vaut 0 ou 1 selon l'état de la ième ligne de ce port),
sa définition est la suivante :

 Le paramètre désigne le port à lire. Il peut prendre les valeurs : GPIOA , GPIOB , GPIOC ,
GPIOD ou GPIOE

16.5.4. Lecture d'une ligne d'un port


La fonction GPIO_ ReadInputDataBit renvoie 0 ou 1 selon l'état de la ligne en entrée de ce port
désignée par le second paramètre, sa définition est la suivante :

 Le premier paramètre désigne le port dont on veut lire une ligne en entrée. Il peut prendre
les valeurs : GPIOA , GPIOB , GPIOC , GPIOD ou GPIOE
 Le second paramètre désigne la ligne à lire. Il peut prendre les valeurs : GPIO_Pin_0 à
GPIO_Pin_15

La fonction GPIO_ ReadOutputDataBit renvoie 0 ou 1 selon l'état de la ligne en sortie de ce port


désignée par le second paramètre, sa définition est la suivante :

 Le premier paramètre désigne le port dont on veut lire une ligne en sortie. Il peut prendre les
valeurs : GPIOA , GPIOB , GPIOC , GPIOD ou GPIOE
 Le second paramètre désigne la ligne à lire. Il peut prendre les valeurs : GPIO_Pin_0 à
GPIO_Pin_15

16.5.5. Ecriture dans un port


La fonction GPIO_Write permet de modifier l'état des lignes en sortie, le second paramètre est un
entier dont la valeur du ième bit définit l'état de la ième ligne de ce port, sa définition est la suivante :

 Le premier paramètre désigne le port dans lequel on veut écrire. Il peut prendre les valeurs :
GPIOA , GPIOB , GPIOC , GPIOD ou GPIOE
 Le second paramètre est la valeur à écrire dans ce port (0 à 65535)

16.5.6. Mise à 0 ou à 1 d'une ligne d'un port


Les fonctions GPIO_SetBits et GPIO_ResetBits permettent de modifier l'état des lignes en sortie
(resp. mise à 1 ou à 0), leurs définitions sont les suivantes :

 Le premier paramètre désigne le port dont on veut modifier les lignes. Il peut prendre les
valeurs : GPIOA , GPIOB , GPIOC , GPIOD ou GPIOE
 Le second paramètre désigne les lignes à modifier. Il peut prendre les valeurs : GPIO_Pin_0
à GPIO_Pin_15 ou GPIO_Pin_All, on peut également modifier plusieurs lignes en une
seule fois en indiquant dans ce paramètre plusieurs valeurs séparées par +

Page | 341 © ISI 2018 Ridha Ghayoula


16.5.7. Ecriture dans une ligne d'un port
La fonction GPIO_WriteBit permet de modifier l'état des lignes en sortie, sa définition est la
suivante :

 Le premier paramètre désigne le port dans les lignes duquel on veut écrire. Il peut prendre
les valeurs : GPIOA , GPIOB , GPIOC , GPIOD ou GPIOE
 Le deuxième paramètre désigne la ligne à écrire. Il peut prendre les valeurs :
GPIO_Pin_0 à GPIO_Pin_15 ou GPIO_Pin_All, on peut également modifier plusieurs lignes en
une seule fois en indiquant dans ce paramètre plusieurs valeurs séparées par +
 Le dernier paramètre indique la valeur à donner à ces lignes. Il peut prendre les valeurs :
Bit_RESET ou Bit_SET

16.5.8. Guide d'utilisation des lignes d'E/S


a) Marche à suivre pour initialiser des lignes d'E/S
1. Déclarer une variable de type GPIO_InitTypeDef
2. Activer l'horloge du port par la fonction RCC_APB2PeriphClockCmd
3. Réinitialiser ce port par la fonction GPIO_DeInit
4. Initialiser la variable de type GPIO_InitTypeDef par la fonction GPIO_StructInit
5. Dans cette variable indiquer la ou les lignes à programmer et le mode (entrée/sortie
numérique/analogique/alternative)
6. programmer cette ou ces lignes par la fonction GPIO_Init
7. recommencer les étapes 5 et 6 pour les autres lignes du même port ayant un mode différent
8. recommencer les étapes 2 à 7 pour chaque port

Remarque : lors de l'étape 5 on peut désigner plusieurs lignes si elles doivent être programmées dans le même mode.

b) Consulter/modifier des lignes d'E/S


o Lecture de toutes les lignes en entrée d'un port par la fonction : GPIO_ReadInputData
o Lecture de toutes les lignes en sortie d'un port par la fonction : GPIO_ReadOutputData
o Lecture d'une ligne en entrée par la fonction : GPIO_ ReadInputDataBit
o Lecture d'une ligne en sortie par la fonction : GPIO_ ReadOutputDataBit
o Ecriture de toutes les lignes en sortie d'un port par la fonction : GPIO_Write
o Ecriture d'une ou de plusieurs lignes en sortie par l'une des fonctions : GPIO_SetBits ou
GPIO_ResetBits ou GPIO_WriteBit

16.5.9. Redirection des lignes connectées en interne à des contrôleurs de périphériques du


microcontrôleur (fonction alternative)
Les lignes utilisées comme entrées/sorties de contrôleurs de périphériques internes peuvent être
redirigées.
La fonction GPIO_PinRemapConfig permet de le faire. Sa définition est la suivante :

 Le premier paramètre désigne le périphérique dont les lignes sont redirigées. Les valeurs
possibles sont indiquées dans le tableau ci dessous :

Page | 342 © ISI 2018 Ridha Ghayoula


Valeur Ligne Sans redirection Avec redirection
TIM1_BKIN PB12 PA6
TIM1_CH1N PB13 PA7
GPIO_PartialRemap_TIM1
TIM1_CH2N PB14 PB0
TIM1_CH3N PB15 PB1
TIM1_ETR PA12 PE7
TIM1_CH1 PA8 PE9
TIM1_CH2 PA9 PE11
GPIO_FullRemap_TIM1 TIM1_CH3 PA10 PE13
TIM1_CH4 PA11 PE14
TIM1_BKIN PB12 PE15
TIM1_CH1N PB13 PE8
TIM1_CH2N PB14 PE10
TIM1_CH3N PB15 PE12
GPIO_PartialRemap1_TIM2 TIM2_CH1 = TIM2_ETR PA0 PA15
TIM2_CH2 PA1 PB3
GPIO_PartialRemap2_TIM2 TIM2_CH3 PA2 PB10
TIM2_CH4 PA3 PB11
TIM2_CH1 = TIM2_ETR PA0 PA15
GPIO_FullRemap_TIM2 TIM2_CH2 PA1 PB3
TIM2_CH3 PA2 PB10
TIM2_CH4 PA3 PB11
GPIO_PartialRemap_TIM3 TIM3_CH1 PA6 PB4
TIM3_CH2 PA7 PB5
TIM3_CH1 PA6 PC6
GPIO_FullRemap_TIM3 TIM3_CH2 PA7 PC7
TIM3_CH3 PB0 PC8
TIM3_CH4 PB1 PC9
GPIO_Remap_TIM4 TIM4_CH1 PB6 PD12
TIM4_CH2 PB7 PD13
TIM4_CH3 PB8 PD14
TIM4_CH4 PB9 PD15
GPIO_Remap_PD01 PD0 lignes OSC_IN
PD1 normales OSC_OUT
GPIO_Remap_TIM5CH4_LSI TIM5_CH4 PA3 Horloge interne pour
calibration
 Le second paramètre indique si la redirection est faite ou pas. Les valeurs possibles de ce
paramètre sont : ENABLE ou DISABLE

16.6. Contrôleur d'interruptions (NVIC)


Les interruptions liées aux périphériques du microcontrôleur utilisent 16 niveaux de priorité. Ces
niveaux peuvent être découpés en niveaux de préemption et sous niveaux de priorité. Une
interruption de niveau de préemption N sera prise en compte même si le processeur est en train
d'exécuter une procédure d'interruption de niveau supérieur à N. Tandis que la sous priorité est
utilisée pour classer les interruptions en attente.

16.6.1. Définition des niveaux de préemption et de sous priorité


La fonction suivante permet de découper les 16 priorités en niveaux de préemption et sous niveaux
de priorité.
Ce découpage s'applique à toutes les interruptions de périphériques.

Page | 343 © ISI 2018 Ridha Ghayoula


 Le paramètre désigne le découpage choisi. Les valeurs possibles sont décrites dans le
tableau suivant:
Niveaux de Sous Description
préemption priorité
NVIC_PriorityGroup_0 0 0-15 pas de niveaux de préemption 4 bits pour la sous priorité
NVIC_PriorityGroup_1 0-1 0-7 1 bit pour la préemption 3 bits pour la sous priorité
NVIC_PriorityGroup_2 0-3 0-3 2 bits pour la préemption 2 bits pour la sous priorité
NVIC_PriorityGroup_3 0-7 0-1 3 bits pour la préemption 1 bit pour la sous priorité
NVIC_PriorityGroup_4 0-15 0 4 bits pour la préemption pas de sous priorité

16.6.2. Définition de la priorité d'une interruption


Chaque interruption utilisée doit être affectée d'un niveau de préemption et d'un sous niveau de
priorité en accord avec le choix de découpage fait par la fonction précédente. La fonction
NVIC_Init permet de définir ces niveaux.
Elle utilise comme paramètre une structure de données de type NVIC_InitTypeDef dont les
champs sont les suivants :

Champ NVIC_IRQChannel, il indique l'interruption à programmer. Les valeurs possibles sont


données dans le tableau suivant :
ADC1_2_IRQn Interruption globale pour ADC1 et ADC2
EXTI0_IRQn Interruption de la ligne externe 0
EXTI1_IRQn Interruption de la ligne externe 1
EXTI2_IRQn Interruption de la ligne externe 2
EXTI3_IRQn Interruption de la ligne externe 3
EXTI4_IRQn Interruption de la ligne externe 4
EXTI9_5_IRQn Interruptions des lignes externes 5 à 9
EXTI15_10_IRQn Interruptions des lignes externes 10 à 15
TIM1_BRK_IRQn Interruption de Break de TIM1
TIM1_UP_IRQn Interruption de débordement de TIM1
TIM1_TRG_COM_IRQn Interruption trigger et communication de TIM1
TIM1_CC_IRQn Interruption de Capture Compare de TIM1
TIM2_IRQn Interruption de TIM2
TIM3_IRQn Interruption de TIM3
TIM4_IRQn Interruption de TIM4
TIM5_IRQn Interruption de TIM5
TIM6_IRQn Interruption de TIM6
TIM7_IRQn Interruption de TIM7
 Champ NVIC_IRQChannelPreemptionPriority, il définit le niveau de préemption.
Les valeurs possibles sont de 0 à 1, 2, 4 ou 15 selon le choix de découpage fait.
 Champ NVIC _IRQChannelSubPriority, il définit le niveau de sous priorité. Les
valeurs possibles sont de 0 à 1, 2, 4 ou 15 selon le choix de découpage fait.
 Champ FunctionalState , il indique si cette interruption est générée ou pas vers le
microcontrôleur. Les valeurs possibles sont : ENABLE ou DISABLE

Page | 344 © ISI 2018 Ridha Ghayoula


 Le paramètre est un pointeur sur une structure de type NVIC_InitTypeDef dont les
champs ont été remplis.

16.6.3. Procédures d'interruption


Lorsqu'une interruption a été activée, sa prise en compte est faite par une procédure d'interruption
dont le nom correspond à cette interruption. Les noms de ces procédures sont imposés et définis
dans le tableau suivant :
Cause de l'interruptionI Interruption nom de la procédure
IT globale pour ADC1 et ADC2 ADC1_2_IRQn ADC1_2_IRQHandler
IT de la ligne externe 0 EXTI0_IRQn EXTI0_IRQHandler
IT de la ligne externe 1 EXTI1_IRQn EXTI1_IRQHandler
IT de la ligne externe 2 EXTI2_IRQn EXTI2_IRQHandler
IT de la ligne externe 3 EXTI3_IRQn EXTI3_IRQHandler
IT de la ligne externe 4 EXTI4_IRQn EXTI4_IRQHandler
ITs des lignes externes 9 à 15 EXTI9_5_IRQn EXTI9_5_IRQHandler
ITs des lignes externes 10 à 15 EXTI15_10_IRQn EXTI15_10_IRQHandler
IT de Break de TIM1 TIM1_BRK_IRQn TIM1_BRK_IRQHandler
IT de débordement de TIM1 TIM1_UP_IRQn TIM1_UP_IRQHandler
IT trigger et communication de TIM1 TIM1 _TRG_COM_IRQn TIM1_TRG_COM_IRQHandler
IT de Capture Compare de TIM1 TIM1_CC_IRQn TIM1_CC_IRQHandler
IT de TIM2 TIM2_IRQn TIM2_IRQHandler
IT de TIM3 TIM3_IRQn TIM3_IRQHandler
IT de TIM4 TIM4_IRQn TIM4_IRQHandler
IT de TIM5 TIM5_IRQn TIM5_IRQHandler
IT de TIM6 TIM6_IRQn TIM6_IRQHandler
IT de TIM7 TIM7_IRQn TIM7_IRQHandler
16.6.4. Guide d'utilisation du contrôleur d'interruptions
o Déclarer une variable de type NVIC_InitTypeDef
o Programmer le découpage entre préemption et priorités par la fonction
NVIC_PriorityGroupConfig
o Initialiser la variable de type NVIC_InitTypeDef avec l'interruption à programmer, le
niveau de préemption, le niveau de priorité et activer ou désactiver l'IT
o Programmer l'IT par la fonction NVIC_Init
o Recommencer les étapes 3 et 4 pour chaque IT à programmer

Les procédures d'interruption ont des noms prédéfinis du type : xxx_IRQHandler (voir tableau
).

16.7. Mémorisation des changements d'état des lignes et génération


d'interruptions externes (EXTI)
Il est parfois nécessaire de déclencher une action lorsqu'une ligne change d'état (passe de 0 à 1 ou de
1 à 0). Si un programme teste l'état d'une ligne et la trouve à 0, puis, plus tard, revient tester l'état de
cette ligne et la trouve toujours à 0, comment savoir si entre ces deux tests elle n'est pas passée à 1 ?
Pour résoudre ce problème les ports peuvent être programmés pour mémoriser de tels changements
d'état. Un indicateur est alors positionné que le programme pourra lire puis effacer. De même les
ports peuvent être programmés pour générer une interruption lors d'un changement d'état. Les
lignes utilisées doivent avoir été programmées en mode entrée (GPIO_Mode_IN_FLOATING,
GPIO_Mode_IPD ou GPIO_Mode_IPU)

Page | 345 © ISI 2018 Ridha Ghayoula


16.7.1. Remise à l'état initial du détecteur de changements d'état et de génération
d'interruptions
La fonction suivante permet de mettre le détecteur de changements d'état et de génération
d'interruptions dans son état initial (comme après un reset). Sa définition est la suivante :

16.7.2. Choix de la ligne


La fonction suivante permet de choisir la ligne dont on veut mémoriser les changements d'état ou
que l'on veut utiliser en génération d'interruption :

 Le premier paramètre désigne le port dont on veut programmer une ligne. Il peut prendre les
valeurs : GPIO_PortSourceGPIOA à GPIO_PortSourceGPIOE
 Le deuxième paramètre désigne la ligne choisie. Les valeurs possibles sont :
GPIO_PinSource0 à GPIO_PinSource15

16.7.3. Programmation de la ligne


La fonction EXTI_Init permet d'initialiser les lignes d'un port pour détecter des changements
d'état. Elle utilise comme paramètre une structure de données de type EXTI_InitTypeDef dont les
champs sont les suivants :

Avant d'être utilisée par EXTI_Init cette structure doit être initialisée par la fonction
EXTI_StructInit définie comme suit :

 Le paramètre est un pointeur sur la structure de type EXTI_InitTypeDef à initialiser.

Avant d'utiliser la fonction pour programmer les lignes il faut remplir les champs de cette
structure en utilisant valeurs suivantes :

Champ EXTI_Line, il désigne la ou les lignes du port à programmer. Les valeurs possibles pour ce
champ sont : EXTI_Line0 à EXTI_Line15. On peut programmer plusieurs lignes en même temps
en mettant dans ce paramètre plusieurs valeurs séparées par des +

Champ EXTI_Mode, il indique si la ligne est programmée pour positionner un indicateur ou pour
générer une interruption. Les valeurs possibles sont :
EXTI_Mode_Event ou EXTI_Mode_Interrupt
Champ EXTI_Trigger, il indique quels changements d'état sont pris en compte. Les valeurs
possibles sont décrites dans le tableau ci-dessous :
EXTI_Trigger_Falling Détection des fronts descendants (passages de 1 à 0)
EXTI_Trigger_Rising Détection des fronts montants (passages de 0 à 1)
EXTI_Trigger_Rising_Falling Détection de tous les changements (passages de 1 à 0 et de 0 à 1)

Page | 346 © ISI 2018 Ridha Ghayoula


Champ EXTI_LineCmd, il permet d'activer ou de désactiver la détection de changement d'état sur
la ligne. Les valeurs possibles sont : ENABLE ou DISABLE

 Le paramètre est un pointeur sur une structure de type EXTI_InitTypeDef préalablement


initialisée par la fonction EXTI_StructInit puis dont les différents champs ont été remplis
en fonction du fonctionnement désiré.

16.7.4. Indicateurs de changement d'état


La fonction suivante permet de tester l'indicateur de changement d'état d'une ligne :

 Le paramètre désigne la ligne du port dont on veut tester l'indicateur de changement


d'état. Les valeurs possibles pour ce champ sont : EXTI_Line0 à EXTI_Line15.
 La valeur renvoyée par la fonction est l'état de cet indicateur. Les valeurs possibles sont :
SET ou RESET

La fonction suivante permet d'effacer l'indicateur de changement d'état d'une ligne :

 Le paramètre désigne la ligne du port dont on veut effacer l'indicateur de changement d'état.
Les valeurs possibles pour ce champ sont : EXTI_Line0 à EXTI_Line15.

16.7.5. Interruptions lors de changements d'état


Une interruption peut être générée lors d'un changement d'état. Les procédures d'interruption
associées sont EXTI0_IRQHandler pour les lignes 0 à EXTI4_IRQHandler pour les lignes 4,
EXTI9_5_IRQHandler pour les lignes 5 à 9 qui sont regroupées en une seule interruption et
EXTI15_10_IRQHandler pour les lignes 10 à 15 qui sont regroupées en une seule interruption.
La fonction suivante permet de tester si une interruption de changement d'état d'une ligne a
été levée :

 Le paramètre désigne la ligne du port dont on veut tester l'interruption. Les valeurs possibles
pour ce champ sont : EXTI_Line0 à EXTI_Line15.
 La valeur renvoyée par la fonction est l'état de cette interruption. Les valeurs possibles sont :
SET ou RESET
La fonction suivante permet d'effacer l'indicateur d'interruption d'une ligne :

 Le paramètre désigne la ligne du port dont on veut effacer l'interruption. Les valeurs
possibles pour ce champ sont : EXTI_Line0 à EXTI_Line15.

16.7.6. Guide d'utilisation des lignes d'E/S en mémorisation d'états ou en génération


d'interruptions
a) Marche à suivre pour initialiser des lignes d'E/S avec mémorisation d'état ou génération
d'interruptions
1. Idem étape 1 du 16.5.8.
2. Déclarer une variable de type EXTI_InitTypeDef

Page | 347 © ISI 2018 Ridha Ghayoula


3. Activer l'horloge du dispositif de mémorisation d'états et de génération d'ITs (AFIO) par la
fonction RCC_APB2PeriphClockCmd
4. Initialiser le dispositif de mémorisation d'états ou de génération d'ITs par la fonction
EXTI_DeInit
5. Programmer en entrée numérique la ligne utilisée (idem étapes 2 à 6 du 16.5.8.).
6. Initialiser la variable de type EXTI_InitTypeDef par la fonction EXTI_StructInit
7. Dans la variable de type EXTI_InitTypeDef indiquer la ligne, le mode (mémorisation d'état ou
génération d'IT), le front déclenchant et l'activer ou la désactiver
8. Programmer la détection par la fonction EXTI_Init
9. Choisir la ligne à utiliser par la fonction GPIO_EXTILineConfig
10. Recommencer les étapes 5 à 9 pour les autres lignes

b) Consulter/modifier des états mémorisés ou des indicateurs d'interruption des lignes


d'E/S
− Lecture de l'état mémorisé d'une ligne en entrée par la fonction EXTI_GetFlagStatus
− Effacement de l'état mémorisé d'une ligne en entrée par la fonction EXTI_ClearFlag
− Lecture de l'indicateur d'IT d'une ligne en entrée par la fonction EXTI_GetITStatus
− Effacement de l'indicateur d'IT d'une ligne en entrée par la fonction EXTI_ClearITPendingBit

16.8. Les Timers (TIM)


Le STM32F107VC dispose de 7 timers. Les timers TIM2 à TIM5 sont des timers d'usage général.
Les timers TIM6 et TIM7 sont des timers possédant moins de fonctionnalités. Le timer TIM1 est
une version plus complète.
Les fonctionnalités sont les suivantes :
Fonctionnalité TIM1 TIM2 à TIM5 TIM6 et TIM7
Compteur sur 16 bits OUI OUI OUI
Comptage en incrémentation ou décrémentation OUI OUI OUI
Rechargement automatique OUI OUI OUI
Pré division d'horloge OUI OUI OUI
Entrées pour capture OUI OUI NON
Sorties pour génération de signaux OUI OUI NON
Mode cycle unique OUI OUI NON
Sorties complémentaires OUI NON NON
Contrôle du timer par lignes externes OUI OUI NON
Interconnexion avec d'autres timers OUI OUI NON
Horloge externe OUI OUI NON
Déclenchement des convertisseurs A/N OUI OUI sauf T5 NON

16.8.1. Remise à l'état initial d'un timer


La fonction TIM_DeInit permet de mettre un timer dans son état initial (comme après un reset)
Sa définition est la suivante :

 Le paramètre désigne le timer à réinitialiser. Il peut prendre les valeurs : TIM1 à TIM7
16.8.2. Initialisation de la base de temps
La fonction TIM_TimeBaseInit permet d'initialiser la base de temps d'un timer. Elle utilise comme
paramètre une structure de données de type TIM_TimeBaseInitTypeDef dont les champs sont
les suivants :

Page | 348 © ISI 2018 Ridha Ghayoula


Avant d'être utilisée par TIM_TimeBaseInit cette structure doit être initialisée par la fonction
TIM_TimeBaseStructInit définie comme suit :

 Le paramètre est un pointeur sur la structure de type TIM_TimeBaseInitTypeDef à


initialiser.
Avant d'utiliser la fonction pour initialiser la base de temps d'un timer il faut remplir les champs de
cette structure en utilisant valeurs suivantes :

 Champ TIM_Prescaler, il définit la division d'horloge à appliquer au timer. Les valeurs


possibles pour ce champ sont 0 à 65535. La fréquence de l'horloge est divisée par cette
valeur+1 de sorte qu'une valeur de 0 provoque une division de la fréquence d'horloge par 1
c'est-à-dire pas de division d'horloge.
 Champ TIM_Period, il définit la limite de comptage du timer (période). Les valeurs
possibles pour ce champ sont 0 à 65535. Le timer parcours les valeurs de 0 à cette limite
incluse.
 Champ TIM_CounterMode, il définit le mode de comptage du timer. Les valeurs possibles
pour ce champ sont indiquées dans le tableau suivant :

Le timer compte de 0 à TIM_Period. Le débordement est signalé au top


TIM_CounterMode_Up d'horloge suivant lorsqu'il a atteint la valeur
TIM_Period

Le timer compte de TIM_Period à 0. Le débordement est signalé au top


TIM_CounterMode_Down
d'horloge suivant lorsqu'il a atteint la valeur 0

Le timer compte de 0 à TIM_Period puis de TIM_Period à 0. Le


TIM_CounterMode_CenterAligned1
débordement est signalé lorsqu'il atteint la valeur TIM_Period

Le timer compte de 0 à TIM_Period puis de TIM_Period à 0. Le


TIM_CounterMode_CenterAligned2
débordement est signalé lorsqu'il atteint la valeur 0

Le timer compte de 0 à TIM_Period puis de TIM_Period à 0. Le


TIM_CounterMode_CenterAligned3 débordement est signalé lorsqu'il atteint la valeur TIM_Period et lorsqu'il
atteint la valeur 0

La fonction TIM_TimeBaseInit est définie comme suit :

 Le premier paramètre désigne le timer à initialiser. Il peut prendre les valeurs : TIM1 à
TIM7

Page | 349 © ISI 2018 Ridha Ghayoula


 Le second paramètre est un pointeur sur une structure de type
TIM_TimeBaseInitTypeDef préparée par la fonction TIM_TimeBaseStructInit puis
dont les champs ont été remplis en fonction du fonctionnement désiré.

Remarque : la durée maximale que l'on peut atteindre en utilisant l'horloge interne à 72MHz est de
59,6 secondes (TIM_Prescaler à 65535 et TIM_Period à 65535).

16.8.3. Modification de la valeur du compteur


Le compteur du timer évolue lorsque le timer fonctionne, il est possible d'en changer la valeur (en
général on le fait lorsqu'il est arrêté) par la fonction :

 Le premier paramètre désigne le timer dont on veut modifier le compteur. Il peut prendre les
valeurs : TIM1 à TIM7
 Le second paramètre définit la nouvelle valeur du compteur du timer. Les valeurs possibles
pour ce champ sont 0 à 65535.

16.8.4. Modification de la période


La période du timer, normalement définie par le champ TIM_Period lors de l'initialisation de la
base de temps du timer, peut être modifiée sans refaire une initialisation complète de la base de
temps par la fonction :

 Le premier paramètre désigne le timer dont on veut modifier la période. Il peut prendre les
valeurs : TIM1 à TIM7
 Le second paramètre définit la nouvelle limite de comptage du timer. Les valeurs possibles
pour ce champ sont 0 à 65535.

16.8.5. Mode unique ou répétitif


Quel que soit le mode choisi le timer peut n'effectuer l'opération qu'une seule fois ou la répéter
lorsqu'il a fini. Ce fonctionnement est programmé par la fonction suivante :

 Le premier paramètre désigne le timer à initialiser. Il peut prendre les valeurs : TIM1 à
TIM7
 Le second paramètre indique le choix de la répétition ou non. Les valeurs possibles sont :
TIM_OPMode_Single ou TIM_OPMode_Repetitive

16.8.6. Lancement/arrêt d'un timer par programme

 Le premier paramètre désigne le timer à lancer ou arrêter. Il peut prendre les valeurs : TIM1
à TIM7
 Le second paramètre indique si le timer est lancé ou arrêté. Les valeurs possibles sont :
ENABLE ou DISABLE

16.8.7. Lignes externes liées à un timer

Page | 350 © ISI 2018 Ridha Ghayoula


− Les timer 3 et 4 possèdent 5 lignes permettant de les piloter. Il s'agit des lignes CH1 à CH4 et de
la ligne ETR.
− Le timer 2 possède 4 lignes permettant de le piloter. Il s'agit des lignes CH1 à CH4 (la ligne ETR
est la même que la ligne CH1).
− Le timer 5 possède 4 lignes permettant de le piloter. Il s'agit des lignes CH1 à CH4 (il n'a pas de
ligne ETR).
− Le timer 1 possède les mêmes lignes que les timers 3 et 4 auxquelles viennent s'ajouter 4 lignes
supplémentaires qui sont des lignes complémentaires CH1N à CH3N et la ligne de commande des
sorties BKIN.
− Les timers 6 et 7 n'ont pas de lignes permettant de les piloter.
− Les lignes CH1 et CH2 peuvent être utilisées comme des entrées (reset, commande marche/arrêt,
déclenchement et horloge externe)
− Les lignes CH1 à CH4 peuvent être utilisées comme des sorties lorsque le timer sert à générer des
signaux.
− La ligne ETR ne peut être utilisée qu'en entrée (reset, commande marche/arrêt, déclenchement et
horloge externe). Elle permet des réglages plus précis du fonctionnement que les lignes CH1 et
CH2.
Le tableau suivant indique les lignes physiques reliées aux timers. Ces lignes peuvent être redirigées
CH1 CH2 CH3 CH4 ETR
direct redirigé direct redirigé direct redirigé direct redirigé direct redirigé
TIM1 PA8 PE PA9(1) PE11(1) PA10 PE13(1) PA11 PE14(1) PA12 PE7(1)
TIM2 PA0 PA1 PB3 PA2 PB10 PA3 PB11 PA0
TIM3 PA6 PC6 PA7 PC7 PB0 PC8 PB1 PC9 PD2
PB4(2) PB5(2)
TIM4 PB6 PD12 PB7 PD13 PB8 PD14 PB9 PD15 PE0
TIM5 PA0 PA1 PA2 PA3
(1)
redirection totale de TIM1
(2)
redirection partielle de TIM3

Les lignes spécifiques au timer 1 sont décrites dans le tableau suivant :


TIM1 CHIN CH2N CH3N BKIN
direct redirigé direct redirigé direct redirigé direct redirigé
redirection
PA7 PB0 PB1 PA6
totale
PB13 PB14 PB15 PB12
redirection
PE8 PE10 PE12 PE15
partielle

Les lignes utilisées comme entrées pour les timers doivent avoir été programmées en mode
GPIO_Mode_IN_FLOATING.
Les lignes utilisées comme sorties pour les timers doivent avoir été programmées en mode
GPIO_Mode_AF_PP.

16.8.8. Choix de l'horloge d'un timer


Les choix possibles pour l'horloge d'un timer sont les suivants :
 Utilisation de l'horloge interne du microcontrôleur (72MHz)
 Horloge provenant de l'une des entrées CH1 ou CH2 du timer (front montant)

Page | 351 © ISI 2018 Ridha Ghayoula


 Horloge provenant de l'entrée ETR du timer (choix du front montant ou descendant) et
possibilité d'ajouter une pré division par 1 , 2 , 4 ou 8
 Horloge provenant d'un autre timer (chaînage)

a) Horloge interne
La fonction suivante permet de choisir de faire fonctionner un timer à partir de l'horloge du
microcontrôleur (72MHz) :

 Le paramètre désigne le timer pour lequel on veut utiliser l'horloge interne. Il peut prendre
les valeurs : TIM1 à TIM7

b) Horloge externe
Pour utiliser les lignes CH1 ou CH2 comme horloges externes la fonction est la suivante :

 Le premier paramètre désigne le timer à initialiser. Il peut prendre les valeurs : TIM1 à
TIM5
 Le second paramètre désigne la ligne utilisée comme horloge externe (le front actif est le
front montant). Les valeurs possibles sont décrites dans le tableau suivant :

TIM_TS_TI1F_ED ligne CH1 directe


TIM_TS_TI1FP1 ligne CH1 après filtrage interne
TIM_TS_TI2FP2 ligne CH2 après filtrage interne
Pour utiliser la ligne ETR comme horloge externe la fonction est la suivante :

 Le premier paramètre désigne le timer à initialiser. Il peut prendre les valeurs : TIM1 à
TIM5
 Le deuxième paramètre permet d'appliquer une pré-division de cette horloge par 1, 2, 4 ou 8.
Les valeurs possibles sont : TIM_ExtTRGPSC_OFF, TIM_ExtTRGPSC_DIV2 ,
TIM_ExtTRGPSC_DIV4 ou TIM_ExtTRGPSC_DIV8
 Le troisième paramètre indique si le timer compte sur les fronts descendants ou montants de
cette horloge. Les valeurs possibles sont respectivement : TIM_ExtTRGPolarity_Inverted
ou TIM_ExtTRGPolarity_NonInverted
 Le dernier paramètre correspond au filtrage appliqué à cette ligne (plus la valeur est élevée
plus la ligne est filtrée). Les valeurs possibles sont 0 à 15.
Pour utiliser un autre timer comme horloge externe il faut utiliser le chaînage de timers
16.8.9. Chaînage de timers
Les timers sont, a priori, indépendants. Lorsque l'on désire les chaîner il faut en désigner un comme
maître (celui qui pilote) et l'autre comme esclave (celui qui est piloté). Le chaînage permet de piloter
un timer par un autre (reset, commande marche/arrêt, déclenchement ou horloge). Toutes les
combinaisons de maître / esclave ne sont pas possibles :
o Le timer 2 ne peut être piloté que par le 1, le 3 ou le 4
o Le timer 3 ne peut être piloté que par le 1, le 2, le 4 ou le 5
o Le timer 4 ne peut être piloté que par le 1, le 2 ou le 3
o Le timer 5 ne peut être piloté que par le 2, le 3 ou le 4
Pour établir le lien entre le maître et l'esclave (qui pilote qui) on utilise la fonction suivante :

Page | 352 © ISI 2018 Ridha Ghayoula


 Le premier paramètre désigne le timer esclave à piloter. Il peut prendre les valeurs : TIM2 à
TIM5
 Le second paramètre désigne le timer maître. Les valeurs possibles sont décrites dans le
tableau suivant (les colonnes du tableau correspondent au timer esclave, les valeurs dans les
cases indiquent quel est le timer maître) :
Timer esclave : TIM2 TIM3 TIM4 TIM5
TIM_TS_ITR0 TIM1 TIM1 TIM1 TIM2
TIM_TS_ITR1 TIM2 TIM2 TIM3
TIM_TS_ITR2 TIM3 TIM5 TIM3 TIM4
TIM_TS_ITR3 TIM4 TIM4
Le timer maître doit être programmé pour piloter le timer esclave. Ceci est obtenu par la fonction
suivante :

 Le premier paramètre désigne le timer maître. Il peut prendre les valeurs : TIM1 à TIM5
 Le deuxième paramètre indique quel événement du timer maître est transmis au timer
esclave. Les valeurs possibles sont décrites dans le tableau ci-dessous :
TIM_TRGOSource_Reset Evénement d'initialisation du timer
TIM_TRGOSource_Enable Evénement de mise en marche du timer
TIM_TRGOSource_Update Evénement de rechargement du timer
TIM_TRGOSource_OC1Ref Evénement de capture déclenchée par CH1 ou activation du signal de sortie sur CH1
TIM_TRGOSource_OC2Ref Evénement de capture déclenchée par CH2 ou activation du signal de sortie sur CH2
TIM_TRGOSource_OC3Ref Evénement de capture déclenchée par CH3 ou activation du signal de sortie sur CH3
TIM_TRGOSource_OC4Ref Evénement de capture déclenchée par CH4 ou activation du signal de sortie sur CH4
Le timer esclave doit être programmé pour être piloté par le timer maître. Ceci est obtenu par
la fonction suivante :

 Le premier paramètre désigne le timer esclave. Il peut prendre les valeurs : TIM2 à TIM5
 Le deuxième paramètre indique comment le timer esclave est piloté par le timer maître. les
valeurs possibles sont décrites dans le tableau ci-dessous :
TIM_SlaveMode_Reset Le maître pilote le reset du timer esclave (front montant)
TIM_SlaveMode_Gated Le maître pilote la commande marche/arrêt du timer esclave (niveau 1)
TIM_SlaveMode_Trigger Le maître pilote le démarrage du timer esclave (front montant)
TIM_SlaveMode_External1 Le maître pilote l'horloge du timer esclave (front montant)
Par exemple pour que le timer 2 utilise comme horloge les événements de rechargement du timer 3,
on fera :

Remarque : la durée maximale que l'on peut atteindre, à partir de l'horloge interne à 72MHz, en
chaînant deux timers est de 2 965 333 jours soit un peu plus de 8000 ans (TIM_Prescaler à 65535
et TIM_Period à 65535 sur le timer maître et le timer esclave).

16.8.10. Pilotage d'un timer par des lignes externes

Page | 353 © ISI 2018 Ridha Ghayoula


Les lignes CH1 et CH2 peuvent être utilisées pour piloter un timer (reset, commande marche / arrêt
et déclenchement). Pour cela il faut choisir la ligne à utiliser puis configurer le timer pour qu'il soit
piloté par cette ligne. Le choix de la ligne de pilotage se fait par la fonction suivante :

 Le premier paramètre désigne le timer à piloter. Il peut prendre les valeurs : TIM1 à TIM5
 Le second paramètre indique la ligne choisie. Les valeurs possibles sont décrites dans le
tableau ci-dessous :
TIM_TS_TI1F_ED ligne CH1
TIM_TS_TI1FP1 ligne CH1 après filtrage interne
TIM_TS_TI2FP2 ligne CH2 après filtrage interne
La désignation de ce que pilote cette ligne se fait par la fonction suivante :

 Le premier paramètre désigne le timer piloté. Il peut prendre les valeurs : TIM1 à TIM5
 Le deuxième paramètre indique comment le timer est piloté par la ligne. les valeurs possibles
sont décrites dans le tableau ci-dessous :
TIM_SlaveMode_Reset) La ligne pilote le reset du timer (front montant
TIM_SlaveMode_Gated La ligne pilote la commande marche/arrêt du timer (niveau 1)
TIM_SlaveMode_Trigger La ligne pilote le démarrage du timer (front montant)

16.8.11. Capture
La capture consiste à copier la valeur du compteur du timer dans l'un des registres CCR1 à CCR4
lors de la détection d'un ou plusieurs fronts (montants ou descendants) sur l'entrée choisie (CH1 à
CH4). Un indicateur est positionné ou une interruption peut être générée à chaque capture.
Le choix de la ligne d'entrée et du mode de capture se fait par la fonction TIM_ICInit qui prend en
paramètre un pointeur sur une structure de type TIM_ICInitTypeDef qui doit avoir au préalable
été initialisée puis dont les champs sont remplis. La structure TIM_ICInitTypeDef possède les
champs suivants :

Avant d'être utilisée par TIM_ICInit cette structure doit être initialisée par la fonction :

 Le paramètre est un pointeur sur la structure à initialiser.

Avant d'utiliser la fonction pour initialiser une ligne de capture il faut remplir les champs de cette
structure en utilisant valeurs suivantes :

 Champ TIM_Channel, il indique la ligne d'entrée (CH1 à CH4) et donc le registre dans
lequel est mise la valeur capturée. Les valeurs possibles sont : TIM_Channel_1 à
TIM_Channel_4

 Champ TIM_ICPolarity, il indique le front (montant ou descendant) actif de cette ligne.


Les valeurs possibles sont : TIM_ICPolarity_Rising ou TIM_ICPolarity_Falling

Page | 354 © ISI 2018 Ridha Ghayoula


 Champ TIM_ICPrescaler, il indique le nombre de fronts à détecter sur la ligne avant de
déclencher la capture (1, 2, 4 ou 8). Les valeurs possibles sont : TIM_ICPSC_DIV1 ,
TIM_ICPSC_DIV2 , TIM_ICPSC_DIV4 ou TIM_ICPSC_DIV8

L'initialisation de la ligne se fait alors par la fonction :

 Le premier paramètre désigne le timer dont on veut capturer la valeur. Il peut prendre les
valeurs : TIM1 à TIM5
 Le second paramètre est un pointeur sur la structure initialisée.

Lors d'une capture, la valeur capturée est placée dans le registre lié à la ligne choisie par le champ
TIM_Channel. Pour lire cette valeur on utilise, en fonction du registre, les fonctions :
uint16_t TIM_GetCapture1(timer)
uint16_t TIM_GetCapture2(timer)
uint16_t TIM_GetCapture3(timer)
uint16_t TIM_GetCapture4(timer)
 Le paramètre désigne le timer dont on veut lire la valeur capturée. Il peut prendre les valeurs
: TIM1 à TIM5
 La valeur de retour est la dernière valeur capturée

16.8.12. Création de signaux de sortie


Un timer peut générer un signal de sortie sur les lignes CH1 à CH4. Selon que le timer a été
programmé en mode unique ou répétitif le signal peut être répété ou non. La ligne utilisée pour cette
sortie doit avoir été initialisée en entrée numérique.
Signal simple : quand le timer atteint la valeur contenue dans l'un des registres CCR1 à CCR4 la
sortie prend l'état choisi (0 ou 1).
Ceci permet de faire changer l'état d'une ligne après un délai donné puisque le signal devient actif
quand le timer atteint CCRi (delai). Que le timer soit mis ou non en mode répétitif ne change rien :
la sortie ne bascule que la première fois que le timer atteint CCRi et reste dans cet état.

Signal carré : La sortie change d'état chaque fois que le timer atteint la valeur définie comme
période. La fréquence est donc déterminée par le double de cette valeur.

Signal à modulation de largeur d'implusion : La fréquence est déterminée par la valeur définie
comme période du timer et le rapport cyclique par l'un des registres CCR1 à CCR4.

Le choix de la ligne de sortie se fait par les fonctions TIM_OCxInit (où x vaut 1, 2, 3 ou 4 selon la
ligne de sortie choisie) qui prennent en paramètre un pointeur sur une structure de type
TIM_OCInitTypeDef qui doit avoir au préalable été initialisée puis dont les champs ont été
remplis. La structure TIM_OCInitTypeDef possède les champs suivants :

Avant d'être utilisée par les fonctions TIM_OCxInit cette structure doit être initialisée par la
fonction :

Page | 355 © ISI 2018 Ridha Ghayoula


 Le paramètre est un pointeur sur la structure à initialiser

Avant d'utiliser la fonction pour initialiser une ligne de génération de signaux il faut remplir les
champs de cette structure en utilisant valeurs suivantes :

Champ TIM_OCMode, il indique le mode de fonctionnement de la ligne de sortie. Les valeurs


possibles sont décrites par le tableau ci-dessous :
TIM_OCMode_Timing La sortie n'est pas utilisée
Mode signal simple : le signal de sortie prend la valeur définie par le champ
TIM_OCMode_Active TIM_OCPolarity quand le timer atteint la valeur de CCRi
TIM_OCMode_Toggle Mode signal carré : le signal de sortie change d'état chaque fois que le timer atteint la
valeur définie comme période. Le champ TIM_Pulse ne sert à rien dans ce mode. La
valeur initiale du signal de sortie est définie par le champ TIM_OCPolarity
TIM_OCMode_PWM1 Mode modulation de largeur d'impulsion :
− Si le timer est mis en mode incrémentation la sortie prend la valeur définie par le
champ TIM_OCPolarity tant que le timer est < CCRi puis est inversée jusqu'à ce que
le timer atteigne la valeur de la période du timer.
− Si le timer est mis en mode décrémentation la sortie prend la valeur inverse de celle
définie par le champ TIM_OCPolarity tant que le timer est > CCRi puis prend la
valeur définie par le champ TIM_OCPolarity jusqu'à ce que le timer atteigne 0.
− Si le timer est mis en mode centré le signal de sortie prend la valeur définie par le
champ TIM_OCPolarity tant que le timer est < CCRi et la valeur inverse quand il est
CCRi
Champ TIM_OutputState, il permet de relier la sortie du timer à la ligne physique ou pas. Les
valeurs possibles sont : TIM_OutputState_Disable ou TIM_OutputState_Enable

Remarque : pour le timer 1, la sortie doit en plus être activée par l'appel de la fonction :
TIM_CtrlPWMOutputs(TIM1, ENABLE);
Champ TIM_Pulse, il contient la valeur à mettre dans le registre CCRi. Les valeurs possibles sont 0
à 65535.
Champ TIM_OCPolarity, il permet de choisir le niveau (0 ou 1) présent sur la ligne de sortie
lorsqu'elle est active. Les valeurs possibles sont :
TIM_OCPolarity_High ou TIM_OCPolarity_Low

Selon la ligne choisie (CH1 à CH4), l'initialisation de la ligne se fait alors par l'une des fonctions :

 Le premier paramètre désigne le timer utilisé. Il peut prendre les valeurs : TIM1 à TIM5
 Le second paramètre est un pointeur sur la structure initialisée.

Le contenu des registres CCRi utilisés pour la génération de signaux peut être modifié sans
réinitialiser les lignes par les fonctions :

Page | 356 © ISI 2018 Ridha Ghayoula


 Le premier paramètre désigne le timer dont on veut modifier le contenu du registre CCRi. Il
peut prendre les valeurs : TIM1 à TIM5
 Le second paramètre définit la nouvelle valeur à mettre dans le registre CCRi. Les valeurs
possibles sont 0 à 65535.

16.8.13. Tests de l'état d'un timer


Le contenu d'un timer peut être lu même lorsqu'il est en fonctionnement par la fonction :

 Le paramètre désigne le timer à lire. Il peut prendre les valeurs : TIM1 à TIM7
 La valeur de retour est le contenu du compteur du timer au moment de la lecture

Lors de certains événements des indicateurs peuvent être positionnés par le timer. Ces indicateurs
pourront par la suite être testés par programme pour savoir quels événements se sont produits.

La fonction permettant de définir les événements que le timer doit mémoriser dans ces indicateurs
est la suivante :

 Le premier paramètre désigne le timer pour lequel on veut que les événements soient
mémorisés. Il peut prendre les valeurs : TIM1 à TIM7
 Le second paramètre désigne le ou les événements à mémoriser. Les valeurs possibles sont
décrites dans le tableau suivant (plusieurs valeurs peuvent être sélectionnées en même temps
en les séparant par des | ) :

TIM_EventSource_Update Rechargement du timer


Evénement déclenchant une capture sur CH1
TIM_EventSource_CC1
Ou quand le timer atteint la valeur contenue dans CCR1

Evénement déclenchant une capture sur CH2


TIM_EventSource_CC2
Ou quand le timer atteint la valeur contenue dans CCR2
Evénement déclenchant une capture sur CH3
TIM_EventSource_CC3
Ou quand le timer atteint la valeur contenue dans CCR3
Evénement déclenchant une capture sur CH4 Ou quand le timer atteint la
TIM_EventSource_CC4
valeur contenue dans CCR4
Evénement de commande du timer (déclenchement,
TIM_EventSource_Trigger
marche/arrêt ou reset)
L'état de ces indicateurs peut être lu par la fonction :

 Le premier paramètre désigne le timer pour lequel on veut lire un indicateur. Il peut prendre
les valeurs : TIM1 à TIM7

Page | 357 © ISI 2018 Ridha Ghayoula


 Le second paramètre désigne l'indicateur à lire. Les valeurs possibles sont décrites dans le
tableau suivant:
TIM_FLAG_Update Rechargement du timer
TIM_FLAG_CC1 Evénement déclenchant une capture sur CH1
Ou quand le timer atteint la valeur contenue dans CCR1
TIM_FLAG_CC2 Evénement déclenchant une capture sur CH2
Ou quand le timer atteint la valeur contenue dans CCR2
TIM_FLAG_CC3 Evénement déclenchant une capture sur CH3
Ou quand le timer atteint la valeur contenue dans CCR3
TIM_FLAG_CC4 Evénement déclenchant une capture sur CH4
Ou quand le timer atteint la valeur contenue dans CCR4
TIM_FLAG_Trigger Evénement de commande du timer (déclenchement, marche/arrêt
ou reset)
 La valeur en retour indique l'état de cet indicateur. Les valeurs possibles sont : SET ou
RESET.

Les indicateurs peuvent être effacés par la fonction :

 Le premier paramètre désigne le timer pour lequel on veut effacer les indicateurs. Il peut
prendre les valeurs : TIM1 à TIM7
 Le second paramètre désigne l'indicateur à effacer. Les valeurs possibles sont celles du
second paramètre de la fonction précédente. Il est possible d'effacer plusieurs indicateurs à le
fois en plaçant plusieurs valeurs séparées par des + .

16.8.14 Génération d'interrutions


Lors de certains événements des interruptions peuvent être générées par le timer. Les procédures
associées sont décrites en 3. La fonction permettant de choisir les événements pour lesquels le timer
doit générer des interruptions est la suivante :

 Le deuxième paramètre désigne l'interruption à activer ou désactiver. Les valeurs possibles


sont décrites dans le tableau suivant:

TIM_IT_Update Rechargement du timer


Evénement déclenchant une capture sur CH1
TIM_IT_CC1 Ou quand le timer atteint la valeur contenue dans CCR1
TIM_IT_CC2 Evénement déclenchant une capture sur CH2
Ou quand le timer atteint la valeur contenue dans CCR2
TIM_IT_CC3 Evénement déclenchant une capture sur CH3
Ou quand le timer atteint la valeur contenue dans CCR3
TIM_IT_CC4 Evénement déclenchant une capture sur CH4
Ou quand le timer atteint la valeur contenue dans CCR4
TIM_IT_Trigger Evénement de commande du timer (déclenchement, marche/arrêt ou reset)
 Le dernier paramètre indique si l'interruption doit être activée ou désactivée. Les valeurs
possibles sont ENABLE ou DISABLE.

L'état de ces interruptions peut être testé par la fonction :

Page | 358 © ISI 2018 Ridha Ghayoula


 Le premier paramètre désigne le timer pour lequel on veut tester l'état des interruptions. Il
peut prendre les valeurs : TIM1 à TIM7
 Le second paramètre désigne l'interruption à tester. Les valeurs possibles sont les mêmes que
pour le deuxième paramètre de la fonction précédente.
 La valeur en retour indique l'état de cette interruption. Les valeurs possibles sont : SET ou
RESET.
Lorsqu'une interruption est prise en compte, son état doit être effacé, ceci est fait par lafonction :

 Le premier paramètre désigne le timer pour lequel on veut effacer l'état des interruptions. Il
peut prendre les valeurs : TIM1 à TIM7
 Le second paramètre désigne l'interruption à effacer. Les valeurs possibles sont les mêmes
que pour le deuxième paramètre de la fonction précédente.

16.8.15. Guide d'utilisation des timers


a) Marche à suivre pour initialiser les timers
1. Déclarer une variable de type TIM_TimeBaseInit
2. Initialiser le timer par la fonction : TIM_DeInit
3. Activer l'horloge du timer par la fonction RCC_APB1PeriphClockCmd pour le timer1 ou
RCC_APB2PeriphClockCmd pour les autres timers.
4. Initialiser la variable de type TIM_TimeBaseInit par la fonction TIM_TimeBaseStructInit
5. Définir dans la variable de type TIM_TimeBaseInit les paramètres du timer : division d'horloge, période (valeur
limite) et mode de comptage
6. Programmer le timer par la fonction TIM_TimeBaseInit
7. Choisir le mode répétitif ou non par la fonction TIM_SelectOnePulseMode
8. Choisir d'utiliser une horloge interne ou externe par l'une des fonctions :
− TIM_InternalClockConfig pour l'horloge interne
− TIM_ITRxExternalClockConfig pour une horloge pilotée par la ligne CH1 (avec ou sans filtrage) ou par
la ligne CH2
− TIM_ETRConfig pour une horloge pilotée par la ligne ETR
9. Autoriser, si nécessaire, la mémorisation de certains états du timer par la fonction TIM_GenerateEvent
10. Autoriser, si nécessaire, la génération de certaines ITs par la fonction TIM_ITConfig
11. Recommencer les étapes 2 à 10 pour chaque timer à programmer
12. Lancer chaque timer par la fonction TIM_Cmd
b) Commander un timer par une ligne externe
1. Suivre les étapes 1 à 10 comme en 5.15.1
2. Choisir la ligne de commande (CH1 ou CH2) par la fonction TIM_SelectInputTrigger
3. Choisir la fonction à commander par la fonction TIM_SelectSlaveMode

La ligne utilisée pour la commande du timer doit avoir été programmée en mode
GPIO_Mode_IN_FLOATING .

c) Utiliser le mode de capture déclenchée par une ligne externe


1. Déclarer une variable de type TIM_ICInitTypeDef
2. Suivre les étapes 1 à 10 comme en 5.15.1

Page | 359 © ISI 2018 Ridha Ghayoula


3. Initialiser la variable de type TIM_ICInitTypeDef par la fonction TIM_ICStructInit
4. Définir dans la variable de type TIM_ICInitTypeDef la ligne de commande (CH1 à CH4), le front de
déclenchement de la commande et le nombre d'événements pour activer la commande (1, 2, 4 ou 8)
5. Programmer la capture par la fonction TIM_ICInit

La ligne utilisée pour la capture doit avoir été programmée en mode


GPIO_Mode_IN_FLOATING.

d) Utiliser un timer pour générer des signaux sur une ligne externe
1. Déclarer une variable de type TIM_OCInitTypeDef
2. Suivre les étapes 1 à 10 comme en 5.15.1
3. Initialiser la variable de type TIM_OCInitTypeDef par la fonction TIM_OCStructInit
4. Définir dans la variable de type TIM_OCInitTypeDef le type de signal (mono coup, carré,
MLI), l'envoi ou non du signal généré sur la ligne de sortie, la largeur d'impulsion (sauf pour le signal carré) et la
polarité (niveau actif 0/1)
5. Programmer la capture par l'une des fonctions TIM_OC1Init à TIM_OC4Init selon la
ligne de sortie choisie (CH1 à CH4)
La ligne utilisée comme sortie doit avoir été programmée en mode GPIO_Mode_AF_PP .

e) Chaîner deux timers


1. Suivre les étapes 1 à 10 comme en a) pour chacun des deux timers
2. Indiquer quel est le timer maître (celui qui pilote l'autre) et quel est le timer esclave (celui qui est piloté) par la
fonction TIM_ITRxExternalClockConfig
3. Pour le timer maître indiquer l'événement utilisé pour piloter l'autre timer par la fonction
TIM_SelectOutputTrigger
4. Pour le timer esclave indiquer la commande pilotée par l'autre timer par la fonction
TIM_SelectSlaveMode

f) Consulter/modifier des états mémorisés ou des ITs de timers


 Lecture de l'état mémorisé d'un timer par la fonction : TIM_GetFlagStatus
 Effacement de l'état mémorisé d'un timer par la fonction : TIM_ClearFlag
 Lecture de l'indicateur d'IT d'un timer par la fonction : TIM_GetITStatus
 Effacement de l'indicateur d'IT d'un timer par la fonction : TIM_ClearITPendingBit
16.9. Convertisseur Analogique / Numérique (ADC)
Le microcontrôleur possède 2 convertisseurs analogique/numérique. Ils peuvent être utilisés pour
faire des mesures en mode continu ou non. Le déclenchement d'une mesure peut être fait par
programme ou par un timer (à intervalles réguliers). Il est également possible de définir des seuils
minimaux et maximaux, lorsque la valeur mesurée sort de ces seuils le convertisseur positionne un
indicateur et peut lever une interruption.

16.9.1. Remise à l'état initial d'un convertisseur


La fonction ADC_DeInit permet de mettre un convertisseur dans son état initial (comme après un
reset). Sa définition est la suivante :

 Le paramètre désigne le convertisseur. Les valeurs possibles sont : ADC1 ou ADC2


16.9.2. Initialisation d'un convertisseur

Page | 360 © ISI 2018 Ridha Ghayoula


La fonction ADC_Init permet d'initialiser un convertisseur. Elle utilise comme paramètre une
structure de données de type ADC_InitTypeDef dont les champs sont les suivants :

Avant d'être utilisée par ADC_Init cette structure doit être initialisée par la fonction
ADC_StructInit définie comme suit :

 Le paramètre est un pointeur sur la structure de type ADC_InitTypeDef à initialiser.


Avant d'utiliser la fonction pour initialiser un convertisseur il faut remplir les champs de cette
structure en utilisant valeurs suivantes :

Champ ADC_ContinuousConvMode, il indique si le convertisseur effectue des mesures en


continu ou pas. Les valeurs possibles sont : ENABLE ou DISABLE. En mode continu dès qu'une
mesure est terminée le convertisseur redémarre la suivante. Ce mode n'est donc utilisable qu'avec un
déclenchement par programme (voir second paramètre).
Champ ADC_ExternalTrigConv, il indique comment sont déclenchées les conversions (par
programme ou par un timer). Les valeurs possibles sont décrites dans le tableau ci-dessous :
ADC_ExternalTrigConv_T1_CC3 Déclenchement par TIM1_CH3
ADC_ExternalTrigConv_None Déclenchement par programme
ADC_ExternalTrigConv_T1_CC1 Déclenchement par TIM1_CH1
ADC_ExternalTrigConv_T1_CC2 Déclenchement par TIM1_CH2
ADC_ExternalTrigConv_T2_CC2 Déclenchement par TIM2_CH2
ADC_ExternalTrigConv_T3_TRGO Déclenchement par le trigger du TIM3
ADC_ExternalTrigConv_T4_CC4 Déclenchement par TIM4_CH4

Remarque : Lorsque les conversions sont déclenchées par timer le premier paramètre doit être
DISABLE.

 Le premier paramètre désigne le convertisseur à initialiser. Il peut prendre les valeurs : ADC1
ou ADC2
 Le second paramètre est un pointeur sur une structure de type ADC_InitTypeDef préparée
par la fonction ADC_StructInit puis dont les champs ont été remplis en fonction du
fonctionnement désiré.
16.9.3. Mise en marche/arrêt d'un convertisseur
Elle se fait par la fonction :

 Le premier paramètre désigne le convertisseur à lancer ou arrêter. Il peut prendre les valeurs
: ADC1 ou ADC2
 Le second paramètre indique si le convertisseur est mis en marche ou arrêté. Les valeurs
possibles sont : ENABLE ou DISABLE

16.9.4 Lignes d'entrée des convertisseurs


Les deux convertisseurs partagent les mêmes lignes d'entrée. Ils ont 18 canaux d'entrée les 16
premiers sont connectés à 16 lignes d'entrée externes et les deux derniers à deux entrées internes

Page | 361 © ISI 2018 Ridha Ghayoula


correspondant à un capteur de température et à une tension de référence de 3,3V. Les 16 lignes
utilisables comme entrées externes sont les suivantes :
canal 0 PA0
canal 1 PA1
canal 2 PA2
canal 3 PA3
canal 4 PA4
canal 5 PA5
canal 6 PA6
canal 7 PA7
canal 8 PB0
canal 9 PB1
canal 10 PC0
canal 11 PC1
canal 12 PC2
canal 13 PC3
canal 14 PC4
canal 15 PC5
Les lignes utilisées comme entrées des convertisseurs doivent être programmées en mode analogique
(GPIO_Mode_AIN) .

16.9.5. Choix de l'entrée à convertir


Il faut définir la ligne sur laquelle est effectuée la mesure et la façon dont le convertisseur effectue
cette mesure.

• Le premier paramètre désigne le convertisseur dont on configure l'entrée. Il peut prendre les
valeurs : ADC1 ou ADC2
• Le deuxième paramètre indique l'entrée du convertisseur configurée. Les valeurs possibles sont :
ADC_Channel_0 à ADC_Channel_15 , ADC_Channel_TempSensor , ADC_Channel_Vrefint
• Le troisième paramètre doit être à 1 (ce paramètre n'a de sens que dans un mode de
fonctionnement particulier que nous n'utiliserons pas).
• Le dernier paramètre indique le nombre de cycles d'horloges attendus avant que la mesure ne soit
faite pour assurer que le signal d'entrée soit stable. Les valeurs possibles sont celles décrites dans le
tableau suivant :
ADC_SampleTime_1Cycles5 1.5 cycles
ADC_SampleTime_7Cycles5 7.5 cycles
ADC_SampleTime_13Cycles5 13.5 cycles
ADC_SampleTime_28Cycles5 28.5 cycles
ADC_SampleTime_41Cycles5 41.5 cycles
ADC_SampleTime_55Cycles5 55.5 cycles
ADC_SampleTime_71Cycles5 71.5 cycles
ADC_SampleTime_239Cycles5 239.5 cycles

16.9.6. Lecture d'une mesure


Les valeurs mesurées sont sur 12 bits (0 à 4095) pour une tension d'entrée comprise entre 0 et 3,3V.
La fonction suivante permet de récupérer la dernière mesure faite :

 Le paramètre désigne le convertisseur dont on lit la mesure. Il peut prendre les valeurs :
ADC1 ou ADC2
Page | 362 © ISI 2018 Ridha Ghayoula
 La valeur de retour est la dernière mesure faite (elle doit être mise en forme par un ET avec
la valeur 0x0FFF)

16.9.7. Lancement de conversion par programme


Lorsque le champ ADC_ExternalTrigConv a été initialisé pour un déclenchement par programme,
ce déclenchement est fait par la fonction :

 Le premier paramètre désigne le convertisseur à lancer. Il peut prendre les valeurs : ADC1
ou ADC2
 Le second paramètre indique si le convertisseur est lancé ou pas. Les valeurs possibles sont :
ENABLE ou DISABLE

16.9.8. Déclenchement du convertisseur par commande externe


Lorsque le champ ADC_ExternalTrigConv a été initialisé pour un déclenchement externe (par
timer), ce déclenchement est activé par la fonction :

 Le premier paramètre désigne le convertisseur dont on configure le déclenchement. Il peut


prendre les valeurs : ADC1 ou ADC2
 Le deuxième paramètre active ou désactive le déclenchement externe. Les valeurs possibles
sont : ENABLE ou DISABLE

Le timer utilisé pour déclencher les mesures doit être programmé :


− Pour sa base de temps par la fonction TIM_BaseInit (division d'horloge, mode et période)
− Pour produire un signal de sortie sur le canal adéquat par la fonction TIM-OCxInit en choisissant
le mode TIM_OCMode_PWM1, une durée d'impulsion de 1 et en validant la sortie avec un niveau
actif à 1). La ligne physique reliée au timer n'a pas besoin d'être programmée pour sa fonction
alternative en mode numérique sauf si elle est également utilisée comme sortie.

16.9.9. Mise en place du contrôle de seuils analogiques


Il est possible de définir des seuils minimaux et maximaux, lorsque la valeur mesurée sort de ces
seuils le convertisseur positionne un indicateur et peut lever une interruption. La fonction utilisée
pour mettre en place ce contrôle de seuil est :

 Le premier paramètre désigne le convertisseur dont on configure le contrôle de seuils. Il peut


prendre les valeurs : ADC1 ou ADC2
 Le deuxième paramètre indique comment s'applique le contrôle de seuils. Les valeurs
possibles sont données dans le tableau ci-dessous :
ADC_AnalogWatchdog_SingleRegEnable Contrôle de seuil sur l'entrée
ADC_AnalogWatchdog_None Pas de contrôle de seuil
La définition des seuils se fait par la fonction suivante :

 Le premier paramètre désigne le convertisseur dont on configure les seuils. Il peut prendre
les valeurs : ADC1 ou ADC2

Page | 363 © ISI 2018 Ridha Ghayoula


 Le deuxième paramètre définit le seuil maximal (valeur entre 0 et 4095)
 Le troisième paramètre définit le seuil minimal (valeur entre 0 et 4095)
La fonction suivante permet d'indiquer l'entrée à contrôler :

 Le premier paramètre désigne le convertisseur dont on configure l'entrée contrôlée. Il peut


prendre les valeurs : ADC1 ou ADC2
 Le deuxième paramètre indique la ligne à contrôler. Les valeurs possibles sont :
ADC_Channel_0 à ADC_Channel_17

16.9.10 Tests de l'état d'un convertisseur


La fonction suivante permet de lire l'état d'un convertisseur :

 Le premier paramètre désigne le convertisseur dont on teste l'état. Il peut prendre les valeurs
: ADC1 ou ADC2
 Le deuxième paramètre désigne l'état à lire. Les valeurs possibles sont :
ADC_FLAG_AWD Lecture de l'indicateur de dépassement des seuils de contrôle
ADC_FLAG_EOC Lecture de l'indicateur de fin de conversion
ADC_FLAG_STRT Lecture de l'indicateur de début de conversion
 La valeur en retour indique l'état de cet indicateur. Les valeurs possibles sont : SET ou
RESET. Lorsqu'un indicateur a été lu il est possible de l'effacer par la fonction :

 Les deux paramètres sont les mêmes que pour la fonction précédente

16.9. 11. Gestion des interruptions d'un convertisseur


On peut programmer les convertisseurs pour qu'ils génèrent une interruption en fin de conversion
ou lorsque les seuils de contrôle ont été dépassés. Les procédures associées sont en 3.
Le choix des motifs d'interruption est fait par la fonction suivante :

 Le premier paramètre désigne le convertisseur dont on configure les interruptions. Il peut


prendre les valeurs : ADC1 ou ADC2
 Le deuxième paramètre désigne le motif d'interruption choisi (on peut activer ou désactiver
les deux interruptions en même temps en mettant dans ce paramètre les deux valeurs
possibles séparées par + ). Les valeurs possibles sont :
ADC_IT_EOC Interruption causée par une fin de conversion
ADC_IT_AWD Interruption causée par un dépassement des seuils de contrôle
 Le dernier paramètre indique si l'on veut activer ou désactiver cette interruption. Les valeurs
possibles sont : ENABLE ou DISABLE
Lorsqu'une interruption se produit, on peut consulter la raison pour laquelle elle a eu lieu
grâce à la fonction :

Page | 364 © ISI 2018 Ridha Ghayoula


 Le premier paramètre désigne le convertisseur dont on teste une interruption. Il peut
prendre les valeurs : ADC1 ou ADC2
 Le deuxième paramètre désigne le motif d'interruption testé (mêmes valeurs que pour le
deuxième paramètre de la fonction précédente).
 La valeur renvoyée par cette fonction indique si l'interruption testée a eu lieu ou pas. Les
valeurs possibles sont SET ou RESET.

Enfin pour effacer un indicateur d'interruption on utilise la fonction :

 Les deux paramètres sont les mêmes que pour la fonction précédente.

16.9.12 Guide d'utilisation des convertisseurs


a) Marche à suivre pour initialiser les convertisseurs A/N
1. Déclarer une variable de type ADC_InitTypeDef
2. Activer l'horloge du convertisseur par la fonction RCC_APB2PeriphClockCmd
3. Réinitialiser ce convertisseur par la fonction ADC_DeInit
4. Initialiser la variable de type ADC_InitTypeDef par la fonction ADC_StructInit
5. Dans cette variable indiquer le mode mono/multi mesures et l'utilisation ou pas d'un déclenchement par timer
6. Programmer le convertisseur par la fonction ADC_Init
7. Choisir la ligne d'entrée et programmer le temps de conversion par la fonction
ADC_RegularChannelConfig
8. Autoriser si nécessaire la génération de certaines ITs par la fonction ADC_ITConfig
9. Activer le convertisseur par la commande ADC_Cmd
Les lignes utilisées comme entrées des convertisseurs doivent être programmées en mode
analogique (GPIO_Mode_AIN)

b) Déclencher un convertisseur A/N par programme


− La conversion est lancée par la fonction ADC_SoftwareStartConvCmd. Si le mode de conversion est continu
le convertisseur recommencera automatiquement une mesure dès que la précédente sera terminée, sinon il devra être
relancé par la fonction
ADC_SoftwareStartConvCmd.

c) Déclencher un convertisseur A/N par un timer


1. Programmer le timer de déclenchement pour générer un signal sur l'une de ses sorties en mode PWM1 avec une
largeur d'impulsion de 1 au niveau haut. Le timer et la sortie choisis doivent correspondre aux commandes possibles
du convertisseur.
2. Suivre les étapes 1 à 9 comme en a) Marche à suivre pour initialiser les convertisseurs A/N. Le convertisseur doit
être mis en mode mono mesure puisqu'il est relancé par le timer.
3. Autoriser la commande du convertisseur par ce timer par la fonction ADC_ExternalTrigConvCmd
4. Activer le convertisseur par la commande ADC_Cmd

d) Lire une mesure sur un convertisseur A/N


− Elle se fait par la fonction : ADC_GetConversionValue comme seulement 12 bits sont significatifs la valeur
renvoyée par cette fonction doit être ajustée par une opération de ET avec 0x0FFF

e) Changer l'entrée à convertir

Page | 365 © ISI 2018 Ridha Ghayoula


− On peut changer la ligne d'entrée et programmer le temps de conversion sur cette ligne par la fonction
ADC_RegularChannelConfig. Si le convertisseur est en mode mono mesure, le changement de l'entrée ne peut
être que fait lorsque la conversion en cours est terminée. S'il est en mode continu, il faut l'arrêter par la fonction
ADC_SoftwareStartConvCmd avant de changer l'entrée.

f) Utiliser le contrôle de seuils sur un convertisseur A/N


1. Suivre les étapes 1 à 9 comme en a).
2. Choisir comment s'applique le contrôle de seuil par la fonction
ADC_AnalogWatchdogCmd
3. Définir l'entrée sur laquelle s'applique le contrôle de seuils par la fonction
ADC_AnalogWatchdogSingleChannelConfig
4. Définir les seuils haut et bas par la fonction ADC_AnalogWatchdogThresholdsConfig
5. Activer le convertisseur par la commande ADC_Cmd

g) Consulter/modifier des états mémorisés ou des ITs de convertisseurs A/N


− Lecture de l'état mémorisé d'un convertisseur par la fonction : ADC_GetFlagStatus
− Effacement de l'état mémorisé d'un convertisseur par la fonction : ADC_ClearFlag
− Lecture de l'indicateur d'IT d'un convertisseur par la fonction : ADC_GetITStatus
− Effacement de l'indicateur d'IT d'un convertisseur par la fonction : ADC_ClearITPendingBit

16.10. Convertisseur numérique / analogique (DAC)


Le STM32F107VC dispose de 2 convertisseurs numérique/analogique. Ils permettent de générer
des niveaux analogiques. Le DAC peut également être programmé pour ajouter au signal produit un
niveau de bruit ou un signal triangulaire.

16.10. 1.Remise à l'état initial d'un convertisseur


La fonction DAC_DeInit permet de mettre un convertisseur dans son état initial (comme après un
reset). Sa définition est la suivante :

 Le premier paramètre désigne le convertisseur. Les valeurs possibles sont :


DAC_Channel_1 ou DAC_Channel_2

16.10. 2.Initialisation d'un convertisseur


La fonction DAC_Init permet d'initialiser un convertisseur. Elle utilise comme paramètre une
structure de données de type DAC_InitTypeDef dont les champs sont les suivants :

Avant d'être utilisée par DAC_Init cette structure doit être initialisée par la fonction
DAC_StructInit définie comme suit :

 Le paramètre est un pointeur sur la structure de type DAC_InitTypeDef à initialiser.

Avant d'utiliser la fonction pour initialiser un convertisseur il faut remplir les champs de cette
structure en utilisant valeurs suivantes :

Page | 366 © ISI 2018 Ridha Ghayoula


Champ DAC_WaveGeneration, il indique si le convertisseur ajoute un bruit ou un signal
triangulaire au signal produit. Les valeurs possibles sont décrites dans le tableau suivant :
DAC_WaveGeneration_None Aucun signal n'est ajouté
DAC_WaveGeneration_Noise Ajout d'un bruit
DAC_WaveGeneration_Triangle Ajout d'un signal triangulaire
Champ DAC_LFSRUnmask_TriangleAmplitude, il indique le niveau de bruit ou de signal
triangulaire ajouté au signal produit. Le signal ajouté modifie un ou plusieurs bits de la valeur écrite
dans le DAC, ce paramètre permet de choisir le nombre de bits modifiés donc l'amplitude du signal
ajouté. Les valeurs possibles sont décrites dans le tableau suivant :

DAC_LFSRUnmask_Bit0 Ajout de bruit : seul le bit 0 est modifié


DAC_LFSRUnmask_Bit1_0 Ajout de bruit : seuls les bits 0 et 1 sont modifiés
DAC_LFSRUnmask_Bit2_0 Ajout de bruit : les bits 0 à 2 sont modifiés
DAC_LFSRUnmask_Bit3_0 Ajout de bruit : les bits 0 à 3 sont modifiés
DAC_LFSRUnmask_Bit4_0 Ajout de bruit : les bits 0 à 4 sont modifiés
DAC_LFSRUnmask_Bit5_0 Ajout de bruit : les bits 0 à 5 sont modifiés
DAC_LFSRUnmask_Bit6_0 Ajout de bruit : les bits 0 à 6 sont modifiés
DAC_LFSRUnmask_Bit7_0 Ajout de bruit : les bits 0 à 7 sont modifiés
DAC_LFSRUnmask_Bit8_0 Ajout de bruit : les bits 0 à 8 sont modifiés
DAC_LFSRUnmask_Bit9_0 Ajout de bruit : les bits 0 à 9 sont modifiés
DAC_LFSRUnmask_Bit10_0 Ajout de bruit : les bits 0 à 10 sont modifiés
DAC_LFSRUnmask_Bit11_0 Ajout de bruit : les bits 0 à 11 sont modifiés
DAC_TriangleAmplitude_1 Ajout d'un signal triangulaire d'amplitude 1
DAC_TriangleAmplitude_3 Ajout d'un signal triangulaire d'amplitude 3
DAC_TriangleAmplitude_7 Ajout d'un signal triangulaire d'amplitude 7
DAC_TriangleAmplitude_15 Ajout d'un signal triangulaire d'amplitude 15
DAC_TriangleAmplitude_31 Ajout d'un signal triangulaire d'amplitude 31
DAC_TriangleAmplitude_63 Ajout d'un signal triangulaire d'amplitude 63
DAC_TriangleAmplitude_127 Ajout d'un signal triangulaire d'amplitude 127
DAC_TriangleAmplitude_255 Ajout d'un signal triangulaire d'amplitude 255
DAC_TriangleAmplitude_511 Ajout d'un signal triangulaire d'amplitude 511
DAC_TriangleAmplitude_1023 Ajout d'un signal triangulaire d'amplitude 1023
DAC_TriangleAmplitude_2047 Ajout d'un signal triangulaire d'amplitude 2047
DAC_TriangleAmplitude_4095 Génération d'un signal triangulaire d'amplitude 4095

Champ DAC_OutputBuffer, il permet d'activer ou non l'amplificateur placé en sortie du DAC.


Les valeurs possibles sont : DAC_OutputBuffer_Enable ou DAC_OutputBuffer_Disable

 Le premier paramètre désigne le convertisseur à initialiser. Il peut prendre les valeurs :


DAC_Channel_1 ou DAC_Channel_2
 Le second paramètre est un pointeur sur une structure de type DAC_InitTypeDef préparée
par la fonction DAC_StructInit puis dont les champs ont été remplis en fonction du
fonctionnement désiré.

16.10. 3. Lancement d'un convertisseur par programme


Le lancement d'un convertisseur se fait par la fonction suivante :

 Le premier paramètre désigne le convertisseur à lancer. Il peut prendre les valeurs :


DAC_Channel_1 ou DAC_Channel_2

Page | 367 © ISI 2018 Ridha Ghayoula


 Le second paramètre indique si le convertisseur est lancé ou pas. Les valeurs possibles sont :
ENABLE ou DISABLE

16.10. 4. Lignes de sortie des convertisseurs

DAC1 sur PA4


DAC2 sur PA5
Les lignes utilisées comme sorties analogiques doivent être programmées en mode sortie analogique

16.10.5. Ecriture d'une valeur dans un convertisseur


Elle se fait par les fonctions :

 Le premier paramètre indique la taille et la façon dont sont alignées les valeurs écrites dans le
DAC. Il peut prendre les valeurs décrites dans le tableau suivant :
DAC_Align_12b_R Données écrites sur 12 bits cadrés à droite
DAC_Align_12b_L Données écrites sur 12 bits cadrés à gauche
DAC_Align_8b_R Données écrites sur 8 bits cadrés à droite
 Le second paramètre contient la valeur à écrire qui est contenue dans un mot de 16 bits et
doit correspondre au format décrit par le premier paramètre.

16.10.7. Lecture de la valeur d'un convertisseur


On peut lire la valeur actuellement contenue dans un convertisseur par la fonction :

 Le paramètre désigne le convertisseur à lire. Il peut prendre les valeurs : DAC_Channel_1


ou DAC_Channel_2
 La valeur de retour est celle contenue dans ce convertisseur.
16.10.8. Guide d'utilisation des convertisseurs N/A
a) Marche à suivre pour initialiser les convertisseurs N/A
1. Déclarer une variable de type DAC_InitTypeDef
2. Activer l'horloge du convertisseur par la fonction RCC_APB1PeriphClockCmd
3. Réinitialiser ce convertisseur par la fonction DAC_DeInit
4. Initialiser la variable de type DAC_InitTypeDef par la fonction DAC_StructInit
5. Dans cette variable indiquer si un amplificateur est ou pas placé en sortie et si un
signal doit être ajouté. Dans ce cas indiquer s'il s'agit d'un signal de bruit ou d'un
signal triangulaire et quelle est son amplitude
6. Programmer le convertisseur par la fonction DAC_Init
7. Activer le convertisseur par la commande DAC_Cmd
8. Recommencer les étapes 3 à 7 pour chaque convertisseur

Les lignes utilisées comme sorties analogiques doivent être programmées en mode sortie analogique
b) Ecrire une valeur à convertir en analogique
− L'écriture de la valeur à convertir se fait par la fonction DAC_SetChannel1Data ou
DAC_SetChannel2Data selon le convertisseur, cette fonction permet également de
préciser la taille et l'alignement de la valeur.

Page | 368 © ISI 2018 Ridha Ghayoula


c) Lire la valeur actuellement convertie en analogique
− La lecture de la valeur actuellement convertie se fait par la fonctionDAC_GetDataOutputValue

16.11. Débuter avec la carte STM32 Nucleo


Cette partie de ce chapitre s'appuie sur les carte NUCLEO-F411RE. Le STM32F411 est un des
microcontôleurs les plus puissants. La licence KEIL µVision pour le STM32 est gratuite.

Figure 16.7. STM32 Nucleo

Il est recommandé d'avoir une bonne connaissance de la carte STM32F411RE


http://www.st.com/web/catalog/mmc/FM141/SC1169/SS1577/LN1877/PF260049?s_searchtype=partnu
mber

Page | 369 © ISI 2018 Ridha Ghayoula


A) Environnement de développement intégré

 Le STM32 : Outils de Développement

Fournisseur Description
Hitex : www.hitex.com Atelier, GNU C/C++, USB/JTAG
IAR : www.iar.com Atelier, IAR C/C++, USB/JTAG
Keil : www.keil.com Atelier, ARM C/C++, USB/JTAG
Raisonance : www.raisonance.com Atelier, GNU C/C++, USB/JTAG
Rowley : www.rowley.co.uk Atelier, GNU C/C++, JTAG
... ...

 Le STM32 : Cartes de Développement

Fournisseur Description
Hitex : www.hitex.com STM3210B-SK/HIT
IAR : www.iar.com STM3210B-SK/IAR
Keil : www.keil.com STM3210B-SK/Keil
Raisonance : www.raisonance.com STM3210B-PRIMER
Raisonance : www.raisonance.com STM3210B-SK/RAIS
ST: www.st.com STM3210B-MCKIT
... ...

 Le STM32 : Systeme d’Exploitation

Page | 370 © ISI 2018 Ridha Ghayoula


Fournisseur RTOS
Micrium : www.micrium.com µC/OS-II
IAR : www.iar.com PowerPac
Keil : www.keil.com ARTX-ARM
www.FreeRTOS.org FreeRTOS
Segger : www.segger.com embOS
CMX Systems : www.cmx.com CMX-RTX
... ...

 IDE intégré à l'ordinateur:

Un générateur de code d'initialisation (pas de compilateur) STM32CUBE est proposé par ST, il
permet une configuration simple, rapide et graphique des périphériques et horloges du
microcontroleur. STMCUBE génère les fichiers d'initialisation et une puissance bibliothèque appelée
HAL. L'IDE (ici Eclipse AC6) permet l'écriture du programme, le téléchargement dans le
microcontrôleur et le debug complet. Il est à noter qu'éclipse fonctionne sur Windows, Linux et
MACOS ARM-KEIL propose un IDE sour Windows très performant mais gratuit uniquement
pour les STM32F0.

Figure 16.8. IDE intégré à l'ordinateur

Page | 371 © ISI 2018 Ridha Ghayoula


ST-LINK Part Mini
USB

Embedded
ST-LINK/V2-1
SWD

B1
USER

I/O I/O

STM32

ST morpho extension header


ST morpho extension header

Micocontroller

Arduino connector
Arduino connector

I/O I/O

RST

B2 LED
RESET LD2

MCU Part

Figure 16.9. STAM32

Page | 372 © ISI 2018 Ridha Ghayoula


(a) (b)
Figure 16.10. STM32 Nucleo-64 board

Figure 16.11. Bottom layout

Page | 373 © ISI 2018 Ridha Ghayoula


Figure 16.12.Connecting the STM32 Nucleo board to program the on-board STM32

STM32CubeMX est un outil graphique pour les microcontrôleurs STM32. Cela fait partie de
STMCube ™ initiative (voir la section 2) et est disponible sous forme d'application standard ou
d'Eclipse plug-in pour intégration dans des environnements de développement intégrés (IDE).

STM32CubeMX a les caractéristiques principales suivantes:

• Sélection de microcontrôleur couvrant tout le portefeuille STM32

• Configuration du microcontrôleur (broches, arbre de l'horloge, périphériques, middleware) et


génération du code C d'initialisation correspondant.

• Commutation facile à un autre microcontrôleur en important un enregistrement précédemment


enregistré.

• Exportation facile de la configuration actuelle vers un microcontrôleur compatible

• Génération de rapports de configuration

Page | 374 © ISI 2018 Ridha Ghayoula


• Génération de projets C intégrés pour une sélection de développement intégré. Les projets
STM32CubeMX incluent l'initialisation générée code C, les pilotes STM32 HAL conformes à
MISRA 2004, les piles de middleware requises pour configuration de l'utilisateur, et tous les fichiers
pertinents pour l'ouverture et la construction du projet dans l’IDE sélectionné.

• Calcul de la consommation d'énergie pour une séquence d'application définie par l'utilisateur

• Mises à jour automatiques permettant à l'utilisateur de garder le STM32CubeMX à jour

• Téléchargement et mise à jour du logiciel embarqué STM32Cube.

A) controller une simple LED

 New Project
Je commence par démarrer STM32CubeMX puis crée un nouveau projet.
Ensuite, je le sélectionne, le Nucleo-F411RE[35-36]

 Pinout

Page | 375 © ISI 2018 Ridha Ghayoula


Page | 376 © ISI 2018 Ridha Ghayoula
 Clock Configuration
La configuration des horloges peut être assez complexe, mais STM32CubeMX simplifie la
tâche.

 NVIC configuration

NVIC (Nested Vector Interrupt Controller) ou contrôleur d'interruption vectoriel imbriqué est
utilisé pour indiquer dynamiquement quelle interruption est la plus importante et pour activer ou
désactiver les interruptions. Il prend en charge jusqu'à 256 vecteurs d'interruption différents.

Page | 377 © ISI 2018 Ridha Ghayoula


Sys Tick
(System Tick Timer)

CortexTM-M
Processsor Core
Peripheral
NMI
NVIC
IRQs System
Configuration Exceptions
Peripherals registers

Bus Interface

Internal bus interconnect

Figure 16.13. NVIC configuration

Page | 378 © ISI 2018 Ridha Ghayoula


 MDK-ARM V
Le kit de développement logiciel MDK version 5 d'ARM est divisé entre packs logiciels et
cœur MDK

 Code Generator

Page | 379 © ISI 2018 Ridha Ghayoula


 main.c

 Download Function

Page | 380 © ISI 2018 Ridha Ghayoula


Page | 381 © ISI 2018 Ridha Ghayoula
Page | 382 © ISI 2018 Ridha Ghayoula
STM32 Outils de développement Ici les fonctions de contrôle des GPIO pour faire simplement
clignoter le LED rouge entrerdans main.c le code :

B) FREE RTOS
Dans cette partie de ce chapitre je vais décrire comment démarrer avec FreeRTOS en utilisant l'outil
de génération de code ST Microelectronics STM32CubeMX sur une carte STM32 Nucleo. Voici un
tutoriel pour faire votre premier RTOS sur une board STM32 Nucleo. Nous utiliserons ici une carte
Nucleo F411RE.
 New Project
Je commence par démarrer STM32CubeMX puis crée un nouveau projet.

Page | 383 © ISI 2018 Ridha Ghayoula


 FREERTOS
Ensuite, on selectionne FREERTOS Enabled

 FREERTOS Configuration
Ensuite, dans Software time definitions changer USE_TIMERS: Enabled

Page | 384 © ISI 2018 Ridha Ghayoula


Ensuite, dans Tasks and Queues ajouter des nouveaux taches New Task

Page | 385 © ISI 2018 Ridha Ghayoula


 Project Settings
Ensuite, dans Tolchain/IDE selectionner MDK-ARM V5

 Project
Dans SYS selectionner Timebase source - TIM1

Page | 386 © ISI 2018 Ridha Ghayoula


Puis selectionner Project : Generate source code

C) STM32CubeMX Tutorial Series : USART

L'exemple suivant illustre trois différents modèles de programmes, l'interrogation de bibliothèque


HAL, l'interruption et le DMA avec l'exemple de la communication série.

Dans la communication série, les données sont transmises en caractères et chaque caractère est
transmis en octets. Il commence toujours à partir du bit de début et se termine avec le bit d'arrêt.
Avant la transmission, assurez-vous que l'hôte et l'esclave utilisent le même débit en bauds.
Généralement, il existe deux modes de communication série de base, la communication synchrone et
la communication asynchrone. Pour la communication asynchrone, les données transmises doivent
être au format: Bit de start + bit de données + paritybit + bit de stop.

 Redéfinir la fonction printf

Page | 387 © ISI 2018 Ridha Ghayoula


Ouvrez un nouveau projet sur STM32CubeMX, puis sélectionnez la puce STMF746IGT6 et High
Speed Clock (HSE). Sélectionnez USART1 comme mode de communication asynchrone.

Réglez PA10 comme RX, et PA9 comme TX.

 Configuration de l'horloge

Configurez l'horloge du système comme 216 MHz. Vous pouvez configurer l'horloge USART en
fonction. La valeur par défaut est 108Mhz.

 Configuration série

Réglez le débit en bauds sur 115200 bits/s, la longueur des données de transmission est de 8 bits.
Parité: Aucune, bit d'arrêt: 1. Les autres paramètres sont définis par défaut.

Page | 388 © ISI 2018 Ridha Ghayoula


Vous pouvez régénérer un nouveau rapport et un nouveau code, puis compiler le programme. Dans
le fichier usart.c, vous pouvez trouver la fonction d'initialisation MX_USART1_UART_Init
(void) et la fonction de configuration de la broche HAL_UART_MspInit ().

Pour les fonctions de sortie standard de la bibliothèque standard en langage C, le périphérique de


sortie par défaut est displayer. Vous devez redéfinir les fonctions de sortie dans la bibliothèque
standard pour implémenter la sortie série ou la sortie LCD. Par exemple, pour sortir la fonction
printf vers le port série, vous devez diriger la sortie de la fonction fputc vers le port série
(redirection). C'est facile à faire. Ajoutez une fonction int fputc (int ch, FILE * f) et assurez-vous
que le port série peut sortir le caractère.

Ajoutez les lignes suivantes derrière le fichier fileusart.c. La définition de macro #ifdef a été ajoutée
au code pour la compilation conditionnelle. Si vous utilisez le compilateur GUNC,
PUTCHAR_PROTOTYPE doit être défini comme la fonction int__io_putchar (int ch), ou bien il
doit être défini comme functionint fputc (int ch, FILE * f).

Page | 389 © ISI 2018 Ridha Ghayoula


L'instruction HAL_UART_Transmit (& huart1, (uint8_t *) & ch, 1, 0xFFFF) signifie la
transmission d'un caractère via le port série port1. ch est l'adresse pour stocker le caractère, 0xFFFF
est le délai d'expiration. Dans le fichier stm32f7xx_hal_uart.c, vous pouvez trouver la fonction
HAL_UART_Transmit.

Dans le fichier filemain.c, ajoutez des fonctions d'application.

Page | 390 © ISI 2018 Ridha Ghayoula


- Compilez le programme et téléchargez-le sur le tableau de développement.
- Connectez la carte à votre PC avec un câble USB et exécutez l'assistant série sur le PC.
- Sélectionnez le numéro de port série correspondant et réglez le débit en bauds sur 115200.
- Appuyez sur le bouton Réinitialiser, vous pouvez recevoir les informations comme indiqué
sur la figure ci-dessous.

Vous pouvez aussi utliser et développer des applications en utiliserant l’interface de développement
en ligne proposé par MBED (http://www.mbed.org).

Page | 391 © ISI 2018 Ridha Ghayoula


17
Altium Designer

17.1. Introduction
Altium Designer est un puissant outil de CAO électronique développé pour la conception de
systèmes électroniques avec FPGA embarqués et pour le PCB (création des circuits imprimés).
On peut également développer le logiciel enfouis pour processeurs discrets et FPGA, faire le
routage, l’édition, la simulation des signaux mixtes et la fabrication de PCB, le tout au sein d’un
environnement de conception unique.

Ce chapitre doit être considérée comme une première étape dans l’utilisation de l’application Altium
Designer. Il s’agit à son terme, de maîtriser l’interface graphique, de créer des bibliothèques des
composants, de modéliser le circuit via la saisie de schéma, de placer les composants et de router les
signaux afin de générer les fichiers de documentation et de fabrication.

La grande force d'Altium Designer c'est les nombreux outils qu'il intègre par défaut. Ce logiciel
représente une seule solution informatique pour concevoir et développer un montage électronique
en allant du schéma jusqu'à la programmation des composants de ce schéma. Voici en outres les
principales caractéristiques de ce logiciel:

 L'outil unique permet de simplifier le travail entre l'éditeur de schématique, la simulation, la


réalisation du circuit imprimé et toutes les autres fonctionnalités
 Réaliser un prototype via le logiciel grâce aux différents outils, incluant un outil de
visualisation 3D
 Adapté pour l'avenir (prend en compte certaines nouvelles technologies et mise à jour
régulière)
 Nombreuses bibliothèques de composants
 Mise à jour continue

Page | 392 © ISI 2018 Ridha Ghayoula


Figure 17.1. Altium Designer

Altium Designer est un outil complet de développement de produits électroniques incluant :


 un outil de routage PCB
 un outil de simulation SPICE
 un outil de développement FPGA
 un outil de développement de code embarqué

On peut démarrer ces différents outils depuis la page de démarrage de l’outil.

Figure 17.2. Page de démarrage du logiciel Altium Designer


17.2. Simulation des circuits électroniques avec Altium Designer
Dans cette partie on présente une introduction rapide à la simulation des circuits électroniques avec
AD.
a) Procédure générale
La simulation d’un circuit électronique utilisant AD peut être réalisée en suivant la procédure
générale montrée dans la Figure suivante.

Page | 393 © ISI 2018 Ridha Ghayoula


Dessiner le schéma
- Ouvrir un nouveau schéma
- Choisir et placer les composants
- Faire les connexions

Définir les paramètres de


simulation
- Définir les sources
- Définir les signaux de sortie
- Définir le mode de simulation
- Choisir la durée et le pas de calcul
- Définir le mode d’acquisition des résultats
- Définir le mode d’affichage

Exécuter la simulation
- Générer le netlist (pour vérifier le schéma)
- Lancer la simulation

Afficher les résultats


- Saisir les résultats
- Tracer les formes d’ondes
- Effctuer les opérations mathématiques
sur les résultats
Figure 17.3. Procédure générale
b) Dessin de schémas
 Créer un nouveau schéma
Dans le menu principal:
New
Schematics

Figure 17.4. Un nouveau schéma avec Altium Designer


 Choisir et placer les composants
Dans le menu principal:

Page | 394 © ISI 2018 Ridha Ghayoula


Place - Part
Choose

Figure 17.5. Les composantes-Altium Designer


 Ouvrir une collection de composants (library en anglais), par exemple Simulation
Sources.IntLib, et choisir un composant.
 Placer le nombre requis de ce composant dans le schéma.
 Continuer à choisir et placer tous les composants nécessaires.
 Placer au moins une connexion de masse (GND).
 Placer les sources d’alimentation (sources DC).
 Avant de continuer, déplacer les composants aux endroits prévus dans le schéma et mettre
les composants dans la bonne orientation (en utilisant la fonction Rotate)

 Faire les connexions


Dans le menu principal:
Place - Wire
 Relier les composants avec le fil électrique et faire les connexions nécessaires pour compléter
le schéma.

Page | 395 © ISI 2018 Ridha Ghayoula


Figure 17.6. Les connexions-Altium Designer

 Composants électroniques discrets


Dans AD, les composants discrets se trouvent dans la collection Miscellaneous Devices.IntLib
(195 composants) et aussi dans les collections spécifiques des fabricants.

Figure 17.7. Les connexions-Altium Designer

Composants passifs
Res1 Resistor
Inductor Inductor
Inductor iron inductor Magnetic-core
Cap Capacitor
Trans Transformer
Trans Eq Transformer (Equivalent circuit model)
Trans3 Three-winding transformer (non-ideal)

Page | 396 © ISI 2018 Ridha Ghayoula


Diodes
Diode 1N4004 1 Amp general purpose rectifier
Diode 1N4148 High conductance fast diode
Diode 1N4934 1 Amp fast recovery rectifier
Diode 1N5404 3 Amp general purpose rectifier
D Schottky Schottky diode
D Zener Zener diode
Bridge1 Full-wave diode bridge
LED0 Typical INFRARED GaAs LED
LED1 Typical RED GaAs LED
LED2 Typical RED, GREEN, YELLOW, AMBER GaAs LED
LED3 Typical BLUE SiC LED

Transistors
2N3904 NPN general purpose amplifier
2N3906 PNP general purpose amplifier
NPN NPN bipolar transistor
NPN1 NPN Darlington bipolar transistor
PNP PNP bipolar transistor
PNP1 PNP Darlington bipolar transistor
JFET-N N-channel JFET
JFET-P P-channel JFET
MOSFET-N N-channel MOSFET
MOSFET-P P-channel MOSFET
 Composants électroniques intégrés
Dans AD, les composants intégrés (CI = Circuits intégrés) se trouvent dans plusieurs collections
nommées suivant leurs marques et fonctions.

 Spécifier les caractéristiques des composants


On sélectionne chaque composant pour donner ses paramètres en utilisant les fenêtres Properties et
Parameters. Par exemple, pour spécifier une résistance:

 Définir les alimentations


Une alimentation DC peut être représentée par une source de tension VSRC. On définit les sources
de tension DC en suivant la procédure montrée dans la prochaine section.

 Définition des sources de signal


Les excitations des circuits électroniques sont représentées par des sources de tension ou de courant.
La nature et les caractéristiques de sources dépendent de l’analyse qu’on veut effectuer.
Les sources de tension et de courant se trouvent dans la collection Simulation Sources.IntLib.
Sources de tension Sources de courant
VEXP Exponential voltage source IEXP Exponential current source
VPULSE Pulse voltage source IPULSE Pulse current source
VPWL Piecewise linear voltage source IPWL Piecewise linear current source
VSFFM Frequency-modulated sinusoidal voltage ISFFM Frequency-modulated sinusoidal current
source source
VSIN Sinusoidal voltage source ISIN Sinusoidal current source
VSRC Voltage source ISRC Current source
ESRC Voltage-controlled voltage source FSRC Current-controlled current source
HSRC Current-controlled voltage source GSRC Voltage-controlled current source

Page | 397 © ISI 2018 Ridha Ghayoula


 VSRC - Source de tension

Figure 17.8. VSRC -Altium Designer


 VSIN - Source de tension sinusoîdale

Figure 17.9. VSIN -Altium Designer

 Définition le mode et les paramètres de simulation


On clique sur Setup Mixed Signal Simulation pour définir le mode et les paramètres de simulation
dans la fenêtre Analysis Setup.
Dans l’exemple suivant, on a choisi Operating Point Analysis et Transient Analysis.

Page | 398 © ISI 2018 Ridha Ghayoula


Figure 17.10. Les paramètres de simulation -Altium Designer
Les paramètres de simulation du mode “Transient Analysis” sont définis dans la fenêtre Transient
Analysis Setup.

Figure 17.11. Analysis Setup -Altium Designer

Les détails concernant les modes de simulation (Operating point analysis, Transient analysis, DC
sweep analysis, AC small signal analysis, Noise analysis, Pole-zero analysis, Tranfer function analysis,
Temperature sweep, parameter sweep, Monte Carlo analysis) seront donnés dans un autre document
“Les modes de simulation avec AD”.

 Exécution de la simulation
On exécute la simulation du circuit en cliquant sur Run Mixed Signal Simulation (F9).

Page | 399 © ISI 2018 Ridha Ghayoula


Figure 17.12. Exécution de la simulation-Altium Designer

 Affichage et traitement des résultats


Les résultats de la simulation (tensions et courants) sont stockés en mémoire. On peut afficher les
formes d’ondes de tension et courant dans une fenêtre.
Pour en savoir plus sur le logiciel, reportez vous au site d’Altium :
http://www.altium.com/products/altiumdesigner/

17.3. Flot de conception d’une carte électronique


La Figure 2 décrit le flot typique de conception d’un circuit imprimé (PCB). Un projet PCB contient
2 documents : une schématique, décrivant le schéma électrique del’application. Les composants
électriques sont représentés par des symboles et reliés par desinterconnexions électriques un
document PCB, décrivant le placement physique des composants sur la carte et le routage des
interconnexions.
Ces 2 documents sont liés. A chaque composant élect ronique, on associe un symbole électrique et
une empreinte sur un circuit imprimé. La première phase consiste à définir le schéma électrique. On
sélectionne dans une librairie les différents symbo les électriques des composants, on leur attribue
des empreintes et on les relie. Après une validation électrique, le document de routage PCB, qui a été
au préalable spécifié, est mis à jour en fonction de la schématique. Les empreintes des composants
sont déposées aléatoirement sur la surface de routage, les interconnexions entre les circuits
apparaissent sous forme de liens virtuels. Les 2 étapes qui suivent sont :
 Le placement des composants sur la carte
 Le routage des interconnexions, qui vont être matérialisées par des lignes métalliques

A la fin de ces 2 phases, une vérification de la correspondance entre le routage et la schématique et


du respect des règles de routage (DRC) est appliquée fin de valider le design. Une fois le design
validé, des fichiers de sortie peuvent être produits pour réaliser les différents masques servant à
fabriquer la carte. Les parties qui vont suivre décrivent comment réaliser ces différentes étapes sous
Altium Designer.

Page | 400 © ISI 2018 Ridha Ghayoula


Création d'un projet
PCB

Document de Schématique
Saisie de la schématique

Lien symboles-
empreintes

Vérification
électronique (ERC)

Transfet de schéma sur Spécification carte et


le document PCB règles de routages
Document de Routage

Placement
Composants/Routage
PCB

Vérification Routage
(DRC)

Ficher de sortie

Figure 17.13. Flot de conception d’un circuit imprimé (PCB)

17.3. Créer un projet PCB


Sous Altium Designer, un projet est composé d’un en semble de documents reliés au design. Les
projets PCB ont l’extension name.PrjPCB. Il s’agit d’un fichier ASCII listant tous les documents et
les réglages de sortie.
Pour créer un nouveau projet, cliquez sur File>New>Project>PCB project depuis la fenêtre de
démarrage d’Altium (Figure 17. 14). Renommer le nouveau projet en conservant l’extension .PrjPCB
et indiquer le chemin d’accès sur le disque, en cliquant sur File>Save Project as. Pour l‘instant, le
projet est vide, aucun document n’a été ajouté. La prochaine étape consiste à créer la schématique et
de l’ajouter dans le projet.

Page | 401 © ISI 2018 Ridha Ghayoula


● Routage automatique
Faire un essai de routage automatique en simple face (dans les « Rules : Routing Layers » ne
sélectionner que le « Bottom layer »). Lancer le routeur par le menu : « Design -> Autoroute All ».
Si le routeur ne s’en sort pas rapidement c’est qu’il est très probable que le routage double face
s'imposera. Dans ce cas aller modifier la règle « Routing Layer » comme indiqué plus haut et
relancer le routage automatique.
Remarque importante. Le routage simple face sera apprécié pour deux raisons : le coût de
réalisation de la carte sera plus faible ; le routage double face donne beaucoup plus de risque de
pannes surtout s’il y a de nombreux « Vias » sur la carte.

● Routage manuel
Il est presque indispensable de reprendre la carte en manuel pour finir le routage, surtout en double
face pour tenter d’éliminer les Vias non indispensa bles et pour revoir le routage de certaines
empreintes qui ne peuvent pas sans supports spéciaux être routées en face avant (circuits intégrés,
borniers etc.). De plus une carte bien routée verrases pistes ne pas faire de détours inutiles ni
posséder d’angles obtus.
Pour faire un routage manuel, sélectionner la couche sur laquelle on souhaite commencer la piste
(sélecteur de couche = onglets de couleur en bas de la fenêtre) et cliquer sur l’icône (Interactively
Route Connections) de la barre de tâ ches en haut. Un clic pour démarrer, un clic pour chaque
changement de direction et deux pour terminer. Touche Escape pour passer à une autre connexion,
à nouveau escape pour terminer le routag e. Il est possible de router en double face de cette même
façon, le changement de couche avec placement automatique du Via se faisant en appuyant
simplement sur le touche + ou – pour changer de couche.
Il est important d’identifier les composants ne pou vant pas être routés en face avant (car
impossibles à souder en face avant comme souvent les borniers, les supports de CI standards, etc.)
et passer en face arrière les pistes correspondantes routées en face avant. De même pour simplifier
la réalisation finale penser à supprimer les vias dès que cela est possible.

● Vérification du PCB
Terminer pas une vérification par le menu Tools->Design Rule Check..., puis cliquer sur « Run
design Rule Check » sans changer les options de la fenêtre ; un rapport s’ouvre et ne doit faire
apparaître aucune « Rule violation » (vérifier aussi les « warning »...).

Page | 402 © ISI 2018 Ridha Ghayoula


Figure 17.14. PCB-Altium Designer

Figure 17.15. PCB-Altium Designer

17.4. Saisie d’une schématique


a) Création d’une schématique
Une nouvelle schématique en cliquant sur File>New>Schematic. Une feuille de saisie de
schématique vierge apparaît, nommée Sheet1.SchDoc, qui est automatiquement ajouté au projet
dans la liste Source documents. On renomme la fiche avec File>Save As. Il est possible d’ajouter

Page | 403 © ISI 2018 Ridha Ghayoula


une schématique existante au projet à l’aide d’une clique droit au dessus du nom du projet dans le
panneau Projectset en sélectionnantAdd Existing to Project.

Figure 17.16. Création d’une nouvelle schématique

Avant de démarrer la saisie de la schématique, il e st nécessaire de paramétrer les options de la fiche.


Aller dans Design>Document Options puis dans Sheet Options. Sélectionner le format de la fiche
(exemple : A4). Dans Units, sélectionner le système métrique pour les unités

Figure 17.17. Modification des options du document de schématique


Ensuite, il faut configurer les préférences générales de la schématique :

Page | 404 © ISI 2018 Ridha Ghayoula


Tools>Schematic Preferences. Sélectionner par exemple dans la liste de gauche Schematic –
Default Primitives et cocher la case Permanent. Terminer en cliquant sur OK.

b) Saisie de la schématique
Maintenant, il est possible de saisir une nouvelle schématique. Dans un premier temps, il est
nécessaire de localiser les composants dans les différentes librairies fournies par l’outil, puis de
charger ces librairies. Cliquez sur Design>Browse Librariespour afficher le panneau d’exploration
des librairies. Le bouton librairie est aussi disponible sur le bord droit de la fenêtre. La fenêtre
présentée Figure 18.6 appraît en cliquant sur ce bouton. Il existe différents moyens de retrouver un
composant : soit en cliquant sur le bouton Search. Une fenêtre de dialogue s’ouvre permettant une
recherche à partir de quelques critères Soit en cherchant dans le contenu d‘une librairie (par défaut,
la librairie Miscellaneous est chargée). Différentes informations sont reliées à chaque composant : un
symbole, une empreinte, un modèle pour la simulation électrique, pour la simulation d’intégrité de
signal.
Pour placer un composant sur la schématique, sélectionnez ce composant dans sa librairie, puis
appuyez sur le bouton Place. Vous pouvez ensuite déplacer le composant qui reste flot tant et le
placer à l’endroit voulu par un simple clic ou en appuyant sur Entrée. Lorsqu’il est flottant, on peut
le faire tourner à l’aide de la barre d’espace, éditer ses propriétés à l’aide de la touche Tab, changer s
on orientation à l’aide de la touche x ou y.

Figure 17.18. Panneau Libraries

Une fois le composant placé, il est possible d’afficher ses caractéristiques par un double clic, de
l’effacer en le sélectionnant et en appuyant sur la touche Suppr. Il est possible de faire tourner un
composant en le sélectionnant et en appuyant sur la barre d’espace (ou en allant dans Edit>Move ).

Page | 405 © ISI 2018 Ridha Ghayoula


En double cliquant sur le composant, on fait apparaître ses propriétés. Dans cette fenêtre, on peut
éditer et modifier le nom, les valeurs, le boîtier, le brochage et d’autres propriétés.

Une fois les composants placés, on peut les connect er. Pour cela, cliquez sur Place>Wire ou sur le
bouton . Cliquer ou appuyer sur entrée pour connecter la p remière extrémité du fil, faites de
même pour connecter la seconde extrémité. Une fois les composants interconnectés, on peut les
déplacer sans casser les connexions en cliquant sur Edit>Move>Drag. Vous pouvez le faire en
bougeant normalement le composant tout en appuyant sur la touche Control.
Enfin, il faut nommer les nœuds. Pour placer des la bels de nœuds, cliquez Place>Net Label et
placer le sur le fil à nommer. Une croix rouge apparaît quand le logiciel détecte un nœud à nommer.
Vous pouvez entrer le nom du label en cliquant sur tab si le label est encore flottant ou en double
cliquant dessus.

c)Exemple d'application Cahier des charges :


 Vous dessinerez un schéma construit autour d’un PIC18F2550
 Cette carte comprendra : le connecteur de programmation IDE, une cellule RESET, un
quartz associé au microcontrôleur, un connecteur d’alimentation, un fusible.
 Seront joints une diode de visualisation commandée par le microcontrôleur et un switch
permettant d’imposer un niveau logique au microcontrôleur.
 Vous devez dessiner et router cette carte au format Europe (100x160 mm) en classe 3.
 Hormis les connecteurs et les switchs tous les composants seront en CMS.

 Création d’un nouveau projet PCB


- Repartir d’un environnement vide :

- Ouvrir les fenêtres projet et message :

Page | 406 © ISI 2018 Ridha Ghayoula


Paramétrer l’environnement de travail d’Altium Designer :  Commande  System ( en bas à
droite )  Messages et Projects.

- Créer et renommer le projet :


Créer un nouveau projet en utilisant la commande :  File  New  PCB Projet.

 Depuis Explorer créer un nouveau répertoire dédié au projet.


 Cliquer droit sur le nom du nouveau projet.

Page | 407 © ISI 2018 Ridha Ghayoula


 Choisir la commande Save Projet as «Carte_Micro_PIC18F» pour sauvegarder le projet dans le
répertoire de travail.

 Les différents fichiers utilisés sous ALTIUM doivent porter des noms différents. ( risque d’erreur de récursion ).
 Organisation des fichiers et répertoires :
Ne pas créer de chemins profonds
Ne pas utiliser le caractères espace « » et/ou le caractère moins «-» dans les noms.
 Ne pas déplacer les fichiers de travail en cours de projet

 Dessin du schéma structurel


- Placer dans le répertoire de travail le fichier Sheet1_A_COMPLETER.Sch et ajouter le au projet :

Vous devez obtenir le schéma à compléter ci-dessous :

Page | 408 © ISI 2018 Ridha Ghayoula


- Placement des composants.
 Si les bibliothèques nécessaires ne sont pas installées voir annexe 2 « Mise en place des librairies
sous ALTIUM. »
 Vous devrez placer sur le schéma les composants R1 et U2 :
Nom du composant Nom du symbole Bibliothèque ou trouver le symbole
C1, C2, C3, C4 Cap Miscellaneous Devices.IntLib
D1, D2 Diode Miscellaneous Devices.IntLib
F1 Fuse 1 Miscellaneous Devices.IntLib
P1 Header 6 Miscellaneous Connectors.IntLib
P2 Header 2 Miscellaneous Connectors.IntLib
R1, R2, R3 Res2 Miscellaneous Devices.IntLib
S1, S2 SW-PB Miscellaneous Devices.IntLib
U1 PIC18F25J50-I/ML Microchip Microcontroller 8-Bit PIC18.IntLib
U2 MC78L05ACP Motorola Power Mgt Voltage Regulator.IntLib
Y1 XTAL Miscellaneous Devices.IntLib

- Vérifier la présence des librairies et les charger si nécessaire :

 Depuis le menu System en bas à droite de l’écran sélectionner System


 Librairies

- Exemple 1 placement du composant R1 : Res2, issu de la bibliothèque Miscellaneous Devices.IntLib.

Page | 409 © ISI 2018 Ridha Ghayoula


- Exemple 2 : placement du composant U2 : MC78L05ACP issu de la bibliothèque Motorola Power Mgt
Voltage Regulator.IntLib

 Editer le schéma structurel complet comme ci-dessous :

Pour dessiner : utiliser les outils de la barre de dessin :

NE PAS CONFONDRE LES BUS ET LES FILS !


Touche ESC pour sortir de la fonction

Page | 410 © ISI 2018 Ridha Ghayoula


 Pour placer un label cliquer sur l’icône label, placer le label sur le fil, renommer le label :

 Association de l’empreinte physique à la représentation schématique du composant :


 Exemple : changement de l’empreinte du microcontrôleur :
 Double cliquer sur le corps du composant U1 pour ouvrir la fenêtre propriété.

Page | 411 © ISI 2018 Ridha Ghayoula


Vous devrez pareillement associer les empreintes physiques de l'ensemble des composants listés ci-
dessous : (ou repartir du corrigé partiel Carte_MicroPIC18F_partiel.PrjPCB avec les empreintes
associées aux composants)
Nom du composant Empreinte Bibliothèque ou trouver l’empreinte
C1 6-0805_M Miscellaneous Devices.IntLib
C2 6-0805_M Miscellaneous Devices.IntLib
C3 C1206 Miscellaneous Devices.IntLib
C4 C1206 Miscellaneous Devices.IntLib
C5 C1206 Miscellaneous Devices.IntLib
D1 3.2X1.6X1.1 Miscellaneous Devices.IntLib
D2 DIODE_SMC Miscellaneous Devices.IntLib
F1 1812 Miscellaneous Devices.IntLib
P1 HDR1X6 Miscellaneous Connectors.IntLib
P2 HDR1X2 Miscellaneous Connectors.IntLib
R1 C1206 Miscellaneous Devices.IntLib
R2 C1206 Miscellaneous Devices.IntLib
R3 C1206 Miscellaneous Devices.IntLib
S1 SW/PB-V4/H7.1 Miscellaneous.PcbLib
S2 SW/PB-V4/H7.1 Miscellaneous.PcbLib
U1 SOIC-SO28_M Microchip Microcontroller 8-Bit PIC18.IntLib
U2 TO-220-AB Miscellaneous Devices.IntLib
Y1 2SMX-3SMXB Crystal Oscillator.PcbLib
 Sauvegarde du schéma sous la forme d'un SNIPSET
 Sélectionner l’ensemble des composants. ( Touche CONTRÔLE + « A »)
 Menu TOOLS  CONVERT
 Create Snippet from selected objects

 Définition des paramètres du routage depuis l'éditeur de schéma sheet


 Vous devez dessiner une carte au format Europe classe 3.
 Cette classe de dessin est normalisée. Cela vous impose donc les caractéristiques mécaniques de
votre typon ( largeur des pistes, écart entre les pistes, diamètre des via ...)
 Voir: Les classes de circuits imprimés.

Page | 412 © ISI 2018 Ridha Ghayoula


 Afin de paramétrer le logiciel en conséquence : Lancez le PCB WIZARD : faites apparaître la
fenêtre FILES depuis le menu SYSTEM ( en bas à droite ).

 Choix des unités :

Conversion des unités Impériales en unités métriques.


Pas Pouce (inch ) Mil ( millième d’inch ) mm (millimètres)
1 0.1 100 2.54
10 1 1000 25.4
Rem : on peut utiliser aussi 1 mil = 1 Thousandth
 Définition des dimensions et de la forme de la carte au format Europe :

Page | 413 © ISI 2018 Ridha Ghayoula


Le PCB est dessiné en deux couches :

 Imposer des via traversant :

Page | 414 © ISI 2018 Ridha Ghayoula


 Pour notre réalisation les composants sont majoritairement des CMS et d’un seul coté :

 Définition des largeurs et écarts des pistes et via :

Page | 415 © ISI 2018 Ridha Ghayoula


 Fin du paramétrage :

 Dessin de la carte électronique (dessin du PCB )


- Ouverture du fichier PCB, Lier le fichier PCB au projet.
 Le « WIZARD » d’Altium ouvre automatiquement une nouvelle fenêtre PCB :

- Paramétrage de l’espace de travail PCB.

Page | 416 © ISI 2018 Ridha Ghayoula


 VIEW
 TOGGLE UNITS ( en bas du menu déroulant )
 Paramétrage de la grille de placement depuis le raccourci GRIDS :

 Suppression du cadre de dessin en arrière plan  Menu DESIGN  Board Option :

 A ce stade enregistrez votre dessin PCB sous votre répertoire de travail.


 Vous êtes prêts à dessiner votre carte.
 Pour voir la zone de dessin dans son intégralité  View ( Touche V )
 Fit Board ( Touche F )
 Transfert du schéma vers le PCB :
 Depuis la fenêtre du schéma structurel Sheet1.SchDoc

Page | 417 © ISI 2018 Ridha Ghayoula


 Menu « Design »  « Update PCB Document »

 Revenez dans la zone de dessin du PCB :


A coté de la fenêtre PCB apparaît la représentation 2D des composants vus de dessus :

Page | 418 © ISI 2018 Ridha Ghayoula


 En 2D le logiciel PCB est un empilement de couches vue du dessus.
 Les couches qui nous intéressent plus particulièrement sont
Nom de la couche Couleur Rôle
TOP LAYER Couche cuivre du dessus

BOTTOM LAYER Couche cuivre du dessous


KEEP OUT LAYER Bord de la carte et réservation

TOP OVERLAY Sérigraphie


BOTTOM OVERLAY Sérigraphie
Mechanical 1, 13, 15 Représentation mécanique des composants

- Dessin du bord de la carte et des réservations


 Le bord de la carte a été généré sur la couche KEEP OUT LAYER lors de l’étape 5.
 Vous devrez rajouter à ce bord une réservation de 1cm² dans chacun des angles.
 L’outil de sélection des couches est la barre d’outils, sous le PCB
 A l’aide des flèches faites défiler les couches et cliquez sur KEEP OUT LAYER

Page | 419 © ISI 2018 Ridha Ghayoula


- Placement des composants
 Cliquez sur le composant et faites le glisser dans la zone PCB
 Pour verrouiller la position d’un composants ( Inutile dans un premier temps )
 Sélectionnez le composant
 bouton de droite :

 Les fonctions de base pour manipuler les composants sont toujours efficientes :
 Pour faire pivoter un composant  Barre espace
 Pour ZOOMER la carte à router :

 Touches de raccourcis Pour Zoomer :


 V + D (intégralité du document)
 ou V + F( seulement la carte à router)
 V + A entourer la zone à zoomer.
- Routage automatique
 Menu Autoroute ALL  Route ALL

Page | 420 © ISI 2018 Ridha Ghayoula


Intérêt du routage automatique :
 Un dessin de qualité respectant toutes les règles CEM ne peut être obtenu par un routage
complet.
 Nous n’utiliserons donc pas le routage automatique pour router notre carte.
 Toutefois cette fonction peut nous permettre de valider le placement de nos composants.
 Pour une carte complexe, il est conseillé de dessiner plusieurs placements de composants.
 En lançant le routeur automatique pour chaque placement vous pouvez comparer les résultats et
retenir le placement optimal. (Informations relatives au dessin de la carte )
 Vous reprendrez ensuite le routage en manuel.

 Lorsque le routage est fini vous obtenez le message :

 Et le PCB :

- Effacement des pistes :


 Pour effacer toutes les pistes routées
 TOOLS
 Un-route
 All
 Pour effacer une piste ou un segment de piste
 Sélectionner la piste
 Touche Suppression ( ou DEL )
- Routage manuel
 Routage manuel d’une piste :
 Pointer le curseur sur la pastille de départ
 Touche « P » puis touche « T »
 Touche « CTRL »
 Cliquer gauche sur la souris

Page | 421 © ISI 2018 Ridha Ghayoula


 Dessiner la piste
 Clic droit pour sortir de la fonction

Manage Set Layer cliquez sur LS  ou cliquer sur « L » raccourci depuis le PCB
 Pour changer de piste ( coté cuivre, coté composant touche ) « touche + » ou « touche - » du
clavier numérique.
- Placement des plans de masse et d’alimentation
 Menu PLACE  Polygon Pour  Dessiner le contour sur le PCB.
Exemple : un plan de masse
 Relié à la masse
 Sur la couche TOP
 Hachuré

- Visualiser votre PCB en trois dimensions


 Menu VIEW  Switch to 3 D 

 Pour faire pivoter la carte


 Touche « SHIFT » + « bouton droit de la souris »
 Retour en 2D  Menu VIEW  Switch to 2 D !

Page | 422 © ISI 2018 Ridha Ghayoula


17.10. Conception FPGA avec Altium Designer
L'objectif principal de cette partie est de rendre les étudiant(e)s compétents dans le processus de
développement, de téléchargement et d'exécution d'un design FPGA sur le NanoBoard. Nous allons
passer par le cadre de conception FPGA et démontrer à quel point la conception FPGA est simple
avec Altium Designer.

Les Objectifs:
Être capable de développer des conceptions des circuits FPGA en utilisant les bibliothèques
standard et l'environnement schématique
• Comprendre et être en mesure de faire usage du processus de génération FPGA
• Connaître les capacités périphériques des la carte et de savoir comment intégrer leur utilisation
dans des conceptions FPGA personnalisées.
• Apprécier les différents mécanismes de communication utilisés par le logiciel pour contrôler et
connecter une conception FPGA en cours d'exécution.
• être compétent avec l'utilisation d'instruments virtuels dans une conception FPGA.

FPGA Project FPGA Schematic FPGA Build


FPGA design
Core Topics

Ceration Extensions Process


built and load
onto nanoBroad

nanoBroad FPGA
Concepts Instruments
Advanced

FPGA Core Digital


Topics

Compoments Simulation

Figure 17.18. Topic Outline for the FPGA Design

a) Création de FPGA Project.

Page | 423 © ISI 2018 Ridha Ghayoula


Tous les composants qui seront combinés en une seule conception FPGA doivent être encapsulés
dans un projet FPGA. Le terme «Project» désigne un groupe de documents qui se combinent
ensemble pour former une seule cible.

Figure 17.19. Création de FPGA Project.


Dans cet exemple, nous allons créer notre première conception FPGA. Afin de compléter cette
tâche, vous devrez utiliser les composants suivants de leurs bibliothèques respectives:
1. Ouvrez un nouveau projet FPGA. Enregistrez-le comme MyPWM.PrjFpg
2. Ajouter un nouveau schéma à votre project et enregistrez-le comme.SchDoc

 Peripheral Components
Beaucoup de ressources matérielles présentes sur le NanoBoard viennent avec des modules
périphériques pouvant être inclus dans la conception FPGA pour faciliter l'interface sur le port
externe.

Page | 424 © ISI 2018 Ridha Ghayoula


Figure 17.20. Peripheral Components
 NanoBoard port plugins
Un résumé des composants est donné ci-dessous:

Page | 425 © ISI 2018 Ridha Ghayoula


Figure 17.21. NanoBoard port plugins

 Generic components
Les composants génériques peuvent être placés à partir de la bibliothèque \ Program Files \ Altium
Designer \ Library \ Fpga \ FPGA Generic.IntLib.
Cette bibliothèque est incluse pour implémenter la logique d'interface dans votre conception. Il
comprend des versions à l'échelle des broches et du bus pour de nombreux composants, ce qui
simplifie la complexité du câblage lorsque vous travaillez avec des bus. En plus d'une large gamme
de fonctions logiques, le générique. La bibliothèque comprend également des composants pullup et
pulldown ainsi qu'une gamme de menuisiers de bus, utilisés pour gérer la fusion, le fractionnement
et le renommage des bus.
Pour une définition de la convention de nommage utilisée dans la bibliothèque générique et une liste
complète des dispositifs disponibles, reportez-vous au document : CR0118 FPGA Generic Library
Guide.pdf. Les caractères Wild Card peuvent être utilisés pour filtrer lors de la recherche de la
bibliothèque de composants.

Page | 426 © ISI 2018 Ridha Ghayoula


Figure 17.22. Using wildcards to quickly find a specific component in the Generic Library

 Application - Créer un PWM


Dans cette application, nous créerons notre premier design FPGA. Pour compléter cette tâche, vous
devrez utiliser les composants suivants à partir de leurs bibliothèques respectives :
1. Ouvrir un nouveau projet FPGA. Enregistrez-le comme MyPWM.PrjFpg
2. Ajouter un nouveau schéma à votre projet et l'enregistrer en tant que MyPWM.SchDoc

Page | 427 © ISI 2018 Ridha Ghayoula


Figure 17.23. Place and wire the components to create the Pulse Width Modulator
Dans cette partie on va Utiliser des composants des deux bibliothèques FPGA Generic.IntLib et
FPGA NanoBoard Port-Plugin.IntLib, placez et téléchargez le schéma.

Figure 17.24. Place and wire the components to create the Pulse Width Modulator

Figure 17.25. Place and wire the components to create the Pulse Width Modulator

b) Targeting the design


Le schéma que nous venons de créer contient toute la connectivité qui doit se produire en interne
sur notre périphérique FPGA, mais nous avons encore besoin d'informations supplémentaires pour

Page | 428 © ISI 2018 Ridha Ghayoula


mapper les ports sur le schéma FPGA aux broches physiques sur un périphérique FPGA réelle. Ce
processus s'appelle le ciblage de notre conception.
 Constraint files
Plutôt que de stocker des données spécifiques aux dispositifs et aux implémentations telles que les
allocations de broches et les propriétés électriques dans les documents VHDL source ou schéma, ces
informations sont stockées dans des fichiers séparés - appelés fichiers de contraintes. Ce découplage
de la définition logique d'une conception FPGA à partir de sa mise en œuvre physique permet un
recentrage rapide et facile d'une conception unique à plusieurs dispositifs et mises en page PCB.
Ci-dessous, nous voyons une représentation conceptuelle d'un design FPGA assis dans un
périphérique FPGA. Les lignes rouges indiquent les mappages port-to-pin qui seraient gérés par le
fichier de contraintes.

Figure 17.26. Vue conceptuelle montrant la liaison des ports sur un schéma FPGA routé vers les
broches des périphériques physiques.
 Création d'un nouveau fichier de contraintes

Page | 429 © ISI 2018 Ridha Ghayoula


Un fichier de contraintes peut être ajouté à un projet en cliquant avec le bouton droit sur le projet
FPGA dans Projets et en sélectionnant Add New to Project » Constraint File. Un fichier de
contraintes de shell sera créé.

 Editing a constraint file


Les ajouts / modifications de fichiers de contraintes peuvent être effectués en éditant manuellement
le fichier de contraintes ou en utilisant le menu Design » Add/Modify Constraint.

Page | 430 © ISI 2018 Ridha Ghayoula


Sélectionnez les catégories Fournisseur (Vendors), Famille, Appareil et Température / Vitesse
comme vous le souhaitez, puis cliquez sur OK. Une ligne similaire à celle ci-dessous sera
automatiquement insérée dans le fichier de contraintes:
Record=Constraint | TargetKind=Part | TargetId=XC2S300E-6PQ208C
 Spécification port contraints
Utilisez le port Add/Modify Contraint #port pour appliquer une contrainte à un port
dans le projet FPGA.

Figure 17.27. Add/Modify Port Constraint dialog box.


Si vous sélectionnez OK dans la boîte de dialogue de la Figure 18.x., la contrainte suivante sera
ajoutée au fichier de contraintes:
Record=Constraint | TargetKind=Port | TargetId=CLK_BRD | FPGA_CLOCK_PIN=True
Cette contrainte garantira que les outils FPGA du fournisseur acheminent le port CLK_BRD vers
une broche d'horloge spécialisée sur le périphérique cible.
Alternativement, la contrainte FPGA_PINNUM peut être spécifiée pour verrouiller le port vers une
broche spécifique sur le périphérique cible

Figure 17.28. Add/Modify Port Constraint dialog box.


La sélection de OK dans la boîte de dialogue de la Figure 18.x ajoutera la contrainte
FPGA_PINNUM = P185 à la contrainte de port CLK_BRD

17.11. Exemples d'applications


a) Utilisation du Bluetooth dans une application Altium Designer AD

Page | 431 © ISI 2018 Ridha Ghayoula


Cet exemple a pour but d’expliquer comment utiliser le bluetooth dans vos applications Altium
Designer AD.

Android inclus un support du Bluetooth, ce qui permet aux devices de pouvoir échanger des
données entre eux en utilisant cette technologie.

As-tu le Bluetooth ?

La première étape dans l’intégration du Bluetooth dans votre application est de vérifier si le device
en question possède cette technologie.

Page | 432 © ISI 2018 Ridha Ghayoula


Figure 17.29. Altium Designer layout

Page | 433 © ISI 2018 Ridha Ghayoula


a) JPEG Decoder
Cet exemple de conception FPGA démontre la gestion de l'image JPEG basique, en utilisant les
décodeurs JPEG. Une image JPEG est liée au projet embarqué (Embedded Project Options »
Compiler Options » Linker » Miscellaneous » Additional linker options). Cette image JPEG
est tracée sur l'écran LCD à l'aide de:
décodage d'un coup
décodage partiel avec taille variable
décodage partiel avec changement d'origine
bloc de lecture des données
bloc d'écriture de données
lecture d'en-tête

Page | 434 © ISI 2018 Ridha Ghayoula


Figure 17.30. JPEG Decoder

Page | 435 © ISI 2018 Ridha Ghayoula


18
Introduction à la création et à la Packaging
Custom IP

18.1. Introduction
Ce chapitre présente les étapes requises pour créer et mettre en package une IP personnalisée dans
l'outil de packaging IP Vivado® Design Suite.
Vivado® Design Suite fournit un flux de conception centré sur IP qui vous permet de transformer
rapidement des conceptions et des algorithmes en IP réutilisables. Comme le montre la figure
suivante, le catalogue IP Vivado est un référentiel IP unifié qui fournit le cadre du flux de
conception IP-centric. Ce catalogue regroupe les IP de toutes les sources, y compris Xilinx® IP, les
IP tierces et les conceptions d'utilisateur final destinées à être réutilisées en tant qu'IP dans un
environnement unique. Ce tutoriel montre comment packager un projet RTL (VHDL) pour créer un
IP personnalisé dans Vivado 2018.2.

18.2. Creating a custom IP in Vivado


Ouvrez Vivado 2018.2 et créez un nouveau projet. Créez un nouveau fichier VHDL appelé
logic_function.vhd.
Nous allons d'abord créer un ET logique 1 bit. Dans la fenêtre « Définir le module», définissez deux
entrées à 1 bit (A_inp et B_inp) et une sortie à 1 bit (P_outp).

Page | 436 © ISI 2018 Ridha Ghayoula


Figure 18.1. Define the module

Dans l'architecture du module, ajoutez simplement la ligne suivante:


P_outp <= A_inp ET B_inp;
 Package le module dans une IP
Cliquez sur “Outils> Créer et créer une nouvelle IP…” pour créer un nouveau projet permettant de
créer une IP. Dans la page «Créer des périphériques, IP de package ou package un bloc de
conception», sélectionnez «Package votre projet actuel».

Figure 18.2. Create and Package New IP

Page | 437 © ISI 2018 Ridha Ghayoula


Dans la page « Package your current project », choisissez l'emplacement de création de l'IP et
sélectionnez «Include .xci files». Si vous utilisez le contrôle de révision (GIT, SVN, etc.) avec votre
définition IP personnalisée, l'UG1118 recommande d'utiliser un emplacement de référentiel externe
(en dehors du projet initial) pour votre IP personnalisée et de placer l'intégralité du répertoire IP
personnalisé dans la révision. Système de contrôle pour préserver toutes les sorties nécessaires du
packager IP.

Figure 18.3. Select Package IP Project Location

Cela crée un projet temporaire dans lequel vous pouvez modifier la configuration IP. Vous devriez
avoir une fenêtre appelée «Package IP - logic_function» ouverte avec différentes sections pour
configurer l’IP. La section «Identification», par exemple, vous permet de modifier le mode
d’identification de l’IP dans le catalogue IP de Vivado.

Page | 438 © ISI 2018 Ridha Ghayoula


Figure 18.4. Package IP – Identification

Si vous souhaitez conserver le projet IP après avoir compressé l'adresse IP (lorsque vous utilisez un
système de contrôle de révision, par exemple), cliquez sur Modifier les paramètres d'emballage (ou
accédez à project settings > IP > Packager) et désactivez Supprimer le projet après packaging.

Figure 18.5. Keep project after packaging

Page | 439 © ISI 2018 Ridha Ghayoula


Nous ne ferons plus de changements pour le moment. Allez dans la section "Review and Package".
Cliquez sur «Package IP». Vivado vous demandera si vous souhaitez fermer le projet, cliquez sur
“Oui”.

Ensuite, dans votre projet initial, si vous allez dans le catalogue IP («Window > IP catalog»), vous
devriez voir la fonction_logique IP sous UserIP.

Figure 18.6. User IP

Remarque: Si vous créez un nouveau projet Vivado, l’IP ne sera pas visible dans le catalogue des utilisateurs. En
effet, le dossier dans lequel se trouve l'adresse IP n'est pas analysé par Vivado. Vous devez ajouter ce dossier aux «IP
repositories» dans les paramètres du projet (IP > Repository).

Si nous sélectionnons l'IP, nous pouvons voir la fenêtre " IP Properties " avec les propriétés de
l'adresse IP. Nous pouvons voir que la version de l’IP est la 1.0 avec la rév. 1. La révision sera
incrémentée automatiquement chaque fois que nous emballons (package) l’IP. La version peut être
modifiée dans le projet de packaging IP.

 Paramétrer la taille des ports


Nous allons modifier l'IP pour faire un ET logique sur les bus (pas seulement sur les signaux 1 bit).
Pour modifier l'IP:

· Si vous avez conservé le projet IP Packager, ouvrez ce projet.

· Si vous n’avez pas conservé le projet IP, ouvrez le catalogue IP et recherchez-le. Cliquez avec le
bouton droit de la souris sur l’IP et cliquez sur «Edit in IP Packager».

Page | 440 © ISI 2018 Ridha Ghayoula


Figure 18.7. Edit in IP Packager
Dans les sources de conception, cliquez deux fois sur le fichier source (logic_function.vhd) pour le
modifier.

Dans la fenêtre «Package IP», vous pouvez voir que certaines sections n’ont pas de marque verte. En
effet, nous avons apporté à la RTL des modifications qui ne sont pas prises en compte dans le projet
IP du package. Pour mettre à jour le projet, allez dans la section “Review and Package”. Cliquez sur
l'un des liens " Merge Changes" sous Modifier les modifications du projet IP.

Remarque: Si l'onglet IP du package n'apparaît pas dans vivado dans votre projet de packaging IP,
vous pouvez l'ouvrir en cliquant sur «Package IP» dans le Flow Navigator.

Page | 441 © ISI 2018 Ridha Ghayoula


Figure 18.8. Merge Changes

Ensuite, dans les paramètres de personnalisation, sous «Hidden Parameters», double-cliquez sur
«DATA_SIZE». Dans la fenêtre «Edit IP Parameter», cochez «Visible in customization GUI» pour
pouvoir modifier la valeur depuis l'interface graphique de configuration lors de l'ajout de l'adresse IP
à un projet à partir du catalogue IP.

Figure 18.9. Customization Parameters tab

Dans «Edit IP Parameter», activez «Specify Range» et sélectionnez «Range of Integer» pour «Type».
Entrez «32» comme valeur maximale et cliquez sur OK.

Page | 442 © ISI 2018 Ridha Ghayoula


Figure 18.10. Edit IP Parameter

Dans la section « Customization GUI », passer le paramètre « Data Size”» sous « Page 0".

Page | 443 © ISI 2018 Ridha Ghayoula


Figure 18.11. Customization GUI

Ensuite re-package l’IP dans la section « Review and Package».Dans le catalogue de la propriété
intellectuelle, nous pouvons voir que la valeur de révision de PI a été incrémentée (Rev.(2).
Maintenant, si l'on ajoute le double-clic sur la propriété intellectuelle dans le catalogue IP, nous
pouvons voir que nous pouvons sélectionner la taille des données dans l’interface GUI.

Figure 18.11. Customize IP


Ajoutant de nouvelles fonctions maintenant, nous allons ajouter de nouvelles fonctions à notre IP :
ou logique, logique NOR et NAND logique.Et l’utilisateur sera en mesure de sélectionner les
fonctionnalités qu’il souhaite utiliser lors de l’ajout de l’IP à un projet.

Page | 444 © ISI 2018 Ridha Ghayoula


 Ouvrez l'IP dans «Package IP», ouvrez le code source et modifiez-le avec le code suivant.
 Enregistrez le fichier source et fusionnez les modifications dans la fenêtre «Package IP».
Editez le paramètre FUNC_SEL dans les paramètres de personnalisation :

 Activer “ Visible in customization GUI ”

 Spécifiez la plage:
o paires
o Clé: Et, Valeur: 0
o Clé: Ou, valeur: 1
o Clé: Nor, Valeur: 2
o Clé: Nand, valeur: 3

Page | 445 © ISI 2018 Ridha Ghayoula


Figure 18.12. Customization of parameter FUNC_SEL

Dans «Customization GUI», déplacez le paramètre «Func Sel» sous Page 0 et reformatez l’IP.
Maintenant, à partir de l'interface graphique IP, vous pouvez sélectionner la fonction de votre choix.

Figure 18.13. Function selection in the IP GUI


 Définir un port comme port non utilisé
Nous allons maintenant ajouter une nouvelle fonction à notre IP: une logique NON. Pour cela, nous
n'avons besoin que d'un seul port d'entrée. L'autre étant inutilisé, nous le désactiverons à partir de
l'IP lorsque la fonction est sélectionnée dans l'interface graphique de personnalisation.

Page | 446 © ISI 2018 Ridha Ghayoula


 Ouvrez l'IP dans « IP Packager», ouvrez le code source et modifiez-le en ajoutant le code
suivant.
 Enregistrez le fichier source et fusionnez les modifications dans la fenêtre « Package IP».
Editez le paramètre FUNC_SEL en ajoutant une nouvelle paire (clé: Non, Valeur: 4).

 Dans la section « Ports and Interfaces », double-cliquez sur B_inp pour ouvrir la fenêtre
«Edit Port. Si l'utilisateur souhaite utiliser la fonction logique NOT, le port d'entrée B_inp
sera inutile. Par conséquent, nous devons définir la présence de port sur « Facultatif », définir
la valeur du pilote sur «0» et écrire «$ FUNC_SEL! = 4» dans la zone ci-dessous, comme
indiqué dans la Figure 18.12.

 Re-package l'IP.
Maintenant, dans notre projet original, nous pouvons voir que si nous sélectionnons la fonction
NOT, le port d’entrée B_inp sera désactivé pour l’IP.

Page | 447 © ISI 2018 Ridha Ghayoula


Remarque: Cela dépend de ce que vous voulez faire. Si vous souhaitez obtenir le résultat dans le PS, vous pouvez
utiliser un DMA après l’IP. Si vous devez contrôler l’ IP ou lire le résultat à partir de registres, vous devrez ajouter
une interface AXI4 (mappée en mémoire, complète ou lite).

Page | 448 © ISI 2018 Ridha Ghayoula


19
Introduction à la programmation
avec Python

19.1. Introduction
Python est un langage de programmation objet, multi-paradigme et multiplateformes. Il favorise la
programmation impérative structurée, fonctionnelle et orientée objet. Il est doté d'un typage
dynamique fort, d'une gestion automatique de la mémoire par ramasse-miettes et d'un système de
gestion d'exceptions ; il est ainsi similaire à Perl, Ruby, Scheme, Smalltalk et Tcl.

Le langage Python est placé sous une licence libre proche de la licence BSD et fonctionne sur la
plupart des plates-formes informatiques, des supercalculateurs aux ordinateurs centraux, de
Windows à Unix avec notamment GNU/Linux en passant par macOS, ou encore Android, iOS, et
aussi avec Java ou encore .NET. Il est conçu pour optimiser la productivité des programmeurs en
offrant des outils de haut niveau et une syntaxe simple à utiliser.

Il est également apprécié par certains pédagogues qui y trouvent un langage où la syntaxe, clairement
séparée des mécanismes de bas niveau, permet une initiation aisée aux concepts de base de la
programmation.

19.2. Calculer avec Python


Python présente la particularité de pouvoir être utilisé de plusieurs manières différentes. Vous allez
d’abord l’utiliser en mode intera ctif, c ’est-à-dire d’une manière telle que vous pourrez dialoguer
avec lui directement depuis le clavier. Cela vous permettra de découvrir très vite un grand nombre
de fonctionnalités du langage. Dans un second temps, vous apprendrez comment créer vos premiers
programmes (scripts) et les sauvegarder sur disque.
Par exemple, vous pouvez tout de suite utiliser l’interpréteur comme une simple calculatrice de
bureau. Veuillez donc vous-même tester les commandes ci-dessous (Prenez l’habitude d’utiliservotre
cahier d’exercices pour noter les résultats qui apparaissent à l’écran):

Page | 449 © ISI 2018 Ridha Ghayoula


Comme vous pouvez le constater, les opérateurs arithmétiques pour l’addition, la soustraction,
la multiplication et la division sont respectivement +, -, * et /. Les parenthèses ont la fonction
attendue.

Affectation (ou assignation)


Nous savons désormais comment choisir judicieusement un nom de variable. Voyons à présent
comment nous pouvons définirune variable et lui affecterune valeur. Les termes « affecter une
valeur» ou «assigner une valeur» à une variable sont équivalents. Ils désignent l’opération par laquelle
on établit un lien entre le nom de la variable et sa valeur (son contenu).
En Python comme dans de nombreux autres langages, l’opération d’affectation est représentéepar le
signe égale

Les exemples ci-dessus illustrent des instructions d’affectation Python tout à fait classiques.
Après qu’on les ait exécutées, il existe dans la mémoire de l’ordinateur, à des endroits différents:
•trois noms de variables, à savoir n, msget pi;
•trois séquences d’octets, où sont encodées le nombre entier 7, la chaîne de caractères Quoide neuf ?
et le nombre réel 3,14159.
Les trois instructions d’affectation ci-dessus ont eu pour effet chacune de réaliser plusieurs
opérations dans la mémoire de l’ordinateur:
•créer et mémoriser un nom de variable;
•lui attribuer un typebien déterminé (ce point sera explicité à la page suivante);
•créer et mémoriser une valeurparticulière;
•établir un lien(par un système interne de pointeurs) entre le nom de la variable et l’emplacement
mémoire de la valeur correspondante.
On peut mieux se représenter tout cela par un diagramme d’état tel que celui-ci:

Page | 450 © ISI 2018 Ridha Ghayoula


n msg pi

7 Quoi de neuf? 3.14159

Les trois noms de variables sont des références, mémorisées dans une zone particulière de la
mémoire que l’on appelle espace de noms, alors que les valeurs correspondantes sont situées ailleurs,
dans des emplacements parfois fort éloignés les uns des autres. Nous aurons l’occasion de préciser
ce concept plus loin dans ces pages.

Afficher la valeur d’une variable


À la suite de l’exercice ci-dessus, nous disposons donc des trois variables n, msg et pi.
Pour afficher leur valeur à l’écran, il existe deux possibilités. La première consiste à entrer au
clavier le nom de la variable, puis <Enter>. Python répond en affichant la valeur correspondante:

Il s’agit cependant là d’une fonctionnalité secondaire de l’interpréteur, qui est destinée à vous faciliter
la vie lorsque vous faites de simples exercices à la ligne de commande. À l’intérieur d’ un
programme, vous utiliserez toujours la fonction print()

Affectations multiples
Sous Python, on peut assigner une valeur à plusieurs variables simultanément. Exemple:

On peut aussi effectuer des affe ctations parallèles à l’aide d’un seul opérateur:

Conversion de type
Il est possible de convertir certains types. Par exemple, la fonction int permet de transformer
un réel en un entier en supprimant la partie à droite de la virgule
Page | 451 © ISI 2018 Ridha Ghayoula
Affectations multiples
Sous Python, on peut assigner une valeur à plusieurs variables simultanément. Exemple :

On peut aussi effectuer des affectations parallèles à l’aide d’un seul opérateur :

Les francophones que nous sommes avons pour habitude d’utiliser la virgule comme séparateur décimal, alors que les
langages de programmation utilisent toujours la convention en vigueur dans les pays de langue anglaise, c’est-à-dire le
point décimal. La virgule, quant à elle, est très généralement utilisée pour séparer différents éléments (arguments, etc.)
comme on le voit dans notre exemple, pour les variables elles-mêmes ainsi que pour les valeurs qu’on leur attribue.

Addition
Dans le programme ci-dessous, nous avons utilisé l'opérateur d'addition arithmétique (+) pour
ajouter deux nombres.

The sum of 1.5 and 6.3 is 7.8


Affichage

Hello, world!
Programme Python pour calculer la racine carrée

Page | 452 © ISI 2018 Ridha Ghayoula


The square root of 8.000 is 2.828

 Programme Python pour calculer l'aire d'un triangle


Si a, b et c sont trois côtés d'un triangle. Alors,
s = (a+b+c)/2

area = √(s(s-a)*(s-b)*(s-c))

The area of the triangle is 14.70

 Programme Python pour résoudre une équation quadratique


La forme standard d'une équation quadratique est la suivante:
ax2 + bx + c = 0, where

a, b and c are real numbers and

Page | 453 © ISI 2018 Ridha Ghayoula


a≠0

The solution are (-3+0j) and (-2+0j)

 Programme Python pour générer un nombre aléatoire


Pour générer un nombre aléatoire en Python, la fonction randint () est utilisée. Cette fonction est
définie dans un module aléatoire.

 Programme Python pour ajouter deux matrices

En Python, nous pouvons implémenter une matrice en tant que liste imbriquée (liste dans une liste).

Nous pouvons traiter chaque élément comme une ligne de la matrice.

Page | 454 © ISI 2018 Ridha Ghayoula


Par exemple, X = [[1, 2], [4, 5], [3, 6]] représenterait une matrice 3x2. La première ligne peut être
sélectionnée en tant que X [0] et l'élément en première ligne, première colonne peut être sélectionné
comme X [0][0].

La multiplication de deux matrices X et Y est définie uniquement si le nombre de colonnes dans X


est égal au nombre de lignes Y.

Si X est une matrice n x m et que Y est une matrice m x l, alors XY est défini et a la dimension n x l
(mais YX n'est pas défini). Voici quelques manières d'implémenter la multiplication de matrice en
Python.

[114, 160, 60, 27]


[74, 97, 73, 14]
[119, 157, 112, 23]

JPEG (prononcer "jay-peg") signifie Joint Photographic Experts Group. C'est l'une des techniques
de compression les plus utilisées pour la compression d'images.

 Programme Python pour trouver la taille (résolution) d'une image


La plupart des formats de fichiers ont des en-têtes (quelques octets initiaux) qui contiennent des
informations utiles sur le fichier.

Par exemple, les en-têtes JPEG contiennent des informations telles que la hauteur, la largeur, le
nombre de couleurs (niveaux de gris ou RVB), etc. Dans ce programme, nous trouvons la résolution
d'une image jpeg lisant ces en-têtes sans utiliser de bibliothèque externe

Page | 455 © ISI 2018 Ridha Ghayoula


The resolution of the image is 280 x 280

 Programme Python pour convertir des kilomètres en milles

Page | 456 © ISI 2018 Ridha Ghayoula


20
Introduction à la programmation
TCL/TK Vivado

20.1. Introduction
Un script Tcl est une série de commandes Tcl, séparées par des nouvelles lignes ou des points-
virgules. Une commande Tcl est une chaîne de mots, séparée par des espaces ou des tabulations.
L'interpréteur Tcl divise la ligne de commande en mots et effectue des substitutions de commandes
et de variables si nécessaire.
L'interpréteur Tcl lit la ligne de gauche à droite, évalue complètement chaque mot avant d'essayer
d'évaluer le suivant. Les substitutions de commandes et de variables sont effectuées de gauche à
droite lors de la lecture de la ligne.

20.2. TCL
Un mot est une chaîne qui peut être un mot unique ou plusieurs mots entre accolades, {} ou
plusieurs mots entre guillemets, “”. Les points-virgules, les crochets, les tabulations, les espaces et les
nouvelles lignes, entre guillemets ou accolades, sont traités comme des caractères ordinaires.
Toutefois, la barre oblique inverse, \, est traitée comme un caractère spécial, même entre accolades
et guillemets, comme indiqué ci-dessous.
Le premier mot identifie la commande et tous les mots suivants sont passés à la commande en tant
qu'arguments.

Dans l'exemple précédent, le premier mot est la commande Tcl set, utilisée pour affecter des
variables.
Les deuxième et troisième mots sont transmis à la commande set en tant que nom de variable
(outputDir) et valeur de la variable (./Tutorial_Created_Data/cpu_output).

Lorsqu'une barre oblique inverse(backslash), "\", est utilisée dans un mot, l’interpréteur Tcl effectue
un remplacement par barre oblique inverse. Dans la plupart des cas, cela signifie simplement que le
caractère qui suit la barre oblique inverse est traité comme un caractère standard dans le mot. Ceci
est utilisé pour ajouter des guillemets, des accolades, des signes dollar ou d'autres caractères spéciaux
à une chaîne. Reportez-vous à une source de référence Tcl/Tk pour plus d'informations sur la
manière dont l'interpréteur Tcl gère le caractère barre oblique inverse.

Page | 457 © ISI 2018 Ridha Ghayoula


Il y a aussi une différence entre l'utilisation des accolades et des guillemets. Aucune substitution n'est
effectuée sur les caractères entre les accolades. Les mots, ou les chaînes, entre accolades sont pris
textuellement et ne sont pas évalués pour la substitution de variables ou de commandes par
l'interpréteur Tcl. Le mot sera composé exactement des caractères entre les accolades externes, sans
compter les accolades elles-mêmes, comme indiqué dans l'exemple ci-dessous. Les chaînes entre
guillemets sont évaluées et les substitutions de variables et de commandes sont effectuées selon les
besoins. La substitution de commande, la substitution de variable et le remplacement de barre
oblique inverse sont effectués sur les caractères entre guillemets.

Notez que dans l'exemple ci-dessus, la commande [version -short] est remplacée par la valeur
renvoyée lorsqu'elle est placée entre guillemets, mais qu'elle n'est pas remplacée par des accolades.
Gardez à l'esprit la substitution lorsque vous choisissez d'utiliser “” ou {} pour joindre une chaîne
de mots.
L'affectation de variables est effectuée à l'aide de la commande set. Vous pouvez accéder à une
variable précédemment attribuée en spécifiant le nom de la variable avec un signe de dollar en tête,
«$». Si un mot commence par un signe dollar, l'interpréteur Tcl effectue une substitution de variable
en remplaçant la variable par la valeur actuellement stockée par la variable. Le "$" est un caractère
réservé dans le langage Tcl.

Les commandes peuvent également être imbriquées dans d'autres commandes entre crochets, [ ], qui
sont évaluées de manière ascendante. L'interpréteur Tcl traite récursivement les chaînes entre
crochets en tant que nouveau script Tcl. Une commande imbriquée peut également contenir d'autres
commandes imbriquées. Le résultat d'une commande imbriquée est transmis à la commande de
niveau supérieur, qui est ensuite traitée.

L'exemple précédent assigne la liste triée des objets de cellule au niveau supérieur de la conception
actuelle à la variable $ listCells. La commande get_cells est exécutée en premier, les objets
renvoyés sont triés par la commande lsort et la liste triée est affectée à la variable spécifiée.
Cependant, Vivado Design Suite gère les crochets différemment des Tcl standard. Les crochets sont
traités comme des caractères standard dans Verilog et VHDL, et identifient généralement un ou
plusieurs éléments de vecteurs, tels que des bus ou des tableaux d'instances. Dans l'outil Vivado, les
crochets ne sont pas évalués de manière ascendante lorsqu'ils sont censés faire partie d'un nom
d'objet de liste de réseaux.
Les trois commandes suivantes sont équivalentes:

Dans la ligne 1, la paire de crochets externe indique une commande imbriquée, [get_pins], comme
dans Tcl. Cependant, les crochets suivants sont interprétés par l'outil Vivado dans le cadre du nom

Page | 458 © ISI 2018 Ridha Ghayoula


d'objet spécifié transformLoop [0]. Ceci est géré automatiquement par Vivado Design Suite, mais
est limité à certains caractères, sinon les parenthèses seront interprétées comme dans Tcl:

• star: [*] - Le caractère générique indique un nombre de bits ou d'instances.


• integer: [12] - L'entier indique un bit ou une instance spécifique.
• vector: [31: 0] - Le vecteur indique une plage spécifique de bits ou un groupe d'instances.

À la ligne 2, l'utilisation des accolades, {}, empêchera la substitution de commandes de la chaîne


entre les accolades. Dans ce cas, les crochets seraient évalués comme faisant partie du nom de
l'objet, transformLoop [0].

À la ligne 3, la barre oblique inverse indique que le crochet doit être interprété comme un caractère
standard plutôt que comme un caractère spécial, ce qui empêche la substitution de commandes
imbriquées.

Les lignes 2 et 3 empêchent les crochets d'être mal interprétés, ces lignes nécessitent l'application
manuelle des accolades ou des barres obliques inverses selon les besoins de la norme Tcl.

La ligne 1 montre comment Vivado Design Suite gère automatiquement cela pour vous.

Enfin, pour ajouter des commentaires à un script Tcl, lancez simplement une nouvelle ligne avec le
signe numérique ou le caractère dièse, «#». Les caractères qui suivent un signe numérique sont
ignorés jusqu'à la nouvelle ligne suivante. Pour ajouter un commentaire à la fin d'une ligne, il suffit
de terminer la commande par un point-virgule, «;», puis de commencer le commentaire par un signe
numérique, comme indiqué ci-dessous:

20.2. 1. Exemple de script: flux de compilation non-projet


Voici un exemple de script Tcl qui définit un flux de conception non-projet.
L'exemple de script utilise une commande personnalisée reportCriticalPaths. Ceci est une illustration
de la manière dont Vivado Design Suite peut être enrichie de commandes et de procédures
personnalisées.

Détails du script exemple


Les étapes clés du script précédent peuvent être décomposées comme suit:

• Étape 1: définit une variable, $ outputDir, qui pointe vers un répertoire de sortie et également
crée physiquement le répertoire. La variable $ outputDir est référencée selon les besoins à d'autres
endroits du script.

Page | 459 © ISI 2018 Ridha Ghayoula


• Étape 2: lit les fichiers VHDL et Verilog contenant la description de la conception et le fichier
XDC contenant les contraintes physiques et / ou temporelles pour la conception. Vous pouvez
également lire les netlists synthétisées à l'aide de la commande read_edif.

Vivado Design Suite utilise des contraintes de conception pour définir les exigences à la fois
physiques et temporelles de la conception. La commande read_xdc lit un fichier de contraintes
XDC qui sera utilisé lors de la synthèse et de l'implémentation.

IMPORTANT: Vivado Design Suite ne prend pas en charge le format UCF. Pour plus d'informations sur la
migration des contraintes UCF vers les commandes XDC, reportez-vous au Guide de méthodologie de migration de
Vivado Design Suite (UG911) pour plus d'informations.

Les commandes read_ * Tcl sont conçues pour être utilisées avec le mode non-projet, car elles
permettent à Vivado Design Suite de lire un fichier sur le disque pour créer une base de données de
conception en mémoire, sans copier le fichier ou créer une dépendance. le fichier de quelque
manière que ce soit, comme dans le mode projet. Toutes les actions entreprises en mode non-projet
sont dirigées vers la base de données en mémoire dans les outils Vivado. Les avantages de cette
approche rendent le mode sans projet extrêmement flexible en ce qui concerne la conception.
Cependant, une limitation du mode non-projet est que vous devez surveiller les modifications
apportées aux fichiers de conception source et mettre à jour la conception selon vos besoins. Pour
plus d'informations sur l'exécution de Vivado Design Suite en utilisant le mode projet ou le mode
non-projet, consultez l'utilisateur de Vivado Design Suite.

• Étape 3: Cette étape compile les fichiers de conception HDL, applique les contraintes de
synchronisation situées dans le fichier XDC et mappe la logique sur les primitives Xilinx pour créer
une base de données de conception en mémoire. La conception en mémoire réside dans l'outil
Vivado, qu'il soit en mode batch, en mode shell Tcl pour les commandes Tcl interactives ou dans
l'environnement de conception intégré Vivado (IDE) pour l'interaction avec les données de
conception sous forme graphique. Une fois la synthèse terminée, un point de contrôle est enregistré
pour référence. À ce stade, la conception est une netlist non synthétisée non placée avec des
contraintes temporelles et physiques. Divers rapports, tels que le calendrier et l'utilisation, peuvent
constituer une ressource utile pour mieux comprendre les défis de la conception.
Cet exemple de script utilise une commande personnalisée, reportCriticalPaths, pour signaler le
TNS / WNS / Violators dans un fichier CSV. Cela vous permet d'identifier rapidement les chemins
critiques.

Page | 460 © ISI 2018 Ridha Ghayoula


Tout fichier XDC supplémentaire lu après la synthèse par les commandes read_xdc ou source ne
sera utilisé que pendant les étapes d'implémentation. Ils seront stockés dans tous les points de
contrôle de conception ultérieurs, avec la netlist.

• Étape 4: optimisation de la logique de pré-placement, en préparation du placement et du routage.


L'objectif de l'optimisation est de simplifier la conception logique avant de s'engager dans des
ressources physiques sur la partie cible. L'optimisation est suivie par un placement basé sur le timing
avec le placer Vivado.
Après chacune de ces étapes, la commande reportCriticalPaths est exécutée pour générer un
nouveau fichier CSV. Le fait de disposer de plusieurs fichiers CSV à différents stades de la
conception vous permet de créer une feuille de calcul récapitulative de la synchronisation
personnalisée qui peut aider à visualiser l'amélioration du timing à chaque étape de la mise en œuvre.
Une fois le placement terminé, le script utilise la commande get_timing_paths pour
examiner la propriété SLACK du pire chemin de synchronisation dans la conception placée. Alors
que la commande report_timing renvoie un rapport de texte détaillé du chemin de synchronisation
avec le plus faible niveau, la commande get_timing_paths renvoie le même chemin de
synchronisation qu'un objet Tcl avec des propriétés correspondant aux principales caractéristiques
de temporisation du chemin.
La propriété SLACK renvoie le relâchement du chemin de synchronisation spécifié ou du pire
chemin dans ce cas. Si le jeu est négatif, le script exécute une optimisation physique pour résoudre
les violations de synchronisation de placement chaque fois que possible.

À la toute fin de l'étape 4, un autre point de contrôle est enregistré et l'utilisation du périphérique est
signalée avec un résumé du calendrier de la conception. Cela vous permettra de comparer
chronométrage pré-routé et post-routé pour évaluer l'impact du routage sur le timing de conception.

Page | 461 © ISI 2018 Ridha Ghayoula


• Étape 5:
le routeur Vivado effectue un routage basé sur la synchronisation et un point de contrôle est
enregistré pour référence. Maintenant que la conception en mémoire est routée, des rapports
supplémentaires fournissent des informations critiques sur la consommation électrique, les violations
des règles de conception et le calendrier final. Vous pouvez générer des rapports sur des fichiers,
pour les consulter ultérieurement, ou vous pouvez diriger les rapports vers l'IDE Vivado pour un
examen plus interactif. Une netlist Verilog est exportée pour être utilisée dans la simulation
temporelle.

Étape 6:
Ecrit un flux de bits (bitstream)pour tester et programmer la conception sur le FPGA Xilinx.

20.2. 2. Définition des procédures


Tcl Vivado Design Suite fournissant un interpréteur Tcl complet intégré à l'outil, la création de
nouvelles commandes et procédures personnalisées est une tâche simple. Vous pouvez écrire des
scripts Tcl à charger et à exécuter depuis l'EDI de Vivado, ou écrire des procédures (ou procs), pour
agir en tant que commandes de conception, prendre des arguments, rechercher des erreurs et
renvoyer des résultats.
Une procédure Tcl est définie avec la commande proc qui prend trois arguments: le nom de la
procédure, la liste des arguments et le corps du code à exécuter. Le code suivant fournit un exemple
simple d'une définition de procédure:

Une procédure a généralement des arguments prédéfinis avec des valeurs par défaut facultatives. Il
renvoie une liste vide à moins que la commande return ne soit utilisée pour renvoyer une valeur
différente. L'exemple suivant définit une procédure, reportWorstViolations, avec trois arguments
prédéfinis:

Page | 462 © ISI 2018 Ridha Ghayoula


Lors de l'exécution de la procédure, tous les arguments sont requis pour terminer la commande,
comme indiqué:

Ce qui suit est une forme différente de la même procédure, où deux des trois arguments ont une
valeur par défaut. La valeur par défaut de corner est Slow et la valeur par défaut de delayType est
Max. Avec les valeurs par défaut fournies, les arguments corner et delayType sont facultatifs lors de
l'appel de la procédure.

Lors de l'exécution de cette procédure, l'une des formes suivantes de la commande fonctionnera:

Voici un exemple de la procédure qui comporte un argument prédéfini, nbrPath, mais accepte
également un nombre quelconque d'arguments supplémentaires. Cela utilise les mots-clés Tcl args
dans la liste des arguments lors de la définition de la procédure. Le mot-clé args indique une liste Tcl
pouvant contenir un nombre quelconque d'éléments, y compris aucun.

Lors de l'exécution de commandes Tcl, vous pouvez utiliser la substitution de variables pour
remplacer certains des arguments de ligne de commande acceptés ou requis par la commande Tcl.
Dans ce cas, vous devez utiliser la commande Tcl eval pour évaluer la ligne de commande avec la
variable Tcl dans le cadre de la commande. Dans l'exemple précédent, la liste de variables des
arguments ($ args) est transmise à la commande encapsulated report_timing en tant que variable et
nécessite donc l'utilisation de la commande eval.
Lors de l'exécution de cette procédure, l'une des formes suivantes de la commande fonctionnera:

Dans le premier exemple, le nombre 2 est transmis à l'argument $ nbrPaths et appliqué à -


max_paths. Dans les deuxième et troisième exemples, les nombres 1 et 10 sont respectivement
appliqués à -max_paths et tous les caractères suivants sont affectés à $ args.
L'exemple suivant fournit la définition de la procédure pour la commande reportCriticalPaths
précédemment utilisée dans l'exemple de script non lié au mode projet. La procédure prend un seul
argument, $ filename, et a été commenté pour expliquer chaque section:

Page | 463 © ISI 2018 Ridha Ghayoula


20.2. 3. Hiérarchie de conception
La plupart des conceptions sont constituées d'une série de blocs ou de modules connectés de
manière hiérarchique. Que la conception soit conçue de bas en haut, ou de haut en bas, ou à partir
du milieu, la recherche dans la hiérarchie de conception pour localiser un objet spécifique est une
tâche courante.

Page | 464 © ISI 2018 Ridha Ghayoula


Figure 20.1. Hiérarchie de conception

Par défaut, les commandes get_ * ne renvoient que les objets du niveau supérieur de la conception.
Vous pouvez utiliser la commande current_instance avant d'utiliser les commandes get_ * pour
définir les requêtes de l'objet de conception sur une instance hiérarchique spécifique de la
conception. Pour ramener la portée au niveau supérieur de la conception, vous devez simplement
utiliser la commande current_instance sans argument.
À titre d'exemple, la Figure 20.1 montre une conception hiérarchique où les modules A et B sont
instanciés au niveau supérieur. Le module A inclut les instances hiérarchiques a1 et a2 et le module B
inclut les instances hiérarchiques b1 et b2. A1, a2, b1 et b2 ont des cellules de feuille à l'intérieur,
comme indiqué sur la Figure.

Bien que les commandes get_* recherchent uniquement le niveau supérieur ou le niveau de
l'instance actuelle, vous pouvez spécifier un modèle de recherche incluant un nom d'instance
hiérarchique par rapport à l'instance actuelle. Par défaut, l'instance actuelle est définie sur le niveau
supérieur de la conception. Pour interroger l'instance b1 à partir du niveau supérieur, vous pouvez
spécifier le modèle de nom suivant:

 Utiliser l'option -hierarchical


Bien que le comportement par défaut consiste à rechercher des objets uniquement au niveau de
l'instance actuelle, la plupart des commandes get_* ont une option hiérarchique permettant de
rechercher le niveau hiérarchique par niveau, en partant du niveau de l'instance actuelle.

Page | 465 © ISI 2018 Ridha Ghayoula


Toutefois, l’une des caractéristiques de l’option -hierarch est que l’outil Vivado tente de faire
correspondre le modèle de nom spécifié à chaque niveau de la hiérarchie de conception, et non le
nom hiérarchique complet d’un objet. Le modèle de nom ne doit pas inclure le séparateur
hiérarchique dans ce cas, comme le montre l'exemple suivant, basé sur la Figure 20.1 précedente:

La recherche -hierarchical équivaut à effectuer manuellement une recherche à chaque niveau de la


hiérarchie, en utilisant la commande current_instance pour définir le niveau de hiérarchie et en
renvoyant tous les objets du niveau actuel correspondant au modèle de nom spécifié.

 Recherche de pins

Figure 20.2. Recherche de noms de broches (I/O)


Les noms des broches sont basés sur l'instance à laquelle ils appartiennent. Lors de la recherche de
broches, vous devez utiliser le caractère séparateur de hiérarchie pour séparer le nom de l'instance et
les modèles de nom de broche. Les exemples suivants sont illustrés par la Figure 20.2.

Page | 466 © ISI 2018 Ridha Ghayoula


Vous pouvez également utiliser l'option -hierarchical lorsque vous recherchez des pins:

 Résultats de filtrage
Plus souvent, lorsque vous utilisez get_* pour rechercher des objets de conception, vous n'êtes
intéressé que par un sous-ensemble des objets renvoyés. Vous pourriez ne pas vouloir tous les objets
netlist dans la conception, mais seulement les cellules d'un certain type, ou les réseaux d'un certain
nom. Dans certains cas, seul un sous-ensemble d'éléments présente un intérêt et doit être renvoyé.

Figure 20.3. Recherche de conceptions hiérarchiques

Vous pouvez limiter les résultats de la recherche en définissant étroitement votre modèle de
recherche, en utilisant des caractères génériques «*» et «?», Ou en utilisant -regexp pour créer des
modèles de recherche complexes à évaluer. Vous pouvez limiter la portée de la hiérarchie faisant
l'objet de la recherche, en définissant le paramètre current_instance ou en spécifiant -hierarchy.

Page | 467 © ISI 2018 Ridha Ghayoula


Par exemple, en utilisant la conception illustrée à la Figure 20.3, les expressions suivantes renvoient
des résultats différents:

L'option -filter vous permet de filtrer les résultats des commandes get_*, en fonction des propriétés
spécifiques des objets recherchés. Par exemple, la commande suivante renvoie toutes les cellules qui
ont B / b * dans leur nom hiérarchique complet et qui n'ont pas été placées par l'utilisateur, de sorte
que IS_LOC_FIXED soit FALSE ou 0:

20.3. Conseils d'automatisation Tcl pour Vivado et Xilinx SDK

L'automatisation Tcl est l'une des fonctionnalités les plus puissantes intégrées dans les outils Vivado
et Xilinx SDK et devrait être pleinement exploitée pour optimiser votre productivité en tant que
développeur FPGA. Dans cet article, j'ai créé un «aide-mémoire» contenant certaines des
commandes et astuces les plus utiles que vous pouvez utiliser pour effectuer davantage de tâches via
les scripts Tcl. Si vous voulez ajouter plus de choses à la liste, faites-le moi savoir dans la section des
commentaires à la fin.

20.3.1.Vivado Tcl Automation Cheat Sheet

 Obtenez le chemin d'installation de Vivado


Utile lorsque vous avez besoin d'accéder aux sources IP.

 Obtenir le nom du module de premier niveau d'un projet Vivado


Nous avons souvent besoin de connaître le module de haut niveau d'un design Vivado afin de
pouvoir nommer d'autres éléments, tels que le projet matériel SDK. Je pense que le moyen le plus
simple d'obtenir ce nom est de rechercher l'un des fichiers du projet Vivado qui utilise le nom du
module de niveau supérieur. Certains de ces fichiers sont: * .bit, * .hwdef, * .sysdef, * .hdf

Page | 468 © ISI 2018 Ridha Ghayoula


 Ouvrir un projet Vivado
Nous ouvrons d'abord un projet dans le script Tcl pour pouvoir synthétiser, implémenter et
exporter la conception.

 Synthétiser un projet Vivado


Le projet doit être ouvert en premier.

 Implémenter un projet Vivado


Le projet doit être ouvert en premier.

 Exporter un projet Vivado pour SDK


Le code ci-dessous élabore le nom du module supérieur à partir du fichier binaire, puis crée un sous-
répertoire .sdk, puis utilise la commande write_sysdef pour exporter la conception.

 Plus d'infos sur Vivado Tcl


Pour plus d'informations sur les commandes Vivado Tcl, reportez-vous au Guide de référence de la
commande Vivado Design Suite Tcl (UG835).

20.2.2. Xilinx SDK Tcl Automation Cheat Sheet


 Obtenez le chemin d'installation du SDK Xilinx
Utile lorsque vous avez besoin d'accéder aux sources du pilote et de la bibliothèque.

 Créer un projet matériel dans un espace de travail SDK

Page | 469 © ISI 2018 Ridha Ghayoula


Pour créer un projet matériel, vous devez donner un nom au projet matériel, par exemple $
{top_module_name} _hw_platform_0 et le chemin d'accès au fichier .hdf qui est le projet Vivado
exporté et qui se trouve généralement dans les fichiers de projet Vivado du fichier. Sous-répertoire $
vivado_folder.sdk. Vous pouvez éviter un message d'erreur en vérifiant s'il existe déjà.

 Récupère le nom du processeur dans la conception


Lors de la création d'applications logicielles, nous devons spécifier le processeur sur lequel
l'application s'exécutera. Pour savoir quels processeurs sont disponibles dans le projet matériel, vous
pouvez analyser la sortie de la procédure getperipherals. La fonction suivante renverra le premier
processeur trouvé.

 Créer un espace de travail SDK


Nous ciblons vraiment un répertoire en tant qu’espace de travail du SDK et, s’il est vide, Xilinx
SDK crée tous les fichiers pour décrire l’espace de travail.

Page | 470 © ISI 2018 Ridha Ghayoula


 Ajouter un référentiel local à l'espace de travail
Si vos applications doivent faire référence à des bibliothèques personnalisées ou modifiées, vous les
placerez généralement dans un répertoire distant et ajouterez ce répertoire en tant que référentiel
SDK local à votre espace de travail. Vous devez d'abord utiliser la commande “setws”.

 Créer une application logicielle à partir de l'un des modèles de SDK Xilinx
Xilinx SDK est fourni avec quelques modèles d’application logicielle qui sont utiles pour effectuer
des tests matériels de base lors de l’introduction de nouvelles cartes. Le code ci-dessous crée
l'application lwIP Echo Server. Notez que le code fait référence à la fonction get_processor_name
décrite ci-dessus.

 Build the BSPs and software applications

 Plus d'infos sur le SDK Tcl


Une simple recherche sur Google apporte de nombreuses informations anciennes sur le mode de lot
SDK, qui a beaucoup évolué depuis 2016.1. La meilleure façon d’obtenir plus d’informations sur les
commandes Xilinx SDK Tcl consiste à accéder à l’aide du SDK Xilinx et à rechercher avec les mots-
clés «mode batch»:
1. Ouvrez le SDK Xilinx
2. Sélectionnez Aide-> Sommaire de l'aide
3. Tapez “batch mode” dans le champ de recherche et appuyez sur Entrée.
4. Cliquez sur «Commandes XSCT» dans les résultats de la recherche.
5. Cliquez sur «Projets SDK» sur la page Commandes XSCT qui s'ouvre.

Page | 471 © ISI 2018 Ridha Ghayoula


21
Création des fichiers MCS (Configuration
Memory File) Vivado

21.1. Introduction
Byte Peripheral Interface (BPI) flash est utilisé pour stocker le bitstream dans le circuit FPGA qui sera
chargé automatiquement à la mise sous tension. Ce chapitre est destiné au développeur FPGA qui
chargera le FPGA ou la configuration flash avec un flux binaire (bitstream) spécifique à l'application.

21.2. Conventions
Ce chapitre utilise les conventions suivantes:
– Les nombres hexadécimaux sont préfixés par «0x» (par exemple, 0x00058C).
– La police en italique est utilisée pour le texte descriptif trouvé sur les écrans de l'interface
graphique.
– La police bleue est utilisée pour les noms de bouton et d’option de menu.
– Les signaux bas actifs sont suivis de _B, par exemple RST_B.

Le texte dans ce format met en évidence des informations utiles ou importantes.


Voici quelques-uns des acronymes utilisés dans ce manuel.
– BPI Interface périphérique Byte (Byte Peripheral Interface)
– BIT Extension de fichier pour les flux binaires FPGA(File extension for FPGA bitstreams)
– MCS Extension de fichier pour les flux binaires de PROM flash(File extension for flash
PROM bitstreams)
– XDC Extension de fichier pour les contraintes de conception Xilinx(File extension for
Xilinx design constraints)

21.3. Architecture matérielle


La figure 21.1 illustre la connexion entre le FPGA et le composant Flash BPI.
La vitesse maximale de configuration est atteinte en utilisant une interface de données 16 bits avec la
fonction de lecture synchrone du flash. Un oscillateur à cristal de 100 MHz est connecté à la broche
de l'horloge de configuration principale externe (EMCCLK) du FPGA. Cette source d'horloge pilote
le moteur de configuration interne du FPGA pour charger le flux binaire à la mise sous tension

Page | 472 © ISI 2018 Ridha Ghayoula


Figure 21.1. BPI Configuration Hardware Interface

La broche de protection en écriture (WP) du flash est tirée vers le haut pour désactiver le
verrouillage de bloc. Les opérations de programmation et d'effacement du flash peuvent être
activées ou désactivées via la broche de tension de programmation (VPP). L'entrée VPP est toujours
pilotée lorsque le câble de programmation JTAG est physiquement connecté à la carte. Cela permet
de programmer le flash indirectement via le FPGA à l'aide d'un câble de programmation Xilinx
JTAG et de l'outil de configuration iMPACT ™. Un hardware jumper optionnel permet également
le contrôle direct du FPGA de la tension de programmation. Le hardware jumper peut être éliminé
en tant qu'option de construction de produit si un client souhaite désactiver la programmation Flash
à partir de la logique de l'application FPGA à des fins de sécurité. Le flash 512 Mbit est
suffisamment grand pour stocker plusieurs flux binaires. Le nombre exact dépend de la taille du
FPGA. Les fonctionnalités de démarrage multiple et de repli Xilinx sont prises en charge via les
connexions à broches FPGA RS [1: 0] aux bits d’adresse supérieure du flash. Reportez-vous au
Guide de l'utilisateur de la configuration Xilinx pour plus de détails.

21.3. 1 Configuration du périphérique (Bitstream Settings)


Deux paramètres de flux binaire de configuration de périphérique doivent être modifiés par rapport
aux valeurs par défaut pour prendre en charge le flash BPI.
Setting Default BPI Value
BITSTREAM.CONFIG.BPI_SYNC_MODE Disable Type1
BITSTREAM.CONFIG.EXTMASTERCCLK_EN Disable div
Ces paramètres sont inclus dans le fichier de contraintes de conception Xilinx (XDC) fourni avec
chaque produit Red Rapids. Des paramètres supplémentaires doivent être modifiés pour prendre en
charge les configurations à démarrage multiple et de secours. Reportez-vous au Guide de l'utilisateur
de la configuration Xilinx pour plus de détails.

Page | 473 © ISI 2018 Ridha Ghayoula


21.4. Génération de fichiers MCS
Avant de pouvoir programmer le flash, un fichier MCS doit être créé à partir du fichier BIT produit
par Vivado ™. Lancez le gestionnaire de matériel Vivado ™, comme illustré à la Figure 21.2, et
entrez la commande suivante dans la console Tcl:

Figure 21.2. MCS File Generation From Vivado™ Hardware Manager

La commande Tcl suppose que Vivado ™ est exécuté à partir de la racine du répertoire du projet et
que le fichier BIT se trouve dans le sous-répertoire SigFPGA_Top.runs/impl_1. Le fichier MCS
résultant sera créé à la racine du répertoire du projet. Reportez-vous au Guide de l'utilisateur de
Xilinx Vivado Design Suite: Programmation et débogage pour plus de détails.

21.5. Programmation JTAG avec Vivado ™


L'outil Vivado ™ permet de programmer directement le FPGA à partir d'un fichier BIT ou de
programmer indirectement le flash BPI à partir d'un fichier MCS. Un câble de programmation Xilinx
est nécessaire pour connecter l'ordinateur hôte au connecteur JTAG de la carte. Le programmateur
Xilinx se branche sur un port USB de l'ordinateur hôte et un câble fourni par Red Rapids connecte
le programmateur au port JTAG du produit.

Page | 474 © ISI 2018 Ridha Ghayoula


Lancez le gestionnaire de matériel Vivado ™ avec le programmateur Xilinx connecté à la carte.
Ouvrez une cible matérielle à partir du gestionnaire de matériel. Cela obligera le câble JTAG à
analyser la chaîne et à identifier le périphérique FPGA, comme illustré à la Figure 21.3.

Figure 21.3. Initialize JTAG Chain

Cliquez avec le bouton droit sur le nom du périphérique FPGA et sélectionnez Program Device…
pour charger directement un fichier BIT sur le FPGA. Une fenêtre de périphérique de programme
s'ouvre, comme illustré à la Figure 4-2. L'emplacement du fichier Bitstream et tout fichier de sondes
de débogage sont entrés dans cette fenêtre. Les valeurs par défaut indiqueront l'emplacement correct
si Vivado ™ est exécuté à partir de la racine du répertoire du projet. Cliquez sur Programme pour
Page | 475 © ISI 2018 Ridha Ghayoula
continuer. L'état du périphérique passera de Non programmé à Programmé si le fichier BIT est
chargé avec succès.

Figure 21.4.Program Device Window

Cliquez avec le bouton droit sur le nom du périphérique FPGA et sélectionnez Ajouter un
périphérique de mémoire de configuration… pour connecter le flash au FPGA. Une fenêtre Ajouter
un périphérique de mémoire de configuration s'ouvre, comme illustré à la Figure 21.5. Sélectionnez
le nom de périphérique mt28gu512aax1e-bpi-x16 et cliquez sur OK pour continuer.

Figure 21.5.Add Configuration Memory Device Window


Le périphérique flash sera désormais répertorié en tant que pièce jointe sur le périphérique FPGA
dans le gestionnaire de matériel, comme illustré à la Figure 21.6.

Page | 476 © ISI 2018 Ridha Ghayoula


Figure 21.6. Add Configuration Memory Device Window

Cliquez avec le bouton droit sur le nom du périphérique flash et sélectionnez Périphérique mémoire
de configuration du programme… pour charger indirectement un fichier MCS dans le flash. Une
fenêtre de périphérique de mémoire de configuration de programme s'ouvre, comme illustré à la
Figure 21.7. L'emplacement du fichier MCS doit être entré dans la boîte de dialogue Fichier de
configuration: cliquez sur OK pour continuer.

Figure 21.7. Program Configuration Memory Device Window

Une séquence de trois fenêtres d'état sera affichée lorsque le flash est programmé. Chaque fenêtre
affiche la progression vers les trois étapes d’effacement, de programmation et de vérification du
contenu du flash. Les trois fenêtres sont illustrées à la Figure 21.8.

Page | 477 © ISI 2018 Ridha Ghayoula


Figure 21.8. Three Flash Programming Status Windows
21.6. Exemples
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity D_FF_VHDL is
port
(
clk : in std_logic;

rst : in std_logic;
pre : in std_logic;
ce : in std_logic;
d : in std_logic;

q : out std_logic
);
end entity D_FF_VHDL;

architecture Behavioral of D_FF_VHDL is

begin
process (clk) is
begin
if rising_edge(clk) then
if (rst='1') then
q <= '0';
elsif (pre='1') then
q <= '1';
elsif (ce='1') then
if (d ='1') then
q <= '1';
elsif (d ='0') then
q<= '0';
end if;

Page | 478 © ISI 2018 Ridha Ghayoula


end if;
end if;
end process;
end architecture Behavioral;

Page | 479 © ISI 2018 Ridha Ghayoula


22
Génération de fichiers cryptés pour les Series 7

22.1. Introduction
Les FPGA Xilinx prennent en charge plusieurs méthodes de cryptage bitstream, notamment AES,
HMAC et DNA.

Ces méthodes sont détaillées dans le guide utilisateur de configuration du FPGA, disponible sur
Xilinx.com.
Nous encourageons vivement les étudiants à lire le guide de l'utilisateur des configurations pour se
familiariser avec l'emplacement de Xilinx en matière de sécurité bitstream et les options disponibles,
ainsi que les informations relatives à leur mise en œuvre.
Vous devrez également utiliser des dispositifs de cryptage externes pour protéger votre conception.

22.22. Introduction

Pour générer un bitstream chiffré, ouvrez une conception implémentée dans IDE Vivado. Dans la
barre d'outils (main toolbar) principale, sélectionnez Flow > Bitstream Settings pour faire
Settings de la boîte de dialogue Paramètres. En haut de la boîte de dialogue, cliquez sur Configure
Additional Bitstream Settings.

Figure 22.1. 7 Series Configure Encryption Settings (a)

Page | 480 © ISI 2018 Ridha Ghayoula


Figure 22.2. 7 Series Configure Encryption Settings(c)

Cela ouvre la boîte de dialogue Modifier les propriétés du périphérique. Sélectionnez Encryption
dans le volet de gauche.

Figure 22.3. 7 Series Configure Encryption Settings(c)

Page | 481 © ISI 2018 Ridha Ghayoula


Dans la boîte de dialogue (Edit Device) Modifier les propriétés du périphérique, spécifiez les
paramètres de chiffrement et de clé:
• Paramètres de cryptage (Encryption Settings)
 Définissez Activer le cryptage Bitstream (Enable Bitstream Encryption)sur YES.
 Définir l'emplacement de la clé de cryptage (Select location of encryption key) sur
BBRAM ou EFUSE.
- L'emplacement de la clé sera intégré dans le Bitstream chiffré.
- Lorsque le flux binaire chiffré est téléchargé sur le périphérique, il indique au
FPGA à utiliser la clé chargée dans le BBR ou le registre de clé eFUSE pour décrypter
le flux binaire chiffré.

Figure 22.3. 7 Series Configure Encryption Settings(d)


• Paramètres clés
 Spécifiez la clé d’authentification HMAC (HMAC authentication key) et le chaînage des
blocs de chiffrement (CBC) (Starting cipher block chaining (CBC))
- Si ces valeurs ne sont pas spécifiées, Vivado génère une valeur aléatoire pour vous.
- Ces valeurs seront intégrées dans le flux binaire chiffré et ne doivent pas nécessairement être
programmé dans le FPGA.
Remarque: Ces valeurs seront stockées dans le fichier de contraintes du projet actuel, sauf si une
entrée le fichier de chiffrement est spécifié. Pour éviter de stocker cette valeur dans le fichier de
contraintes, spécifiez le fichier de chiffrement en entrée.
° Spécifiez la clé de cryptage AES à utiliser lors du cryptage du flux binaire. Vous pouvez utiliser
jusqu'à 64 caractères hexadécimaux pour spécifier la clé 256 bits.
- La clé sera écrite dans un fichier avec l'extension de fichier .nky. Utilisez ce fichier quand charger la
clé dans le BBR ou lors de la programmation de la clé dans la clé eFUSE registre.
Remarque: Ces valeurs seront stockées dans le fichier de contraintes du projet en cours, sauf si un fichier de
chiffrement en entrée est spécifié. Pour éviter de stocker cette valeur dans le fichier de contraintes, spécifiez le fichier de
chiffrement en entrée.

Page | 482 © ISI 2018 Ridha Ghayoula


 Spécifier le fichier de cryptage en entrée.
- Spécifiez un fichier. nky existant pour obtenir les paramètres de la clé de chiffrement. Ce
champ est optionnel et peut être omis si vous spécifiez manuellement les AES, HMAC et CBC.
Après avoir spécifié les paramètres de chiffrement, cliquez sur OK pour appliquer les paramètres au
projet et régénérer votre bitstream. En cas de réussite du script write_bitstream
opération, vous aurez un fichier de programmation avec un fichier de cryptage .nky.

22.3. Génération de fichiers cryptés et authentifiés pour UltraScale et


UltraScale +

Pour générer un bitstream chiffré, ouvrez une conception implémentée dans IDE Vivado. Dans la
barre d'outils (main toolbar) principale, sélectionnez Flow > Bitstream Settings pour faire
Settings de la boîte de dialogue Paramètres. En haut de la boîte de dialogue, cliquez sur Configure
Additional Bitstream Settings.

Figure 22.4. UltraScale and UltraScale+ Configure Additional Bitstream Settings

Cela ouvre la boîte de dialogue (Edit Device Properties) Modifier les propriétés du périphérique.
Sélectionnez Cryptage(Encryption) dans le volet de gauche.

Page | 483 © ISI 2018 Ridha Ghayoula


Figure 22.5. UltraScale Configure Encryption Settings

Dans la boîte de dialogue (Edit Device Properties) Modifier les propriétés du périphérique
(Encryption Settings), spécifiez les paramètres de chiffrement et la clé (Key Settings).

Page | 484 © ISI 2018 Ridha Ghayoula


Paramètres:
• Paramètres de cryptage
 Définissez Activer le cryptage Bitstream (Enable Bitstream Encryption) sur YES.
 Définir l'emplacement de la clé de cryptage sur BBRAM ou EFUSE.
- L'emplacement de la clé est intégré dans le flux binaire chiffré.
- Lorsque le flux binaire chiffré est téléchargé sur le périphérique, il indique au
FPGA à utiliser la clé chargée dans le BBR ou le registre de clé eFUSE pour décrypter le flux
binaire chiffré.
° Définissez (Enable obfuscated key load) sur ENABLE ou DISABLE.
- Lorsqu'elle est activée, cette clé générée par l'utilisateur est chiffrée avant d'être stockée dans le
BBRAM. Si cette option est désactivée, la clé est stockée «telle quelle» dans la BBRAM.

• Paramètres clés
° Spécifiez (Starting AES encryption key (key0)) à utiliser lors du chiffrement du bitstream. Vous
pouvez utiliser jusqu'à 64 caractères hexadécimaux pour spécifier la clé 256 bits.
- La clé sera écrite dans un fichier avec une extension de fichier .nky.
Utilisez ce fichier quand charger la clé dans le BBR ou lors de la programmation de la clé dans la clé
eFUSE.
Remarque: Cette valeur sera stockée dans le fichier de contraintes du projet actuel, sauf si une entrée le fichier de
chiffrement est spécifié. Pour éviter de stocker cette valeur dans le fichier de contraintes, spécifiez l'entrée fichier de
cryptage.
° Spécifier le fichier de cryptage en entrée (Input encryption file).
- Spécifiez un fichier .nky existant pour obtenir les paramètres de la clé de chiffrement. Ce champ
est optionnel et peut être omis si vous spécifiez manuellement AES, HMAC et CBC.
° Spécifier Number of encryption blocks per key et Number of frames per AES-256 key
- Le nombre de blocs de cryptage et de trames est utilisé pour spécifier combien sections un flux
binaire sera divisé avec des clés distinctes.
° Spécifiez la valeur initiale du vecteur AES (IV0) (Starting AES initial vector (IV0) value).
- Vecteur d'initialisation pour la première clé. Notez que chaque clé a besoin d’une valeur de vecteur
d'initialisation pouvant être fournie via le fichier de cryptage en entrée.

Spécifiez la valeur initiale du vecteur initial (Obfuscate IV0).


- Vecteur d'initialisation pour obfuscated key.
Remarque: Cette valeur sera stockée dans le fichier de contraintes du projet en cours. Pour éviter de stocker cette valeur
dans le fichier de contraintes, spécifiez le fichier de chiffrement en entrée.

Pour les paramètres d'authentification, sélectionnez Authentification dans le volet de gauche.

Page | 485 © ISI 2018 Ridha Ghayoula


Figure 22.6. UltraScale Configure Encryption Settings

22.4. Chargement de la clé de cryptage


Les clés symétriques 256 bits de BBRAM et eFUSE peuvent uniquement être chargées sur un
périphérique via l'interface JTAG à l'aide de l'outil Vivado Device Programmer. Pour les
périphériques UltraScale, ce chemin de chargement de clé est en écriture seule sur le périphérique. Il
n'y a pas de chemin de données physique pour relire l'une ou l'autre des clés.
Lorsqu'une clé est écrite sur le périphérique via JTAG, un contrôle d'intégrité de la clé est lancé en
écrivant la valeur CRC32 attendue via JTAG sur le périphérique. Un contrôle d'intégrité CRC32 réel
est calculé sur la clé stockée par le périphérique (en interne) et comparé au CRC32 attendu qui vient
d'être reçu via le port JTAG. Un résultat de type réussite / échec est ensuite écrit par le périphérique
sur le port JTAG au lieu des données de clé réelles pour indiquer l'état d'intégrité. La suppression du
chemin de relecture physique de la clé augmente la sécurité de la clé stockée.

 Les solutions de programmation clés de BBRAM comprennent:


° Utilisation de l'outil Vivado Device Programmer et du câble JTAG
Remarque: pour les clés basées sur BBRAM, avant d'écrire la clé, la clé existante dans BBRAM est
mise à zéro (effacé et vérifié).
 Les solutions de programmation clés eFUSE comprennent:
• programmation Xilinx
° Flux ATE en ligne entièrement automatisé chez Xilinx
° Programmation sécurisée pour des volumes moyens à élevés - avec des réglages uniformes
• programmation Avnet
° Possibilités de sécurité, de manipulation, de sérialisation et autres différenciateurs
° Idéal pour la programmation de volumes modérés à faibles volumes
• flux de fabrication du client
° Outil tiers, ou intégré à la conception (XAPP1283), utilisant la programmation Xilinx
La technologie
Page | 486 © ISI 2018 Ridha Ghayoula
° Idéal pour les besoins personnalisés, y compris le traitement d'informations hautement
confidentielles

- Empêcher ou effacer le FPGA d'une conception configurée afin de minimiser le bruit


d'alimentation au sein du FPGA.
- Si possible, arrêtez les horloges système au niveau de la carte afin de minimiser le bruit
d'alimentation du système.
Après la connexion à une cible matérielle valide à l’aide de Vivado Hardware Manager, cliquez avec
le bouton droit de la souris sur le bouton.
FPGA UltraScale pour permettre la sélection du programme clé BBR ... ou du programme eFUSE
Registres ... en fonction de l'option de stockage que vous avez sélectionnée précédemment (voir
Figure 22.7).

Figure 22.7. Vivado HW_Manager Key Programming Selection

 BBRAM
Lorsque l'option Program BBR Key ... est sélectionnée, vous avez la possibilité de rechercher le
dernier fichier généré.
NKY dans le répertoire du projet. Après avoir ajouté le fichier NKY, vous avez également la
possibilité de doubler
vérifiez la valeur de la clé et vérifiez qu'il s'agit bien de la clé AES que vous avez l'intention de
programmer dans le périphérique (Voir la Figure 22.8).

Page | 487 © ISI 2018 Ridha Ghayoula


Figure 22.8. BBRAM Programming GUI

Remarque: Si le fichier NKY contient un champ KeyObfuscate car la propriété


BITSTREAM.ENCRYPTION.OBFUSCATEKEY était activée avant write_bitstream, puis l'indicateur de clé
masquée dans eFUSE ou BBRAM est défini automatiquement par le logiciel Vivado lors de la programmation de la
clé AES-256.
La case à cocher Activer DPA_PROTECT active le décompte DPA de la configuration BBRAM
Mécanisme de protection.
• DPA_COUNT spécifie la valeur de charge initiale du compteur de configuration. Une fois que le nombre atteint 0,
la BBRAM est effacée.
• DPA_MODE spécifie dans quelles conditions le DPA_COUNT doit être décrémenté. Les deux choix sont
INVALID_CONFIGURATIONS, qui est le paramètre DPA typique, et ALL_CONFIGURATIONS,
qui décrémente le compte de chaque configuration afin que le périphérique dispose d'un nombre fixe de configurations à
utiliser.

 eFUSE
Lorsque vous sélectionnez (Program eFUSE Registers.) ..., un assistant apparaît et vous guide tout
au long du processus de sélection du fichier NKY et des différents registres eFUSE que vous
souhaitez programmer. Après avoir ajouté le fichier NKY ou PEM, vous avez également la
possibilité de vérifier les valeurs de clé et de vérifier qu’il s’agit des clés AES et RSA que vous
souhaitez programmer dans le périphérique. (Voir la figure 4.)

Page | 488 © ISI 2018 Ridha Ghayoula


Figure 22.9. eFUSE Programming Cryptographic Key Setup

L’écran de configuration du registre d’utilisateurs (User Register setup screen)est présenté à la Figure
22.10. Il vous permet de spécifier une valeur unique 32 bits et / ou 128 bits à programmer dans les
bits du registre FUSE_USER. Ces registres sont lisibles à partir de la logique FPGA en utilisant la
primitive eFUSE_USR.

Figure 22.10. eFUSE Programming USER Register Setup

Page | 489 © ISI 2018 Ridha Ghayoula


L’écran de configuration du registre de contrôle (Control Register setup screen) est illustré à la
Figure 22.11. Cela vous permet de sélectionner les bits de registre FUSE_CNTL à programmer.
Ces bits assurent la sécurité en désactivant les opérations de lecture et d'écriture sur différents
registres de contrôle eFUSE.

Figure 22.11. eFUSE Programming Control Register Setup


L’écran de configuration du registre de sécurité (Security Register setup screen) est illustré à la Figure
22.12. Cela vous permet de sélectionner les bits du registre FUSE_SEC à programmer. Ces bits
offrent une sécurité supplémentaire en autorisant uniquement les trains de bits chiffrés ou en
activant l'authentification RSA.

Figure 22.12. eFUSE Programming Security Register Setup

Page | 490 © ISI 2018 Ridha Ghayoula


Remarque: Si le fichier NKY contient un champ KeyObfuscate car la propriété
BITSTREAM.ENCRYPTION.OBFUSCATEKEY était activée avant write_bitstream, puis l'indicateur de clé
masquée dans eFUSE ou BBRAM est défini automatiquement par le logiciel Vivado lors de la programmation de la
clé AES-256.

Le dernier écran (Figure 22.13) est l'écran de résumé que vous pouvez utiliser pour vérifier que les
options que vous avez sélectionnées sont celles que vous souhaitez implémenter. N'oubliez pas que
les registres eFUSE sont programmables une fois et ne peuvent PAS être modifiés ultérieurement.

Figure 22.13. Summary

 Vérification du matériel
Vous souhaiterez probablement valider que la clé AES a été programmée correctement dans les bits BBRAM ou
eFUSE. Voici une liste de contrôle des étapes de vérification:
1. Générez des trains de bits à l’aide de Vivado 2018.x ou version ultérieure: un flux de données non chiffré, un
fichier chiffré. bitstream avec votre clé personnalisée, un flux crypté avec une clé tout-un et un flux crypté avec une clé
tout-zéros.
2. Consultez les flux de bits générés pour valider que le chiffrement a eu lieu.
3. Vérifiez le matériel: utilisez Vivado Device Programmer pour vous connecter au FPGA, téléchargez le fichier bit
non crypté via JTAG. Vérifiez que la conception fonctionne comme prévu.
4. Testez le décrypteur FPGA: Téléchargez le fichier .bit chiffré avec la clé tout-zéros (pour eFUSE).
5. Programmez la clé AES via JTAG en suivant les recommandations de la section précédente. (Si vous utilisez
eFUSE, commencez par les étapes 5 et 6 avec la clé BBRAM comme vérification de validation; ensuite, si vous
travaillez comme prévu, programmez eFUSE pour le test final.)
6. Clé de test: Téléchargez le fichier .bit crypté avec votre clé personnalisée.
7. Clé de test: Téléchargez le fichier .bit crypté avec la clé tout-zéros (échec attendu).
8. Testez les paramètres de clé: téléchargez le fichier .bit non crypté (les résultats peuvent varier en fonction des
paramètres de sécurité).

Page | 491 © ISI 2018 Ridha Ghayoula


9. Vérifiez la sécurité de la clé: vérifiez que la clé est protégée en lecture.

Figure 22.14. Vérification du matériel

Page | 492 © ISI 2018 Ridha Ghayoula


23
Vivado Design Suite avec les contraintes XDC
23.1. Introduction
Les contraintes de conception définissent les exigences auxquelles le flux de compilation doit
satisfaire pour que la conception soit fonctionnelle sur le board. Toutes les contraintes ne sont pas
utilisées par toutes les étapes du flux de compilation. Par exemple, les contraintes physiques ne sont
utilisées que lors des étapes d'implémentation (c'est-à-dire par le placeur et le routeur).
Les algorithmes de synthèse et de mise en œuvre de l'environnement de conception intégré (IDE)
Vivado ™ étant pilotés par le temps, vous devez créer des contraintes de synchronisation
appropriées. Vous devez utiliser des contraintes raisonnables correspondant aux exigences de votre
application.

23.2. Organisation des contraintes


L'IDE Vivado vous permet d'utiliser un ou plusieurs fichiers de contraintes. Bien que l'utilisation
d'un fichier de contraintes unique pour l'ensemble du flux de compilation puisse sembler plus
pratique, il peut être difficile de conserver toutes les contraintes à mesure que la conception devient
plus complexe. C'est généralement le cas pour les conceptions qui utilisent plusieurs adresses IP ou
de gros blocs développés par différentes équipes.
La Figure 32.1, Single ou Multi XDC, montre deux ensembles de contraintes dans un projet:
• Le premier ensemble de contraintes comprend deux fichiers XDC.
• Le deuxième ensemble de contraintes utilise un seul fichier XDC contenant toutes les contraintes.

Page | 493 © ISI 2018 Ridha Ghayoula


Figure 23.1. Single or Multi XDC

 Flux non liés au projet (Non-Project Flows)


Pour obtenir le même résultat dans un flux autre qu'un projet, lisez chaque fichier individuellement
avant d'exécuter les commandes de compilation.
L'exemple de script ci-dessous montre comment utiliser un ou plusieurs fichiers XDC pour la
synthèse et l'implémentation.

 Utilisation d'un fichier de contraintes pour la synthèse ou l'implémentation


Vous pouvez utiliser un fichier de contraintes pour:
 Synthèse uniquement
 Mise en œuvre uniquement
 Synthèse et mise en œuvre
Modifiez les propriétés du fichier de contrainte pour indiquer si le fichier sera utilisé uniquement
pour la synthèse, l'implémentation uniquement ou les deux.
Par exemple, pour utiliser un fichier de contraintes uniquement pour l'implémentation:
1. Sélectionnez le fichier de contraintes dans la fenêtre Sources.
2. Dans la fenêtre Propriétés du fichier source:
i. Décochez la synthèse (Synthesis).
ii. Vérifiez la mise en œuvre (Implementation).
3. Sélectionnez Appliquer (Apply)

Figure 23.2. Source File Properties Window

Page | 494 © ISI 2018 Ridha Ghayoula


Les commandes Tcl équivalentes sont:

Lorsque vous exécutez Vivado IDE sans projet, vous pouvez lire les contraintes directement entre
les différentes étapes du flux.
Le script Tcl suivant montre comment lire deux fichiers XDC:

Tableau 23.1. Reading Two XDC Files


File Name File Placement Used For
wave_gen_timing.xdc Before synthesis • Synthesis
• Implementation
wave_gen_pins.xdc After synthesis • Implementation

23.3. Commander vos contraintes


Les contraintes XDC étant appliquées de manière séquentielle et hiérarchisées selon des règles de
priorité claires, vous devez examiner attentivement l'ordre de vos contraintes. Pour plus
d'informations, reportez-vous au chapitre 6, Priorité XDC.
L'IDE Vivado offre une visibilité complète sur votre conception. Pour valider vos contraintes pas à
pas:
1. Exécutez les commandes de rapport appropriées.
2. Consultez les messages dans la console Tcl ou la fenêtre Messages.

 Séquence de contraintes recommandée


RECOMMANDÉ: Si vous utilisiez un ou plusieurs fichiers XDC pour votre conception, organisez vos contraintes
dans l'ordre suivant.

## Timing Assertions Section


# Primary clocks
# Virtual clocks
# Generated clocks
# Clock Groups
# Input and output delay constraints

## Timing Exceptions Section


# False Paths
# Max Delay / Min Delay
# Multicycle Paths
# Case Analysis
# Disable Timing

## Physical Constraints Section


# located anywhere in the file, preferably before or after the timing constraints
# or stored in a separate XDC file

Page | 495 © ISI 2018 Ridha Ghayoula


Commencez avec les définitions de l'horloge. Les horloges doivent être créées avant de pouvoir être
utilisées par des contraintes ultérieures. Toute référence à une horloge avant sa déclaration entraîne
une erreur et la contrainte correspondante est ignorée. Cela est vrai dans un fichier XDC individuel,
ainsi que dans tous les fichiers XDC de votre conception.

 Ordre des fichiers XDC


L'ordre des fichiers XDC est important. Vous devez vous assurer que les contraintes de chaque
fichier ne reposent pas sur les contraintes d'un autre fichier. Dans ce cas, vous devez lire le fichier
contenant les dépendances de contrainte en dernier. Si deux fichiers de contraintes ont des
interdépendances, vous devez soit:
• Fusionnez-les manuellement dans un fichier contenant la séquence appropriée, ou
• Divisez les fichiers en plusieurs fichiers distincts et classez-les correctement.

 Commande de fichiers de contraintes


Dans un flux de projet, les contraintes sont situées dans un ensemble de contraintes. Lors de
l'ouverture de la netlist élaborée ou post-synthèse, les fichiers de contrainte sont chargés dans le
même ordre que celui indiqué dans le jeu de contraintes, c'est-à-dire de haut en bas, comme dans
l'EDI Vivado.
Tableau 23.2. Constraint Files Order
FIle Order File Name Read In
First wave_gen_timing.xdc First
Second wave_gen_pins.xdc Second

 Modification de l'ordre de lecture


Pour changer l'ordre de lecture:
1. Sélectionnez le fichier XDC que vous souhaitez déplacer.
2. Faites glisser le fichier XDC à l’endroit souhaité dans la liste.
La commande équivalente Tcl est:

La séquence des appels read_xdc détermine l'ordre des fichiers de contrainte. Si vous utilisez les IPs
natives fournies avec un fichier de contrainte, les fichiers IP XDC sont chargés après vos fichiers,
dans le même ordre que les IPs répertoriées dans la fenêtre Sources IP.
Par exemple, la Figure 23.3, Fichiers XDC dans les sources IP, montre que l’un des IP du projet est
livré avec un fichier XDC.

Page | 496 © ISI 2018 Ridha Ghayoula


Figure 23.3. XDC Files in the IP Sources

Lorsque vous ouvrez votre conception, le fichier journal indique que le fichier IP XDC a été chargé
en dernier:

Vous ne pouvez pas modifier l'ordre des fichiers IP XDC. Si vous devez modifier la commande,
procédez comme suit:
1. Désactivez les fichiers IP XDC correspondants (voir Propriétés).
2. Copiez leur contenu.
3. Collez le contenu dans l'un des fichiers XDC inclus dans votre jeu de contraintes.
4. Mettez à jour les noms avec le chemin hiérarchique complet dans les contraintes IP XDC copiées.

23.4. Saisie des contraintes


Vivado IDE offre plusieurs manières de saisir vos contraintes. Sauf si vous modifiez directement le
fichier XDC dans un éditeur de texte, vous devez ouvrir une base de données de conception
(élaborée, synthétisée ou implémentée) pour accéder aux fenêtres de contraintes de l'EDI Vivado.
 Enregistrement des contraintes en mémoire

Page | 497 © ISI 2018 Ridha Ghayoula


Vous devez avoir un design en mémoire pour valider vos contraintes lors de l'édition. Lorsque vous
modifiez une contrainte à l'aide de l'interface utilisateur de Vivado IDE, la commande XDC
équivalente est émise dans la console Tcl afin de l'appliquer en mémoire (à l'exception de l'éditeur
Timing Contraints).
Avant de pouvoir exécuter la synthèse ou l'implémentation, vous devez enregistrer les contraintes en
mémoire dans un fichier XDC appartenant au projet. Vivado IDE vous invite à enregistrer vos
contraintes chaque fois que nécessaire.

Pour enregistrer manuellement vos contraintes:


• Cliquez sur le bouton Enregistrer ou
• Sélectionnez Fichier> Enregistrer les contraintes.

 Option d'interface utilisateur


Vivado IDE gérant vos contraintes, vous ne devez pas éditer vos fichiers XDC en même temps.
Lorsque l'IDE Vivado enregistre le contenu de la mémoire:
• Les contraintes modifiées remplacent les contraintes d'origine dans leur fichier d'origine.
• Les nouvelles contraintes sont ajoutées au fichier marqué comme cible.
• Toutes les modifications manuelles dans les fichiers XDC sont écrasées.
 Option d'édition manuelle
Lorsque vous utilisez l'option d'édition manuelle, vous êtes responsable de l'édition et de la
maintenance des fichiers XDC. Bien que vous utilisiez probablement la console Tcl pour vérifier la
syntaxe de certaines contraintes, vous devez ignorer les modifications apportées en mémoire lors de
la fermeture ou du rechargement de votre conception.
En cas de conflit lors de la sauvegarde des contraintes, vous êtes invité à choisir entre:
• Ignorer les modifications apportées en mémoire, ou
• Enregistrer les modifications dans un nouveau fichier ou
• Écraser les fichiers XDC

Page | 498 © ISI 2018 Ridha Ghayoula


Load your design in
memory

Vivado
database

1. Editor files in text Editor


Use Vivado IDE editors Analyse your design 2. Save your XDC files
(Device/Physical/Timing/Oth (Schematic/device/Reports) 3.reload your design
ers...) Tcl Console

Yes (Hand Edit


Yes (GUI option) option)
Need more
contraints

Close your design/Run compilation:


GUI Option: save changes to XDC file(s) (new or existing)
Hand Edit Option: do nothing (or discard any changes)

Figure 23.4. Constraints Editing Flow

La création de contraintes est itérative. Vous pouvez utiliser les fonctionnalités d'interface dans
certains cas et modifier manuellement le fichier de contraintes dans d'autres.
Dans chaque itération décrite à la Figure 23.4, Flux de modification des contraintes, n'utilisez pas les
deux options en même temps.
Si vous basculez entre les deux options, vous devez d’abord enregistrer vos contraintes ou recharger
votre conception afin de vous assurer que les contraintes en mémoire sont correctement
synchronisées avec les fichiers XDC.

 Affectation des broches I/O


Pour créer et éditer un placement de ports de niveau supérieur existant:
1. Sélectionnez la disposition préconfigurée I/O Planning (the I/O Planning pre-configured layout.)
2. Ouvrez les fenêtres indiquées dans le tableau suivant (Open the windows shown in the following
table).
Tableau 23.3. Creating and Editing Existing Top-Level Ports Placement
Window Function
Device View and edit the location of the ports on the device
floorplan.
Package View and edit the location of the ports on the device
package.
I/O Ports Select a port, drag and drop it to a location on the Device
or Package view, as well as review current assignment and
properties of each port.
Package Pins View the resource utilization in each I/O bank.

Page | 499 © ISI 2018 Ridha Ghayoula


 Affectation des ressources d'horloge
Pour afficher et modifier l'emplacement de vos arbres d'horloge:
1. Sélectionnez la disposition préconfigurée pour la planification de l'horloge.
2. Ouvrez les fenêtres indiquées dans le tableau suivant.

Tableau 23.4. Viewing and Editing the Placement of Clock Trees


Window Function
Clock Resources • View the connectivity between the clock resources in the architecture.
• View where your clock tree cells are currently located.
Netlist • Drag and drop the clock resources from your netlist to a specific location in the Clock
Resources window or Device window.

 Floorplanning
Pour créer et éditer des Pblocks:
1. Sélectionnez la disposition préconfigurée Floorplanning.
2. Ouvrez les fenêtres indiquées dans le tableau suivant.

Tableau 23.5. Creating and Editing Pblocks


Window Function
Netlist Select the cells to be assigned to a Pblock.
Physical Constraints Review the existing Pblocks and their properties.
Device Create or edit the shape and location of your Pblocks in the device.

Pour créer des contraintes de placement de cellule particulier:sur un BEL ou SITE.


1. Sélectionnez la cellule dans la vue Netlist.
2. Faites glisser la cellule vers l'emplacement cible dans la vue Périphérique.

 Contraintes de timing
La fenêtre Contraintes de cadencement (Timing Constraints window )est disponible uniquement
pour les conceptions synthétisées et implémentées.
Pour les contraintes de conception élaborées, voir Création de contraintes de synthèse.
Vous pouvez ouvrir la fenêtre Contraintes de cadencement en utilisant l’une des trois options
suivantes: affiché à la Figure 23.5
• Choisissez Window > Timing Constraints.
• Dans la section Synthèse du panneau Flow Navigator, Synthesized Design > Edit Timing
Constraints.
Contraintes de timing.
• Dans la section Implémentation du panneau Flow Navigator, sélectionnez Implemented Design
> Edit Timing Constraints.

Page | 500 © ISI 2018 Ridha Ghayoula


Figure 23.5. Multiple Methods for Opening the Timing Constraints Window

L’éditeur de contraintes de synchronisation affiche les contraintes de synchronisation en mémoire,


soit:
• la même séquence que dans le fichier XDC, ou
• La même séquence dans laquelle vous les avez entrées dans la console Tcl.

 Tableur des contraintes


La feuille de calcul des contraintes affiche les détails de toutes les contraintes existantes d'un type
spécifique.
Utilisez la feuille de calcul des contraintes pour examiner et modifier les options de contrainte.
Bien que Xilinx vous recommande d'utiliser les assistants de création de contraintes, vous pouvez
créer une contrainte supplémentaire du même type en cliquant sur le bouton +. Une nouvelle ligne
dans la feuille de calcul est ajoutée, vous permettant de fournir la valeur pour chaque option.
Pour vérifier que la nouvelle contrainte a été ajoutée à la fin des contraintes, examinez le nombre
affiché dans la colonne Position.
Cette nouvelle contrainte n'est ni validée ni appliquée en mémoire tant que vous n'avez pas cliqué
sur Appliquer. En cliquant Apply:
• Réinitialise les contraintes de synchronisation en mémoire avant de toutes les appliquer.
• n'enregistre pas les contraintes dans le fichier XDC

 Création de contraintes, regroupées par catégorie


Lorsque vous sélectionnez une contrainte, la feuille de calcul correspondante apparaît dans la sous-
fenêtre de droite. Pour créer une nouvelle contrainte, double-cliquez sur le nom. Un assistant vous
permet de spécifier la valeur de chaque option. Lorsque vous cliquez sur OK, l’assistant:
1. Valide la syntaxe.
2. l'applique à la mémoire.
3. Ajoute la nouvelle contrainte à la fin de la feuille de calcul.
4. Ajoute la nouvelle contrainte à la fin de votre liste complète de contraintes.

 Toutes les contraintes


La partie inférieure de la fenêtre affiche la liste complète des contraintes chargées en mémoire, en

Page | 501 © ISI 2018 Ridha Ghayoula


la même séquence comme ils ont été appliqués.
• Pour supprimer une contrainte, sélectionnez-la et cliquez sur X.
• Utilisez le mode feuille de calcul pour modifier les options de contrainte et les réappliquer.

Figure 23.6. Timing Constraints Editor

Si vous tapez une nouvelle contrainte de synchronisation valide dans la console Tcl, elle apparaît
immédiatement à la fin de la liste des contraintes existantes dans la fenêtre Contraintes de
synchronisation.
Lorsque vous créez une nouvelle contrainte ou modifiez une contrainte existante dans spreadsheet
view in the Timing Constraints window, la contrainte n'est pas appliquée en mémoire tant que vous
n'avez pas cliqué sur Apply.

23.4. Setup and Hold Analysis


Vivado IDE analyse et signale le mou (slack ) aux extrémités de la trajectoire temporelle. Le temps
mort (slack )est la différence entre le temps requis pour les données et le moment d'arrivée des
données au point de terminaison du chemin.
Si le jeu est positif, le chemin est considéré fonctionnel du point de vue de la synchronisation.
Vérification de la configuration
Pour calculer le temps requis pour l'analyse de la configuration, le moteur de synchronisation:
1. Détermine la période commune entre l’horloge source et l’horloge cible. Si aucun ne peut être
trouvé, jusqu'à 1 000 cycles d'horloge sont pris en compte pour l'analyse.
2. Examine tous les fronts montant et descendant des horloges de point de départ et d'arrivée sur
leur période commune.
3. Détermine le plus petit delta positif entre deux arêtes actives. Ce delta s'appelle l'exigence de
chemin de synchronisation pour l'analyse de la configuration.

Page | 502 © ISI 2018 Ridha Ghayoula


 Exemple Setup Path Requirement
Considérons un chemin entre deux registres sensibles au front montant de leur horloge respective.
Les fronts d'horloge actifs de ce trajet sont uniquement les fronts montants. Les horloges sont
défini comme suit:
• clk0 a une période de 6ns
• clk1 a une période de 4ns
Common period

clk0 launch edges

Setup (1) Setup (2)

clk1 launch edges

0ns 2ns 4ns 6ns 8ns 10ns 12ns

Figure 23.7. Setup Path Requirement Example

La Figure 23.7 montre qu'il existe deux fronts d'horloge uniques source et cible qui sont admissibles
pour l'analyse de configuration: setup (1) et setup (2).
Le plus petit delta positif de clk0 à clk1 est 2ns, ce qui correspond à la setup (2):

Lors du calcul de l'exigence de chemin, deux considérations importantes sont prises en compte:
1. Les bords de l'horloge (clock edges )sont idéaux, c'est-à-dire que le délai d'insertion de l'arbre
d'horloge n'est pas encore pris en compte.
2. Les horloges sont alignées par défaut sur la phase zéro au temps zéro, à moins que leur définition
de forme d'onde n'introduise un déphasage. Les horloges asynchrones n'ont pas de relation de phase
connue.
Le moteur de synchronisation applique l'hypothèse par défaut lors de l'analyse des chemins entre
eux.
 Temps requis pour l'analyse de la configuration(Data Required Time For
Setup Analysis)
Le temps requis pour l'analyse de configuration est le temps avant lequel les données doivent être
stables pour que la cellule de destination le verrouille en toute sécurité. Sa valeur est basée sur:
• heure de capture de l'horloge de destination (Destination clock capture edge time)
• délai d'horloge de destination
• Incertitude de l'horloge source et de destination
• heure d'établissement de la cellule de destination (setup time)

 Heure d'arrivée des données pour l'analyse de la configuration (Data Arrival


Time For Setup Analysis)

Page | 503 © ISI 2018 Ridha Ghayoula


L'heure d'arrivée des données pour l'analyse de configuration est le temps nécessaire pour que les
données soient stables au point de terminaison du chemin après leur lancement par l'horloge source.
Sa valeur est basée:
• Heure du bord de lancement de l'horloge source
• délai d'horloge source
• délai Datapath
Le délai de chemin de données inclut tous les délais de cellule et de réseau, du point de départ au
point final.
Dans les rapports de minutage, Vivado IDE considère le temps de configuration comme faisant
partie du chemin de données.
En conséquence, l'équation pour l'arrivée des données et le temps requis est la suivante:

Le slack d'installation (The setup slack) est la différence entre l'heure requise et l'heure d'arrivée:

Une configuration négative sur une broche de données d'entrée de registre (negative setup
slack)signifie que le registre peut potentiellement verrouiller une valeur inconnue et passer à un état
métastable.

 Vérification en attente (Hold Check)

Le calcul du slack en attente(hold slack computation) est directement lié au calcul du slack en
configuration. Bien que l'analyse de la configuration(setup analysis) confirme que les données
peuvent être capturées en toute sécurité dans le scénario le plus pessimiste, l'analyse des suspensions
garantit que:
• Les mêmes données ne peuvent pas être capturées à tort par le bord d'horloge de destination
précédent.
• Les données lancées par le prochain front d'horloge source ne peuvent pas être capturées par le
le front d'horloge de destination utilisé pour l'analyse de la configuration.
Par conséquent, afin de déterminer l'exigence de chemin de synchronisation pour l'analyse de
maintien, le moteur de synchronisation considère toutes les combinaisons possibles des fronts
d'horloge source et de destination pour l'analyse de configuration.
Pour chaque combinaison possible, le moteur de chronométrage:
• Examine la différence de temps entre le bord de lancement et le bord de capture moins une
période d'horloge de destination.
• Examine la différence de temps entre le front de lancement plus une période d'horloge source et le
front de capture.
• Conserve uniquement les fronts de lancement et de capture associés au plus grand décalage
horaire.
 Hold Path Requirement Example

Les exigences de maintien correspondantes(hold requirements) sont les suivantes.

Page | 504 © ISI 2018 Ridha Ghayoula


La plus grande exigence de maintien(hold requirement) est 0ns, ce qui correspond au premier front
montant des horloges source et cible.

23.5. Timing Analysis


Les chemins de synchronisation sont définis par la connectivité entre les instances de la conception.
Dans les conceptions numériques, les chemins de synchronisation sont formés par une paire
d'éléments séquentiels contrôlés par la même horloge ou par deux horloges différentes.

 Chemins de temps communs(Common Timing Paths)


Les chemins les plus courants dans toute conception sont:
• Port d'entrée vers le chemin de cellule séquentiel interne(Input Port to Internal Sequential Cell
Path)
• Chemin interne d'une cellule séquentielle à une cellule séquentielle(Internal Path from Sequential
Cell to Sequential Cell)
• Cellule séquentielle interne vers le chemin du port de sortie(Internal Sequential Cell to Output Port
Path)
• Port d’entrée au chemin du port de sortie(Input Port to Output Port Path)
 Exemple de chemin
La Figure 23.8 montre les chemins décrits ci-dessus. Dans cet exemple, l'horloge de conception
CLK0 peut être utilisée comme horloge de port pour les contraintes de délai DIN et DOUT

Figure 23.8. Exemple

 Chemin d'horloge de destination


Le chemin d'horloge de destination est le chemin suivi par l'horloge de destination depuis son point
source, généralement un port d'entrée, jusqu'à la broche d'horloge de la cellule séquentielle de

Page | 505 © ISI 2018 Ridha Ghayoula


capture. Pour un chemin de synchronisation se terminant par un port de sortie, il n'y a pas de
chemin d'horloge de destination.
La Figure 23.9 illustre les trois sections d’un chemin de synchronisation typique.

Figure 23.9. Typical Timing Path

23.6. Setup and Hold Analysis

Vivado IDE analyse et signale le mou (slack )aux points de terminaison du chemin de
synchronisation. Le temps mort est la différence entre le temps requis pour les données et le
moment d'arrivée des données au point de terminaison du chemin. Si le jeu est positif, le chemin est
considéré fonctionnel du point de vue de la synchronisation.

 Vérification de la configuration(Setup Check)


Pour calculer le temps requis pour l'analyse de la configuration, le moteur de synchronisation:
1. Détermine la période commune entre l’horloge source et l’horloge cible. Si aucun ne peut être
trouvé, jusqu'à 1 000 cycles d'horloge sont pris en compte pour l'analyse.
2. Examine tous les fronts montant et descendant des horloges de point de départ et d'arrivée sur
leur période commune.
3. Détermine le plus petit delta positif entre deux arêtes actives. Ce delta s'appelle l'exigence de
chemin de synchronisation pour l'analyse de la configuration.

 Exemple de condition de chemin d'installation(Setup Path Requirement)


Considérons un chemin entre deux registres sensibles au front montant de leur horloge respective.
Les fronts d'horloge actifs de ce chemin sont les fronts montants. Les horloges sont définies comme
suit:
• clk0 a une période de 6ns
• clk1 a une période de 4ns

Page | 506 © ISI 2018 Ridha Ghayoula


Figure 23.10. Setup Path Requirement Example
La Figure 23.10 montre qu'il existe deux fronts d'horloge uniques source et cible qui sont
admissibles pour l'analyse de configuration : Setup (1) et Setup (2).

Le plus petit delta positif de clk0 à clk1 est 2ns, ce qui correspond à la Setup (2):

Lors du calcul de l'exigence de chemin, deux considérations importantes sont prises en compte:
1. Les bords de l'horloge sont idéaux, c'est-à-dire que le délai d'insertion de l'arbre d'horloge n'est
pas encore pris en compte.
2. Les horloges sont alignées par défaut sur la phase zéro au temps zéro, à moins que la définition de
leur forme d'onde n'introduise un déphasage. Les horloges asynchrones n'ont pas de relation de
phase connue.
Le moteur de synchronisation applique l'hypothèse par défaut lors de l'analyse des chemins entre
eux. Pour plus d'informations sur les horloges asynchrones, voir les sections suivantes.

Page | 507 © ISI 2018 Ridha Ghayoula


24
Software Development Kit (SDK)

24.1. Intoduction
Dans les systèmes embarqués, un BSP (Board Support Package) est un ensemble de fichiers
contenant du code spécifique à votre système matériel afin de pouvoir développer l’application
logicielle. Par exemple, le BSP permet de dire au SDK quelles sont les ressources matérielles
disponibles ainsi que leur adresse. Il s’agit en général de fichiers source en C, de fichiers d’entête .h,
de fichiers d’initialisation, … Le SDK vous permet :
• D’importer les spécifications matérielles fournies par Vivado.
• De créer le BSP.
• De créer le projet d’application logicielle.
• De générer le FSBL.
• De configurer la PL.
• D’exécuter le programme ARM et de le debugger.
•…
Ce chapitre explique comment créer et exécuter un système simple basé sur MicroBlaze sur une
carte de prototypage Digilent Nexys-4. Un tel système nécessite à la fois de spécifier l'architecture
matérielle et le logiciel qui y est exécuté.
Ces deux éléments sont ensuite combinés dans une configuration FPGA unique, utilisée pour
configurer le FPGA Artix-7 situé sur la carte Nexys-4.
Cette partie de ce chapitre s'articule autour de la création d'un système co-design (matériel et logiciel)
pouvant émettre un simple message via l'UART (dans notre cas, via USB-UART) et faire clignoter
quelques voyants sur le tableau. La plus simple des architectures matérielles programmables pouvant
être construites implique un seul processeur, un MicroBlaze dans notre cas, et une prise en charge
minimale (mémoire, interconnexion). En plus de cela, la fonctionnalité de communication via
l'UART est nécessaire. De plus, sans effort, on peut ajouter des fonctionnalités pour détecter et
contrôler d’autres composants physiques présents sur la carte Nexys-4 (tels que boutons poussoirs,
commutateurs, capteur de température, accéléromètre).
Naturellement, une architecture matérielle programmable nécessitera un programme (logiciel) pour
s'exécuter. Dans une seconde phase, le chapitrel abordera les étapes nécessaires à la création d’un
environnement logiciel simple via Xilinx Software Development Kit SDK.
Enfin, la dernière partie de ce chapitre explique comment configurer le FPGA avec le matériel et les
logiciels que vous venez de construire, comment exécuter votre conception et afficher le résultat de
l'UART.

Page | 508 © ISI 2018 Ridha Ghayoula


La figure 1 présente une vue d'ensemble simplifiée du flux de conception utilisé pour la construction
de l'ensemble du système. Notez que des étapes similaires sont suivies à la fois pour les flux de
matériel et de logiciel, mais que la terminologie est un peu différente.

24.2. Création de l'architecture système (matériel)


Les architectures matérielles sont créées à l'aide de Xilinx Vivado, une interface graphique qui vous
aide à spécifier
• quels processeurs, blocs de mémoire et autres IPs logicielles (périphériques)
• comment les différentes IPs sont interconnectées
• le mappage de mémoire, c’est-à-dire pour les adresses d’IO / périphériques mappés en mémoire
• comment les différents signaux d’entrée / sortie correspondent aux broches réelles du FPGA et
donc aux ressources de la carte

Figure 24.1. Overview of the Design Flow in this Tutorial (simplistic)

Le résultat de Vivado correspond à la partie de la configuration FPGA qui décrit le matériel de votre
système. Les ressources de carte et de FPGA nécessitent cette configuration pour émuler
l'architecture matérielle que vous avez décrite dans Vivado.
L'architecture matérielle de ce chapitre, illustrée à la Figure 24.2, comprendra:
• Un processeur: MicroBlaze
• Mémoire locale associée, double port - un port pour les données, un pour les instructions
• Quelques périphériques (IP): UART (gestion des connexions série), GPIO (gestion des leds
intégrées), Minuterie (pour obtenir
données de performance)
• Un bus reliant les périphériques au processeur: AXI
• Un générateur d’horloge et un générateur de réinitialisation associé à l’ensemble du système

Page | 509 © ISI 2018 Ridha Ghayoula


Instr. Port A
CLK
CPU Local
Microblaze memory
RST Data Port B

Peripheral Bus (AXI)

UART GPIOs Timer

Figure 24.2. Overview of the Hardware Architecture in this chapter

24.2.1.IDE Vivado et création d'un projet


a. Ouvrez l'EDI de Vivado en cliquant sur l'icône du bureau ou en tapant vivado sur
une ligne de commande de terminal. Du Page de démarrage rapide (Figure 2.43),
sélectionnez Créer un nouveau projet(Create New Project). L'assistant Nouveau
projet s'ouvre.
b. Dans la boîte de dialogue Nom du projet(Project Name), tapez le nom et
l'emplacement du projet.

Figure 24.3. Vivado Quick Start Page

note Notez que le chemin ne peut pas contenir d'espaces. En outre, en raison des stratégies de
groupe dans nos machines Windows, vous ne serez que
capable de travailler correctement avec le projet à partir de certains répertoires. Assurez-vous de localiser
tous vos projets sous C: / Utilisateurs / ID-utilisateur / Programme / ou vous ne pourrez pas exécuter
certaines étapes!
Assurez-vous que Créer un sous-répertoire est coché. Cliquez sur Suivant.
c. Dans la boîte de dialogue Type de projet, sélectionnez Projet RTL. Cliquez sur
Suivant.
d. Dans la boîte de dialogue Ajouter des sources, assurez-vous que la langue cible est
définie sur VHDL ou Verilog. Quitter le langue du simulateur définie sur sa valeur
par défaut Mixte. Cliquez sur Suivant
e. Dans la boîte de dialogue Ajouter une adresse IP existante, cliquez sur Suivant.

Page | 510 © ISI 2018 Ridha Ghayoula


f. Dans la boîte de dialogue Ajouter des contraintes, cliquez sur Suivant.
g. Dans la boîte de dialogue Default Part, sélectionnez Boards et choisissez Nexys-4,
voir Figure 24.4. Cliquez sur Suivant.
h. Vérifiez le résumé du projet (New Project Summary)dans la boîte de dialogue Nouveau
projet avant de cliquer sur Terminer pour créer le projet.

24.2.2. Create an IP Integrator Design


a. Dans la fenêtre Flow Navigator (généralement la plus à gauche dans Vivado), sous IP
Integrator, sélectionnez Créer un bloc. Conception. La boîte de dialogue Créer une
conception de bloc s'ouvre, comme dans la Figure 24.5.
b. Spécifiez le nom de conception du sous-système IP. Pour cette étape, ce chapitre
utilisera la valeur par défaut, mais tout nom sans les espaces feront. Laissez le champ
Répertoire défini sur sa valeur par défaut <Local to Project>.
c. Laissez la liste déroulante Spécifier le jeu de sources à sa valeur par défaut, Sources
de conception.
d. Cliquez sur OK dans la boîte de dialogue Créer une conception de bloc, illustrée à la
Figure 24.5.
e. Dans la zone de conception de bloc, l’onglet Diagramme doit ressembler à celui de la
figure 6. Vous pouvez soit sélectionner Ajouter une IP ici, soit rechercher le fichier
correspondant. Bouton Ajouter une IP situé à gauche de l'onglet Diagramme (vous
utiliserez ce bouton lorsque le dessin n'est pas vide).
f. Comme illustré à la figure 7, tapez micr dans le champ Rechercher pour trouver l’IP
MicroBlaze, puis sélectionnez MicroBlaze et appuyez sur la touche Entrée.

note Remarque La fenêtre Détails IP peut être affichée en cliquant sur les touches CTRL + Q du clavier.

Page | 511 © ISI 2018 Ridha Ghayoula


Figure 24.4. Select the Nexys-4 Board as Target.

Figure 24.5. Name Block Design Figure 24.6. Add IP

Page | 512 © ISI 2018 Ridha Ghayoula


Figure 24.7. Search Field
 Utiliser l'onglet Carte pour se connecter aux interfaces de carte (Board Interfaces)
Il existe plusieurs manières d'utiliser une interface existante dans IP Integrator. Utilisez l'onglet Carte
pour instancier certaines des interfaces qui sont présents sur le conseil Nexys-4.
a. Cliquez sur l'onglet Tableau. Comme le montre la Figure 24.8, vous pouvez voir que
plusieurs composants sont répertoriés dans cet onglet. Celles-ci des composants sont
présents sur la carte Nexys-4. Ils sont répertoriés sous différentes catégories dans la
Board window.

Figure 24.8. Using the Board Part Interfaces

Page | 513 © ISI 2018 Ridha Ghayoula


b. Dans la fenêtre Board, sélectionnez System Clock (Horloge système) dans le dossier
Clock (Horloge), puis faites-la glisser dans le canevas de conception de bloc. Cela
vous permettra d'utiliser l'horloge 100 MHz générée à bord et d'ajouter une logique
d'horloge à votre conception. (Comme nos conceptions sont toutes synchrones, des
horloges seront toujours nécessaires!) Cliquez sur OK dans la boîte de dialogue
Connexion automatique.
c. Dans la fenêtre Board, sélectionnez 16 LED dans le dossier GPIO et faites-les
glisser dans le canevas de conception de bloc. Cela vous permettra de contrôler les
16 voyants sur le tableau. Cliquez sur OK dans la boîte de dialogue Connexion
automatique.
d. Dans la fenêtre Board, sélectionnez Reset, faites-le glisser et déposez-le dans le
canevas de conception de bloc. Cela vous permettra d'utiliser le bouton-poussoir
Réinitialiser sur le tableau pour réinitialiser votre système. Cliquez sur OK dans la
boîte de dialogue Connexion automatique.
e. Dans la fenêtre Board, sélectionnez USB UART et faites-le glisser dans le canevas de
conception de bloc (voir la Figure 24.9). Cela vous permettra de communiquer via
votre interface avec l'interface UART de la carte. Ceci sera utilisé pour afficher des
messages texte simples de votre logiciel fonctionnant sur votre carte, dans une
console connectée à la carte via une série. Cliquez sur OK dans la boîte de dialogue
Connexion automatique.

Figure 24.9. Selected Board Interfaces

f. La conception du bloc devrait maintenant ressembler à celle de la Ligure 24.10.

Page | 514 © ISI 2018 Ridha Ghayoula


Figure 24.10. Block Design after Connecting the UART

Figure 24.11. Run Block Automation

Figure 24.12. Run Block Automation Dialog Box

Page | 515 © ISI 2018 Ridha Ghayoula


 Utiliser l'automatisation de la connexion(Use Connection Automation)
Vivado vous aide également à connecter les blocs présents dans votre conception. Run Connection
Automation fournit plusieurs options que vous pouvez sélectionner pour établir des connexions.
a. Cliquez sur Run Connection Automation comme illustré à la Figure 24.14.
b. La boîte de dialogue Run Connection Automation s'ouvre, comme dans la Figure
24.15. Vérifiez toutes les interfaces dans le volet de gauche comme dans la figure.
Vous pouvez laisser des interfaces non cochées si vous envisagez de les connecter
ultérieurement. Vous devez également vérifier les options que vous avez pour les
éléments sélectionnés dans le volet de gauche. Cependant, à ce stade, il n'est pas
nécessaire de changer quoi que ce soit.
c. Une fois que vous avez cliqué sur OK, les blocs de votre conception seront
connectés.
Vous pouvez utiliser Run Connection Automation chaque fois que vous ajoutez de nouvelles IP à votre
conception, qui doivent être connectées au reste du système.

 Ajout de plus d'IP (Adding More IPs)


Certaines conceptions nécessitent plus des IPs que celle introduite jusqu'à présent. Ceux-ci peuvent
être ajoutés de la même manière que vous avez ajouté le Processeur MicroBlaze, en cliquant sur le
bouton Ajouter une adresse IP, comme dans le texte faisant référence à la Figure 24.6. Ajoutons une
minuterie, qui sera nécessaire pour enregistrer la performance de nos algorithmes dans les derniers
laboratoires.
a. Sélectionnez le bouton Ajouter une IP Add IP dans la partie gauche de l'onglet
Diagramme, dans la zone de conception de bloc.
b. Comme le montre la Figure 24.16, saisissez l'heure dans le champ Rechercher,
sélectionnez AXI Timer et appuyez sur la touche Entrée.
c. Vous devez maintenant exécuter à nouveau Connection Automation.
d. Enfin, Vivado peut également redessiner le diagramme en cliquant sur le bouton
Régénérer la présentation. trouvé dans la même barre d’outils avec le bouton Add IP.

À ce stade, votre diagramme devrait ressembler à celui de la Figure 24.17. L’emplacement relatif de
vos IPs peut être légèrement différent.

Page | 516 © ISI 2018 Ridha Ghayoula


Figure 24.13. MicroBlaze System

Figure 24.14. Run Connection Automation

Figure 24.15. Run Connection Automation Dialog Box

Page | 517 © ISI 2018 Ridha Ghayoula


Figure 24.16. Adding a timer IP

Figure 24.17. MicroBlaze Connected to UART, GPIO, and AXI Timer

 Inspection et modification manuelle d'un design


Il existe des moyens de modifier individuellement les connexions et les IPs sans faire appel aux
fonctionnalités automatiques de Vivado pour les connexions et l'automatisation de bloc.
Nous illustrerons ensuite certaines de ces capacités.
En particulier, notre système présente un défaut de conception, qui sera identifié ultérieurement lors
de la synthèse et de la génération de la configuration FPGA par la vérification des règles de
conception (DRC), mais n’est pas évident à ce stade. En particulier, la réinitialisation de l’entrée du
système provient d’un bouton, ce qui signifie qu’elle est actionnée plus bas (0 logique) lorsqu’elle est
enfoncée. Cependant, comme c'est le cas actuellement, la logique de l'horloge nécessite une
réinitialisation active élevée (logique 1). Un système entièrement implémenté sera donc toujours
réinitialisé. . . à moins que on appuie sur le bouton de réinitialisation! Faisons en sorte que les deux
signaux aient la même polarité:
a. Sélectionnez l'entrée de réinitialisation en cliquant dessus dans le diagramme de
conception de bloc. Les informations sur l'élément sélectionné seront affichées
comme dans la Figure 24.18. Notez que la polarité est active basse(Polarity is Active
Low).

Page | 518 © ISI 2018 Ridha Ghayoula


Figure 24.18. Reset Input Port Properties
b. Examinons maintenant la logique de synchronisation. Double-cliquez sur le bloc
Assistant de synchronisation(Clocking Wizard block). Ceci devrait faire apparaître le Re-
customize IP , comme illustré à la Figure 24.19. Les paramètres de toutes les IPs
peuvent être inspectés et modifiés via cette boîte de dialogue, appelés de la même
manière.
c. Dans l'onglet Clocking Output, notez la section Reset Type, qui correspond à Active
High. Changez-le en Active Low, comme illustré à la figure 20.
d. Cliquez sur OK. Notez le changement dans la description de l'Assistant de
synchronisation - le port de réinitialisation s'appelle maintenant resetn et comporte
un cercle à l'entrée (voir la Figure 24.21). Ces deux conventions sont des conventions
indiquant que le signal est actif bas (à 0).
e. Notez que le port d'entrée de réinitialisation et l'entrée de l'assistant de
synchronisation ne sont plus connectés. Connectez le via la souris en faisant glisser
une ligne du port d'entrée de réinitialisation vers l'entrée de l'Assistant de
synchronisation. Une fois connecté, votre dessin devrait ressembler à celui de la
Figure 24.22.
L'architecture matérielle est maintenant terminée.

24.2.3. Mappage de la mémoire des périphériques dans IP Integrator (Memory-Mapping the


Peripherals in IP Integrator)
Le processeur (MicroBlaze) voit sa mémoire et ses périphériques à différentes adresses dans l'espace
d'adressage. L'accès à une adresse spécifique peut accéder à la mémoire ou à un périphérique, selon
ce qui est mappé à cette adresse spécifique. Pour examiner la mappe d'adresses (ce qui est mappé où
dans l'espace d'adressage), sélectionnez l'onglet Editeur d'adresses, situé à côté de l'onglet
Diagramme dans la fenêtre Conception de bloc. La carte mémoire devrait ressembler à celle de la
Figure 24.23. Vous ne pouvez pas modifier aucune des mappages ici, mais Vivado est généralement
très efficace pour sélectionner une carte minimisant la complexité du décodage d'adresse. Il n'est
donc pas nécessaire de changer quoi que ce soit ici.

24.2.4. Valider le bloc de la conception (Validate Block Design)


Pour exécuter les contrôles de règle de design sur la conception:
a. Cliquez sur le bouton Valider la conception de la barre d’outils ou sélectionnez
Tools→Validate Design.

Page | 519 © ISI 2018 Ridha Ghayoula


b. Validate Design button vous informe qu'il n'y a pas d'avertissements ni d'erreurs
critiques dans la conception. Cliquez sur OK.
c. Enregistrez votre conception en utilisant Ctrl + S ou Fichier → Enregistrer la
conception du bloc (Block Design).

Figure 24.19. Re-Customize IP Dialog Box

Figure 24.20. Change Reset Polarity for Clocking Wizard

Page | 520 © ISI 2018 Ridha Ghayoula


Figure 24.21. Clocking Wizard Now with Figure 24.22. Clocking Wizard Resetn
Active Low Reset Connected to the Reset Input Port

Figure 24.23. System Address Space Map


24.2.5. Generate Output Products
a. Dans la fenêtre Sources (voir la Figure 24.24), sélectionnez la conception du bloc
(block design), cliquez dessus avec le bouton droit de la souris et sélectionnez Générer
des produits de sortie(Generate Output Products). Vous pouvez également cliquer sur
Générer une conception de bloc dans le Flow Navigator. La boîte de dialogue
Générer les produits de sortie (voir Figure 24.25).

Figure 24.24. Sources Window Figure 24.25. Generate Output Products


Dialog Box

Page | 521 © ISI 2018 Ridha Ghayoula


b. Sélectionnez Global dans Options de synthèse et cliquez sur Générer (Generate).
c. Cliquez sur OK dans Generate Output Products dialog box

24.3. Créer un Top-level HDL wrapper HDL

a. Sous Sources, cliquez avec le bouton droit sur votre conception, puis cliquez sur
Create HDL Wrapper
b. Dans la boîte de dialogue Create HDL Wrapper, sélectionnez Let Vivado
manage wrapper and auto-update, puis cliquez OK.

Figure 24.26. Creating an HDL Wrapper

24.4. Synthétiser la conception(Synthesize Design)


a. Dans le Flow Navigator, cliquez sur Run Synthesis. Cela prendra un certain temps,
mais vous pouvez vérifier les progrès et les messages de sortie dans la fenêtre
inférieure droite, onglet Journal de synthèse (voir la Figure 24.27).

Figure 24.27. Following the Synthesis Log


b. Une fois la synthèse terminée, vous pouvez choisir de consulter la conception
synthétisée, mais vous devez enfin Exécuter (Run Implementation) la mise en œuvre
dans la boîte de dialogue Synthèse terminée (voir la Figure 24.28). Alors que l’étape

Page | 522 © ISI 2018 Ridha Ghayoula


de synthèse consiste à affiner la conception dans un format générique (similaire au
logiciel compilé dans un format intermédiaire), l’étape de mise en œuvre génère une
conception spécifique du FPGA sur votre carte (par exemple, générer le code
d’assemblage à partir du format intermédiaire). .
c. Cliquez sur OK.

24.5. Passez de la conception à la mise en œuvre


Le résultat final de l'étape de conception matérielle est un train de bits, qui correspond à la
configuration de bas niveau du FPGA cible.
En principe, le choix de Generate Bitstream dans Flow Navigator s’applique à toutes les étapes
nécessaires à la génération de cette configuration. Si vous suivez le processus mentionné dans la
section précédente et que vous avez choisi de lancer la mise en œuvre directement, une nouvelle
boîte de dialogue s’ouvrira, comme dans la Figure 24.29. Choisissez Generate Bitstream, puis cliquez
sur OK.
Notez que ce n'est toujours que le matériel à émuler, mais qu'aucun logiciel ne doit être exécuté
dessus; celle-ci sera créée ultérieurement via le SDK et intégrée au train de bits en tant que contenu
de la mémoire (s’il est situé dans la mémoire sur puce)

Figure 24.28. Synthesis Completed Dialog Box Figure 24.29. Implementation Completed
Dialog Box

Tout au long du processus, vous pouvez également vérifier les différents types de rapports des
différentes étapes, disponibles dans la fenêtre inférieure, onglet Rapports, comme dans la Figure
24.30.

Page | 523 © ISI 2018 Ridha Ghayoula


Figure 24.30. Reports
Une fois la mise en œuvre terminée, il est facile de vérifier toutes sortes de paramètres pour la
conception en sélectionnant le bon rapport.
dans Flow Navigator, section Implémentation, comme dans la Figure 24.31.

Figure 24.31. Implementation in Flow Navigator

Page | 524 © ISI 2018 Ridha Ghayoula


24.5.1. Timing
Vous pouvez vérifier, par exemple, que les contraintes de synchronisation ont été satisfaites (par
exemple, la logique peut suivre la fréquence d'horloge spécifiée) en sélectionnant Report Timing
Summary. Ceci affichera des informations détaillées dans la fenêtre inférieure, comme dans la
Figure 24.32. Vérifiez les différents détails du résumé.

Figure 24.32. Timing Summary. All timing constraints are met in this case.

24.5.2. Utilisation
Vous pouvez également avoir une idée de la quantité de ressources FPGA que votre conception
utilise en sélectionnant Utilisation du rapport (Report Utilization).
Cela affichera des informations détaillées dans la fenêtre inférieure, comme dans la Figure 24.33.
Inspectez les différents détails du résumé, car vous devrez rapporter ces chiffres.

24.5.3. Puissance
Enfin, vous pouvez également obtenir une estimation de la consommation d'énergie de la
conception en sélectionnant Rapporter l'alimentation(Report Power). Ceci affichera des informations
détaillées dans la fenêtre inférieure, comme dans la Figure 24.34. Inspectez les différents détails du
résumé, car vous devrez rapporter cette figure et l'utiliser pour calculer la consommation d'énergie
des différents algorithmes mis en œuvre dans les prochainstravaux.

Figure 24.33. Utilization Summary

Page | 525 © ISI 2018 Ridha Ghayoula


Figure 24.34. Power Summary

24.5. Création du logiciel


Une fois le flux binaire généré, l’architecture matérielle est terminée, mais il s’agit d’une ardoise
vierge, sans logiciel sur lequel tourner.
- Pour créer le logiciel, vous utiliserez un autre outil, le SDK Xilinx, basé sur Eclipse. Pour ces
travaux, vous travaillerez en C, bien que l’utilisation de C ++ soit également possible. Le logiciel
compilé sera fusionné avec le matériel pour former la configuration complète du FPGA.

24.6. Exporter la conception vers le SDK

Le kit de développement logiciel doit connaître l'architecture matérielle sous-jacente. Si vous venez
de construire votre matériel, vous pouvez l'exporter vers le SDK.

Page | 526 © ISI 2018 Ridha Ghayoula


Figure 24.35. Export Hardware Dialog Box

a. Sélectionnez File→Export→Export Hardware


b. Dans la boîte de dialogue Exporter le matériel, cochez la case Include bitstream, comme
illustré à la Figure 24.35. Assurez-vous que le champ Exporter vers <Local to Project>.

Figure 24.36. Launch SDK Dialog Box

c. Cliquez sur OK. Le SDK se lance dans une fenêtre séparée.

Prenez le temps d'examiner la structure des répertoires et les fichiers résidant dans le répertoire de
votre projet. Vous remarquerez un dossier se terminant par .sdk, qui est un espace de travail SDK.
Cela contient également un fichier .hdf, la description complète de la cible architecture matérielle.

Remarque Il est également possible de lancer le Kit de développement logiciel (SDK) sans créer de plate-forme
matérielle, si cela est déjà fourni sous forme de fichier .hdf.
Ensuite, vous devrez démarrer le SDK à partir du menu ou de la ligne de commande, Créer un projet d'application et
spécifier Nouveau ... Matériel cible. Une boîte de dialogue Nouveau projet de matériel apparaît, dans laquelle vous
devez parcourir ... après la spécification de matériel cible, à savoir le fichier .hdf susmentionné.

24.7. Créer une application «Test de périphérique» (Create a ”Peripheral Test”


Application)

Page | 527 © ISI 2018 Ridha Ghayoula


Comme pour la plupart des étapes de ce chapitre, il existe plusieurs façons d'obtenir le même
résultat, car les mêmes commandes peuvent être émises dans l'interface utilisateur à différents
endroits. Voici une des manières de créer une nouvelle application.
a. In SDK, right-click mb_subsystem_wrapper_hw_platform_0 dans le Project Explorer et
selectionnez New→Project. comme illustré à la Figure 24.37.

Figure 24.37. SDK New Project Selection


b. Dans la boîte de dialogue Nouveau projet, sélectionnez Xilinx Application Project (Figure
24.38).

Figure 24.38. SDK New Project Wizard

Page | 528 © ISI 2018 Ridha Ghayoula


c. Cliquez sur Suivant.
d. Saisissez un nom (tel que peri_test) pour votre projet et choisissez autonome en tant
que plate-forme de système d'exploitation, comme illustré à la Figure 24.39.
e. Cliquez sur Suivant.
f. Sélectionnez le modèle d'application Tests de périphérique (Peripheral Tests),
comme illustré à la Figure 24.40, puis cliquez sur Terminer. Notez que vous pouvez
choisir d'autres modèles, prenant en charge divers types d'applications. Il est très
courant de commencer avec une de ces applications (par exemple, «Hello World») et
développez-la dans l'application que vous souhaitez réellement implémenter.

Le SDK crée une nouvelle application de «peri_test» (voir Figure 24.41). Notez qu'il existe trois
projets ouverts: le premier est la description du matériel, le deuxieme est votre nouvelle application
et le troisième est le package de support de la carte, BSP, qui contient les bibliothèques nécessaires
pour programmer avec les IP dans votre architecture. Ouvrez peri_text_bsp, puis BSP
Documentation, puis tmrctr_v4_2 pour examiner la documentation de l'API AXI Timer. Cette
documentation contient souvent des exemples de code dans la liste des fichiers. Pour les futurs
travaux dotés du AXI Timer, le fichier xtmrctr_polled_example.c est pertinent.

Figure 24.39. New Project: Application Project Wizard

Page | 529 © ISI 2018 Ridha Ghayoula


Figure 24.40. New Project: Template Wizard

Figure 24.41. Project Explorer with the new peri test application

24.8. Exécution de l'application sur Nexys-4


Enfin, il est temps d'exécuter le logiciel sur l'architecture matérielle conçue précédemment, qui est
émulée sur le FPGA.

Page | 530 © ISI 2018 Ridha Ghayoula


Cela signifie que le FPGA sera configuré avec le matériel et les logiciels que vous avez produits dans
ce chapitre.
Assurez-vous que vous avez connecté la carte cible à l’ordinateur hôte (broche USB - PROG /
UART) et que la carte est allumé.
1. Sélectionnez Outils Xilinx → Program FPGA pour ouvrir la boîte de dialogue Program FPGA.
2. Dans la boîte de dialogue Program FPGA, assurez-vous de changer le bootloop (ne fait rien /
utilisé dans le débogage) dans la Configuration de Software pour pointer vers le bon exécutable,
comme illustré dans la Figure 24.42. Cliquez sur Program.

Figure 24.42. Project Explorer with the new peri_test application

3. Bien que le système soit opérationnel (check the LEDs), il n’ya aucun moyen de voir les
impressions sauf si nous nous connectons à la carte via un terminal. Cela peut être fait dans le SDK.
Sélectionnez l'onglet SDK Terminal dans la zone inférieure / Console, comme illustré à la Figure
24.43, puis cliquez sur + pour vous connecter à un port série.

Figure 24.43. SDK Terminal Tab


4. Dans la boîte de dialogue Connexion au port série, sélectionnez le bon port COM (qui peut varier
selon votre système) et assurez-vous que les paramètres sont configurés de la même manière que
dans la Figure 24.44. Cliquez sur OK.

Page | 531 © ISI 2018 Ridha Ghayoula


Figure 24.44. Connect to Serial Port Dialog Box

5. Votre fenêtre de terminal devrait maintenant recevoir un texte de la carte, similaire à celui de la
Figure 24.45. Essayez d'appuyer sur le bouton rouge CPU RESET de la carte Nexys-4 et examinez
les LEDs et la sortie du terminal.

Figure 24.45. Terminal Output via the Serial Connection

À la fin de ce cours, vous devriez maintenant être capable de:


• créer une architecture matérielle simple et unique MicroBlaze dans Vivado
• collecter des statistiques sur le timing de votre conception, l'utilisation du périphérique et la
consommation d'énergie dans Vivado
• exporter l'architecture matérielle dans le SDK
• créer une application simple en utilisant votre architecture dans le SDK
• exécuter des systèmes complets sur les carte Nexys-4, kintex-7 et artix-7.

Page | 532 © ISI 2018 Ridha Ghayoula


Les Références Bibliographiques
[1] http ://www.altera.com
[2] http ://microprocesseur.wikibis.com/processeur_softcore.php
[3] http ://proxacutor.free.fr/index.htm
[4] http ://www.gaisler.com
[5] http ://uuu.enseirb.fr/~kadionik/embedded/tipe-pham_viet_hung.pdf
[6] Patrice Kadionik “Linux et le Système sur Silicium”, ENSEIRB
[7] Embedded system-design with soft and hardcore FPGA's. P. Pelgrims and al.
[8] http://emsys.denayer.wenk.be
[9] Le site d'Altera http://www.altera.com
[10] Le site de Xilinx http://www.xilinx.com
[11] Le site de l'auteur http://www.enseirb.fr/~kadionik
[12] Le site des blocs IP libres opencores.org www.opencores.org
[13] Le page de l'auteur sur le System On Chip
http://www.enseirb.fr/~kadionik/SoC/soc.html
[14] Le projet μClinux http://www.uclinux.org
[15] Le site de Microtronix http://www.microtronix.com
[16] Le forum NIOS forum http://www.niosforum.com/forum
[17] Jack E. Volder, The CORDIC Trigonometric Computing Technique, IRE
Transactions on Electronic Computers, septembre 1959
[18] Daggett, D. H., Decimal-Binary conversions in CORDIC, IRE Transactions on
Electronic Computers, Vol. EC-8 n°5, pp335-339, IRE, septembre 1959.
[19] J. E. Meggitt, Pseudo Division and Pseudo Multiplication Processes, IBM Journal,
avril 1962.
[20] Vladimir Baykov, Problems of Elementary Functions Evaluation Based on Digit by
Digit (CORDIC) Technique, rapport de thèse, Université d'État de Leningrad d'ingénierie
électrique, 1972
[21] Schmid, Hermann, Decimal computation. New York, Wiley, 1974
[22] http://eduscol.education.fr/sti/sites/eduscol.education.fr.sti/files/ressources/pedag
ogiques/4346/4346-7-rpi-serveur-web.pdf
[23] http://manpages.ubuntu.com/manpages/natty/fr/man8/
[24] http://www.in2p3.fr/actions/formation/Info09/Duval_EmbededLinuxARMADE
US.pdf
[25] http://www.gaisler.com/index.php/downloads/leongrlib
[26] https://fr.wikipedia.org/wiki/CORDIC
[27] http://eduscol.education.fr/sti/sites/eduscol.education.fr.sti/files/ressources/pedag
ogiques/4585/4585 raspberrypi-pilite.pdf
[28] http://www.kubii.fr/fr/
[29] http://fr.farnell.com/raspberry-pi
[30] http://www.element14.com/community/community/raspberry-pi
[31] http://www.tekin.fr/wp-content/uploads/2015/09/NEWS-Mai-2015-serveur-web-
emb.pdf
[32] System Summary 4.1: A short version of the MMCA System Specification 4.1.
[33] http://www.mmca.org/compliance/buy_spec/MMCA_System_SummaryV41.pdf
[34] SD Card Physical Layer Specification: Simplified version V1.01.
http://www.sdcard.org/sdio/Simplified Physical

Page | 533 © ISI 2018 Ridha Ghayoula


[35] Layer Specification.PDF
[36] http://www.penseeprofonde.org/images/0/09/Cours_Cmini_PIC.pdf
[37] Programmation des périphériques du microcontrôleur STM32F107VC, M. Dalmau –
IUT de Bayonne Pays-Basque
[38] http://www.st.com/content/ccc/resource/technical/document/user_manual/10/c
5/1a/43/3a/70/43/7d/DM00104712.pdf/files/DM00104712.pdf/jcr:content/translations/
en.DM00104712.pdf
[39] https://www.youtube.com/watch?v=xQPOxOfhZlY
[40] https://www.python.org/downloads/release/python-362/ [archive]
[41] https://www.python.org/downloads/ [archive]
[42] http://www.mouser.fr/new/stmicroelectronics/STM32/
[43] http://www.farnell.com/datasheets/1947285.pdf?_ga=2.158617658.1674811992.15
06654873-1098145787.1506654873
[44] https://www.wikihow.com/Create-a-Project-to-Program-a-PIC-Using-MPLAB-
IDE-V8.56
[45] http://eduscol.education.fr/sti/sites/eduscol.education.fr.sti/files/ressources/pedag
ogiques/1390/1390-tp-initiation-pcb-altium.pdf
[46] http://softasm.com/altium-designer-17-crack/
[47] http://eduscol.education.fr/sti/sites/eduscol.education.fr.sti/files/ressources/pedag
ogiques/1390/1390-tp-initiation-pcb-altium.pdf
[48] http://designcontent.live.altium.com.cn/ReferenceDesignDetail/Eval_board_Sparta
n_III
[49] http://xcotton.pagesperso-orange.fr/electron/coursetdocs.htm
[50] http://www.applelogic.org/CarteBlancheIIProj3.html
[51] http://blog.dev-flow.com/en/12-creating-a-custom-ip-in-vivado/
[52] http://www.applelogic.org/Downloads.html
[53] https://www.xilinx.com/support/documentation/sw_manuals/xilinx2012_3/ug894
-vivado-tcl-scripting.pdf
[54] https://www.redrapids.com/images/documents/REF-002-000-R01.pdf
[55] http://www.linux-france.org/prj/embedded/telechargement/sdcc_course.pdf
[56] https://www.xilinx.com/support/documentation/sw_manuals/xilinx2012_2/ug903
-vivado-using-constraints.pdf
[57] http://fileadmin.cs.lth.se/cs/Education/EDAN15/labs/lab1/vivado_tutorial.pdf
[58] https://www.xilinx.com/support/documentation/sw_manuals/xilinx2012_2/ug903
-vivado-using-constraints.pdf
[59] http://easytp.cnam.fr/alexandre/index_fichiers/support/zynq_cours_tp_vivado_zc
702.pdf
[60] https://www.programiz.com/python-programming/examples
[61] http://www.apprendre-en-ligne.net/python3/2/chapitre2.pdf
[62] http://www.fpgadeveloper.com/2018/03/how-to-accelerate-a-python
function-with-pynq.html
[63] http://www.apprendre-en-ligne.net/python3/2/chapitre2.pdf

Page | 534 © ISI 2018 Ridha Ghayoula

Vous aimerez peut-être aussi