Académique Documents
Professionnel Documents
Culture Documents
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.
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 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 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 23 Vivado Design Suite avec les contraintes XDC ................................................. 493
23.1. Introduction ..................................................................................................................................... 493
23.2. Organisation des contraintes ......................................................................................................... 493
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.
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
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.
le système contrôlé
le système de contrôle
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.
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
Activité de calcul, qui lit ses données et ses entrées lors de son démarrage, qui fournit ses sorties,
puis meurt.
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.
Capteur
d’entrée
Compteur
Horloge
Nombre Max
de places
Capteur
de sortie
Comparateur
≥ <
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.
Niveau_H
Niv_S2_A Niv_S2_B
Niveau_L
Niv_S1_A Niv_S1_B
N Niv_S1_A N
Niv_out
N Niv_S1_B
N
Niv_S2_A N
N Erreur
Niv_S2_B
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.
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
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 ".
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]
Adress_mem
Mémoire Mémoire
clk
Mem_L clk
Mem_LZ
rst 8 7..0 rst (a) 8 7..0
(b)
17..0
9 bits
Adress_mem
Mémoire
clk
Mem_2L
rst 8 7..0
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).
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
Adresse 2 Sector_lobe_2
Adresse n Sector_lobe_n
1 2 8
1 1 1
D Q D Q D Q
0 0 0 OUT
R R R
Clk
Load
Rst
MEM_L
MEM_LZ
MEM_2L
17..0
MEM_L
8 7..0
1i
17..0
MUX
MEM_LZ
8 7..0
8 i
17..0
MEM_2L
8 7..0
Act_L
Act_LZ
Act_2L
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 :
reset
fermer_entree_piece
Clk
FPGA servir_cafe piece
piece_introduite
( Processeur à but activer_cafe1 piece
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.
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”.
Unité de
contrôle
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
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.
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
code
Etat 1 start
CODE
code
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.
a) CODE VHDL
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.
( 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)
VOLmax VILmax
0
0
0 0
Niveaux de sortie circuit 1 Niveaux d’entrée circuit 2
Figure 2.3. Niveaux logiques
50%
t
Figure 2.4. Temps moyen de propagation
Remarque : Ce temps détermine la fréquence maximale FMAX à laquelle les circuits intégrés sont capables de
réagir.
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
Remarque : La documentation constructeur fournie les données suivantes : IOH, IIH, IOL, IIL.
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)
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.
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.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).
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.
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.
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.
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.
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.
Figure 3. RAM Dynamique organisée en matrice 4 x 4 avec son circuit de lecture écriture
- 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.
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
Multiplieur Mqi
2. Déduire la description structurelle ce cet architecture.
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.
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
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
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:
Logique
de READ_STROBE
décodage CLK WRITE_STROBE
RD R_DATA
PicoBlaze
RD R_DATA
RD R_DATA
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.
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 :
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
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] :
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
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
Le picoblaze est un cœur de microcontrôleur 8bits disponible sous forme d’un fichier VHDL :
KCPSM3.VHD
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
Implantation standard utilisant un bloc RAM 1Kx18 pour stocker les instructions
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
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)
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
MicoBlaze
D-LMB AXI4
BRAM AXI
I-LMB interconnect
Block
AXI4-Lite
UARTLITE RS232
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.
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.
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.
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
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.
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.
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.
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
i3.4) Browse to the Lab1 project directory using Windows Explorer. Several directories containing
VHDL wrappers and implementation netlists have been created
i4.3)In Select a workspace window, browse to c:\ .... and click OK.
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
Instr. Port A
CLK
CPU Local
Microblaze memory
RST Data Port B
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
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é.
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.
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.
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.
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é.
À 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é.
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.
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.
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
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
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é ?
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
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
µ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
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
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
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
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
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]
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
Exemple 1: Le PGCD de ces nombres, est le plus grand diviseur commun, c'est-à-dire 1.
PGCD(26;15)=1
Exemple 2: PGCD(96;36)=12
Exemple 3: PGCD(161;14)=7
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.
result[31..0]
32 bits
MUX
sel
output [31..0]
input_reg [31..0]
rst
output_reg [31..0]
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;
Comparateur
!=
x_lt_y
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;
Comparateur
<
x_neq_y
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;
4.2.5. Soustracteur :
x [31..0] y [31..0]
x_neq_y
Soustracteur
rst -
output[31..0]
x_lt_y
x_neq_y
FSM
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;
rst
clk
PGCD
d_o [31..0]
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;
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;
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].
V'
y'
y V
φ
x' x X
Figure 5.1 – Rotation du vecteur V dans le plan cartésien
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
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 :
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.
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
m 1
k a tan 2 k
k sgn z k
x0 1
y0 0
z 0 en radians
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
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;
}
COS SIN
Angle start done
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
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;
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);
ibus_s(31)&ibus_s(31)&ibus_s(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);
ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)&ibus_s(31)
&ibus_s(31)&ibus_s(31)&ibus_s(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;
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
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 :
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);
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 ;
BEGIN
clocked : PROCESS( clk, reset )
BEGIN
IF (reset='0') THEN
state <= s0;
ELSIF (clk'EVENT AND clk = '1') THEN
state <= nextstate;
END IF;
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.
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
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
–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
- Exemple: operation semblable; mais ne retenir que les variables qui contiennent la chaine
HO dans le nom
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 :
Ecran
Fichier
Clavier
Figure 6.1. Notion de redirection
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
Ventes
Vendeur1
Informatique
Tech1
Entreprise
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
–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
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)
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.
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.
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 »:
Code Source
X86
X86 APF27
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
Noyau
kernel headers
Librairies C
Applications
Figure 6.4. Composants de Linux embarqué (c)
Compilateur et librairie C
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
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
Mémoires utilisées
execution
reset/load
i.MAX37
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
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
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
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
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
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);
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.
(b)
Figure 7.1. Architecture du processeur Leon
• 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 ».
• Ensuite dans le menu « processor » nous utilisons le noyau leonFT à tolérance de pannes au lieu de
la norme FT non leon3.
• 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.
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.
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.
• Nous activons « SCSI device support » pour que nous puissions relier des périphériques à notre
ordinateur.
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
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 ?
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é
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
Le matériel dans
son Votre
environnement Client
operationnel
Vous
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…)
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…
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.
"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."
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 .
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>
http://eduscol.education.fr/sti/sites/eduscol.education.fr.sti/files/ressources/pedagogiques/4346/4346-7-rpi-
serveur-web.pdf
À 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.
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.
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 :
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.
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.
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.
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 :
Le reste des menus n'est pas intéressant pour l'instant, on y reviendra plus tard, avant de commencer
à programmer.
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
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 :
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;
{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},
};
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();
}
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
/*
unsigned char i;
unsigned char j;
/*Port Definitions*/
int Max7219_pinCLK = 10;
int Max7219_pinCS = 9;
int Max7219_pinDIN = 8;
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);
}
}
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
1.25 ms = 0 degré
1.50 ms = 90 degrés
1.75 ms = 180 degrés
Centré
10 à 20ms
1 ms
-45 deg
10 à 20ms
2 ms
45 Deg
10 à 20ms
5V
GND
USB
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 );
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;
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 );
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
}
10.1. Introduction
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
UART_RX UART_TX
TX
Registre a decalage
Générateur
d'horloge
RX
Registre a decalage
Clock
Registre de reception
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
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;
begin
case r_SM_Main is
end rtl;
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;
begin
case r_SM_Main is
end case;
end if;
end process p_UART_TX;
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;
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
-- 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
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,
process is
begin
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.
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.
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)
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
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()
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
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
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
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
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
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
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
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
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
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 :
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
SCLK SCLK
MISI MISI
7 0 SS SS 7 0
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.
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
SCLK
MOSI SPI
MISI Slave
SS
SCLK
MOSI SPI
MISI Slave
SS
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.
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.
Figure 12.7. Simulation of FSM_CTRL module character sending followed by escape sequences
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;
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 :
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 , ...).
+5v
I2C
SDA
BUS SCL
Slave_01 Master_02
Ox34 OxXX
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
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
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
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.
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.
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
SDAR
A6 A5 A4 A3 A2 A1 A0 A D7 D6 D5 D4 D3 D2 D1 D0 A
R/W C C
K K
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.
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
SDAR
A6 A5 A4 A3 A2 A1 A0 A D7 D6 D5 D4 D3 D2 D1 D0 A
R/W C C
K K
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 :
Il relira forcément '0' et continuera à transmettre. Il ne peut pas alors détecter un éventuel
conflit.
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.
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)
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.
Après l'émission d'un appel général, les circuits ayant la capacité de traiter ce genre d'appel émettent
un acquittement.
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.
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
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.
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
end.
-- 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;
-- input signals
start,
-- 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
--
case (state) is
-- idle
when idle =>
case cmd is
when CMD_START =>
nxt_state := start_a;
icmd_ack := '1'; -- command completed
---------------------------------------------------------------------
---- ----
---- 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
--
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
--------------------------------------------------------------------- ----
---- 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)
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;
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
--------------------------------------------------------------------
---- ----
---- 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
);
begin
-- generate internal reset signal
rst_i <= arst_i xor ARST_LVL;
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;
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
istart := '0';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := x"AC";
end if;
istart := '0';
istart := '1';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := (slave_addr & '0'); -- write to slave (R/W = '0')
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
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;
istart := '0';
iread := '1';
iwrite := '0';
iack := '0'; --ACK
istop := '0';
end if;
-- 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;
-- 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;
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)
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
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
istart := '0';
iread := '1';
iwrite := '0';
iack := '0'; --ACK
istop := '0';
end if;
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;
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.
b0 b1 b2 bN
y[n]
∑ ∑ ∑
∑
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ù xi 1in représente les valeurs du signal d'entrée et yi 1in les valeurs du signal de sortie.
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
b0 b1 b2 bN
y[n]
∑ ∑ ∑
∑
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;
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.
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
Dans cet exemple les accolades sont superflues, il n’y a qu’une instruction dans la boucle)
Do {instructions} while (expression), comme while mais la boucle est effectuée au moins
une fois
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)
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.
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
15.13. Union
Dans une UNION les champs partagent les mêmes adresses.
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
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
Soit 0x5A
Un bit supplémentaire est nécessaire pour indiquer le signe (+/-)
Sm se En E0 Mm M0
Compilateur: Programmateur
Fabriqué le programme Transfert le programme
du PC au PIC (hard+soft)
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.
Dans le menu Project, sélectionner Project Wizard. Cela lance un assistant permettant de
Définir certaines options du projet.
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.
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".
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.
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.
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).
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
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 :
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
Déconnexion
Enfin, pour fermer la connexion, il y a la fonction close() de BluetoothSocket :
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.
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.
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.
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 ).
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
Le paramètre désigne le port à réinitialiser. Il peut prendre les valeurs : GPIOA , GPIOB , GPIOC ,
GPIOD ou GPIOE
Avant d'être utilisée par GPIO_Init cette structure doit être initialisée par la fonction
GPIO_StructInit définie comme suit :
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é.
Le paramètre désigne le port à lire. Il peut prendre les valeurs : GPIOA , GPIOB , GPIOC ,
GPIOD ou GPIOE
Le paramètre désigne le port à lire. Il peut prendre les valeurs : GPIOA , GPIOB , GPIOC ,
GPIOD ou GPIOE
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
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
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)
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 +
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
Remarque : lors de l'étape 5 on peut désigner plusieurs lignes si elles doivent être programmées dans le même mode.
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 :
Les procédures d'interruption ont des noms prédéfinis du type : xxx_IRQHandler (voir tableau
).
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
Avant d'être utilisée par EXTI_Init cette structure doit être initialisée par la fonction
EXTI_StructInit définie comme suit :
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)
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.
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.
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 :
Le premier paramètre désigne le timer à initialiser. Il peut prendre les valeurs : TIM1 à
TIM7
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).
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.
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.
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
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
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.
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 :
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 :
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).
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 :
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
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
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 :
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 :
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 :
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 | ) :
Le premier paramètre désigne le timer pour lequel on veut lire un indicateur. Il peut prendre
les valeurs : TIM1 à TIM7
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 + .
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.
La ligne utilisée pour la commande du timer 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 .
Avant d'être utilisée par ADC_Init cette structure doit être initialisée par la fonction
ADC_StructInit définie comme suit :
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
• 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
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)
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
Le premier paramètre désigne le convertisseur dont on configure les seuils. Il peut prendre
les valeurs : ADC1 ou ADC2
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
Les deux paramètres sont les mêmes que pour la fonction précédente.
Avant d'être utilisée par DAC_Init cette structure doit être initialisée par la fonction
DAC_StructInit définie comme suit :
Avant d'utiliser la fonction pour initialiser un convertisseur il faut remplir les champs de cette
structure en utilisant valeurs suivantes :
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.
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.
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
... ...
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
... ...
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.
Embedded
ST-LINK/V2-1
SWD
B1
USER
I/O I/O
STM32
Micocontroller
Arduino connector
Arduino connector
I/O I/O
RST
B2 LED
RESET LD2
MCU Part
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).
• Calcul de la consommation d'énergie pour une séquence d'application définie par l'utilisateur
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
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.
CortexTM-M
Processsor Core
Peripheral
NMI
NVIC
IRQs System
Configuration Exceptions
Peripherals registers
Bus Interface
Code Generator
Download Function
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.
FREERTOS Configuration
Ensuite, dans Software time definitions changer USE_TIMERS: Enabled
Project
Dans SYS selectionner Timebase source - TIM1
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.
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.
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).
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).
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:
Exécuter la simulation
- Générer le netlist (pour vérifier le schéma)
- Lancer la simulation
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)
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.
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).
Document de Schématique
Saisie de la schématique
Lien symboles-
empreintes
Vérification
électronique (ERC)
Placement
Composants/Routage
PCB
Vérification Routage
(DRC)
Ficher de sortie
● 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 »...).
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.
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 ).
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.
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
Les fonctions de base pour manipuler les composants sont toujours efficientes :
Pour faire pivoter un composant Barre espace
Pour ZOOMER la carte à router :
Et le PCB :
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é
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.
nanoBroad FPGA
Concepts Instruments
Advanced
Compoments Simulation
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.
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.
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
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
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.
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.
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.
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.
Ensuite, dans votre projet initial, si vous allez dans le catalogue IP («Window > IP catalog»), vous
devriez voir la fonction_logique IP sous UserIP.
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.
· 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».
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.
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.
Dans «Edit IP Parameter», activez «Specify Range» et sélectionnez «Range of Integer» pour «Type».
Entrez «32» comme valeur maximale et cliquez sur OK.
Dans la section « Customization GUI », passer le paramètre « Data Size”» sous « Page 0".
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.
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
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.
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.
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.
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:
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.
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.
Hello, world!
Programme Python pour calculer la racine carrée
area = √(s(s-a)*(s-b)*(s-c))
En Python, nous pouvons implémenter une matrice en tant que liste imbriquée (liste dans une liste).
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.
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.
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
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.
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
À 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:
• É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.
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.
À 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.
Étape 6:
Ecrit un flux de bits (bitstream)pour tester et programmer la conception sur le FPGA Xilinx.
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:
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:
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:
Recherche de 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é.
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.
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:
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.
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.
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.
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.
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.
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.
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.
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.
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.
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;
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;
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.
Cela ouvre la boîte de dialogue Modifier les propriétés du périphérique. Sélectionnez Encryption
dans le volet de gauche.
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.
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.
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).
• 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.
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).
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.)
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.
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.
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é).
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:
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.
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.
Vivado
database
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.
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.
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.
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.
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)
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.
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
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.
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.
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.
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
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.
note Remarque La fenêtre Détails IP peut être affichée en cliquant sur les touches CTRL + Q du clavier.
À 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.
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.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.
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.
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.
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é.
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.41. 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.
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.