Option Electronique Digitale (I11) -...
Transcript of Option Electronique Digitale (I11) -...
Université de Nice Sophia-Antipolis Année 2005-2006Master STIC 1ère année Informatique
Option Electronique Digitale (I11)
Laurence PIERRE([email protected])
L'objectif de ce cours, conçu pour un public d'étudiants informaticiens, est de
proposer une découverte de quelques techniques et outils utilisés dans un
environnement de CAO de circuits, il peut servir de préambule au cours de Master
2 "Modélisation et validation des systèmes numériques" (Master 2 STIC, spécialité
Systèmes Embarqués).
2
PLAN DU COURS
I. Introduction - Présentation 4
II. Rappels 7
II.1 Algèbre de Boole
II.2 Synthèse de circuits combinatoires
III. CAO de circuits et langages 11
III.1 Synthèse et simulation
III.2 Langages de description de matériel
IV. VHDL. Entités et architectures 17
IV.1 Premières notions
IV.2 Types et opérateurs
IV.3 Configurations, entités de test
V. VHDL. Instructions concurrentes simples 27
V.1 Signaux et variables
V.2 Instructions concurrentesV.2.1 Affectation concurrente de signal
V.2.2 Affectations conditionnelles
V.2.3 Instanciation de composant
V.2.4 Generate
V.2.5 Block
VI. Circuits séquentiels synchrones 34
VI.1 Machines de Mealy et de Moore
VI.2 Equivalence entre ces deux modèles
3
VII. Méthodes associées 42
VII.1 Optimisation
VII.2 SynthèseVII.2.1 Principe
VII.2.2 Codages
VIII. VHDL. Descriptions comportementales 54
VIII.1 Instruction process
VIII.2 Instructions séquentiellesVIII.2.1 Wait
VIII.2.2 Instructions conditionnelles
VIII.2.3 Boucles
VIII.3 SimulationVIII.3.1 Boucle de simulation
VIII.3.2 Pilotes, affectations en mode inertiel
VIII.3.3 Retards delta
IX. Descriptions d'automates 66
IX.1 Constructions utilisées
IX.2 Synthèse de descriptions VHDL
4
I. INTRODUCTION - PRESENTATION
La conception d'un circuit digital, depuis son cahier des charges jusqu'à l'ultime
processus de fabrication, met en oeuvre une panoplie de méthodes.
dessin extrait de http://www-fr.netapp.com/solutions/se-manu.html
A partir d'une spécification relativement informelle du système à construire, une
formalisation à l'aide d'un langage ad hoc (il s'agit souvent d'un langage spécialisé
pour la description de systèmes matériels, comme VHDL, Verilog,...) pourra servir
d'entrée aux divers outils offerts par un environnement de CAO de circuits.
Les simulateurs peuvent fournir des chronogrammes traduisant l'évolution dusystème dans le temps, suivant diverses séquences d'entrées.
5
Les outils de synthèse permettent de produire des descriptions du système de moins
en moins abstraites et de plus en plus détaillées, en vue de la réalisation matérielle.
Nous proposerons dans ce cours une introduction à l'un des langages standard
IEEE pour la description de systèmes matériels, le langage VHDL , et nous
étudierons les aspects simulation et synthèse dans le contexte de la conception de
machines d'états finis.
Le dessin ci-dessous illustre les points abordés.
Nous étudierons les techniques utilisées lors de la spécification du comportement
d'un système digital sous la forme d'une machine d'états :
- l'automate considéré peut être une machine de Moore ou une machine de
Mealy , nous rappellerons ces définitions et illustrerons sur quelques
exemples, puis nous décrirons comment un modèle de type Moore peut être
transformé en un modèle de type Mealy équivalent et vice-versa.
- nous aborderons également les techniques liées à l'optimisation d'une machine
6
d'états.
- enfin, nous verrons comment réaliser la synthèse, à partir d'une machine
d'états, d'une description du circuit sous forme d'une interconnexion de portes
logiques et de registres.
Chacun de ces niveaux de spécification sera associé à une description VHDL : une
machine d'états est décrite en VHDL au niveau de description dit comportemental,
et un circuit synthétisé sous forme d'une interconnexion de portes logiques et de
registres correspond à une description VHDL dite structurelle ou flot de données.
7
II. RAPPELS
Rappelons tout d'abord quelques notions élémentaires concernant la conception de
circuits combinatoires.
II.1 Algèbre de Boole
L'analyse du comportement des circuits logiques repose sur la logique booléenne,
dans laquelle les variables ne peuvent prendre que les valeurs binaires 0 et 1,
souvent assimilée à l'algèbre de Boole (de George Boole, mathématicien anglais,
1815-1864), voir par exemple http://en.wikipedia.org/wiki/Boolean_algebra
pour une présentation plus complète.
Chaque porte logique (NON, ET, OU, NAND, NOR, XOR) réalise une fonction
qu'on caractérise généralement par une table de vérité qui donne la valeur de sa
sortie en fonction des valeurs des entrées.
Exemples :
x z
x z = not(x)
01
10
x y z = x and y
0
110
00
1 1
0001
xy z
Les expressions logiques construites à base des opérateurs NON, ET, et OU,
peuvent être simplifiées grâce à un certain nombre de lois de l'algèbre de Boole.
8
Ceci peut notamment permettre de réduire le nombre de portes logiques dans un
circuit et donc de minimiser son coût.
Ces lois sont les suivantes :
commutativité : a . b = b . a a + b = b + a
associativité : (a.b).c = a.(b.c) (a+b)+c = a+(b+c)
distributivité : a+(b.c) = (a+b).(a+c) a.(b+c) = (a.b)+(a.c)
idempotence : a . a = a a + a = a
lois d'identité : 1 . a = a 0 + a = a
lois de nullité : 0 . a = 0 1 + a = 1
lois d'inversion : a . not(a) = 0 a + not(a) = 1
lois d'absorption : a. (a + b) = a a + (a . b) = a
lois de De Morgan : not(a . b) = not(a) + not(b)
not(a + b) = not(a) . not(b)
II.2 Synthèse de circuits combinatoires
On se pose le problème suivant : à partir de l'expression informelle de la fonction
logique qu'on veut réaliser, comment faire la synthèse du circuit correspondant ?
On procède de la façon suivante :
1. on exprime, pour chaque combinaison possible des entrées, la valeur que l'on
souhaite avoir sur la sortie, c'est à dire qu'on construit la table de vérité (une
alternative consiste à utiliser le modèle des tables de Karnaugh).
2. on en dérive une expression algébrique, soit sous forme d'une somme de
produits ("minterms") soit sous forme d'un produit de sommes ("maxterms").
9
Obtention d'une somme de produits : on considère les lignes de la table de
vérité pour lesquelles la sortie vaut 1. Dans chaque produit, les variables
d'entrée qui ont la valeur 1 sont prises telles quelles et les autres sont
complémentées.
Obtention d'un produit de sommes : on considère les lignes de la table de vérité
pour lesquelles la sortie vaut 0. Dans chaque somme, les variables d'entrée qui
ont la valeur 0 sont prises telles quelles et les autres sont complémentées.
3. si possible, on simplifie cette expression, par exemple en utilisant les théorèmes
de l'algèbre de Boole vus précédemment.
4. on construit le circuit en utilisant les portes logiques correspondant aux
opérateurs de l'expression, ou en utilisant une bibliothèque donnée de portes
logiques.
Par exemple, dans le cas où on obtient les expressions
y = (c and d) or (e and f) et z = (a and b) or y
le circuit correspondant est naturellement le suivant
ab
cdef
x
y
z
Mais dans le cas où on dispose d'une bibliothèque de portes NAND et NOT, on
pourrait obtenir
ab
cdef
x
y
z
car y = (c and d) or (e and f) = (c nand d) nand (e nand f)
10
et z = (a and b) or y = (a nand b) nand (not y)
Exemple de synthèse : étant données 3 entrées A, B et C, la fonction qu'on souhaite
réaliser pour la sortie S est la suivante : S ne vaut 1 que lorsqu'un nombre impair
d'entrées est à 1.
1. Construction de la table de vérité :
A B C S
0 0 0 00 0 1 10 1 0 10 1 1 01 0 0 11 0 1 01 1 0 01 1 1 1
2. Construction de l'expression associée sous forme d'une somme de produits :
S = (not A).(not B).C + (not A).B.(not C) + A.(not B).(not C) + A.B.C
3. Transformation (simplification) :
S = (not A).((not B).C + B.(not C)) + A.(B.C + (not B).(not C))
= (not A).(B xor C) + A.(B equ C)
= (not A).(B xor C) + A.(not(B xor C))
= A xor B xor C
4. Circuit :AB C
S
Ces principes vont s'étendre au cas des circuits séquentiels, dans la section VII.
11
III. CAO DE CIRCUITS ET LANGAGES
III.1 Synthèse et simulation
Un système matériel complexe (circuit imprimé) regroupe une grande variété de
composants. La conception de certains composants nécessite la synthèse de blocs
fonctionnels, où l'on trouve des éléments de base (portes, multiplexeurs, flip-
flops,...).
Remarquons qu'à partir d'une spécification du comportement attendu pour un
système matériel, il est possible de réaliser sa synthèse sous forme d'ASIC
(Application Specific Integrated Circuit) ou de procéder à une synthèse sur FPGA
(Field Programmable Gate Array).
Un FPGA est un circuit qui peut être (re)programmé après sa fabrication. Il se
présente par exemple comme suit (dessin provenant de http://euler.ecs.
umass.edu/ece655/simulator/FPGA/help.html) :
12
Ses blocs logiques configurables (CLBs) peuvent prendre la forme suivante (dessin
provenant de http://www-inst.eecs.berkeley.edu/~cs150/sp00/) :
La LUT (Look-Up Table) est un élément combinatoire qui peut réaliser n'importe
quelle fonction booléenne. Le flip-flop peut permettre, si nécessaire, de mémoriser
1 bit.
Nous nous intéresserons par la suite à la synthèse de blocs fonctionnels spécifiés
sous la forme de machines d'états finis. La conception s'effectue au sein d'un
environnement de CAO de circuits. La démarche est la suivante :
- la machine d'état est décrite à l'aide d'un langage de description de matériel
- cette description comportementale peut être simulée
13
- par synthèse, une description de type "netlist" (interconnexion de portes et
registres) peut être obtenue
- la description synthétisée peut à son tour être simulée, sur les mêmes jeux
d'essais que ceux utilisés sur la description initiale, afin de vérifier que les
résultats de simulation sont identiques (timing compris).
Avant d'étudier le langage de description VHDL, et son mécanisme de simulation,
donnons une vision intuitive de la simulation dirigée par événements (event-driven
simulation). Le petit circuit ci-dessous contient 3 portes logiques, de temps de
traversée 2ns, 5ns et 4ns. Voyons l'évolution de ce système suivant les événements
(changements de valeurs) s'y produisant, si l'on fait passer l'entrée A à 0 au temps
20 ns :
14
10 nsA
B
S2ns
5ns
4ns
1
01
10
22 ns1
A
B
S2ns
5ns
4ns
1
0 1
26 ns1
1A
B
S2ns
5ns
4ns
1
0 1
27 ns0
A
B
S2ns
5ns
4ns
1
0 1
31 ns 00
A
B
S2ns
5ns
4ns
1
0 1
15
III.2 Langages de description de matériel
Les langages de description de matériel (Hardware Description Languages) ont vu
le jour à la fin des années 1960, dans le but de décrire et simuler les circuits. Entre
1968 et 1975, il y a eu prolifération de langages (et simulateurs), couvrant divers
niveaux d'abstraction.
Une première tentative de standardisation a eu lieu à partir de 1973, avec le projet
CONLAN (CONsensus LANguage). A l'heure actuelle, il existe deux standards
IEEE : Verilog et VHDL.
Généralement, les langages de description de matériel offrent plusieurs des niveaux
de description suivants :
- algorithmique : modélisation de l'algorithme que le circuit doit réaliser
- comportemental (ou système) : modélisation du comportement du circuit
(automate, réseau de Pétri,...)
- transfert de registres (RTL) : modélisation du circuit par des équations (qui
expriment la mise à jour des registres)
- portes logiques : modélisation comme une interconnexion de portes logiques
(peut être hiérarchique : interconnexion de composants eux-mêmes intercon-
nexions de portes logiques)
- transistors
Verilog (http://www.verilog.com/) est né au début des années 1980 (Gateway
Design Automation), avec le simulateur logique Verilog-XL. Il a été mis dans le
domaine public en 1990 par Cadence (acquéreur de Gateway Design Automation),
puis standardisé par l'IEEE en 1995 (IEEE Std. 1364-1995).
Il propose les niveaux de description algorithmique, RTL, portes logiques et
transistors.
16
Le développement de VHDL a été entrepris en 1981 par le Département de la
Défense des USA (DoD), des industriels ont été largement impliqués dans le
processus de standardisation. Le premier manuel de référence a été rédigé fin 1984,
et les premiers outils ont été proposés en 1986 (vraiment disponibles en 1988). Il a
été standardisé par l'IEEE en 1987, une révision a eu lieu en 1993.
Il propose les niveaux de description algorithmique, RTL et portes logiques.
17
IV. VHDL. ENTITES ET ARCHITECTURES
IV.1 Premières notions
VHDL signifie VHSIC (Very High Speed Integrated Circuits) Hardware
Description Language. Il a été conçu avec des objectifs de documentation et de
simulation, sa sémantique est donc décrite en termes du moteur de simulation
dirigée par événements, diverses constructions ne sont pas synthétisables. Nous
étudions ci-dessous une partie de VHDL'87.
Une description VHDL se compose d'une déclaration d'entité et d'une ou plusieurs
architectures, se situant généralement à des niveaux d'abstraction différents.
La déclaration d'entité décrit essentiellement l'interface (les ports d'entrée/sortie).
Elle peut aussi spécifier des paramètres génériques qui permettent de modéliser des
familles de circuits (paramètres de temps, taille des ports, nombre de composants
utilisés,…). Sa forme, légèrement simplifiée, est la suivante :
entity nom is generic (paramètres-génériques);
port (ports d'entrées/sorties); déclarations diverses: types, constantes…;end nom;
Les ports d'entrées/sorties peuvent être spécifiés :
- in : ports d'entrée, ne peuvent pas être modifiés- out : ports de sortie, ne peuvent pas être lus- inout : ports bidirectionnels, servant en entrée et en sortie- buffer : ports de sortie pouvant être lus
Exemple : additionneur 1 bit
entity full_adder is port(X,Y,Cin : in Bit; -- ports d'entrée Sum,Cout : out Bit); -- ports de sortie end full_adder;
18
Les paramètres génériques peuvent être de n'importe quel type, avoir une valeur
par défaut, et ils sont considérés comme des constantes.
Exemples :
entity Add_N_bit is generic(N: Natural); port(A,B: in Bit_vector(N downto 1); Cin: in Bit; S: out Bit_vector(N downto 1); Cout: out Bit); end Add_N_bit;
entity async_transmitter is generic(Bit_time: time := 20 ms); port(parallel_in: in bit_vector (7 downto 0); load: in bit; serial_out : out bit := '0'; done : out bit := '1'); end async_transmitter;
Les architectures permettent de décrire le comportement ou la structure des
composants représentés par les entités. Plusieurs architectures, éventuellement
données à différents niveaux d'abstraction, peuvent être associées à une même
entité. Trois styles de description peuvent être utilisés en VHDL :
- le style "structurel" : interconnexion de composants, chacun d'eux étant une
instance de couple entité/architecture
- le style "dataflow" (s'apparente au niveau d'abstraction RTL) : ensemble
d'instructions sur signaux qui décrivent les connexions entre portes logiques
et les chargements de registres
- le style "comportemental" : ensemble de processus qui expriment le
comportement du système
Une définition d'architecture a la forme suivante :
architecture nom of nom-entité is déclarationsbegin
19
instructions-concurrentesend nom;
Dans la partie déclarations peuvent se trouver des déclarations de types, de
constantes, de fonctions et procédures, de composants, et de signaux. On ne peut
pas trouver de déclarations de variables (VHDL'87).
Attention, Les instructions se trouvant dans une architecture sont toutes des
instructions concurrentes.
Exemple :
x
y
cin sum
cout
architecture Structure_view of full_adder is-- déclaration des composants utilisés :
component Half_adder port(I1,I2: in Bit; Carry,Sum: out Bit); end component;
component Or_gate port(I1,I2: in Bit; O: out Bit); end component;-- déclaration des "signaux" internes :
signal A,B,C : Bit;begin U1: Half_adder port map(X,Y,A,B); U2: Half_adder port map(B,Cin,C,Sum); U3: Or_gate port map(A,C,Cout);end Structure_view;
Dans le style structurel, on décrit une hiérarchie de composants interconnectés.
Les communications se font par les interfaces (ports d'E/S), les interconnexions
sont exprimées par les port map. Les composants utilisés doivent faire l'objet
d'une configuration (voir plus loin).
20
xy
cin sum
cout
architecture Dataflow_view of full_adder is signal S : Bit;begin
S <= X xor Y after 5 ns; Sum <= S xor Cin after 5 ns; Cout <= (X and Y) or (S and Cin) after 20 ns;
end Dataflow_view;
Ici la description traduit les équations caractéristiques du circuit, les temps de
traversée des portes correspondant aux opérateurs utilisés peuvent être explicités.
IV.2 Types et opérateurs
Quelques conventions lexicales : les identificateurs sont formés de lettres, chiffres
et "_". Ils commencent par une lettre, deux "_" ne peuvent pas se suivre, il n'y a
pas de distinction entre les majuscules et les minuscules. Les entiers peuvent être
écrits en base 10, 2, 8 ou 16, par exemple 2#00110#, 8#3607#, 16#07FF#. Les
caractères sont placés entre quotes, et les chaînes de caractères entre guillemets.
Les principaux types prédéfinis sont :
- les entiers (integer), les entiers naturels (natural), les entiers positifs
(positive)
- les réels (real)
- les caractères (character) et les chaînes de caractères (string)
- les booléens (boolean) : false, true
- les bits (bit) : '0', '1'
- les vecteurs de bits (bit_vector), par exemple B"1101"
21
Un type utilisateur peut être défini de la façon suivante :
Type Nom is Définition;
On peut notamment définir des types intervalles (range) et tableaux (array). Les
tableaux peuvent avoir plusieurs dimensions, chacune d'elles étant d'un type
discret, ils peuvent être contraints (bornes spécifiées) ou non contraints (bornes
non spécifiées).
Exemples :
Type Byte is range -128 to 127; Type Bit_position is range 7 downto 0;
Type Word is array(15 downto 0) of Bit;
Type Column is range 1 to 80; Type Row is range 1 to 24; Type Matrix is array(Row, Column) of Boolean;
Type Bit_vector is array(Natural range <>) of Bit; Type String is array(Positive range <>) of Character;
Il est possible de faire référence à un élément d'un tableau ou à toute une "tranche"
(pour un tableau unidimensionnel), par exemple :
signal M: Matrix;
ici M est la matrice entière et M(20,35) est un élément
Type Byte is array(7 downto 0) of Bit; signal Octet: Byte;
Octet(6 downto 4) est une "tranche" de 3 éléments du tableau Octet.
Enfin, notons la possibilité de définir des types énumérés, par exemple :
Type three_level_logic is ('0','1', 'Z');
22
Les opérateurs de VHDL sont les suivants, rangés par catégorie :
- opérateurs arithmétiques :
+ plus unaire , addition
- moins unaire, soustraction
*, / multiplication, division
rem,mod reste de la division entière(x rem y a le signe de x, et x mod y le signe de y)
** puissance
abs valeur absolue
- opérateurs relationnels :
= égal
/= différent
<, <= inférieur, inférieur ou égal
>, >= supérieur, supérieur ou égal
- opérateurs logiques :
and et
or ou
nand non et
nor non ou
xor ou exclusif
not négation
- opérateur de concaténation (pour les caractères, chaînes de caractères, bits, et
tous tableaux uni-dimensionnels) : &
23
IV.3 Configurations, entités de test
Nous reviendrons plus loin sur l'instruction d'instanciation de composant, utilisée
dans le style structurel. Voyons les configurations, qui permettent de spécifier les
couples entités/architectures choisis pour instancier des composants.
Une spécification de configuration peut être simplement placée dans l'architecture
même. Elle a la forme suivante :
for instance(s)_de_composant : nom_composant use entity
nom_library.nom_entité(nom_architecture);
Alternativement, on peut faire appel à une unité de conception configuration, qui a
la forme ci-dessous :
configuration nom of nom_entité is for nom_arch for instance(s)_de_composant : nom_composant use entity
nom_library.nom_entité(nom_architecture); end for;
... end for;
...end nom;
Cela est utile si l'on souhaite retarder le choix de configuration et/ou avoir
plusieurs configurations pour une même architecture; nom_arch est généralement
un nom d'architecture (mais peut être une étiquette de block ou de generate, voir
plus loin).
Exemple : reprenons le petit exemple illustratif vu à la page 14
24
A
B
S2ns
5ns
4nsS1
S2
L'entité correspondante est la suivante : entity Exemple is port(a,b: in Bit; s: out Bit); end Exemple;
Une description totalement dataflow ne nécessite pas de configuration :
architecture RTL of Exemple is signal s1,s2: Bit;
begin s1 <= not a after 2 ns; s2 <= s1 nand b after 5 ns; s <= s1 and s2 after 4 ns; end RTL;
Voyons maintenant une description mixte structurelle/dataflow, avec configuration
incorporée :
entity porteET is port(x,y: in bit; s: out bit); end porteET;
architecture RTL of porteET is begin s <= x and y after 4 ns; end RTL;
entity porteNAND is port(x,y: in bit; s: out bit); end porteNAND;
architecture RTL of porteNAND is begin s <= x nand y after 5 ns; end RTL;
architecture Struct of Exemple is -- déclaration des composants utilisés : component porteET port(x,y: in bit; s: out bit);
end component; component porteNAND port(x,y: in bit; s: out bit);
25
end component; -- configuration : for P1:porteET use entity work.porteET(RTL); for P2:porteNAND use entity work.porteNAND(RTL); -- déclaration des "signaux" internes :
signal s1,s2: Bit; begin s1 <= not a after 2 ns; P1: porteET port map(s1, s2, s); P2: porteNAND port map(s1, b, s2); end Struct;
Alternativement, une unité de conception spécifique peut être utilisée :
architecture Struct of Exemple is component porteET port(x,y: in bit; s: out bit); end component;
component porteNAND port(x,y: in bit; s: out bit); end component; signal s1,s2: Bit;
begin s1 <= not a after 2 ns; P1: porteET port map(s1, s2, s); P2: porteNAND port map(s1, b, s2); end Struct;
configuration Config1 of Exemple is for Struct -- pour l'architecture Struct de Exemple for P1: porteET use entity work.porteET(RTL); end for; for P2: porteNAND use entity work.porteNAND(RTL); end for; end for; end Config1;
Dans ce second cas, lorsqu'une instance de Exemple sera à son tour utilisée, la
configuration mettra en jeu use configuration au lieu de use entity : for E:Exemple use configuration work.Config1;
au lieu de for E:Exemple use entity work.Exemple(Struct);
26
Remarque : les packages peuvent être utilisés pour rassembler des déclarations
(types, constantes,...) et des définitions de sous-programmes. Les déclarations de
composants peuvent également être placées dans un package, nous n'aborderons
pas cette possibilité ici.
La simulation nécessite préalablement la définition d'une entité de test, sans port.
Celle-ci comporte une instance du composant que l'on veut tester, et des
instructions qui spécifient les jeux d'essai souhaités (valeurs à affecter aux ports
d'entrée). Lors de la simulation, on observera le comportement des ports de sortie,
voire des signaux internes.
Exemple :
entity testExemple is end testExemple;
architecture test1 of testExemple is component Exemple port(a,b:in bit; s:out bit); end component; signal x,y,w: bit; for E:Exemple use entity work.Exemple(Struct); -- ou -- for E:Exemple use configuration work.Config1; begin E: Exemple port map(x,y,w); x <= '1' after 4 ns, '0' after 20 ns; y <= '1' after 4 ns, '0' after 35 ns; end test1;
27
V. VHDL. INSTRUCTIONS CONCURRENTES SIMPLES
V.1 Signaux et variables
Nous avons déjà mentionné que les architectures VHDL ne contiennent que des
instructions concurrentes. Ces instructions mettent en jeu des signaux.
L'une de ces instructions, le process (voir plus loin), contient des instructions
séquentielles qui peuvent utiliser des variables. Il s'agit de variables au sens
classique des langages de programmation. Une variable est déclarée grâce au mot-
clé variable, elle a un type et une valeur. L'instruction d'affectation de variable
est notée :=
Un signal représente un élément de connexion (fil, bus,…), et peut dans certains
cas représenter un registre. Ce concept est donc plutôt lié à la notion d'instruction
concurrente. Un signal est déclaré grâce au mot-clé signal, il a un type, une
valeur courante, ainsi qu'un historique. Variables et signaux peuvent échanger des
valeurs, pourvu que leurs types soient les mêmes.
Des attributs sur signaux sont prédéfinis, ils correspondent à des caractéristiques
dynamiques du signal auquels ils se rattachent. L'utilisation d'un attribut se fait de
la façon suivante : nom-du-signal'nom-attribut
Voyons quelques attributs, assez couramment utilisés (illustrés sur un exemple ci-
dessous) :
- event : booléen, qui vaut true si un événement vient de se produire sur le
signal (changement de valeur)
- delayed(t) : signal implicite, identique au signal auquel l'attribut est
appliqué, retardé d'un temps t
28
- stable(t) : signal implicite de type booléen, qui prend la valeur false
chaque fois qu'un événement s'est produit sur le signal depuis un temps
inférieur à t
1 2 3 4 5 6 7 8 9 10 11
S
S'delayed(1ns)
S'stable(2ns)
V.2 Instructions concurrentes
V.2.1 Affectation concurrente de signal
Cette instruction est essentiellement utilisée dans le style dataflow, sa syntaxe
simplifiée est la suivante :
signal <= exp1 after expression-temporelle1, exp2 after expression-temporelle2, ... ;
La clause after peut être absente. Dans le cas où l'on spécifie plusieurs valeurs à
affecter successivement, ces clauses doivent être présentes et les expressions
temporelles doivent correspondre à des temps croissants, par exemple :
x <= 3 after 1 ns, 0 after 3 ns, 2 after 7 ns;
Attention, placée hors d'un process, cette instruction est concurrente. En
particulier, l'ordre dans lequel ces instructions sont écrites dans le corps de
l'architecture n'a aucune importance.
29
Exemple : supposons que a , b et c soient trois signaux entiers dont les valeurs
courantes sont respectivement 6, 13 et 4. Après exécution des instructions
a <= b+c;b <= a;
la valeur du signal a sera 17, et celle du signal b sera 6.
V.2.2 Affectations conditionnelles
L'instruction concurrente d'affectation de signal peut prendre une forme
conditionnelle et une forme sélective. L'affectation conditionnelle se présente
comme suit :
signal <= exp1 when condition1 else exp2 when condition2 else ... expN-1 when conditionN-1 else expN;
Elle permet le choix de la source du signal, la source choisie correspond à la
première condition booléenne évaluée à vrai. Le dernier else est obligatoire.
Chaque expi peut être de la forme :
expr1 after expr-temp1, expr2 after expr-temp2,...
Une expression expi égale à null signifie qu'il n'y a pas de changement devaleur.
Exemple :
entity DFF is port(Preset, Clear, Cl, D: in Bit; Q, QBar: out Bit); constant Delay: Time := 5 ns;end DFF;
architecture Simple of DFF issignal Q1: Bit;begin Q1 <= '0' after Delay when Clear = '1' else '1' after Delay when Preset = '1' else
30
D after Delay when Cl = '1' else Q1; Q <= Q1; QBar <= not Q1;end Simple;
L'affectation sélective a la syntaxe suivante :
with expression select signal <= exp1 when choix1, exp2 when choix2, ... expN when choixN;
Elle permet le choix de la source du signal suivant la valeur d'une expression.
Chaque expi peut prendre la même forme que ci-dessus. Chaque choixi peut
être de la forme : un-choix1 | un-choix2 | un-choix3 ...
Enfin choixN peut prendre la valeur others, ce qui signifiera "dans tous les
autres cas".
Exemple :
entity Decoder is port(Sel: in Bit_vector(2 downto 0) ; Dout: out Bit_vector(7 downto 0)); constant Delay: Time := 5 ns;end Decoder;
architecture Selection of Decoder isbegin with Sel select Dout <= "00000001" after Delay when "000", "00000010" after Delay when "001", "00000100" after Delay when "010", "00001000" after Delay when "011", "00010000" after Delay when "100", "00100000" after Delay when "101", "01000000" after Delay when "110", "10000000" after Delay when "111";end Selection;
31
V.2.3 Instanciation de composant
Cette instruction est utilisée dans le style structurel. Elle permet la description
hiérarchique de systèmes matériels. Lors de l'instanciation d'un composant, ports
effectifs et paramètres génériques effectifs doivent être spécifiés, de la façon
suivante :étiquette : nom generic map (paramètres-génériques-effectifs) port map (ports-effectifs);
Pour l'association paramètres formels/paramètres effectifs (resp. ports
formels/ports effectifs), on peut soit lister les paramètres (resp. les ports) effectifs
dans le bon ordre, soit lister des expressions de la formeparamètre-formel => paramètre-effectif
(resp. port-formel => port-effectif) dans un ordre quelconque.
Toute instanciation de composant doit être précédée de la déclaration du
composant (soit dans la partie déclarative de l'architecture, soit dans un package).
Voir la section VI.3 pour les configurations.
V.2.4 Generate
Nous ne parlerons que de l'instruction for..generate, qui permet l'élaboration
itérative d'instructions concurrentes. Sa syntaxe est la suivante :
for index in intervalle generate instructions-concurrentes
end generate;
L'intervalle parcouru est borné par des valeurs constantes ou paramètres
génériques. Comme toute instruction concurrente, une instruction generate peut
avoir une étiquette. Voyons comment elle peut s'associer à l'instruction d'instan-
ciation de composant.
32
Exemple : additionneur à retenue propagée, version 8 bits
entity Adder is port(a,b:in bit_vector(0 to 7); c:in bit; s:out bit_vector(0 to 8));end Adder;
C1
S1
C2
A 1 B1A
0B
0C0
S 0S n
C
S n-1
B n-1A n-1
n-1
architecture struct of Adder is component full_adder port(X,Y,Cin:in bit; Sum,Cout:out bit); end component; for all:full_adder use entity work.full_adder(Dataflow_view); signal carry:bit_vector(0 to 8);begin fadd:for I in 0 to 7 generate f1:full_adder port map(a(I),b(I),carry(I), s(I),carry(I+1)); end generate; carry(0) <= c; s(8) <= carry(8);end struct;
et la version N bits, utilisant un paramètre générique :
entity AdderN is generic(N:positive); port(a,b:in bit_vector(0 to N-1); c:in bit; s:out bit_vector(0 to N));end AdderN;
architecture struct of AdderN is component full_adder
33
port(X,Y,Cin:in bit; Sum,Cout:out bit); end component; for all:full_adder use entity work.full_adder(Dataflow_view); signal carry:bit_vector(0 to N);begin fadd:for I in 0 to N-1 generate f1:full_adder port map(a(I),b(I),carry(I), s(I),carry(I+1)); end generate; carry(0) <= c; s(N) <= carry(N);end struct;
V.2.5 Block
Le block permet de regrouper un ensemble d'instructions concurrentes, il peut
contenir une partie déclarative. On peut lui associer une expression de garde
(booléenne). Dans ce cas, le rôle du block est de permettre de contrôler
l'affectation des signaux gardés par cette expression (le mot-clé guarded apparaît
dans l'instruction d'affectation). La syntaxe est :
étiquette : block (expression-de-garde) partie-déclarativebegin instructions-concurrentesend block;
Exemple :
entity Cl_DFF is port(Clock, D: in Bit; Q, QBar: out Bit);end Cl_DFF;
architecture RTL of Cl_DFF isbegin B: block(Clock'event and Clock = '1') begin Q <= guarded D; QBar <= guarded not D; end block;end RTL;
34
VI. CIRCUITS SEQUENTIELS SYNCHRONES
VI.1 Machines de Mealy et de Moore
Les circuits combinatoires ne permettent pas de mémoriser des valeurs. En général,
un système numérique est formé d'une partie combinatoire et d'une partie faite de
dispositifs à mémoire :
circuitscombinatoires
éléments demémorisation
entrées primaires
sorties primaires(combinatoires)
sorties primaires(des éléments de mémorisation)
Voyons ce qui compose un tel système :
- des entrées (primaires)
- des sorties (primaires)
- des éléments mémorisants, pour mémoriser l'état
- à chaque top d'horloge, les sorties et l'état sont mis à jour. Les fonctions
correspondantes sont caractérisées par la partie combinatoire.
Cette figure correspond en fait à une machine de Mealy, c'est à dire que l'état
suivant dépend de la valeur courante des entrées et de la valeur courante de l'état,
et que la valeur courante des sorties dépend également de la valeur courante des
entrées et de la valeur courante de l'état.
Plus précisément, une machine de Mealy est un tuple :
35
(Q, I, O, t, f, q0)
où Q ensemble des états
I ensemble des entrées
O ensemble des sortiest fonction de transition, t : Q x I Æ Q
f fonction de sortie, f : Q x I Æ O
q0 état initial
Exemple : additionneur séquentiel pour deux vecteurs an ... a
1 a0 et bn ... b
1 b0 entrés
en séquence, à partir du bit de poids faible. L'état sert à mémoriser la dernière
retenue :
Q0 : dernière retenue à 0 (état initial)
Q1 : dernière retenue à 1
Q0
a xor b / 1
Q1
a xor b / 0
a.b / 1
a.b / 0
a.b / 0a.b / 1
Q = { Q0, Q1 }, q0 = Q0
I = {0,1}2
O = {0,1}
t : { Q0, Q1 } x {0,1}2 Æ { Q0, Q1 }
f : { Q0, Q1 } x {0,1}2 Æ {0,1}
36
Dans le cas d'une machine de Moore, l'état suivant dépend toujours de la valeur
courante des entrées et de la valeur courante de l'état, mais la valeur courante des
sorties ne dépend que de la valeur courante de l'état, ce qui correspond à une figure
du type :
circuitscombinatoires
éléments demémorisation
entrées primaires
sorties primaires
Plus précisément, une machine de Moore est un tuple :
(Q, I, O, t, f, q0)
où Q ensemble des états
I ensemble des entrées
O ensemble des sortiest fonction de transition, t : Q x I Æ Q
f fonction de sortie, f : Q Æ O
q0 état initial
Exemple : compteur 2 bits avec une entrée de contrôle C, i.e. comportement 00 Æ
01 Æ 10 Æ 11 Æ 00 … pourvu que l'entrée C soit à 1.
Il y a 4 états possibles, qui correspondent aux valeurs possibles des sorties S1 S0
37
Q0
Q3
Q2
Q1
0
00
1
1
1
0
1
1 0S S = 00
1 0S S = 01
1 0S S = 10
1 0S S = 11
Q = { Q0, Q1, Q2, Q3 }, q0 = Q0
I = {0,1}
O = {0,1}2
t : { Q0, Q1, Q2, Q3 } x {0,1} Æ { Q0, Q1, Q2, Q3 }
f : { Q0, Q1, Q2, Q3 } Æ {0,1}2
VI.2 Equivalence entre ces deux modèles
Nous allons étudier l'équivalence possible entre machine de Mealy et machine de
Moore. Si seqmo est la séquence des sorties produites par une machine de Moore
MO pour une séquence d'entrées donnée, et si seqme est la séquence produite par
une machine de Mealy ME pour la même séquence d'entrées, on remarque que
longueur(seqmo) = 1 + longueur(seqme)
Pour obtenir l'équivalence de ces deux machines, on cherchera à avoir, pour toute
séquence d'entrée
seqmo = s.seqme
où s est la sortie produite par MO dans son état initial.
38
VI.2.1 Transformation Moore / Mealy
Soit MO = (Q, I, O, t, fmo : Q Æ O, q0) une machine de Moore. Il existe une
machine de Mealy ME équivalente que l'on construit de la façon suivante :
ME = (Q, I, O, t, fme : Q x I Æ O, q0)
avec " q Œ Q et " x Œ I, fme(q,x) = fmo(t(q,x))
Alors MO et ME parcourent la même séquence d'états pour la même séquence
d'entrées, et sur chaque transition ME produit les sorties que MO associe avec l'état
atteint.
Exemple : soit le compteur 2 bits ci-dessus, spécifié par la table suivante
q S i q'q0 00 0 q0q0 00 1 q1q1 01 0 q1q1 01 1 q2q2 10 0 q2q2 10 1 q3q3 11 0 q3q3 11 1 q0
La machine de Mealy correspondante est
q i q' Sq0 0 q0 00q0 1 q1 01q1 0 q1 01q1 1 q2 10q2 0 q2 10q2 1 q3 11q3 0 q3 11q3 1 q0 00
39
Q0
Q3
Q2
Q1
0 / 00
0 / 010 / 11
1 / 01
1 / 10
1 / 00
0 / 10
1 / 11
Observons par exemple les valeurs des sorties pour la séquence d'entrée 1101 :
i 1 1 0 1
état q0 q1 q2 q2 q3
seqmo 00 01 10 10 11
seqme 01 10 10 11
VI.2.2 Transformation Mealy / Moore
Soit ME = (Q, I, O, tme : Q x I Æ Q, fme : Q x I Æ O, q0) une machine de Mealy. Il
existe une machine de Moore MO équivalente que l'on construit ainsi :
MO = (Q x O, I, O, tmo : Q x O x I Æ Q x O, fmo : Q x O Æ O, [q0,s0])
où s0 est un élément de O arbitraire.
Les états de MO sont des couples [q,s] formés d'un état de ME et d'une valeur de
sortie. Les fonctions tmo et fmo sont définies comme suit :
" q Œ Q, " x Œ I, " s Œ O,
tmo([q,s],x) = [ tme(q,x), fme(q,x) ]
40
fmo([q,s]) = s
Exemple : soit la machine de Mealy suivante
Q = { q0, p0, p1 }
I = {0,1}
O = {y, n}t : { q0, p0, p1 } x {0,1} Æ { q0, p0, p1 }
f : { q0, p0, p1 } x {0,1} Æ {y, n}
q0
p0
0 / y
0 / n
p1
1 / y
1 / n
1 / n
0 / n
à laquelle on associe la table ci-dessous :
x q q' o0 q0 p0 n1 q0 p1 n0 p0 p0 y1 p0 p1 n0 p1 p0 n1 p1 p1 y
La machine de Moore équivalente est la suivante :
MO = ( { [q0,y], [q0,n], [p0,y], [p0,n], [p1,y], [p1,n] },{0,1}, {y, n}, tmo, fmo, [q0,s0] )
41
Les états de MO sont des couples [q,s] formés d'un état de ME { q0, p0, p1 } et
d'une valeur de sortie. Les fonctions tmo et fmo sont définies comme suit :
tmo([q,s],x) = [ tme(q,x), fme(q,x) ] , fmo([q,s]) = s
[q,s] x [q',s'] s[q0,y] 0 [p0,n] y[q0,y] 1 [p1,n] y[q0,n] 0 [p0,n] n[q0,n] 1 [p1,n] n[p0,y] 0 [p0,y] y[p0,y] 1 [p1,n] y[p0,n] 0 [p0,y] n[p0,n] 1 [p1,n] n[p1,y] 0 [p0,n] y[p1,y] 1 [p1,y] y[p1,n] 0 [p0,n] n[p1,n] 1 [p1,y] n
q0, y
p1, y
q0, n
p0, n
p1, n
p0, y
01
0
0
0
0
0
1
1
1
1
1
s = n
s = y
s = y
s = y
s = n
s = n
42
VII. METHODES ASSOCIEES
VII.1 Optimisation
Les comportements des entrées/sorties de deux FSMs peuvent être identiques,
même si les deux FSMs ont des tables de transition et de sorties différentes, et
même si elles n'ont pas le même nombre d'états. Autrement dit, les deux FSMs ne
sont pas distinguables.
Lorsqu'on veut réaliser l'optimisation d'un circuit séquentiel, on cherche la plus
petite FSM équivalente à une FSM d'origine.
Equivalence d'états : soient s1 et s
2 des états des machines M
1 et M
2
respectivement; s1 est équivalent à s
2 si et seulement si, pour toute séquence finie
d'entrées, les sorties résultant de l'application de cette séquence à M1 dans s
1 sont
identiques aux sorties résultant de l'application de cette même séquence à M2 dans
s2.
Equivalence de machines d'états finis : soient q1 et q
2 les états initiaux des
machines M1 et M
2 respectivement; M
1 et M
2 sont équivalentes si et seulement si q
1
est équivalent à q2.
Une optimisation possible consiste à réduire le nombre d'états. Autrement dit, àpartir d'une FSM M
1, on cherche à produire une FSM M
2 équivalente mais avec un
plus petit nombre d'états.
Il suffit de déterminer les paires d'états équivalents (si, s
j) et de les combiner en un
seul état.
43
Pour ce faire, un algorithme possible (dit algorithme de relaxation) consiste à
supposer a priori que tous les états sont équivalents, puis à itérer en enlevant les
paires d'états non équivalents, et ceci au moyen des deux règles suivantes :
- si si et s
j produisent des sorties différentes, ils ne sont pas équivalents
- si, pour une combinaison des entrées i1, i
2,… i
n, l'état s
i conduit à l'état s
i', et
l'état sj conduit à l'état s
j', où s
i' et s
j' ne sont pas équivalents, alors s
i et s
j ne
sont pas équivalents.
Exemple : minimisation de la FSM suivante
Q3out = 1
Q1out = 0
Q4out = 0
Q0out = 1
Q2out = 0
1 0
1
1
1
1 0
0
00
1ère étape, on suppose que tous les états sont équivalents
état sortie transition à 0 transition à 1Q0= Q1= Q2= Q3= Q4 ? ? ?
2ème étape, on remarque que Q0 et Q3 produisent tous deux la sortie 1, et que les
autres produisent la sortie 0
état sortie transition à 0 transition à 1Q0 = Q3 1 Q1 = Q4 ? Q0
Q1 = Q2 = Q4 0 Q2 ?
44
3ème étape, on remarque que Q1 et Q4 conduisent tous deux à Q3 dans le cas où
ils reçoivent 1 (alors que Q2 conduit à Q4, qui n'est pas équivalent à Q3)
état sortie transition à 0 transition à 1Q0 = Q3 1 Q1 = Q4 Q0
Q1 = Q4 0 Q2 Q3
Q2 0 Q2 Q4
On obtient donc :
Q1,4out = 0
Q2out = 0
Q0,3out = 1
1 0
11
00
La méthode dite de l'implication chart procède sur un diagramme (implication
chart) permettant de mettre en relation les états deux à deux. On itère en réalisant
les actions suivantes sur ce diagramme :
- si deux états si et s
j produisent des sorties différentes ou ont des états suivants
qui ne sont pas équivalents, ils n'ont aucune chance d'être équivalents, on met
une croix dans la case correspondante
- sinon, on place dans la case correspondante les couples d'états suivants qui
doivent être équivalents pour que si et s
j puissent l'être
Exemple : reprenons la minimisation de la FSM ci-dessus
Q3out = 1
Q1out = 0
Q4out = 0
Q0out = 1
Q2out = 0
1 0
1
1
1
1 0
0
00
45
A l'itération 1, on place des croix pour tous les couples d'états produisant des
sorties différentes
Q0 Q1 Q2 Q3
Q4
Q3
Q2
Q1
Q1 - Q4
Q0 - Q0
Q2 - Q2
Q3 - Q3
Q2 - Q2
Q4 - Q3
Q2 - Q2
Q3 - Q4
A l'itération 2, on rajoute des croix pour les couples d'états dont les successeurs ne
sont pas équivalents : Q3 et Q4 ne pouvant être équivalents, on élimine également
les couples Q1-Q2 et Q2-Q4. Par ailleurs, il est définitivement décidé que Q1 et
Q4 sont équivalents (suivants identiques)
Q0 Q1 Q2 Q3
Q4
Q3
Q2
Q1
Q1 - Q4
Q0 - Q0
Q2 - Q2
Q3 - Q3
46
Enfin, à l'itération 3, on peut décider que Q0 et Q3 sont équivalents, puisque
l'itération précédente a déterminé que Q1 et Q4 le sont.
Q0 Q1 Q2 Q3
Q4
Q3
Q2
Q1
Q1 - Q4
Q0 - Q0
Q2 - Q2
Q3 - Q3
Le diagramme a atteint un état stable, les couples d'états équivalents sont Q0-Q3 et
Q1-Q4.
VII.2 Synthèse
VII.2.1 Principe
La synthèse d'un circuit séquentiel synchrone se fait par les étapes suivantes :
1. on dessine le diagramme de transitions d'états et on construit les tables
associées, chaque table doit prendre en compte toutes les combinaisons
d'entrées possibles.
2. la partie combinatoire du circuit est déduite de ces tables, en dérivant des
expressions algébriques (soit sous forme de sommes de produits soit sous
forme de produits de sommes) que l'on simplifie si possible. Il faut
préalablement avoir décidé d'un codage pour l'état.
47
3. pour la partie mémorisante : le codage choisi pour l'état détermine le nombre
de flip-flops nécessaires, k bits de variables d'état permettent de coder jusqu'à
2k états.Dans le cas d'un codage binaire classique, nbff = log2 (nbétats). On peut donc
remarquer que doubler le nombre d'états possibles revient à rajouter 1 flip-flop.
Nous évoquerons plus loin les codages de Gray et One Hot.
Remarques :
- le circuit ne doit pas contenir de "boucles combinatoires", i.e. toute boucle
structurelle doit contenir au moins 1 flip-flop,
- la période d'horloge sera déterminée soigneusement, elle devra être plus
longue que le temps de propagation dans la partie combinatoire.
Exemple 1 : additionneur séquentiel (section VI.1)
a b q q' s
0 0 Q0 Q0 0
0 0 Q1 Q0 1
0 1 Q0 Q0 1
0 1 Q1 Q1 0
1 0 Q0 Q0 1
1 0 Q1 Q1 0
1 1 Q0 Q1 0
1 1 Q1 Q1 1
48
Q0
a xor b / 1
Q1
a xor b / 0
a.b / 1
a.b / 0
a.b / 0a.b / 1
d'où :
a b q q' s0 0 0 0 0
0 0 1 0 10 1 0 0 10 1 1 1 0
1 0 0 0 11 0 1 1 0
1 1 0 1 0
1 1 1 1 1
ce qui donne : q' = not(a).b.q + a.not(b).q + a.b.not(q) + a.b.q = (a xor b).q + a.b
s = not(a).not(b).q + not(a).b.not(q) + a.not(b).not(q) + a.b.q
FA
C
q
A B
S
Exemple 2 : compteur 2 bits (section VI.1)
49
Q0
Q3
Q2
Q1
0
00
1
1
1
0
1
1 0S S = 00
1 0S S = 01
1 0S S = 10
1 0S S = 11
c q = q1 q0 q'0 Q0 = 00 Q0 = 00
0 Q1 = 01 Q1 = 010 Q2 = 10 Q2 = 10
0 Q3 = 11 Q3 = 111 Q0 = 00 Q1 = 011 Q1 = 01 Q2 = 10
1 Q2 = 10 Q3 = 111 Q3 = 11 Q0 = 00
q0' = not(c).not(q1).q0 + not(c).q1.q0 + c.not(q1).not(q0) + c.q1.not(q0) = not(c).q0 + c.not(q0)
q1' = not(c).q1.not(q0) + not(c).q1.q0 + c.not(q1).q0 + c.q1.not(q0) = not(c).q1 + c.(q0 xor q1)
q = q1 q0 S1 S0Q0 = 00 00
Q1 = 01 01Q2 = 10 10
Q3 = 11 11
50
S0 = not(q1).q0 + q1.q0 = q0, S1 = q1.not(q0) + q1.q0 = q1
S0
S1
Cq0
q1
VII.2.2 Codages
Revenons sur les différents codages de l'état. Dans le codage binaire classique, les
états sont associés aux séquences binaires correspondant aux entiers 0, 1, 2,… Lesavantages sont une minimisation du nombre de flips-flops (puisque log2 (nbétats)
flips-flops suffisent) et donc une optimisation de la surface du circuit. Mais ce
codage présente aussi des inconvénients : plusieurs bits d'état changent à chaque
top d'horloge, la partie combinatoire en est rendue assez complexe, et la puissance
requise est importante.
Une alternative est le codage de Gray : la numérotation est similaire à celle du
codage binaire, mais l'objectif est d'associer des codes de Gray "adjacents" à des
états consécutifs. Par exemple, sur 3 bits :
0 0 0 01 0 0 12 0 1 13 0 1 04 1 1 05 1 1 16 1 0 17 1 0 0
51
Le nombre de flips-flops nécessaires est le même que pour le codage binaire. La
puissance requise est moindre car 1 seul bit d'état change, pour des états adjacents.
La partie combinatoire est toujours assez complexe.
Ce type de codage est approprié pour des systèmes orientés contrôle présentant de
longs chemins sans branchement dans leur diagramme de transitions d'états.
Enfin, le codage One-Hot est très différent : un flip-flop est simplement associé à
chaque état, et un seul flip-flop peut donc être à 1 à tout moment. Les avantages
sont que la logique combinatoire associée est très simple (la vitesse est donc
optimisée), et que seulement deux bits d'état changent à tout instant (la puissance
nécessaire est donc limitée). L'inconvénient est que le nombre de flips-flops utilisés
est grand. C'est une solution appropriée pour des réalisations sur FPGAs puisque,
généralement, chaque CLB (bloc logique configurable) a son flip-flop.
Exemple : illustrons les résultats de ces 3 codages sur un exemple de compteur
modulo 4 sans entrée, la sortie passant à 1 chaque fois qu'on atteint le nombre 3
q q' szero un 0
un deux 0
deux trois 0
trois zero 1
Le codage binaire donne le résultat suivant :
q q' s00 01 0
01 10 0
10 11 0
11 00 1
52
q0' = not(q0).not(q1) + not(q0).q1 = not(q0)
q1' = q0 xor q1
s = q0.q1
q0 q1s
Le codage de Gray conduit au circuit ci-dessous :
q q' s00 01 0
01 11 0
11 10 0
10 00 1
q0' = not(q0).not(q1) + q0.not(q1) = not(q1)
q1' = q0.not(q1) + q0.q1 = q0
s = not(q0).q1 = not(q0 + not(q1))
q0 q1s
Et avec le codage One-Hot, on obtient (schéma avec reset) :
q q' s0001 0010 0
0010 0100 0
53
0100 1000 0
1000 0001 1
q0' = q3, q1' = q0
q2' = q1, q3' = q2
s = q3
54
VIII. VHDL. DESCRIPTIONS COMPORTEMENTALES
VIII.1 Instruction process
Le process est une instruction concurrente qui contient des instructions
séquentielles, grâce auxquelles des descriptions algorithmiques peuvent être
réalisées. Des variables peuvent être déclarées localement au process, qui accède
par ailleurs aux signaux de l'architecture. Plusieurs processes peuvent être actifs
simultanément, comme nous le verrons par la suite, mais plusieurs processes ne
peuvent modifier un même signal. Un process se présente de la façon suivante :
process (liste-de-sensibilité) déclarationsbegin instructions-séquentiellesend process;
ou
process déclarationsbegin instructions-séquentiellesend process;
La réactivation du process est conditionnée par le contenu de sa liste de sensibilité,
ou par ses instructions wait.
Dans le premier cas, la liste-de-sensibilité est une liste de signaux. Le
process est réactivé chaque fois qu'au moins l'un de ces signaux subit une mise à
jour de sa valeur. Les instructions-séquentielles sont alors exécutées,
puis le process est à nouveau suspendu. Le process ne doit contenir aucune
instruction wait.
Dans le deuxième cas, le process doit contenir au moins une instruction wait, dont
nous allons parler ci-dessous.
55
VIII.2 Instructions séquentielles
VIII.2.1 Wait
Cette instruction permet de suspendre l'exécution d'une instruction process. Elle
peut figurer n'importe où dans le process. Les instructions du process s'exécutent
en séquence jusqu'à la première instruction wait. Le processus est alors suspendu
jusqu'à ce que la condition de réactivation du wait soit satisfaite. A ce moment, le
process est réactivé et les instructions s'exécutent jusqu'à la prochaine instruction
wait, et ainsi de suite.
Elle peut prendre la forme :
wait on liste-signaux until condition for temps;
Dans le cas wait on liste-signaux; le process est suspendu jusqu'à
l'arrivée d'un événement sur l'un des signaux.
Une instruction de la forme wait until condition; suspend le process
jusqu'à ce que condition devienne vraie.
Enfin, si la clause for temps est présente, alors temps donne le temps
maximum de suspension du process.
Exemple :
And_process : processbegin wait on A,B until Enable = '1'; T <= A and B after 5 ns;end process;
Nous nous intéressons essentiellement ici aux systèmes synchronisés par horloge.
Nous ne considérerons donc, pour les chargements de registres, que des processes
dont la condition de réactivation est un front montant de l'horloge de
synchronisation, ce qui s'exprime par exemple par :
56
wait until clk'event and clk='1';
clk étant un signal de type bit. Cette instruction sera la seule instruction wait du
process et sera placée comme première instruction.
Pour les parties combinatoires, nous rencontrerons également des instructions
concurrentes d'affectations de signaux, sans retard explicite (clause after). Notons
qu'une instruction concurrente d'affectation de signal est équivalente à un process
qui ne contient que cette instruction et dont la liste de sensibilité contient tous les
signaux apparaissant en partie droite, par exemple :
Output <= A or B;
est équivalente à :
process(A,B)begin Output <= A or B;end process ;
Exemple : reprenons l'exemple du compteur modulo 4 de la page 52
q0 q1s
entity Compt is port(clk : in Bit; S : out Bit);
end Compt;
architecture Dataflow of Compt is signal q0,q1:Bit;
begin -- chargement des registres sur front montant process begin wait until clk'event and clk='1'; q0 <= not q0; q1 <= q0 xor q1;
57
end process; -- mise à jour de la sortie S <= q0 and q1;
end Dataflow;
L'entité de test utilisée pour simuler un tel circuit devra faire apparaître une
instruction pour la génération de l'horloge, par exemple :
entity testCompt is end testCompt;
architecture test1 of testCompt is component Compt port(clk : in Bit; S : out Bit); end component; signal ck,z: bit; for C:Compt use entity work.Compt(Dataflow); begin C: Compt port map(ck,z); ck <= not ck after 10 ns; end test1;
VIII.2.2 Instructions conditionnelles
Des conditionnelles peuvent être exprimées au moyen des instructions if et case.
La syntaxe de l'instruction if est la suivante :
if condition1 then instructions1elsif condition2 then instructions2elsif condition3 then instructions3...else instructionsNend if;
Les clauses elsif et else sont optionnelles. Les conditioni sont des expres-
sions booléennes et les instructionsi des suites d'instructions séquentielles.
Exemple :
And_behav: processbegin
58
if In1 = '0' or In2 ='0' then Output <= '0' after 5 ns; elsif In1 = 'X' or In2= 'X' then Output <= 'X' after 5 ns; else Output <= '1' after 5 ns; end if; wait on In1, In2;end process;
L'instruction case se présente comme suit :
case expression is when choix1 => instructions1 when choix2 => instructions2 ... when choixN => instructionsNend case;
Les instructionsi sont des instructions séquentielles. L'expression doit
être d'un type discret (ou une matrice uni-dimensionnelle). Toutes les valeurs
possibles pour expression doivent être considérées, dans exactement une
clause when. Chaque choixi peut être de la forme :
un-choix1 | un-choix2 | un-choix3 ...
Enfin choixN peut être others, ce qui permet de considérer globalement tous
les cas restants.
Exemple :
Selection: processbegin case X is when 1 => Output <= 0; when 2 | 3 => Output <= 1; when others => Output <= 2; end case; wait on X;end process;
59
VIII.2.3 Boucles
Nous finirons par les instructions itératives. D'autres types de constructions
séquentielles existent dans le langage, notamment les fonctions et procédures, nous
ne les étudierons pas.
L'instruction loop peut prendre la forme while..loop ou for..loop, ce qui
se traduit syntaxiquement par :
while condition loop instructions-séquentiellesend loop;
ou
for identificateur in intervalle loop instructions-séquentiellesend loop;
La première forme permet de faire un traitement itératif tant que condition est
vraie. La seconde forme permet de faire un traitement itératif en faisant parcourir à
l'indice de boucle identificateur un intervalle discret.
Dans le cas de l'instruction for..loop, l'indice de boucle identificateur
n'a pas à être déclaré, et n'est connu qu'à l'intérieur de la boucle. L'intervalle discret
intervalle peut être croissant ou décroissant. Il est fréquent d'utiliser dans ce
contexte les attributs sur types range et reverse_range.
Divers attributs sur types sont prédéfinis, ils correspondent à des caractéristiques
du type auquel ils se rattachent. L'utilisation d'un attribut se fait de la façon
suivante :
nom-du-type'nom-attributou identificateur-objet-du-type'nom-attribut
s'il s'agit d'un type tableau.
60
Parmi les attributs sur types tableaux se trouvent les attributs suivants :
- left(n) : borne gauche de la nième dimension
- right(n) : borne droite de la nième dimension
- range(n) : plage de variation des indices dans la nième dimension (range dans
le cas d'une seule dimension)
- reverse_range(n) : plage de variation, à l'envers, des indices dans la nième
dimension (reverse_range dans le cas d'une seule dimension)
Exemple :
signal A,B,C : bit_vector(0 to 7);...processbegin for i in A'range loop C(i) <= A(i) and B(i); end loop; ...end;
VIII.3 Simulation
VIII.3.1 Boucle de simulation
La construction du modèle simulable met en jeu une procédure d'élaboration.
L'élaboration crée un modèle de la hiérarchie de conception (entité et architecture
+ configuration) qui est ensuite lié à un processus noyau. Dans ce modèle, toutes
les instructions concurrentes sont converties en processes. Le processus noyau
coordonne l'activité des processus utilisateur durant la simulation.
La simulation commence par une phase d'initialisation :
- initialisation des signaux
- exécution de tous les processes jusqu'à suspension
- initialisation du temps courant de simulation NOW à 0
61
Après cette phase d'initialisation, la boucle de simulation qui s'exécute est lasuivante :
Tant que le temps courant NOW est inférieur au temps de fin de simulation faire
NOW avance jusqu'au temps où un process devient actif;
les signaux explicites, puis implicites, sont mis à jour;
tout process P sensible à l'un des signaux ayant subit un événement est
réactivé et exécuté, jusqu'à suspension;
Fin tant que
VIII.3.2 Pilotes, affectations en mode inertiel
La suite des valeurs prises par un signal durant la simulation est représentée par un
pilote (ou driver).
Un pilote est une séquence ordonnée de couples (v,t), appelés des transactions,
où v représente une valeur future prévue pour le signal, et t le temps où la
transaction doit avoir lieu.
Tout signal possède un pilote, plus exactement il y a un pilote par signal par
process.
Exemple :
signal step: integer := 0 ;processbegin step <= 1 after 5 ns, 2 after 10 ns, 1 after 15 ns, 0 after 20ns; wait;end process;
01 2
5 ns 10 ns
1
15 ns
0
20 ns
62
Dans une affectation de signal, la forme d'onde peut être précédée d'un mot-clé qui
indique le mode de propagation, transport ou inertial. Le mode
inertial est le mode par défaut, nous n'étudierons que celui-ci.
Une affectation suivant le mode inertiel modélise un dispositif qui ne réagit que si
une valeur sur son entrée reste inchangée pour une durée donnée. L'effet d'une telle
affectation sur le pilote du signal est le suivant :
- les transactions prévues après la date de la nouvelle transaction sont
supprimées du pilote, et la nouvelle transaction est ajoutée à la fin du pilote
- les transactions prévues avant la date de la nouvelle transaction sont
supprimées du pilote, sauf celles se trouvant immédiatement avant la
nouvelle transaction si leur valeur est identique à la valeur de la nouvelle
transaction.
Exemple : voyons un exemple simple avec 2 affectations du même signal
signal S: Integer := 0;processbegin S <= 1 after 1 ns; S <= 2 after 2 ns; wait;end process;
S <= 2 after 2 ns;02
2 ns
S <= 1 after 1 ns;01
1 ns
Exemple : reprenons le petit exemple vu page 14, avec la description suivante
entity Exemple is port(A,B: in Bit; S: out Bit);end Exemple;
63
architecture RTL of Exemple issignal X,Y: Bit;begin process (A,B,X,Y) begin X <= not A after 2 ns; Y <= X nand B after 5 ns; S <= X and Y after 4 ns; end process;end RTL;
Remarquons toutefois que cette description peu naturelle a été choisie pour
illustrer l'évolution des pilotes. Une description plus naturelle pour ce circuit serait
celle proposée page 24.
Supposons qu'on soit, à 10 ns, dans la configuration suivante où X = '0', Y='1', et
S='0' :
A
B
S2ns
5ns
4ns
1
01
10
X
Y
Au temps 20 ns, A passe à '0', ce qui provoque la mise à jour des pilotes comme
suit :
1 / 22 nsX 1 / 25 nsY 0 / 24 nsS
Au temps 22 ns, l'événement sur X se produit, on a X = '1'
1
A
B
S2ns
5ns
4ns
1
0 1
et les pilotes prennent la forme suivante :
1 / 24 nsX 0 / 27 nsY 1 / 26 nsS
Au temps 24 ns, la transaction sur X se produit, mais elle n'induit pas d'événement.
64
Au temps 26 ns, l'événement sur S se produit, on a S = '1'
11
A
B
S2ns
5ns
4ns
1
0 1
et l'état courant des pilotes est :
X 0 / 27 nsY S
Au temps 27 ns, l'événement sur Y se produit, on a Y = '0'
0
A
B
S2ns
5ns
4ns
1
0 1
et les pilotes prennent la forme suivante :
1 / 29 nsX 0 / 32 nsY 0 / 31 nsS
Au temps 29 ns, la transaction sur X se produit, mais elle n'induit pas d'événement.
Au temps 31 ns, l'événement sur S se produit, on a S = '0'
00
A
B
S2ns
5ns
4ns
1
0 1
Au temps 32 ns, la transaction sur Y se produit, qui n'induit pas d'événement.
VIII.3.3 Retards delta
Une affectation de signal sans clause after induit un retard delta. Il représente
un pas de simulation de toute la description, sans modification du temps physique.
Plusieurs retards delta peuvent se succéder, jusqu'à stabilisation des valeurs des
signaux.
65
Exemple : reprenons le full-adder en style flot de données, sans retards explicites
entity full_adder is port(X,Y,Cin : in Bit; Sum,Cout : out Bit);
end full_adder;
architecture Dataflow_view of full_adder is signal S : Bit;begin
S <= X xor Y; Sum <= S xor Cin; Cout <= (X and Y) or (S and Cin);
end Dataflow_view;
entity test isend test;
architecture Struct1 of test is component full_adder port(X,Y,Cin : in Bit; Sum,Cout : out Bit); end component; signal A,B,C,S,C2 : Bit; for F1: full_adder use entity work.full_adder(Dataflow_view);
begin F1: full_adder port map(A,B,C,S,C2); A <= '1' after 10 ns; B <= '0' after 10 ns; C <= '0' after 10 ns;end Struct1;
alors à 10 ns, les signaux seront mis à jour comme suit :
- à 10 ns + 1 delta, S prend la valeur A xor B = '1' xor '0' = '1'
- à 10 ns + 1 delta, Sum a la valeur S xor C = '0' xor '0' = '0'
- à 10 ns + 1 delta, Cout prend la valeur (A and B) or (S and C) = ('1' and '0')
or ('0' and '0') = '0'
- à 10 ns + 2 deltas, Sum prend la valeur S xor C = '1' xor '0' = '1'
- à 10 ns + 2 deltas, Cout prend la valeur (A and B) or (S and C) = ('1' and '0')
or ('1' and '0') = '0'
66
IX. DESCRIPTIONS D'AUTOMATES
IX.1 Constructions utilisées
La modélisation d'une machine d'états finis peut se faire de diverses façons en
VHDL. Nous allons voir certaines conventions qu'il est préférable d'utiliser pour
que la machine soit synthétisable par un outil du commerce.
Notons toutefois que, bien qu'il existe un document de standardisation pour la
synthèse au niveau RTL (IEEE Std 1076.6-1999 IEEE Standard for VHDL
Register Transfer Level Synthesis), le sous-ensemble du langage reconnu et les
conventions adoptées varient d'un outil à l'autre.
La représentation des états symboliques donne lieu à la définition d'un type
énuméré. Un signal spécifique est utilisé pour mémoriser l'état courant de la
machine, un deuxième signal peut être utilisé pour le calcul de l'état suivant.
La modélisation d'une FSM correspond au codage de la fonction de transition et de
la fonction de sortie :
- les sorties sont des éléments combinatoires, un ensemble d'instructions
concurrentes d'affectations de signaux (ou le process correspondant) sera
utilisé. Ces instructions ne doivent pas faire apparaître de retards explicites.
Pour ne pas prendre implicitement un caractère mémorisant sans contrôle de
l'horloge, ces signaux doivent être affectés dans toutes les branches des
instructions conditionnelles
- un process synchronisé par horloge traduit la mise à jour du registre d'état.
Calcul de l'état suivant (fonction combinatoire) et mise à jour du registre
d'état peuvent se trouver dans deux processes distincts
- un reset asynchrone est généralement autorisé, pour placer l'automate dans
son état initial, voire initialiser d'autres registres (indiquer dans la
67
description des valeurs initiales pour les signaux n'a pas de sens pour la
synthèse).
Par ailleurs, les configurations ne sont généralement pas admises, les réels et
matrices multi-dimensionnelles non plus, et la plupart des opérateurs sont admis,
sous quelques restrictions.
Exemple : reprenons le système reconnaisseur de code BCD vu en exercice
STATE0
STATE1
STATE2
STATE3
STATE4
STATE5
0/1
0/11/1
1/1
0/1 1/0
/1
/1/1
0/1
Il peut être décrit comme suit :
entity DCB is port(X,clk: in Bit; Z: out Bit);
end DCB;
architecture Auto of DCB is -- états de l'automate
type States is (STATE0,STATE1,STATE2,STATE3, STATE4,STATE5);signal state: States;begin
-- mise à jour de l'état process begin
--attente du front montant wait until clk'event and clk='1'; case state is when STATE0 => state <= STATE1;
68
when STATE1 => if X='0' then state <= STATE2; else state <= STATE4; end if; when STATE2 => if X='0' then state <= STATE3; else state <= STATE5; end if; when STATE3 => state <= STATE0; when STATE4 => state <= STATE5; when STATE5 => state <= STATE0; end case; end process; -- mise à jour de la sortie Z <= '0' when (state=STATE5) and (X='1') else '1';end Auto;
Voyons une autre façon de le décrire, avec trois processes (calcul de l'état suivant,
mise à jour de l'état, mise à jour des sorties). Un signal supplémentaire
nextstate sert au calcul de l'état suivant. Un signal de reset a également été
considéré dans cette description.
entity DCB is port(X,reset,clk: in Bit; Z: out Bit);
end DCB;
architecture Auto of DCB is -- états de l'automate
type States is (STATE0,STATE1,STATE2,STATE3, STATE4,STATE5);signal state, nextstate: States;begin
-- calcul de l'état suivant (process combinatoire) process (state, X) begin case state is when STATE0 => nextstate <= STATE1; when STATE1 => if X='0' then nextstate <= STATE2; else nextstate <= STATE4; end if;
69
when STATE2 => if X='0' then nextstate <= STATE3; else nextstate <= STATE5; end if; when STATE3 => nextstate <= STATE0; when STATE4 => nextstate <= STATE5; when STATE5 => nextstate <= STATE0; end case; end process; -- mise à jour de l'état process (reset, clk) begin -- si reset asynchrone if (reset = '1') then state <= STATE0; -- sur front montant elsif (clk'event and clk='1') then state <= nextstate; end if; end process; -- mise à jour de la sortie (process équivalent) process (state, X) begin if (state=STATE5) and (X='1') then Z <= '0'; else Z <= '1'; end if; end process;end Auto;
Remarque : on rencontre fréquemment, à la place du type bit , les types
std_logic ou std_ulogic. Ce sont des types définis dans le standard IEEE
1164, qui contiennent 9 valeurs symboliques, sur le modèle suivant :
type std_ulogic is ('U',! !-- Uninitialized!!!!!!!!!!!!!!!!!!!!'X',!! -- Forcing Unknown!!!!!!!!!!!!!!!!!!!!'0',!! -- Forcing 0!!!!!!!!!!!!!!!!!!!!'1',!! -- Forcing 1!!!!!!!!!!!!!!!!!!! 'Z',!! -- High Impedance!!!!!!!!!!!!!!!!!!!!! 'W',!! -- Weak Unknown!!!!!!!!!!!!!!!!!!! 'L',!! -- Weak 0!!!!!!!!!!!!!!!!!!!!!!!!! 'H',!! -- Weak 1!!!!!!!!!!!!!!!!!!!!!!!!! '-'!!! -- Don't care!!!!!!!!!!!!!!!! );
70
Les descriptions contiennent alors les directives suivantes :library ieee;use ieee.std_logic_1164.all;
IX.2 Synthèse de descriptions VHDL
La synthèse peut alors être effectuée, suivant la méthodologie décrite dans la
section VII. Le processus de synthèse peut être réalisé en tenant compte d'une
bibliothèque donnée de composants, la description obtenue dans ce cas sera dans le
style structurel, interconnexion des composants de base nécessaires.
Voyons une description synthétisée, dans le style dataflow, sur l'exemple précédent
du reconnaisseur de code BCD (version 1). Après synthèse (voir exercice) le
système obtenu est le suivant :
q1
q2
q0
X
Z
entity DCB is port(X,clk: in Bit; Z: out Bit);
end DCB;
architecture dataflow of DCB issignal q0,q1,q2 : Bit;begin
-- mise à jour des registres process begin
71
wait until clk'event and clk='1'; q0 <= not q0; q1 <= (not X) and (not q2) and (q1 xor q0); q2 <= (X and (not q2) and (q1 xor q0)) or
(q2 and (not q1) and (not q0)); end process; -- mise à jour de la sortie
Z <= (not q2) or ((not q1) and (not q0 or not X));end dataflow;
Illustrons maintenant l'intégralité du processus sur l'exemple du compteur 2 bits
étudié dans la section VII.2.1 (page 49). On rappelle que l'automate spécifiant ce
système est le suivant :
Q0
Q3
Q2
Q1
0
00
1
1
1
0
1
1 0S S = 00
1 0S S = 01
1 0S S = 10
1 0S S = 11
entity Compteur is port(C, clk : in Bit; S0, S1 : out Bit);end Compteur;
architecture Automate of Compteur is-- états de l'automatetype ETATS is (Q0, Q1, Q2, Q3);signal state: ETATS;begin-- mise à jour de l'état
processbegin
--attente du front montant wait until clk'event and clk='1';
72
case state is when Q0 => if C='0' then state <= Q0; else state <= Q1; end if; when Q1 => if C='0' then state <= Q1; else state <= Q2; end if; when Q2 => if C='0' then state <= Q2; else state <= Q3; end if; when Q3 => if C='0' then state <= Q3; else state <= Q0; end if; end case;end process;
-- mise à jour des sortiesS0 <= '0' when (state=Q0) or (state=Q2) else '1';S1 <= '0' when (state=Q0) or (state=Q1) else '1';
end Automate;
Les équations obtenues par synthèse sont les suivantes :
q0' = not(c).not(q1).q0 + not(c).q1.q0 + c.not(q1).not(q0) + c.q1.not(q0) = not(c).q0 + c.not(q0)
q1' = not(c).q1.not(q0) + not(c).q1.q0 + c.not(q1).q0 + c.q1.not(q0) = not(c).q1 + c.(q0 xor q1)
S0 = not(q1).q0 + q1.q0 = q0
S1 = q1.not(q0) + q1.q0 = q1
ce qui peut être associé à la description VHDL :
architecture Dataflow of Compteur issignal q0,q1:Bit;begin
73
-- chargement des registres sur front montant process begin wait until clk'event and clk='1'; q0 <= (not C and q0) or (C and not q0); q1 <= (not C and q1) or (C and (q0 xor q1)); end process; -- mise à jour des sorties S0 <= q0;
S1 <= q1;end Dataflow;
S0
S1
Cq0
q1
Enfin, reprenons ce même exemple avec l'outil domaine public Alliance (voir
http://www-asim.lip6.fr/recherche/alliance/). Le style VHDL à utiliser
nécessite un process pour le calcul de l'état suivant et un process pour la mise à
jour de l'état, un signal supplémentaire nextst sert au calcul de l'état suivant.
entity Compteur is port(clk : in Bit; C: in Bit; vdd : in Bit; vss : in Bit; S0: out Bit; S1 : out Bit);end Compteur;
architecture Automate of Compteur is-- etats de l'automatetype ETATS is (Q0, Q1, Q2, Q3);signal state, nextst: ETATS;
--PRAGMA CURRENT_STATE state--PRAGMA NEXT_STATE nextst
74
--PRAGMA CLOCK clk--PRAGMA FIRST_STATE Q0
begin -- calcul de l'etat suivant et des sorties process (state, C) begin case state is when Q0 => if C='0' then nextst <= Q0; else nextst <= Q1; end if; S0 <= '0'; S1 <= '0'; when Q1 => if C='0' then nextst <= Q1; else nextst <= Q2; end if; S0 <= '1'; S1 <= '0'; when Q2 => if C='0' then nextst <= Q2; else nextst <= Q3; end if; S0 <= '0'; S1 <= '1'; when Q3 => if C='0' then nextst <= Q3; else nextst <= Q0; end if; S0 <= '1'; S1 <= '1'; end case;end process;
process (clk)begin if (clk='1' and not clk'stable) then state <= nextst; end if;end process;
end Automate;
75
Les outils syf (synthèse de FSM), boom (minimisation booléenne) et boog
(mapping sur une bibliothèque de composants) de la suite Alliance permettent de
procéder à une synthèse de cette description :
mamachine% syf -u -V Compteur.fsm Compteursynthmamachine% cat Compteur.enc# Mon choix de codage pour l'etat-compteur m 2q3 3q2 2q1 1q0 0 First statemamachine% boom Compteursynth.vbemamachine% boog Compteursynth_o
On obtient le résultat suivant :
en effet, on peut remarquer qu'on a :
q0' = not(c).not(q1).q0 + not(c).q1.q0 + c.not(q1).not(q0) + c.q1.not(q0) = not(c).q0 + c.not(q0) = c xor q0
q1' = not(c).q1.not(q0) + not(c).q1.q0 + c.not(q1).q0 + c.q1.not(q0) = not(c).q1 + c.not(q1).q0 + c.q1.not(q0) + not(c).q1.not(q0) = not(c).q1 + c.not(q1).q0 + q1.not(q0) = (not(c) + not(q0)).q1 + c.not(q1).q0 = (not(c.q0)).q1 + c.q0.not(q1) = (c.q0) xor q1
76
Parmi les sources de ce cours...
3 "Circuits numériques - Théorie et applications". Ronald J. Tocci. Dunod, 1997.
3 "Architecture et technologie des ordinateurs". P.Zanella, Y.Ligier. Dunod, 1998.
3 "Technologie des ordinateurs et des réseaux". P.A.Goupille. Dunod, 2000.
3 "Introduction to automata theory, languages and computation". J.Hopcroft,
J.Ullman. Addison-Wesley.
3 "A Guide to VHDL". S.Mazor, P.Langstraat. Kluwer Academic Pub., 1993.
3 "VHDL Coding Styles and Methodologies". B.Cohen. Kluwer Academic Pub.,
1995.
3 http://mikro.e-technik.uni-ulm.de/vhdl/anl-engl.syn/html/node3.html