Présentation
du langage VHDL-AMS
Préparée par P. Bakowski, R. Caillet & Olivier Piron
transparents en français pour un cours
1.0 Introduction
Le VHDL (Very High Speed Integrated Circuits Hardware Desription Langage)
est un puissant langage de description des circuits d'électronique
numérique. Avec le VHDL, il est possible de simuler et de synthètiser
des circuits numériques pour différentes technologies. Toutes
entités déjà créées sont archivables
dans une librairie pour être modifiées ou réutilisées
plus tard. Le gros avantage en matière de productivité est
lorsque une librairie comporte beaucoup de composants simples près
a être intégrés à des systèmes plus complexes.
La première standardisation de ce langage a eu lieu en 1987.
En 1993, une version améliorée a elle aussi été
standardisée. Elle devait permettre d'intégrer la modélisation
de systèmes analogiques mais beaucoup de travail devait être
réalisé pour y parvenir. Un groupe de travail spécifique
a donc été formé pour développer une extension
au langage qui pourrait permettre la description et la simulation de systèmes
mixtes analogiques numériques. Cette version étendu a pour
nom VHDL-AMS (AMS : Analog and Mixed Signal) et a été standardisé
récemment comme standard IEEE - VHDL 1076.1.
L'objet de ce tutorial est donc de présenter la version VHDL-AMS
(peu de documents existent en francais), les nouveaux mecanismes introduits
pour gérer les problèmes liés aux phénomènes
analogiques. De plus il sera présenté des composants analogiques
très simples décrits en langage VHDL-AMS, qui pourront servir
plus tard à l'élaboration de systèmes analogiques
ou mixtes plus complexes. Il serait délicat à ce jour (fin
1998) de vouloir présenter des systèmes complexes car aucun
simulateur complet de VHDL-AMS n'est disponible.
Toutefois, le premier travail avant de réaliser des circuits
plus important était la constitution d'une librairie de composants
de base. Les composants de base ainsi que la présentation dans ce
tutorial du VHDL-AMS, sont autant d'outils qui permettront de développer
rapidement des circuits plus conséquents.
2.0 Standard VHDL-AMS
2.1. But de ce standard
Le but de ce standard était de fournir un outil de description hiérarchique
et de simulation des systèmes continus et mixtes (analogique-numérique)
en conservation d'énergie ou non. Le langage devait supporter la
modélisation à différents niveaux d'abstraction en
domaine électrique et non-électrique (systemes constitués
d'éléments hydrauliques, thermiques etc... ) Les circuits
à modéliser sont descriptibles par des systèmes d'équations
différentielles et algébriques (DAE). La résolution
de ces systèmes devait inclure la gestion des discontinuites. D'autre
part il fallait respecter les exigences au niveau des intéractions
entre partie numérique et partie continue des systèmes mixtes.
On voit donc que la spécificité des comportements analogiques
et des systèmes mixtes devaient entrainer la création d'un
certain nombre d'éléments nouveaux :
-
la création d'un noyau de résolution analogique pour résoudre
les systèmes d'équations,
-
une notation pour ces systèmes d'équations,
-
la création de nouvelles quantités pour exprimer les différences
de potentiel aux bornes d'une branche et le courant la traversant ainsi
que la notion de tolérance,
-
une redéfinition du cycle de simulation pour la simulation des systèmes
mixtes,
-
création d'instructions simultanées.
2.2. Description des systèmes continus
Les aspects continus des comportements des morceaux de systèmes
visés par VHDL 1076.1 peuvent être décrits par un système
d'équations différentielles et algébriques (DAE) avec
le temps comme variable indépendante. Ces équations sont
de la forme :
F(x,dx/dt,t)
(1)
avec x le vecteur des inconnues, dx/dt le vecteur des
dérivées des inconnues et t le temps. Il n'y a pas
d'autre possibilité de représentation d'une telle puissance
et étendue. La plupart de ces systèmes d'équations
n'ont pas de solution analytiques, donc en pratique les solutions doivent
être approximées en utilisant des techniques numériques.
2.3. Quantité
Les inconnues des DAE introduites précédemment sont des
fonctions analytiques du temps. Elles sont continues par morceaux avec
un nombre fini de discontinuités. Les algorithmes de résolution
numériques résolvent les systèmes simultanément
pour les valeurs de toutes les inconnues à certains instants déterminés
par l'algorithme. Aucun objet VHDL n'obtient ces valeurs d'une telle façon.
Pour cette raison une nouvelle classe d'objet est créée pour
les inconnues des DAE : la quantité (quantity).
Les quantités doivent avoir des sous-éléments de
type scalaire comme les types flottants pour approximer les propriétés
continues du formalisme mis en avant. Un objet quantité peut apparaître
dans une expression ou, partout où une valeur de ce type est autorisée.
Dans cette section nous décrivons les caractéristiques
des quantités scalaires. Les caractéristiques continues d'une
quantité composée sont simplement l'ensemble des caractéristiques
de chacun de ces sous-éléments scalaires. Le comportement
de chaque sous-élément est indépendant des autres.
Les quantités peuvent être déclarées partout
où un signal peut être déclaré excepté
dans un package. La déclaration suivante créé deux
quantités de type réel :
Cet objet peut aussi s'appliquer pour les ports d'E/S. Une quantité
d'interface est appelée une quantité port, par analogie à
un signal port. Les quantités interfaces supportent la modélisation
des signaux. Elles ont un mode, de la même manière que les
signaux d'interface. Par exemple, voici la déclaration d'un modèle
en flot de données d'un additionneur deux entrées. Cet additionneur
à deux quantités d'interface en mode entrée et une
en mode sortie :
entity adder is
port( quantity
in1, in2 : in Real);
quantity out:out
Real);
end entity adder;
Quand ce modèle est instancié, chaque quantité d'interface
est contraint d'avoir la même valeur que la quantité avec
laquelle elles peuvent être associées dans une association
de quantité.
De plus, pour expliquer les quantités, le langage définit
un nombre de quantités implicites dont la plupart seront abordées
plus tard. Ici, nous nous focalisons sur les quantités nécessaires
à l'écriture de DAE. Pour chaque quantité Q
: on note Q'Dot pour désigner la quantité du même
type que Q qui représente la dérivé de
Q en fonction du temps. On note Q'Integ pour désigner
une quantité du même type que Q qui représente
l'intégration de Q en fonction du temps de 0.0 à
l'instant courant. Pour les dérivés des ordres supérieures,
il suffit d'écrire : Q'Dot'Dot (ordre 2). Il en est de
même pour les intégrales avec Q'Integ'Integ (ordre
2).
2.4. Groupe de tolérance
La tolérance sous VHDL-AMS est basée sur la notion de groupe
de tolérance. Un groupe de tolérance est la collection d'éléments
de solution - quantités et expressions caractéristiques du
modèle - qui ont les mêmes propriétés de tolérances.
Typiquement, les éléments de solutions dans un groupe de
tolérance ont le même ordre de grandeur.
Les groupes de tolérance d'un élément de solution
est spécifié dans le texte du modèle contenant cet
élément. Le lien d'un élément au sein d'une
entité VHDL peut être effacé jusqu'à ce que
le composant correspondant soit instancié.
Les propriétés des tolérance de groupe ne sont
pas spécifiés dans la définition car chaque algorithme
caractérise la tolérance de manière différente.
Pour les logiciels du type Spice les propriétés des tolérances
sont inclues dans les nombre "retlol", "abstol" et "vntol".
Un groupe de tolérance est noté par le code de tolérance
du type chaîne de caractères.
subtype charge
is Real tolerance "toler1";
Cet exemple déclare un sous-type charge de type réel avec
pour tolérance "toler1".
Dans cet exemple, on déclare q0 de type charge
avec la tolérance "toler1"
et on déclare q1 et q2 de type charge
avec la tolérance "toler2"
Les dérivés ou les intégrations de q0 héritent
de la tolérance de q0.
2.5. Systèmes conservatifs
Les systèmes conservatifs - par exemple, les systèmes
électriques obéissant aux lois de Kirchhoff - nécessitent
un traitement spécial car ils sont rencontrés très
souvent. Des syntaxes et sémantiques spéciales peuvent fournir
des notations simplifiées qui réduiront le risque d'erreur
et ainsi augmenteront la productivité. Avec VHDL-AMS, les équations
décrivant l'aspect conservatif de ces systèmes n'ont pas
besoin d'être explicitées par le concepteur.
La description des systèmes conservatifs utilise la théorie
des graphes. Dans le langage, on utilise la quantité de branche
(branch quantities) qui se décompose en deux éléments,
la quantité aux bornes de la branche (across quantities)
qui représente l'effort lié à l'effet, la quantité
à travers la branche (through quantities) qui représente
le flot lié à l'effet.
Effort et effet pour différents domaines
Domaine
|
effort
|
flot |
électrique |
|
|
thermique |
|
|
hydraulique |
|
|
mécanique |
|
|
rotation |
|
|
Par exemple, une résistance est une branche régie par
la loi d'Ohm qui relie la tension à ses bornes (across quantity)
et le courant qui la traverse (through quantity).
Une branche est déclarée avec deux bornes. Les bornes
sont de type nature simple, où de nature composite avec
un sous-élément scalaire qui sont de nature simple.
Chaque nature simple dépend de la domaine (électrique,
thermique, hydraulique...). Dans l'exemple suivant, on déclare deux
sous-types Voltage et Current avec leur tolérance
respective de nature simple Electrical, deux bornes sont de cette
nature, et une quantité aux bornes et deux entre les mêmes
bornes.
subtype Voltage is
Real tolerance "tol_voltage";
subtype Current is
Real tolerance "tol_current";
nature Electrical
is Voltage across
Current through;
terminal t1, t2 : Electrical;
quantity v across
i1, i2 through t1 to
t2;
Il existe deux types prédéfinis : N'Across
qui désigne le type aux bornes de l'élément nature
N, dans l'exemple "Voltage" et N'Through
qui désigne le type à travers les bornes de l'élément
nature N, dans l'exemple "Current".
v est la différence de potentiel entre les bornes, qui
est du type Voltage et a pour code de tolérance "tol_voltage''.
De même, i1 et i2 qui représentent deux
branches parallèles, est de type Current et leur tolérance
est "tol_current''. Les deux bornes sont appelées
plus et moins, la direction de la branche est de plus
vers moins, qui est le sens positif du courant.
Dans l'exemple suivant, on déclare un tableau de type nature,
deux bornes de ce type et différentes combinaisons de ces bornes.
nature Electrical_vector is
array(Natural
range <>) of
Electrical;
terminal t3, t4 : Electrical_vector(1
to 5);
quantity i3 through
t3 to t1;
quantity i4 through
t2 to t4;
quantity i5 through
t3 to t4;
Le groupe de tolérance d'une branche est déterminé
par son sous-type. Il est possible de redéfinir dans la sous-nature
de la déclaration ou dans la déclaration de la branche.
L'exemple suivant déclare une sous-nature Highvoltage
avec la tolérance appropriée, deux bornes de cette sous-nature,
et deux quantités entre ces bornes et une à travers ces deux
bornes.
subnature Highvoltag is
Electrical;
tolerance "tol_highvoltage"
across "tol_highcurrent"
through;
terminal t5, t6 : Highvoltage;
quantity vh1 across
ih1 through t5 to
t6:
quantity vh2 tolerance
"tol_voltage" across
t5 to t6;
Les tolérances des branches vh1 et ih1 sont définies
par la déclaration sous-nature, soit "tol_highvoltage''
et "tol_highcurrent". La tolérance de vh2 est
"tol_voltage''.
Une borne peut être déclarée n'importe où
un signal peut être déclaré. Une borne peut être
déclaré dans un port
port (terminal
anode, cathode : Electrical);
La déclaration d'une nature simple génère une
borne de référence (la masse). La référence
de la borne T de nature N est désignée
par N'Reference. Si une branche est
déclarée avec seulement une borne (moins ou plus), cela signifie
que l'autre est reliée à la masse. La déclaration
de T crée deux quantités :
-
La référence (référence quantity), T'Reference,
qui est la quantité entre les deux bornes avec T et N'Reference
comme bornes plus et moins.
-
La contribution (contribution quantity), T'Contribution
est la quantité à travers les deux bornes qui est égale
à la somme des quantités incidentes de T (avec le
signe approprié).
Si T est composée alors de T'Reference
et T'Contribution et les règles
s'appliquent pour chaque sous-élément de T.
2.6. Déclarations simultanées.
VHDL-AMS ajoute aux deux types d'instruction de VHDL, séquentielle
et parallèle, un nouveau type d'instruction pour les équations
différentielles et algébriques : l'instruction simultanée.
Elle inclut les expressions VHDL ordinaires qui peuvent être évaluées
de manière ordinaire mais l'interprétation sur la valeur
résultante et l'effet sur le comportement des objets supportant
ces valeurs est novatrice.
Les instructions simultanées peuvent avoir lieu partout où
un signal parallèle peut être assigné. La forme de
base de la déclaration est la suivante :
[label :] simple_expression == simple_expression;
Par exemple l'équation décrivant une résistance
pourrait être écrite i == v/r; où i est
une quantité qui traverse la résistance (le courant) et v
une quantité qui relie les deux bornes (la tension) et r
la valeur de la résistance. Les quantités peuvent avoir des
composantes : dans ce cas chaque sous-élément de gauche doit
avoir un sous-élément correspondant à droite. Les
expressions peuvent se referrer a une quantité, un signal, une constante,
variable partagée, fonction. Lorsque le calculateur analogique a
correctement établi les valeurs de chaque quantité les sous-éléments
correspondants seront approximativement égaux.
Le langage définie deuxformes d'instruction simultanée
:
-
la déclaration simultanée procédurale qui fournit
à l'utilisateur la notation DAE avec le style séquentiel.
Il peut inclure toutes les déclarations du langage VHDL sauf les
déclarations d'attentes (wait)
et de signaux.
-
la déclaration simultanée case
et if qui supporte la description
comportementale. Chacune contient une liste arbitraire de déclarations
simultanées dans la partie déclarative.
L'exemple suivant présente les nouveaux concepts du VHDL-AMS.
entity limiter is
generic (gain : Real
:= 1.0; limit : Real);
port ( terminal
inp, inm : in Electrical; -- terminaux d'entrée
terminal p, m : out Electrical);
-- terminaux de sortie
end entity limiter;
-- architecture simultanée
architecture simult of
limiter is
quantity in across
inp to inm;
quantity v across
i through p to m;
begin
if gain*vin > limit use
v==limit;
-- instruction simultanéé
elsif gain*vin < -limit use
else
end use;
end architecture simult;
Chaque expression caractéristique correspond à une expression
de la forme F(x,dx/dt,t). Chaque déclaration simple est une
collection d'expressions caractéristiques, une pour chaque sous-élément
scalaire de l'expression.
Le calculateur analogique détermine la valeur de chaque quantité
de manière à ce que les valeurs des expressions caractéristiques
soient proches de 0 et résout alors les DAE du modèle. Chaque
expression caractéristique comme chaque quantité appartient
à un groupe de tolérance. Le groupe de tolérance par
défaut, pour les expressions caractéristiques d'une simple
déclaration simultanée dont la partie gauche est du nom d'une
quantité, est le groupe de tolérance de la quantité.
Si la condition de cette forme n'est pas de cette forme mais que la partie
droite porte le nom d'une quantité le groupe de tolérance
est celui de la quantité. Sinon, le concepteur du modèle
doit spécifier le groupe de tolérance lors de la déclaration.
Par exemple, le groupe de tolérance est défini lors de la
déclaration :
i == v/r tolerance "toler1''
La définition du langage laisse une autre concession à
la réalité dans les algorithmes. Les algorithmes itératifs
considèrent lors d'une séquence d'itérations que seule
la valeur des quantités change, contrôlé par le moteur
itératif. Si une déclaration simultanée inclut des
variables partagées ou des appels à des fonctions impures,
et si leurs valeurs changent durant une séquence itérative
pour une raison différente qu'un changement en tant qu'argument
d'une fonction, alors la déclaration simultanée doit être
marquée comme impure. Par défaut, les déclarations
simultanées sont pures et les modèles avec des déclarations
simultanées sont potentiellement non compatibles. Remarquons qu'une
déclaration simultanée appellant la fonction impure now
est pure car le temps n'avance pas pendant ces itérations : now
retourne toujours la même valeur. Il est prudent d'empêcher
des déclarations avec effet de bord dans les déclarations
simultanées (comme assert
et report) car leurs effets ne sont
pas contrôlés par le modèle dans un contexte itératif.
2.7. Cycle de simulation et temps
La synchronisation entre le calculateur analogique et le noyau de simulation
VHDL requière un formalisme du temps de simulation pour la simulation
discrète et continue. Cela a généré une nouvelle
définition du type Universal_Time,
par analogie avec Universal_Integer et
Universal_Real. Universal_Time
a une précision suffisante pour représenter exactement le
temps. Cette précision est supérieure ou égale à
un type flottant. Le cycle de simulation utilise Universal_Time
pour la variable du kernel Tc, qui représente le temps
courant dans la simulation, et Tn, qui représente le temps
suivant.
La fonction now est définie
pour retourner la valeur du temps courant de simulation, une valeur de
type Universal_Time, convertie après
troncature en une valeur la plus proche au format temps réel. Il
y a une autre fonction now qui retourne
la valeur courante de simulation tronquée à la valeur la
plus proche au format réel.
La fonction prédéfinie S'Last_Event,
charge une valeur de format réel, retourne le temps écoulé
depuis le dernier événement sur S.
Le cycle de simulation VHDL a été augmenté pour
prendre en compte le temps utilisé par l'algorithme analogique.
Le calcumateur analogique est activé dans chaque cycle de simulation,
juste avant l'avancement du temps courant (Tc).
2.8. Intéraction A/D et D/A
Si une des quantités spécifiées dépasse
le seuil d'une amplitude désignée (thresholds), avant
la fin du calcul de la solution (prochain événement), le
calculateur finira le travail prématurément. Pour n'importe
quelle valeur scalaire Q, le booléen Q'Above(level)
est vrai si Q > level et réciproquement. Un événement
attaché à Q'Above(level),
intervient à chaque changement de signe de Q - level. Le
dépassement d'un seuil peut être utilisé pour la conversion
Analogiqe-Numérique (NA), comme dans le comparateur suivant :
Un processus numérique qui est sensible à un tel signal,
s'exécute à ce moment précis lorsque le seuil est
dépassé, phénomène qui ne peut avoir de représentation
dans la base de temps réel. De tel temps sont appelés offset
time. Tout processus se déclenchant à partir d'un signal
assigné après un retard dans un processus déclenché
par un offset time est lui aussi exécuté à
partir de cet offset time et les processus repoussés, comme
d'habitude, s'exécutent juste avant que le temps soit mis à
jour. Néanmoins tout assignation retardée de signaux arrive
à un moment représentable en base de temps réel, traduit
par troncation.
Si une discontinuité apparaît dans la solution du DAE,
la structure mathématique l'indique au calculateur. Ce mécanisme
d'arrêt (break) dessert ce
but : un modèle doit générer un pseudo-événement
à chaque temps où intervient une discontinuité. Une
discontinuité apparaîtra si une quantité est assimilée
à un signal dans une simple déclaration et qu'un événement
intervient sur ce signal. Il n'y a aucun algorithme connu qui peut de manière
sure et efficace détecter et corriger correctement les discontinuités
sans connaissance du moment d'apparition. Par conséquent le langage
inclue une déclaration d'arrêt (break)
qui a une forme séquentielle et simultanée. L'exécution
d'un break crée un événement
sur le signal break implicite, ce signal n'est pas visible dans le modèle.
La sémantique du langage requière que le calculateur assume
la discontinuité quand le processus assigné au signal break
est actif. La déclaration de break
inclue une possibilité pour la spécification des nouvelles
conditions initialisées pour les quantités spécifiées,
qui seront appliquées juste après la discontinuité.
L'exemple suivant démontre l'utilisation d'un arrêt dans un
convertisseur simple NA :
entity dac is
generic (vhigh : Real
:= 5.0); -- tension de sortie pour s='1'
port ( signal
s : in bit;
-- entrée binaire
terminal a : out
Electrical); -- sortie analogique
end entity dac;
architecture simple of
dac is
quantity v across
i through a; -- branch quantities to
ground
begin
if s='0' use
else v==high; -- high output
end use;
break on s; -- prevision de
discontinuite
end architecture simple;
Un modèle doit inclure une déclaration d'arrêt appropriée
si le nom du signal apparaît dans une expression d'une déclaration
simultanée et si un événement sur se signal cause
une discontinuité. De même, une déclaration d'arrêt
est requise si une discontinuité est introduite par la sélection
d'une valeur différente d'une déclaration simultanée,
par exemple, lorsque la valeur de la condition du mot clé if
change.
Néanmoins, les déclarations de break
ne sont pas nécessaires dans les quantités prédéfinies
S'Ramp ou S'Slew
même si ces quantités apparaissent dans des expressions d'instructions
simultanées.
2.9. Initialisation et point stable de fonctionnement
La solution d'un système DAE dans un intervalle continu dépend
uniquement des inconnues au début d'intervalle. Ces valeurs doivent
être des solutions du DAE et dépendant de la méthode
d'initialisation, d'autres équations vont en découler. Le
modèle continu doit être initialisé avec un algorithme
convenable avant que la simulation ne commence et doit être réinitialisé
à chaque discontinuité.
En général, il y a plusieurs conditions initiales qui
satisfont le DAE, car durant l'initialisation il y a plus d'inconnues que
d'équations (x et dx/dt sont des inconnues durant
l'initialisation). La sélection d'un membre particulier du système
dépend de paramètres tels que la convention interne ou le
choix de l'utilisateur.
Le langage VHDL-AMS distingue entre l'initialisation réelle,
qui étend le pas d'initialisation défini par VHDL à
un pas similaire pour les parties continues des modèles, et la recherche
du point stable de fonctionnement d'un modèle. Pour un modèle
purement continu le point de fonctionnement représente, en l'absence
de spécification des conditions d'initialisation par l'utilisateur,
le point stable de fonctionnement continu du modèle. Ce choix est
très important pour le concepteur analogique et c'est une partie
importante de la simulation fréquentielle.
Le langage défini le point stable de fonctionnement d'un modèle
comme l'état précédent juste au début des processus
prolongés, à l'instant 0.0. Pendant la recherche du point
de fonctionnement stable, le système d'équations est augmenté
en absence de spécification des conditions initiales de l'utilisateur,
par :
Les conditions initiales sont spécifiées au même instant
que la déclaration du break,
décrite plus tôt :
break q1 => expression1, q2 => expression2;
Les conséquences de la spécification des conditions initiales
sont que les équations provenant du système (2) sont
remplacées par les conditions initiales. Par exemple les équations
dq1/dt et dq2/dt égalent à zéro. Ceci
n'intervient simplement que si q1'Dot et q2'Dot apparaissent
dans le modèle, sinon ces équations ne font pas parties de
(2). Des recherches sont en cours pour étendre la syntaxe de la
déclaration du break pour
fournir plus de flexibilité dans la spécification des conditions
initiales.
Le processus du noyau de simulateur contrôle le driver du signal
prédéfini DOMAIN, de type énuméré
: DOMAIN_TYPE. Pendant l'initialisation, la valeur du signal DOMAIN
est positionnée à INITIALIZATION_DOMAIN. Quand le
point de fonctionnement stable a été trouvé le noyau
assigne une nouvelle valeur au signal DOMAIN : TIME_DOMAIN
si le point de fonctionnement stable a été trouvé
durant une simulation temporelle, et FREQUENDY_DOMAIN si la simulation
est fréquentielle. En conséquence l'exécution des
processus repoussés (posponed)
est sautée et au moins un autre cycle delta est exécuté
pour mettre à jour le signal DOMAIN. Ceci signifie qu'il
est possible de reinitialiser un processus quand le point de fonctionnement
stable a été trouvé, et de définir différentes
manières de trouver le point de fonctionnement stable, en simulation
temporelle ou fréquentielle.
2.10. Modélisation et simulation dans le domaine
fréquentiel.
Les concepteurs sont souvent intéressés par le comportement
des systèmes continus dans le domaine fréquentiel. La plupart
des systèmes dont la solution fréquentielle est intéressante,
sont utilisés en fonctionnement linéaire et des algorithmes
spécifiques sont disponibles pour retrouver la réponse fréquentielle
très efficacement. Le langage VHDL-AMS inclue des définitions
qui supportent les simulations dans le bruit et en régime alternatif
comme Spice de manière compatible, basées sur les modèles
petits signaux dérivés des équations (1).
Le modèle petit signal est défini par le terme
linéaire du développement en série de Taylor avec
le respect de toutes les quantités, du système (1) obtenues
pour la valeur du signal DOMAIN : FREQUENCY_DOMAIN, avec
l'évaluation partielle des dérivées au point stable
de fonctionnement. Le modèle petit signal est un modèle
linéaire incrémental décrit par un système
linéaire d'équations avec incrémentation des quantités
des inconnues. Par conséquent, les résultat de la simulation
petit signaux ne sont que des approximations du vrai comportement
physique du système.
Le système d'équations décrivant le modèle
petit signal est homogène à moins que le modèle
ne spécifie des stimulations spécifiques du domaine fréquentiel.
Le langage définie deux sortes de sources (source quantities).
La source spectrale qui définie les stimulations pour la
simulation fréquentielle, une source de bruit qui spécifie
une source de bruit pour la simulation fréquentielle du bruit. Les
sources doivent être déclarées à l'aide d'une
syntaxe spéciale ; leur type peut être un type composé.
L'exemple suivant montre l'exemple d'un modèle d'une source de courant.
Sa valeur est constante, et définie aussi une stimulation pour les
simulations en domaine fréquentiel en alternatif et en bruit au
travers d'une source spectrale à l'aide des valeurs q_ac
pour les sources spectrales et q_ns pour le bruit.
entity current_source is
generic (dc, ac_mag, ac_phase, ns_mag
: Real :=0.0);
port (terminal p, m : out
Electrical);
end entity current_source;
architecture unlikely of
current_source is
quantity i through
p to m;
quantity q_ac : Real
spectrum ac_mag, ac_phase;
quantity q_ns : Real
noise ns_mag;
begin
end architecture unlikely;
Les expressions définissant l'amplitude pour une source ou la phase
pour une source spectrale sont des expressions VHDL générales.
En particulier, elles peuvent inclure les noms d'autres quantités,
qui permettent, par exemple, de définir des sources de bruit dépendantes.
De plus ces expressions peuvent inclure des appels à la fonction
FREQUENCY qui retourne la fréquence
de simulation courante. C'est le seul endroit ou cette fonction peut être
appelée, c'est à dire que le langage supporte la spécification
de stimulations fréquentielles dépendantes mais pas la spécification
de comportements fréquentiels liés.
2.11. Divers
VHDL-AMS contient d'autres attributs résumés ici. En plus,
des quantités explicites et implicites déjà introduites,
le langage définit un certain nombre d'autres quantités implicites.
La plupart ont été défini pour simplifier l'écriture
des modèles; leurs fonctionnalités sont définies par
un bloc équivalent. Dans la définition Q et
S représentent respectivement une quantité et un signal.
-
la quantité Q'Delayed(T),
où T est une expression statique de type réel, elle
implémente un délai idéal, c'est à dire que
la valeur de Q est fixée pour le temps courant moins T.
Son type est celui de Q, il peut être du type composé.
-
la quantité Q'Zoh(T, Initial_Delay), où T et
Initial_Delay sont des expressions statiques de type réel,
implémente le maintien à zéro pour un période
T et à un après Initial_Delay secondes. Son
type est celui de Q, il peut être du type composé.
-
La quantité Q'Ltf(Num, Den)
implémente la transformée de Laplace avec Q en
entrée, c'est à dire le rapport de deux polynômes en
s, avec pour numérateur les coefficients spécifiés
par Num et même chose pour le dénominateur. Num
et Den doivent être des expressions statiques de type prédéfini
vecteur réel. Le type de Q'Lft
est le type de Q et doit être de type scalaire.
-
la quantité Q'Ztf(Num, Den, T,
Initial_Delay) implémente la transformé en z de
Q, c'est à dire le rapport de deux polynômes en z,
avec les coefficients du numérateur défini par Num
et les coefficient du dénominateur défini par Den.
La période d'échantillonnage est T et le premier
échantillon intervient après Initial_Delay seconde.
Num et Den sont des expressions statiques de type vecteur
réel, T et Initial_Delay doivent être des
expression statique de type réel. Le type de Q'Zft
est le type de Q et doit être de type scalaire.
-
la quantité Q'Slew(Max_Rising_Slope,
Max_Falling_Slope) suit Q, mais son changement au cours du
temps est restreint par la valeur maximum de la pente. Max_Rising_Slop
et Max_Falling_Slop doivent être de type réels.
Si Max_Falling_Slop n'est pas défini sa valeur par défaut
est Max_Rising_Slop, si rien n'est spécifié la valeur
de Q'Slew est identique à
Q à tous moments. Le type de Q'Slew
est le type de Q et doit être de type scalaire.
-
la quantité S'Slew(Max_Rising_Slope,
Max_Falling_Slope) ou S est un signal de type flottant
qui suit S, mais varie linéairement en rampe avec sa
valeur courante quand le signal S a un évènement
sur la nouvelle valeur de S. Max_Rising_Slop et Max_Falling_Slop
doivent être de type réels. Si Max_Falling_Slop
n'est pas défini sa valeur par défaut est Max_Rising_Slop,
si rien n'est spécifié la valeur de S'Slew
est identique à S à tous moments. Le type de S'Slew
est le type de S. Un modèle utilisant S'Slew
n'as pas besoin de déclaré des break
pour la discontinuité de S'Slew.
-
la quantité S'Ramp(Tr, Tf)
ou S et un signal de type flottant suit S mais varie
linéairement en rampe durant un temps de montée Tr et
un temps de descente Tf à partir de sa valeur courante
quand S a un évènement sur la nouvelle valeur de
S. Tr et Tf doivent être de type réels.
Si Tr n'est pas défini sa valeur par défaut est
Tf. Si aucun de deux n'est spécifié leurs valeurs
par défaut sont 0.0 c'est à dire que la valeur de S'Ramp
est identique à la valeur de S à tous instant. Le
type de S'Ramp est le type de S.
Un modèle utilisant S'Ramp
n'as pas besoin de déclaré des break
pour la discontinuité de S'Ramp.
Les modèles continus ont souvent besoin de fonctions mathématiques
pour décrire le comportement d'un composant physique. De tels fonctions
ne font pas parties du langage VHDL-AMS mais sont disponibles avec les
packages VHDL 1076.2.
En plus, une condition nécessaire pour la résolution du
système d'équations (1) est qu'il y ait autant d'équations
que d'inconnues. La définition du langage VHDL-AMS inclue des règles
supplémentaires pour chaque entité conçue qui garanti
que cette condition est satisfaite.
3.0 Modeles de base.
3.1. Resistance
La modélisation d'une resistance est assez simple. L'équation
régissant une résistance est : U = R * I.
Le programme suivant décrit une résistance :
architecture one of
resistor is
quantity resistor_u across
n1 to n2;
quantity resistor_i through
n1 to n2;
begin
resistor_i == resistor_u / resistance;
-- ou resistor_u == resistance * resistance_i
end architecture one;
La modélisation de la résistance peut etre plus complète
en tenant compte de sa variation en fonction de la température.
L'équation qui régit la valeur de la résistance en
fonction de la température est :
Le programme suivant met en oeuvre cette équation :
3.2. Inductance
Comme pour la modélisation de la résistance, le programme
décrivant une inductance est assez simple. L'équation qui
décrit une inductance est :
La fonction dérivée utilisée pour l'équation
décrivant une inductance est :
Le programme suivant décris une inductance :
entity inductor is
generic( L : real);
port (terminal
n1, n2 : electrical);
end inductor;
architecture one of
inductor is
quantity inductor_u across
n1 to n2;
quantity inductor_i through
n1 to n2;
begin
inductor_u == L * inductor_i'dot;
end one;
3.3. Capacité
L'équation qui décrit un condensateur est :
ou en impliquant les charges :
Le programme suivant décrit un condensateur :
architecture one of
capacitor is
quantity capacitor_u across
n1 to n2;
quantity capacitor_i through
n1 to n2;
begin
capacitor_i == C * capacitor_u'dot;
end one;
3.4. Diode
Le programme suivant décrit une diode. Les équations
(pour ce modèle) qui décrivent la diode sont les suivantes
:
Nous pouvons alors écrire le programme :
architecture one of
diode is
quantity vdiode across
a to c;
qauantity idiode, cap through
a to c;
quantity charge : coulomb;
begin
idiode == A*Iss*(exp((vdiode-Rs*idiode)/(n*Vt))
-1);
charge == tau*idiode-2.0*Cj0*sqrt(Phi**2-Phi*vdiode);
icap == charge'dot;
total_current == icap+idiode;
end one;
Dans la description de la diode, les paramètres Iss, n, Vt,
tau, Cjo, Phi doivent être initialisés par l'utilisateur,
lors de l'utilisation de la diode en tant que composant dans un circuit.
3.5. Ligne de transmission
Une ligne de transmission est composée de deux ports qui sont constitués
d'une source de tension en série avec une résistance. La
source de tension est dépendante du temps present moins le temps
de délai.
Les deux équations pour une ligne de transmission sont :
C'est deux équations peuvent être transcrit en VHDL-AMS.
-----------------------------
-- ligne de transmission
-----------------------------
entity ligne
generic (td, z0: real);
port (terminal
t1, t1r, t2, t2r: electrical);
end ligne;
architecture t_ligne of
ligne is
terminal t1x, t2x : electrical; --
2 noeuds externes
quantity v1r across
t1 to t1r;
quantity v1x across
i1x through t1 to
t1x;
quantity v1xr across
t1x to t1r;
quantity v2r across
t2 to t2r;
quantity v2x across
i2x through t2 to t2x;
quantity v2xr across
t2x to t2r;
begin
v1xr == v2r'delay(td) + z0 * i2x'delay(td);
v2xr == v1r'delay(td) + z0 * i1x'delay(td);
end t_ligne;
Lorsque l'on voudra utiliser le composant décrivant une ligne de
transmission, il faut donner une valeur a td et z0. Nous
aurons alors un programme de ce style.
architecture XXX of
YYY is
component ligne
port(terminal
t1, t1r, t2, t2r : electrical);
generic (td, z0 : real);
end ligne;
...
begin
line1 : ligne
port map( t1 => XX, t1r => YY, t2
=> ZZ, t2r => WW);
generic map (td => AA, z0 => BB);
-- ici, on fournis les valeurs
....
end XXX;
3.6. Transistor bipolaire
Pour décrire un transistor bipolaire, plusieurs niveaux de modélisation
sont possibles. Nous allons tout d'abord modéliser le transistor
bipolaire avec les équations d'Ebers et Moll.
Rappel des équations Ebers et Moll :
Pour mettre en oeuvre ces équations il faut au préalable
définir les coefficients suivant : BetaF, BetaR, Is0, Vbe, Nf,
Nr, Vth. Le coefficient Vth est défini en fonction de
la température et de deux constantes.
Ces différents coefficients sont déclarés dans
la partie generic :
generic( Iso : real;
-- courrant de saturation de transport
Bf : real; -- beta direct ideal
Nf : real; -- coefficient d'emission
direct
Br : real; -- beta inverse ideal
Nr : real; -- coefficeint d'emission
inverse
Temperature : real -- temperature);
Pour le coefficient Vth, il est donné comme une constante. Il sera
implémenté de la maniere suivante :
constant ElectronCharge : real
:= 1.6021892E-19;
constant Boltzmann : real
:= 1.380662E-23;
constant Vth : real
:= Boltzmann * Temperature / ElectronCharge;
-- la temperature etant definie dans le generic
Nous pouvons alors écrire le programme décrivant le transistor
bipolaire avec les équations d'Ebers et Moll.
entity BJT is
generic( Iso : real;
-- courrant de saturation de transport
Bf : real; -- beta direct ideal
Nf : real; -- coefficient d'emission
direct
Br : real; -- beta inverse ideal
Nr : real; -- coefficient d'emission
inverse
Temperature : real -- temperature);
port( terminal collector,
base, emitter : electrical);
end BJT;
architecture EBERS_MOLL of
BJT is
constant ElectronCharge : real
:= 1.6021892E-19;
constant Boltzmann : real
:= 1.380662E-23;
constant Vth : real
:= Boltzmann * Temperature / ElectronCharge;
-- la temperature etant definie dans le generic
quantity Vbc across
Ibc through base to
collector;
quantity Vbe across
Ibe through base to
emitter;
quantity Itc through
collector to emitter;
begin
-- equation de la jonction collecteur
Ibc == Is0 / Br * exp( Vbc / ( Nr * Vth ) );
-- equation de la jonction emetteur
Ibe == Is0 / Bf * exp( Vbe / ( Nf * Vth ) );
-- equation de courant de transport
Itc == Ibe * Bf - Ibc * Br;
end EBERS_MOLL;
Nous pouvons aussi utiliser un package
pour définir les différents paramètres du transistor.
package BJT_0 is
type BJT_model0 is
record
Iso : real; -- courant de transport
sature
Bf : real; -- beta direct ideal
Nf : real; -- coefficient d'emission
direct
Br : real; -- beta inverse ideal
Nr : real; -- coefficient d'emission
inverse
end record BJT_model0;
end package BJT;
Dans le programme précédent, nous insérerons le package
de la manière suivante :
entity BJT is
generic(
model : BJT_model0 :=
( Is0 => 1E-16,
Bf => 100.0,
Nf => 1.0,
Br => 1.0,
Nr => 1.0)
);
port( terminal .....
end BJT;
Pour utiliser les paramètres, il est conseillé de les appeler
de la manière suivante :
model.Is0, model.Bf, model.Nf ...
Le transistor bipolaire peut être aussi modélisé avec
le modèle petits signaux hybride en pi de Giacoletto.
A la différence de la modélisation précédente,
la modélisation suivante ne fait pas appel a une modélisation
par équations mais à une modélisation par schéma
équivalent avec des éléments R, C, et
source de courant.
Pour écrire ce circuit, nous allons créer un package contenant
les valeurs des différents composants :
package Giacoletto is
type Giacoletto_model is
record
r_b : real; -- ohm
r_c : real; -- ohm
r_e : real; -- ohm
r_pi : real; -- ohm
r_o : real; -- ohm
r_mu : real; -- ohm
c_pi : real; -- farad
c_js : real; -- farad
c_mu : real; -- farad
g_mf : real; -- a/v
end record Giacoletto_model;
end package Giacoletto;
Pour décrire le modèle, nous allons assembler les modèles
des composants décrits précédement pour la résistance,
le condensateur et nous décrirons, en premier, le modèle
de la source de courant commandée en tension.
Le modèle décrivant une source de courant commandée
en tension est très simple. L'équation qui régit le
fonctionnement d'une telle source est : I = V * g
Un tel composant ne peut pas etre écrit seul, car il n'a que
deux noeuds de connections et il y a besoin de deux autres noeuds pour
spécifier la tension ou le courant de contrôle et ces deux
noeuds ne peuvent pas être des noeuds internes car ils sont reliés
à d'autres composants.
Donc le seul moyen pour décrire une source controlée
est de définir dans la description du circuit l'équation
de cette source.
Le modèle décrivant le schéma de Giacoletto est
le suivant:
entity Transistor_Giacoletto is
generic(
model : Giacoletto_model :=
( r_b => 300;
r_c => 50;
r_e => 2;
r_pi => 5.2e3; -- 5.2k
r_o => 100e3; -- 100k
r_mu => 200e6; -- 200M
c_pi => 15.6e-12; -- 15.6p
c_js => 0.44e-12; -- 0.44p
c_mu =>0.16e-12; -- 0.16p
g_mf => 38e-3; -- 38 mA/V
)
);
port( terminal collecteur,
base, emetteur : elecrtical);
end entity Transistor_Giacoletto;
architecture Giacoletto of
Transistor_Giacoletto is
-- declaration des noeuds internes
terminal b, e, c : eletrical;
-- declaration des tensions et des courants
quantity vf across
b to e;
quantity I_ce throught
c to e;
-- declaration des composants
component resistor is
generic (resistance: real);
port (terminal
n1, n2: electrical);
end component;
component capacitor is
generic( c : real);
port (terminal
n1, n2 : electrical);
end component;
begin
r_b : resistor port map (n1 => base,
n2 => b);
r_c : reistor port map (n1 =>collector,
n2 => c);
r_e : resistor port map (n1 => emetteur,
n2 => e);
r_pi : resistor port map (n1 => b, n2
=> e);
r_o : resistor port map (n1 => c, n2 =>
e);
r_mu : resistor port map (n1 => b, n2
=> c);
c_pi : capacitor port map (n1 => b, n2
=> e);
c_js : capacitor port map (n1 => c, n2
=> ground);
c_mu : capacitor port map (n1 => b, n2
=> c);
generic
map (c_m);
-- la source de courant commandee en tension
I_ce == g_mf * vf;
end Giacoletto;
3.7. Transistor MOS
Pour décrire un transistor MOS, il éxiste plusieurs modeles.
Nous allons présenter en premier un modéle NMOS au niveau
1.
Nous avons les équations du MOS au niveau 1 comme suit:
Avec :
Nous avons alors comme paramètres: Qss, tox, Eg, k, T, q,
Na, ni, W, L,Vbs
Ces différents paramètres peuvent être réunis
dans un package; d'autres peuvent être définis comme des constantes.
package MOS_param is
type mosmodel_1 is
record
Nss : real;
Tox : real;
Eg : real;
Phim : real;
Ki : real;
mun : real;
Na : real;
Vbs : real;
end record mosmodel_1;
constant EpsilonS0 : real
:= 8.85418e-12;
constant EpsilonOX : real
:= 3.9 * EpsilonS0;
constant EpsilonSI : real
:= 11.7 * EpsilonS0;
constant ElectronCharge : real
:= 1.6021892e-23;
constant Boltzmann : real
:= 1.380662e-23;
constant ni : real
:= 1.45e16;
end package MOS_param;
Le programme s'écrit de la manière suivante :
architectural mos1 of
mos is
quantity Id through
drain;
quantity Vbs across
bulk to source;
quantity Vds across
drain to source;
quantity Vgs across
gate to source;
begin
mos_procedural : procedural is
variable Vth, Phi_F, Phi_ms, Cox,
Qss, Vfb, gamma, Vt0, beta : real;
begin
Vth := Boltzmann * Temperature / ElectronCharge;
Phi_F := Vth * ln( Na / ni);
Phi_ms := Phi_m - ( Ki + Eg / 2 + Phi_F);
Cox := EpsilonOX / Tox;
Qss := Nss * ElectronCharge;
Vfb := Phi_ms - Qss / Cox;
gamma := sqrt( 2 * ElectronCharge * EpsilonSI * Na) / Cox;
Vt0 := Vfb + 2 * Phi_F + gamma * sqrt( 2 * Phi_F);
Vt := Vt0 + gamma * ( sqrt(2 * Phi_F - Vbs) - sqrt(2 * Phi_F));
beta := mu_n * Cox * W / L;
if Vds < Vgs -Vt use
Id := beta * (1 + lamda * Vds) * ((Vgs - Vt) * Vds - Vds**2 / 2);
else
Id := beta / 2 * (1 + lamda * Vds) * (Vgs - Vt)**2;
end use;
end procedural;
end mos1;
Avec ce programme, lors de l'utilisation de ce composant, l'utilisateur
est obligé de donner une valeur aux différents paramètres
défini dans le generic de l'entity, car il n'y pas de procédure
d'initialisation des paramètres.
En annexe, il est fournit un modèle de transistor
MOS de niveau 3.
3.8. Amplificateur opérationnel
Comme pour les autres composants, l'amplificateur opérationnel peut
être décrit avec plus ou moins de précision.
Le programme qui suit présente un amplificateur opérationnel
simple :
entity aop is
generic(
model : AOPmodel1 :=
( gain => 10.0,
vmin => -15.0,
vmax => 15.0)
);
port (terminal vout,
vp, vn: electrical);
end entity aop;
architecture basic of
aop is
quantity vs across
vout to ground;
quantity vepsilon across
vp to vn;
begin
vs == model.gain * vepsilon;
-- limitation de la valeur de sortie aux valeurs des alimentations
if (vs >= model.vmax) use
end use;
if (vs <= model.vmin) use
end use;
end basic;
Dans ce modèle, le courant n'est pas pris en compte, il est seulement
décrit en fonction de la tension.
Le modèle suivant répresente mieux le comportement d'un
amplificateur opérationnel. Il prend en compte : le gain en boucle
ouverte, le produit gain*bande, les résistances d'entrée,
les courants d'entrée, le gain maximum en courant, le slew-rate
et la marge de la tension de sortie en fonction de la tension d'alimentation.
L'entité de cette structure est :
entity amplifcateur is
generic( gain, -- gain en boucle ouverte
gbw, -- produit gain-bande
rin, -- resistance d'entree
ibin, -- courant d'entree
imax, -- gain maximum du courant
sr, -- slew rate
ro, -- resistance de sortie
delta : real); -- limite de la tension
de sortie en dessous
-- de la tension d'alimentation
port( terminal vout,
vin_n, vin_p, vp, vn : electrical);
end entity amplificateur;
Nous avons comme constantes :
architecture ampli of
amplificateur is
constant c1 : real
:= imax / (sr*1.0e6); -- capacite gbw
constant gmnom : real
:= 2.0 * math_pi * gbw * c1; -- transconductance
constant r1 : real
:= gain / gmnom; -- resistance gbw
constant dvmax : real
:= gain / gmnom; -- region avec le gain lineaire
Les différentes quantités :
quantity Vin across
vin_p to vin_n;
quantity Iin through
vin_p to vin_n;
quantity Iin_p through
vin_p to ground;
quantity Iin_n through
vin_n to ground;
quantity Vout_p across
vout to vp;
quantity Vout_n across
vout to vn;
pour introduire les autres quantités, il faut déclarer un
noeud interne :
terminal cout : electrical;
et les quantités associées:
quantity Vout across
cout to ground;
quantity Igain, Irc, Ilimit through
ground to cout;
quantity Vcout_out across
cout to out;
Maintenant que les quantités sont données, nous pouvons écrire
le modéle.
begin
-- etage d'entree
Iin == Vin / rin;
Iin_p == ibin;
Iin_n == ibin;
-- gain en courant
assert abs(gmnom * dvmax) = abs(imax);
if Vin > dvmax use
elsif Vin < - dvmax use
else
end use;
-- pole dominant
Irc == c1 * Vcout'dot + Vcout / r1;
-- impedance de sortie
Icout_out == Vcout_out / ro;
-- limitation de la sortie
if Vout_p > - soft use
Ilimit == - gmnom * (Vout_p + soft);
elsif Vout_n < soft use
Ilimit == - gmnom * (Vout_n - soft);
else
end use;
end architecture ampli;
3.9. Sources controlées
Les différentes sources controlées sont :
-
la source de tension controlée en tension : VCVS,
-
la source de tension controlée en courant : CCVS,
-
la source de courant controlée en courant : CCCS,
-
la source de courant controlée en tension : VCCS.
Les équations les décrivants sont :
-
pour une VCVS :
Vsource = g_vcvs * Vcontrole,
g_vcvs est sans unité,
-
pour une CCVS :
Vsource = g_ccvs * Icontrole,
g_ccvs en V/A,
-
pour une CCCS :
Isource = g_cccs * Icontrole,
g_cccs sans unité,
-
pour une VCCS :
Isource = g_vccs * Vcontrole,
g_vccs en A/V.
Pour la réalisation d'une source controlée, il faut deux
noeuds pour la source controlée et deux noeuds pour la différence
de potentiel ou pour connaitre le courant traversant le branche qui commande.
Comme nous l'avons vu pour la réalisation du transistor bipolaire
à partir du modèle de Giacoletto, nous ne pouvons pas définir
un composant pour une source controlée.
Le seul moyen est d'écrire dans l'architecture du programme
l'équation qui régit la source controlée et de déclarer
les tensions et les courants utiles (quantity).
3.10. Stimulis
Pour exciter le circuit analogique, il existe différents types de
générateurs. En premier, les sources fixes de tension et
de courant, pour les définir, il suffit d'écrire :
On peut, facilement, implanter une source de tension alternative ou autre.
Il suffit de donner l'équation décrivant cette source :
library Discplines, IEEE;
use Disciplines.electrical_system.all;
use IEEE.math_real.all;
entity gene_sin
is
generic( ampl, freq : real);
port ( terminal
p, m : electrical);
end entity gene_sin;
architecture sin of
gene_sin is
quantity Ve across
p to m;
constant Pi : real
:= 3.1459;
...
begin
Ve == ampl * sin(2 * Pi * freq * NOW);
...
end architecture sin;
Le parametre NOW dans l'équation
représente le temps courant de simulation.
4.0 Description d'un système mixte : cas d'une
PLL.
Cet exemple illustre le cas d'un système mixte analogique-numérique
ou la plupart des mécanismes VHDL de base sont exploités.
On y voit:
-
l'utilisation de structures écrites précédement et
placées dans des librairies,
-
l'utilisation de composants décrits de manière comportementale
et structurel,
-
l'utilisation de composants numériques et analogiques.
Dans un premier temps, nous commentons les composants utilisés par
le système un à un.
4.1. Le VCO : description comportementale
Partie déclarative du VCO :
entity VCO is
generic(
fc: real := 1E6; -- frequence de coupure
fc pour la tension Vc
df: real := 0.5E6; -- [Hz/V], rapport
frequence/tension
Vc: voltage := 0.0 -- tension pour la frequence centrale
);
port( quantity
Vin: in voltage;
terminal OutTerminal: electrical);
-- la sortie est de type electrique
end entity VCO;
Partie description du VCO :
architecture PhaseIntegrator of
VCO is
constant TwoPi: real
:= 6.283118530718; -- 2pi
quantity Phase : real;
-- Phase is a free quantity:
-- definition d'une branche pour la tension de sortie
quantity Vout across
Iout through OutTerminal to
ground;
begin
break Phase => 0.0;
-- l'instruction break permet le positionnement des conditions
initiales
break Phase => Phase mod TwoPi on
Phase'above(TwoPi);
-- ici, break permet de conserver la phase dans le bon intervalle.
Phase'dot == TwoPi*realmax(0.5E6,
fc+(Vin-Vc)*df); -- equation de la phase
Vout == 2.5*(1.0+sin(Phase)); -- equation de la tension de sortie.
end architecture PhaseIntegrator;
4.2. Le comparateur analogique : description comportementale
Partie déclarative du comparateur.
entity AnalogComparator is
generic( Vthreshold: voltage := 0.0
); -- [V] tension de comparaison
port( terminal
Pve_T,Nve_T: electrical; -- entree analogique
signal Out_T: out
BIT ); -- sortie numerique
end entity AnalogComparator;
Description du comparateur analogique :
architecture Behavior of
AnalogComparator is
quantity DeltaV across
Pve_T to Nve_Y; -- tension d'entree differentielle
begin
-- the architecture consists of one concurrent signal assignment
statement
Vout <= `1' when DeltaV'above(0.0)
-- trigger event when V+>V-
else `0' when
not DeltaV'above(0.0); -- trigger event
when V+<=Vt-
end architecture Behavior;
4.3. Description du détecteur de phase
Description d'une bascule RS :
Description structurelle du détecteur de phase qui utlise les bascules
RS :
4.4. Description du filtre analogique
4.5. Description du compteur numérique
4.6. Description de la PLL
On peut se rendre compte avec cet exemple de la puissance du VHDL. Dans
un premier temps, tous les composants qui vont être utilisés
sont décrits un à un : ces composants de base sont très
faciles a décrire. Beaucoup entre ces composants sont deja présents
dans des librairies. L'étape finale consiste à utiliser la
fonction port map pour connecter
l'ensemble des composants utilisés pour décrire le système.
Pendant l'assemblage du système il faut prèter attention
aux différents types de signaux utilisés pour être
certain qu'ils soient compatibles.
5.0 Autres documentation sur le VHDL-AMS.
Quoiqu'assez nouveau, le VHDL-AMS est l'objet de beaucoup de travaux. Les
quelques adresses internet ainsi que les documentations suivantes peuvent
permettre de s'investir encore un peu plus dans le sujet.
5.1. Documentations délivrées par l'IEEE
(exemples et problèmes)
Site sur le problème du temps en VHDL-AMS :
Documentation du BRC (Ballot Resolution Commitee) :
Présentation du VHDL-AMS par Alain Vachoux :
Site en allemand :
5.2. Traducteur SPICE vers VHDL-AMS
Document présentant un traducteur Spice vers VHDL-AMS, avec des
exemples:
5.3. Sites universitaires
Site complet,à Southampton :
Site de l'universite de Cincinnati :
5.4. Scanner syntaxique
au Japon :
à Southampton :
Site de l'entreprise LEDA :
ANNEXE : Modélisation
au niveau 3 du MOS
Ce programme est composé de deux parties. La première
s'occupe de l'initialisation des paramètres des équations
décrivant le MOS. La seconde présente ces équations.
---------------------------------------------
-- modele VHDL-AMS a partir du transistor MOS de niveau 3 de SPICE
------------------------------------------------
library IEEE;
use IEEE.math_real.all;
-- declaration des differents parametres
package mosdata is
type mosmodel is
record
vt0 : real;
kp : real;
gamma : real;
phi : real;
tox : real;
nsub : real;
nss : real;
nfs : real;
tpg : real;
xj : real;
ld : real;
u0 : real;
vmax : real;
xqc : real;
kf : real;
af : real;
fc : real;
delta : real;
theta : real;
eta : real;
kappa : real;
end record mosmodel;
architecture mos3 of
mos is
vbulk:=Gamma*fshort*D+fn*A;
if model.nfs=0.0 then
else
delv:=kTQ*(1.0+qnfscox+vbulk*0.5/A);
end if; -- nfs = 0
vth:=Vfb+vbulk;
Vgstos:=Vgs-Vfb;
Vgst:=max(Vgs-vth,delv);
if (vgs>=vth) or (delv/=0.0) then
if (Vbs<=0.0) or (Phi /= 0.0) then
else
end if;
mobdeg:=1.0/(1.0+theta*Vgst);
if (model.vmax /=0.0) then
Ueff:=model.u0*mobdeg;
Tau:=Ueff/Leff*model.vmax;
else
end if;
Vsat:=Vgst/(1.0+B);
Vsat:=Vsat*(1.0-0.5*Tau*Vsat); -- not quite the same as SPICE
Vpp:=min(Vds,Vsat);
fdrain:=1.0/(1.0+Tau*Vpp);
if (Vgs<vth+delv) and (nfs>0.0)
then
stfct:=exp((Vgs-vth-delv)/delv);
else
end if;
if Vds>=Vsat then
if (model.kappa>0.0) and (xd>0.0)
then
if model.vmax=0.0 then
deltal:=sqrt(model.kappa*xd*xd*(Vds-Vsat));
else
dcrit:=(xd*xd*model.vmax*0.5)/(Ueff*(1.0-fdrain));
deltal:=sqrt(model.kappa*xd*xd*(Vds-Vsat)+dcrit*dcrit)-dcrit;
end if;
if deltal<=0.5*Leff then
else
end if;
else --kappa=0.0 or xd=0.0
end if;
It:=Vgst-Vpp*(1.0+B)*0.5;
Beta:=Beta*mobdeg;
Ids:=Beta*Vpp*It*C*fdrain*stfct;
else
end if; -- vgs >= vth
if Cox /= 0.0 then
--Charges
if Vgs<=vth then
if Gamma /= 0.0 then
if Vgstos < -A then
Qg:=Cox*(Vgstos+A); -- Accumulation
else
Qg:=0.5*Gamma*Cox*(sqrt(4.0*(Vgstos+A)+sqr(Gamma))-Gamma);
end if ; -- vgstos <-A
else-- Gamma = 0.0
end if; -- gamma /= 0
Qb:=-Qg;
Qc:=0.0;
else
-- depletion mode:
R:=(1.0+B)*Vpp*Vpp/(12.0*It);
Qg:=Cox*(Vgstos-Vpp*0.5+R);
Qc:=-Cox*(Vgst+(1.0+B)*(R-Vpp*0.5));
Qb:=-(Qc+Qg);
end if; -- vgs<=vth
else
Qg:=0.0;
Qc:=0.0;
Qb:=0.0;
end if; -- cox /= 0
-- equations for charges (in a procedural we have assignments to
quantitites):
Qcq := Qc;
Qgq := Qg;
Qbq := Qb;
-- equations for currents:
Idq := channel*forward*Ids+channel*xqc*Qc'dot;
Igq := channel*Qg'dot;
Ibq := channel*Qb'dot;
Isq := -Idq - Igq - Ibq;
end procedural;
end architecture mos3;
retour
au debut