• Aucun résultat trouvé

1.2 Initialisation de la mémoire

N/A
N/A
Protected

Academic year: 2022

Partager "1.2 Initialisation de la mémoire "

Copied!
22
0
0

Texte intégral

(1)

Scilab

L’étude d’un oscillateur à contrôle numérique (OCN ou NCO en anglais), encore appelé oscillateur modulateur à contrôle numérique (OMCN) va nous permettre d’approcher les « méga-fonctions » que propose le logiciel de synthèse de FPGA et CPLD, Max+plus II. Celles-ci permettent une implantation rapide et efficace de composants numériques complexes tel que mémoires, additionneurs, registres multiplieurs numériques etc…. On trouvera plus de détails en annexe 1.

Ces composants traitant souvent des données analogiques numérisées, il peut être intéressant de visualiser les signaux à l’entrée du CAN et la sortie du CNA. Le simulateur de Max+plus II ne permettant pas cette option, nous utiliserons ses fichiers d’initialisation et de résultat pour réaliser une interface avec un logiciel tel que Scilab (logiciel gratuit –voir annexe 2- aux fonctionnalités similaires à Matlab). Cette interface nous permettra alors l’affichage des grandeurs souhaitées.

Une (très) légère familiarisation avec le logiciel Scilab est évidemment nécessaire pour mener à bien cette étude. Quelques notions (très légère également) de langage C sont les bienvenues. La connaissance des fonctionnalités de base de Maxplus II est par contre indispensable.

Le prétexte de l’étude sera un oscillateur numérique commandé, circuit très en vogue actuellement (exemple le circuit HSP 45-116 de chez Harris), en particuliers dans le domaine des télécommunications.

Comme son nom l’indique, ce circuit permet de générer numériquement un signal, dont on va pouvoir ajuster les paramètres, en particulier la fréquence, mais aussi la phase et l’amplitude, de manière numérique également. Deux solutions sont classiquement utilisées pour la synthèse de signaux : - la synthèse indirecte à boucle à verrouillage de phase semi-numérique ;

- la synthèse numérique directe (SND ou DDS pour Direct Digital Synthesis), que nous allons étudier maintenant.

-

La première solution présente l’avantage de pouvoir directement travailler avec une fréquence de sortie élevée (l’oscillateur étant analogique), tandis que la seconde entièrement numérique (hormis le CNA en fin de chaîne) présente tous les avantages liés à cette technologie. L’inconvénient lié à une fréquence de sortie limitée peut être pallié par un décalage fréquentiel du signal de sortie du CNA du NCO.

1 Principe de base

L’idée de départ de la synthèse numérique de fréquence est l’incrémentation à fréquence fixe par une horloge à quartz, d’un compteur dont la sortie va lire une mémoire morte. Si dans celle-ci, à chaque adresse correspondant à l’incrément de temps, se trouve l’amplitude du signal souhaité, après conversion numérique analogique, on obtient le signal recherché.

Généralement celui-ci est sinusoïdal, mais ce n’est pas une obligation (en particulier en instrumentation). Dans le cas sinusoïdal, les données de la mémoire peuvent être vues comme la phase instantanée du signal, et les adresses comme un incrément de phase.

Cette structure ne permet pour l’instant pas d’ajustage de fréquence, ni d’aucun autre paramètre ; nous la modifierons en conséquence par la suite.

(2)

1.1 Saisie du schéma

Décrivons d’abord cette première partie avec le logiciel Max+plus II. Bien que sur les circuits réels le nombre de bits utilisés soit important, nous nous contenterons ici d’une mémoire de 256 mots de 8 bits afin de ne pas trop alourdir le projet ; il sera aisé de le modifier par la suite.

Ouvrir une nouvelle feuille graphique (.gdf) et y implanter le compteur et la mémoire, par le biais des composants prédéfinis (clic droit dans la feuille, puis Enter Symbol). Nous utiliserons :

- le composant LPM_COUNTER de la bibliothèque c:\maxplus2\maxlib\mega_lpm pour le compteur ; la fenêtre qui s’ouvre alors permet de définir un compteur 8 bits, avec une horloge comme seul signal d’entrée ;

- la mémoire RAM LPM_RAM_IO de la même bibliothèque ; le choix d’une RAM plutôt qu’une ROM (dans un FPGA, la différence se situe simplement au niveau de la possibilité d’écriture) est justifié par une mise en œuvre plus facile (le compilateur ne génère pas d’erreur en cas d’absence de fichier d’initialisation). Choisir les paramètres comme indiqué sur le schéma ci-après en optant pour une mémoire de 256 mots de 8 bits, à lecture et écriture asynchrone (pas d’horloges, juste un signal d’écriture toujours placé au niveau logique 0). Pour fichier d’initialisation, laisser la case

« LPM FILE » vierge pour l’instant.

Placer les ports d’entrées et de sortie, faire une compilation en vue de simulation fonctionnelle (le fichier à été sauvegardé ici sous le nom « basic.gdf »).

1.2 Initialisation de la mémoire

Afin de pouvoir tester notre circuit, il va falloir écrire les données dans la mémoire. Cela peut se faire en indiquant un fichier d’initialisation (LPM_FILE), dans les paramètres. Ce fichier, d’extension

« .mif », pour « memory initialization file », est un fichier texte précisant la valeur de chaque mot à chaque adresse. Pour obtenir le format souhaiter, taper « memory initialization file » dans la recherche de l’aide en ligne. Observer la structure de ce type de fichier.

Pour générer le fichier « .mif », plutôt que d’entrer les 256 valeurs une par une, nous allons les générer automatiquement à l’aide de Scilab.

Ouvrir ce dernier et entrer le script suivant : //écriture d'un fichier mémoire

clear;

//

// changement du répertoire courant vers celui de max+plus // ici h:\max\Nco\cmpt_mem

chdir('h:\max\Nco\comp_mem') ; //

// définition des 256 incréments de phase correspondant aux adresses

(3)

//

// et mise sous forme de vecteur colonne ft=0:255;ft=ft';

//

// contenu de la mémoire, sinusoïde centrée sur le milieu de la dynamique des valeurs x=127*(1+sin(2*%pi*ft/256));

//

// création et ouverture d’un fichier « mem.mif » en écriture fd=mopen("mem.mif","w");

//

// écriture des adresses et données, sous forme d’entiers (%i), avec caractère de tabulation (\t) // séparées par « : » et ligne terminée par « ; », puis retour à la ligne (\n)

mfprintf(fd,"\t%i : \t%i \t ; \n",ft,x);

//

// fermeture du fichier mclose(fd);

Après la définition des variables, les fonctions d’écriture, d’ouverture et fermeture du fichier ont la même syntaxe qu’en langage C.

Ouvrir ensuite le fichier avec un éditeur de texte quelconque. Celui de Max+plus convient parfaitement, la gestion des extensions y étant d’autre part très simple ; il faudra cependant être attentif au moment d’enregistrer que le fichier désiré est bien celui du projet courant (Ctrl Shift J).

Cette solution présente d’autre part l’avantage de laisser libre le Bloc-notes pour les programmes Scilab.

Modifier alors le fichier de manière à le rendre compatible avec un fichier « .mif ».

On obtient finalement ceci : DEPTH = 256;

WIDTH = 8;

ADDRESS_RADIX =DEC;

DATA_RADIX =DEC;

CONTENT

BEGIN

0 : 127 ; 1 : 130 ; 2 : 133 ; 3 : 136 ; 4 : 139 ;

………..

252 : 114 ; 253 : 117 ; 254 : 120 ; 255 : 123 ; END;

Remarque : ces dernières opérations pouvaient se faire également au moyen d’instructions Scilab ; il serait également envisageable de décrire une fonction réalisant ces opérations automatiquement.

Déclarer ensuite le fichier « mem.mif » dans les paramètres de la mémoire (le nom doit être entre guillemet anglais et ne pas contenir de caractères particuliers, du type souligné ou autres).

Compiler le projet et lancer une simulation fonctionnelle sur 30 µs avec une horloge à 100 ns (grille à 50 ns).

(4)

On vérifie bien que les données inscrites en mémoires se retrouve en sortie lorsque leur adresse est présente sur le bus (revoir les premières lignes du fichier d’initialisation).

1.3 Lecture d’un fichier de sortie du simulateur

Afin de pouvoir afficher ces données sous forme analogique dans Scilab, nous allons maintenant demander au simulateur de créer un fichier table de résultat, de type « .tbl » : File \ Create Table File.

Si aucune spécification contraire n’est donnée, le fichier prend le nom du projet en cours avec l’extension « .tbl » (ici « basic.tbl »).

Ouvrir ce fichier avec un éditeur de texte quelconque, observer sa structure. Supprimer tout ce qui est commentaire et initialisation des paramètres (y compris la dernière ligne de données indéfinies, ainsi que le « ; » qui suit), pour ne garder que les données et obtenir le fichier suivant, que l’on sauvegardera avec un nom différent de préférence (basic_scilab.tbl par exemple).

0.0> 0 = 7F 00 50.0> 1 = 7F 00 50.1> 1 = 82 01 100.0> 0 = 82 01 150.0> 1 = 82 01 150.1> 1 = 85 02 200.0> 0 = 85 02 250.0> 1 = 85 02 250.1> 1 = 88 03 300.0> 0 = 88 03 350.0> 1 = 88 03 350.1> 1 = 8B 04 400.0> 0 = 8B 04

………

49850.0> 1 = 59 F2 49850.1> 1 = 5C F3 49900.0> 0 = 5C F3 49950.0> 1 = 5C F3 49950.1> 1 = 5F F4

Nous récupérons ensuite dans Scilab les données qui nous intéressent. Comme nous pouvons le remarquer, le simulateur nous fournit trois fois la même valeur par période d’horloge. Notre système étant synchrone, nous prendrons donc une valeur sur trois.

Dans Scilab, on écrit alors le programme suivant :

// lecture d'un fichier « .tbl » issus de Max+plus clear;

//

// changement du répertoire courant vers celui de max+plus // ici h:\max\Nco\cmpt_mem

(5)

//

chdir('h:\max\Nco\comp_mem') ; //

// ouverture du fichier basic_scilba.tbl fd=mopen("basic_scilab.tbl","r");

//

// récupération des données, qui se présentent sous la forme d’un flottant (%f), d’un caractère « > », // d’un entier (%i), du signe « = » et de deux nombres en hexadécimal (%x),

// ils seront convertis en décimal

// n est renvoyé par Scilab pour préciser le nombre de données par ligne [n,temps,hor,donnee, adresse]=mfscanf(-1,fd,"%f> %i = %x %x");

//

// fermeture du fichier mclose(fd);

//

// « data » comprend tous les échantillons de donnée // du premier à la longueur de donnée, par pas de 3 data=donnee(1:3:length(donnee));

On peut ensuite afficher le résultat dans Scilab par le programme suivant :

//affichage des résultats //

// création d’un variable temps, de même longueur que data // d’incrément 100 ns, exprimée en µs

t=.1*(0: length(data)-1);

//

// effacement de la fenêtre d’affichage et initialisation de la fonte à 4 pixels xbasc(); xset("font size",4);

//

// affichage et titre plot2d2(t,data);

xtitle("sinusoïde en sortie du CNA","temps en µs","amplitude");

On obtient bien une sinusoïde centrée sur le milieu de la dynamique.

La mémoire contenant 28 incréments de phase, adressé à une fréquence de 10 MHz, on trouve donc en sortie une fréquence de 10 MHz/28 soit 39,04 kHz (25,6 µs).

0 10 20 30 40 50

0 40 80 120 160 200 240 280

sinusoïde en sortie du CNA

temps en µs amplitude

(6)

Remarque : seules un quart des données mises en mémoire sont réellement utiles, les autres étant identiques à un décalage près. La taille mémoire pourrait donc être réduite au prix de quelques petites modifications.

2 Ajustement de la fréquence

Celle-ci pourrait être modifiée en divisant la valeur de la fréquence d’horloge, mais les performances du synthétiseur serait atténuées par rapport à la solution retenue, présentée ci-après.

2.1 Modification du schéma de base

La solution adoptée, beaucoup plus efficace, consiste à modifier l’incrément d’adressage de la mémoire (c’est à dire l’incrément de phase) en remplaçant le compteur par un additionneur suivi d’un registre fonctionnant à la fréquence d’horloge, comme l’indique le schéma ci-après :

Détail de la modification :

(7)

Si le nombre à l’entrée FM augmente, l’incrément de phase sur le bus d’adresse de la mémoire augmente également, et la mémoire est lue plus rapidement (toutes les valeurs n’étant pas lues comme dans le cas précédent). La fréquence de sortie augmente alors.

On peut remarquer qu’un nombre de bit important sur l’additionneur et le registre permet une bonne précision au niveau de l’incrément de phase ; il n’est cependant pas nécessaire d’utiliser tous les bits pour lire la mémoire, ce qui permet de garder la précision tout en diminuant la taille de la ROM.

On peut également remarquer que l’ensemble additionneur registre se comporte comme un intégrateur numérique ; si on place à l’entrée un nombre représentatif de la fréquence, une fois intégré, celui-ci représente la phase.

2.2 Calcul de la fréquence de sortie et problème du filtrage

Si L est la taille du bus du registre à incrémentation de phase, MF le nombre présent à l’entrée de commande de la fréquence (sur le bus FM) et FCK la fréquence du signal d’horloge, nous avons alors en sortie une fréquence F0 :

F0=MF . FCK / 2 L

En entrant la valeur décimale16, soit 010 en hexadécimal pour MF, on retrouve le signal précédent à 39 kHz. (les quatre bits de poids faible en sortie du registre ne sont pas utilisés pour lire la mémoire).

Etudions maintenant ce qui se passe pour MF=29, soit 200 en hexadécimal, avec un temps de simulation de 1,6 µs. D’après les calculs précédents, on doit retrouver une fréquence de sortie de 10 MHz/28 soit 1,25 MHz.

Voici les chronogrammes obtenus dans le simulateur :

Voici la structure du fichier “.tbl une fois modifié :

0.0> 0 200 = 7F 50.0> 1 200 = 7F 50.1> 1 200 = D8 100.0> 0 200 = D8 150.0> 1 200 = D8 150.1> 1 200 = FE 200.0> 0 200 = FE 250.0> 1 200 = FE 250.1> 1 200 = D8

………..

1400.0> 0 200 = 00 1450.0> 1 200 = 00 1450.1> 1 200 = 25 1500.0> 0 200 = 25 1550.0> 1 200 = 25 1550.1> 1 200 = 7F

(8)

Comme nous pouvons le remarquer l’agencement des variables n’est pas tout à fait identique du fait de la présence d’une nouvelle entrée, nous obligeant à modifier le programme Scilab comme suit (en plus des différents changements de répertoires et de nom de fichier)

[n,temps,hor,adresse,donnee ]=mfscanf(-1,fd,"%f> %i %x = %x");

Une incrémentation de trois pour récupérer les données est par contre toujours valable.

Si on appelle le fichier modifié « nvco_scilab.gdf » et qu’il se trouve dans le répertoire h:\max\Nco\mod_freq, le programme Scilab complet devient alors :

// lecture d'un fichier « .tbl » issus de Max+plus et affichage clear;

//

chdir('h:\max\Nco\mod_freq') ; fd=mopen("nvco_scilab.tbl","r");

//

[n,temps,hor,adresse,donnee ]=mfscanf(-1,fd,"%f> %i %x = %x");

//

mclose(fd);

//

data=donnee(1:3:length(donnee));

//

t=.1*(0: length(data)-1);

//

xbasc(); xset("font size",4);

plot2d2(t,data); xtitle("sinusoïde en sortie du CNA","temps en µs","amplitude");

On retrouve bien la fréquence attendue de 1,25 MHz soit 0,8 µs.

0 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6

0 40 80 120 160 200 240 280

sinusoïde en sortie du CNA

temps en µs amplitude

Comme on peut le voir sur le chronogramme, le signal comprend cette fois un nombre d’harmoniques important, mettant en évidence le problème du filtrage et du repliement de spectre.

Le programme ci-après permet d’afficher l’aspect spectral des signaux.

On détermine dans un premier temps la transformée de Fourrier du signal calculé par notre montage. Le calcul effectué par Scilab est pondéré par la fréquence d’échantillonnage et le nombre d’échantillons afin d’obtenir réellement le spectre du signal échantillonné. Les données reçues par le logiciel correspondent en effet à 16 échantillons, échantillonnés à la fréquence unitaire, alors que notre signal présente un nombre infini d’échantillons échantillonnés à 10 MHz.

On détermine ensuite la fonction de transfert du blocage d’ordre zéro inhérent au CNA. La réponse impulsionnelle d’un tel bloqueur est un créneau unitaire de largeur 1/FCK, le module

(9)

de sa réponse fréquentielle est donc un sinus cardinal, d’amplitude 1/FCK et dont le premier passage à zéro se fera à FCK. Le problème de l’indétermination pour f=0 est géré par le test

« f==0 » qui renvoie la valeur 1 si la condition est vérifiée, 0 dans les autres cas.

Enfin, le spectre du signal en sortie du CNA est le produit des deux spectres précédents.

// paramètre fréquence d'échantillonnage Fck=10e6;

//

// création d'une variable fréquence de 0 à (presque) Fck f=Fck/length(data)*(0:length(data)-1);

//

// calcul de la fft du signal échantillonné fdata=1/length(data)*Fck*fft(data,-1);

//

// module de la fonction de transfert du bloqueur

B=1/Fck*(sin(2*%pi*f/Fck/2)./(2*%pi*f/Fck/2+(f==0))+(f==0));

//

// spectre en sortie du CNA S=B.*(abs(fdata))';

//

// affichage

xbasc();xset("font size",4);

//

xsetech([0,0,1,1/3]);plot2d3(f,abs(fdata),rect=[-1e6,0,9e6,1.5e9]);

//

xtitle("spectre du signal de sortie (sans le blocage)","fréquence (Hz)","amplitude");

//

xsetech([0,1/3,1,1/3]);plot2d(f,B,rect=[-1e6,0,9e6,150e-9]);

xtitle("réponse fréquentielle du bloqueur","fréquence (Hz)","amplitude");

//

xsetech([0,2/3,1,1/3]);plot2d3(f,S,rect=[-1e6,0,9e6,140]);

xtitle("spectre en sortie du CNA","fréquence (Hz)","amplitude");

Voici le résultat obtenu :

-1e6 0 1e6 2e6 3e6 4e6 5e6 6e6 7e6 8e6 9e6

0 2e8 4e8 6e88e8 10e8 12e8 14e8

16e8 spectre du signal de sortie (sans le blocage)

fréquence (Hz) amplitude

-1e6 0 1e6 2e6 3e6 4e6 5e6 6e6 7e6 8e6 9e6

2e-80 4e-8 6e-8 8e-8 10e-8 12e-8 14e-8

16e-8 réponse fréquentielle du bloqueur

fréquence (Hz) amplitude

-1e6 0 1e6 2e6 3e6 4e6 5e6 6e6 7e6 8e6 9e6

0 20 40 60 80 100 120

140 spectre en sortie du CNA

fréquence (Hz) amplitude

(10)

Le spectre du premier signal est périodique, de période FCK ; la représentation est effectuée ici sur une période.

Nous retrouvons bien sur le spectre du signal de sortie du CNA une raie en continu (notre signal est centré sur 127), ainsi que la raie à 1,25 MHz. L’amplitude de cette dernière est environ 127/2 (il s’agit d’un spectre bilatéral), atténué légèrement par la réponse du bloqueur. Les autres raies à k.FCK +/- F0 (k étant un entier), dues à l’échantillonnage du signal (à 10 MHz) sont fortement atténuées par le blocage. Entre le fondamental à 1,25 MHz et le premier harmonique à 8,75 MHz, il y a une atténuation d’environ19 dB.

Nous pouvons voir sur ces représentations que notre signal doit vérifier le théorème de Shannon et ne pas avoir une fréquence supérieure à FCK/2, ce qui limite MF à 7FF en hexadécimal.

Dans la pratique, le filtrage réalisé n’étant pas parfait, on ne dépasse pas 0,2 à 0,4.FCK.

2.3 Modulation de fréquence et Initialisation du simulateur

L’entrée FM laisse la possibilité de réaliser une modulation numérique de fréquence. Pour entrer le signal modulant, nous allons utiliser la possibilité que laisse le simulateur de Max+plus d’initialiser les variables avec un fichier texte « .vec », de format similaire aux fichiers « .tbl ».

Afin de générer facilement le fichier « .vec » et observer sa structure, nous allons d’abord créer un fichier « .tlb » à partir uniquement de nos paramètres de simulation (sans les résultats).

Décrire pour cela un fichier « .scf » comme ci-après, avec une grille à 50 ns et un temps de simulation de 16 µs. Placer l’horloge, ainsi qu’une incrémentation toutes les 100 ns pour le signal FM.

Générer ensuite un fichier « .tbl ».

Après suppression des commentaires on obtient la description suivante :

GROUP CREATE FM[11..0] = FM11 FM10 FM9 FM8 FM7 FM6 FM5 FM4 FM3 FM2 FM1 FM0 ; GROUP CREATE sortie[7..0] = sortie7 sortie6 sortie5 sortie4 sortie3 sortie2 sortie1 sortie0 ; INPUTS horloge FM[11..0] ;

OUTPUTS sortie[7..0] ; UNIT ns ;

RADIX HEX ; PATTERN

0.0> 0 000 = XX 50.0> 1 000 = XX 100.0> 0 001 = XX 150.0> 1 001 = XX 200.0> 0 002 = XX 250.0> 1 002 = XX 300.0> 0 003 = XX 350.0> 1 003 = XX 400.0> 0 004 = XX 450.0> 1 004 = XX 500.0> 0 005 = XX

(11)

………

15950.0> 1 09F = XX 16000.0> X XXX = XX

;

Comme on peut le constater, le fichier commence par la description des regroupements en bus des bits (ici « FM » et « sortie »), puis énonce les entrées et sorties, l’unité de représentation de l’échelle des temps, puis le mode de représentation des groupes (ici en hexadécimal) ; enfin arrive la suite de valeurs.

Nous allons maintenant initialiser les valeurs de FM pour visualiser la modulation d’une porteuse à 0,625 MHz (soit MF=28, pour une période de 1,6µs), par un signal modulant sinusoïdal, de fréquence 10 fois plus faible, avec une l’excursion de fréquence de +/-20% du signal porteur (ce qui donne un indice de modulation de 0,2/0,1 soit 2).

Le programme Scilab suivant permet de générer les valeurs nécessaires : // création d’un fichier « .vec »

clear; chdir('h:\max\Nco\mod_freq') ; //

// définition des paramètres fréquence du signal modulant //

// période d’horloge (en ns), durée de simulation (en ns) Fmod=62.5e3; Tck=100; Tend=16e3;

//

// génération du temps (en ns) t=Tck*(0:Tend/Tck-1);

// mise sous forme de matrice colonne avec un pas de 50 ns (voir structure fichier .vec) t2=Tck/2*(0:Tend/(Tck/2)-1)';

//

// génération de Mf

Mf=2^8*(1+.2*sin(2*%pi*Fmod*t*1e-9));

//

// à chaque période d’horloge correspond une suite 0 1 dans le fichier « .vec » h=[0;1]*ones(1,length(t));

hor=matrix(h,2*length(t),1);

//

// dédoublement des valeurs de Mf, afin de suivre les 0 1 de l’horloge Mf2=[1;1]*Mf;

Mf3=matrix(Mf2,2*length(t),1);

//

// création du fichier

fd=mopen("modfm_scilab.vec","w");

mfprintf(fd,"\t%i> \t%i \t%i =\t XX \n",t2, hor, Mf3);

mclose(fd);

On modifie ensuite le fichier obtenu pour placer les paramètres d’en tête ; on en profite pour modifier le « radix » de l’hexadécimal vers le décimal. On n’oubliera pas d’ajouter la dernière ligne et le « ; ».

GROUP CREATE FM[11..0] = FM11 FM10 FM9 FM8 FM7 FM6 FM5 FM4 FM3 FM2 FM1 FM0 ; GROUP CREATE sortie[7..0] = sortie7 sortie6 sortie5 sortie4 sortie3 sortie2 sortie1 sortie0 ; INPUTS horloge FM[11..0] ;

OUTPUTS sortie[7..0] ; UNIT ns ;

RADIX DEC ; PATTERN

0> 0 256 = XX 50> 1 256 = XX

(12)

100> 0 258 = XX 150> 1 258 = XX 200> 0 260 = XX 250> 1 260 = XX 300> 0 262 = XX 350> 1 262 = XX 400> 0 264 = XX 450> 1 264 = XX 500> 0 265 = XX

………..

15950> 1 253 = XX 16000> X XXX = XX

;

Sauvegarder ensuite ce fichier dans le répertoire de travail de Max+plus avec une extension « .vec ».

Pour créer un nouveau fichier de simulation « .snf » avec notre « .vec », ouvrir l’éditeur de chronogrammes (en .snf), puis File \ Import Vector File… (attention, cette option n’existe que dans l’éditeur de chronogrammes).

Déclarer notre « .vec », ce qui génère le « .snf », s’il n’y pas eu d’erreur.

En cas d’erreur, le logiciel les signale et les localise, ce qui rend la correction facile.

Une simple dilatation d’échelle permet de vérifier grossièrement la périodicité du signal modulant :

Sauvegarder le fichier « .scf » en lui donnant le même nom que le projet courant et lancer la simulation.

(13)

Créer ensuite un fichier résultat « .tbl », supprimer les parties indésirables et réaliser le traitement avec Scilab pour l’affichage :

//

fd=mopen("mod_freq_res_scilab.tbl","r");

[n,temps,hor,FM,sortie ]=mfscanf(-1,fd,"%f> %i %x = %x");

mclose(fd);

//

data=sortie(1:3:length(sortie));

FM2=FM(1:3:length(FM));

//

t=.1*(0: length(data)-1);

//

xbasc(); xset("font size",4);

xsetech([0,0,1,1/2]); plot2d2(t,FM2); xtitle("signal modulant","temps en µs","amplitude");

xsetech([0,1/2,1,1/2]); plot2d2(t,data); xtitle("signal modulé","temps en µs","amplitude");

et afficher les résultats.

0 2 4 6 8 10 12 14 16

200 220 240 260 280 300 320

signal modulant

temps en µs amplitude

0 2 4 6 8 10 12 14 16

0 40 80 120 160 200 240 280

signal modulé

temps en µs amplitude

Nous retrouvons bien notre signal modulant de période 16 µs ; le signal modulé présente quant à lui une fréquence moyenne 10 fois supérieure (10 périodes affichées dans une période du modulant). On

(14)

peut également constater que la fréquence de ce dernier est faible lorsque l’amplitude du signal modulant est faible et inversement ; il s’agit donc bien d’une modulation de fréquence.

Tester cette solution en implantant la fonction sur le FLEX10K20 (ou FLEX10K100) de la carte DLP associée à la carte auxiliaire de conversion depuis et vers l’analogique ; observer les signaux à l’oscilloscope et faire une FFT.

3 Modulations angulaires et d’amplitude

En vous inspirant de la documentation du HSP 45116, proposer une modification du schéma pour obtenir les entrées suivantes :

- entrée numérique « fréquence centrale » ; - entrée numérique « modulation de fréquence » ; - entrée numérique « modulation de phase » ; - entrée numérique « modulation d’amplitude ».

Tester votre solution par simulation et sur les cartes de développement.

Evaluer la synthèse en terme de vitesse de fonctionnement et précision. A titre de comparaison, le HSP 45116 propose une fréquence de sortie de 33 MHz avec une précision de 8 mHz (ce sont bien des « milli », il ne s’agit pas d’une erreur de frappe).

4 Modulation de données numériques

Pour générer les données numériques, proposer en VHDL un générateur pseudo aléatoire (voir annexe 1 bis les sorties à relier à l’entrée). On pourra s’inspirer du TP sur l’émission réception d’un signal codé manchester.

Proposer un modulateur à déplacement de fréquence avec un indice de modulation de 1/2 ; simuler et visualiser à l’oscilloscope le signal en sortie ainsi que son spectre ; comparer par rapport à d’autres indices.

Proposer un modulateur à déplacement de fréquence, 6 symboles (3 bits par symboles) ; on prendra un rapport de 1,5 entre la période de la porteuse et l’horloge bit. Simuler et visualiser à l’oscilloscope le signal de sortie.

Modifier la structure de base de l’oscillateur afin de lui permettre de générer deux sinusoïdes en quadrature. Générer une modulation MAQ sur 16 états.

Bibliographie

Documentation du HPS 45116

Introduction au traitement du signal avec Scilab du même auteur sur

http://artemmis.univ-mrs.fr/iufm-genelec-forum/SCILAB/introduction_pages_scilab.htm Programmer les entrées-sorties par Serge Steer dans Linux Magazine de Juin 2001

(15)

Annexe 1 : implantation des « méga-fonctions"

Le logiciel Max+plus II propose un certain nombre de fonctions complexes (mémoires, multiplieurs, comparateurs etc…) optimisées pour les circuits Altera ; on peut y accéder dans différentes descriptions (graphique, VHDL, Verilog etc…), nous nous limiterons à la description graphique (pour les autres descriptions, consulter l’aide).

Deux possibilités d’implantation sont offertes :

- dans l’éditeur graphique, par le menu contextuel ou par le menu Symbol / Enter Symbol on accède à la fenêtre de gauche de la figure suivante :

On a ensuite le choix entre les différentes bibliothèques proposées dans le logiciel, plus de bibliothèques personnelles. Celles-ci peuvent être ajoutées depuis l’éditeur graphique par le menu Options / Users Librairies… . Parmi les bibliothèques d’origine la plus intéressante est

« mega_lpm », les autres proposant soit des composants de base (port d’entrée sortie), soit des descriptions de fonctions réalisées par d’anciens composants TTL ou CMOS. Altera déconseille l’utilisation de ces fonctions.

Une fois le composant choisi, on accède à la fenêtre de droite de la figure précédente où celui-ci peut être paramètré. La partie « Port » permet de sélectionner les entrées et sorties qui seront utilisées, tandis que la partie « Parameters » permet de configurer le composant. On peut obtenir de l’aide sur la description du composant grâce à l’icône en haut à droite.

Une fois le composant paramètré, le symbole ci- contre s’affiche.

Par un double clic gauche dans la partie description des paramètres, il est possible de les modifier.

Par un double clic gauche sur le composant, on accède à sa description en AHDL (langage propriétaire Altera).

Par un clic gauche avec l’icône d’aide (le « ? » de l’éditeur graphique) sur le symbole, on accède à la description des paramètres.

(16)

- la seconde solution commence de la même manière, mais après la première fenêtre, on sélectionne le « MegaWizard Plug-In Manager… » qui ouvre alors la fenêtre de gauche de la figure suivante, qui permet de créer un nouveau composant ou d’éditer un composant déjà créé :

Si on choisit un nouveau composant la fenêtre de gauche s’ouvre et permet de choisir parmi les composants de calcul (additionneur, multiplieurs…), les composants divers (multiplexeurs, décodeurs…) ou les composants de stockage (mémoires, registres…).

On donne un nom au nouveau composant créé et on choisit l’endroit où on souhaite le stocker (répertoire qu’il faudra déclarer dans le projet par Options / Users Librairies… si ce n’est pas le même que le répertoire courant).

Les composants Altera étant décrits en AHDL, on laisse cette option validée pour la création du fichier de sortie.

Une fois le composant paramètré, le symbole ci- contre s’affiche.

Par un double clic gauche dessus, on peut modifier le paramètrage ; pour que celui-ci soit effectif, il faut mettre à jour dans l’éditeur graphique par Symbol / Update Symbol

Annexe 1 bis : connexion des générateurs pseudo-aléatoires

Le générateur pseudo aléatoire est composé de n bascules D synchrones, la sortie de chaque bascule étant reliée à l’entrée de la suivante. L’entrée de la première bascule est attaquée par un OU exclusif dont les entrées sont les sortie des bascules indiquées ci-dessous (la première bascule est de rang 1).

n sorties n sorties

3 2 3 8 4 5 6 8

4 3 4 9 5 9

5 3 5 10 7 10

6 5 6 11 9 11

7 6 7 12 1 4 6 12

(17)

Annexe 2 : notions de base sur Scilab

(extrait de « Introduction au traitement du signal avec Scilab » même auteur)

Les outils logiciels sont devenus un élément indispensable en traitement du signal, que ce soit pour l’apprentissage ou le développement de système, en particulier depuis l’apparition des techniques numériques.

Un signal numérisé peut être en effet vu comme une suite de valeurs, c’est à dire un vecteur. Un vecteur n’est qu’une matrice à une ligne ou une colonne.

Dans le cas de traitement d’images par exemple, les signaux étant à deux dimensions, on arrive directement à la notion de matrices. On pourrait trouver de nombreux exemples où le signal à traiter présente une dimension supérieure encore.

Il était donc naturel de se tourner vers des logiciels spécialisés en calcul matriciel, tel que Matlab (contraction de MAtrix LABoratory).

Nous utiliserons pour notre part un logiciel quasiment similaire, Scilab (pour SCIentific LABoratoty), qui présente l’avantage par rapport au précédent d’être libre et gratuit.

Scilab est développé par l’INRIA Rocquencourt (78). On peut le télécharger gratuitement avec sa documentation et de nombreuses applications, à l’adresse :

http://scilabsoft.inria.fr/

Les possibilités de Scilab sont très importantes, notre objectif est ici de passer en revue les fonctionnalités de base, ainsi que celles qui nous seront utiles pour le traitement du signal.

Quelques règles pratiques

Avant toutes choses, il faut comprendre que Scilab est un langage interprété (comme le Basic) et non compilé (comme le C ou le Pascal).

Les premiers programmes seront écris ligne par ligne directement dans l’éditeur de Scilab ; lorsqu’on a un peu l’habitude, il est cependant plus efficace d’utiliser un éditeur de texte annexe, comme le bloc note de Windows ou WordPad, puis de faire ensuite des copier coller (attention le « ctrl V » ne fonctionne pas dans Scilab, on fera donc « clic droit » puis « paste »).

Passons maintenant en revue quelques règles pratiques :

- pour chaque fonction, une aide est disponible en tapant « help Nom_de_la_fonction » à l’invite.

- en cas d’erreur, il est inutile de réécrire les instructions, les flèches du clavier permettant de se déplacer dans le jeu des instructions précédemment entrées ; les touches de raccourci « Ctrl C » et « Ctrl V » pour le copier coller ne fonctionnent pas sous Scilab ; utiliser le menu contextuel accessible par un clic droit dans la fenêtre.

- Scilab fait la différence entre majuscules et minuscules.

- il est fortement conseillé de définir en début de programme toutes les constantes de manière littérale, afin de pouvoir modifier simplement l’une d’elle par la suite, si nécessaire.

Initialiser

Avant de commencer un nouveau programme, il est conseillé d’initialiser toutes les variables du logiciel par l’instruction « clear » (en minuscules), à moins que l’on souhaite garder des variables précédemment définies.

Entrer un vecteur ligne Plusieurs syntaxes possibles : -->s=[0 1 2 3]

s =

! 0. 1. 2. 3. !

-->s=[0,1,2,3]

s =

! 0. 1. 2. 3. !

-->s=[0:1:3]

s =

! 0. 1. 2. 3. !

-->s=[0:3]

s =

! 0. 1. 2. 3. ! La troisième syntaxe se lit comme un vecteur allant de 0 à 3 par pas de 1, celui-ci étant 1 par défaut il peut être omis comme dans la quatrième syntaxe.

Dans le cas d’un incrément, les crochets peuvent être omis, ou remplacés par des parenthèses :

(18)

-->s=(0:3) s =

! 0. 1. 2. 3. !

-->s=0:3 s =

! 0. 1. 2. 3. ! Un point virgule à la fin de la ligne évite l’affichage du résultat.

-->s=0:3;

Entrer un vecteur colonne Plusieurs syntaxes possibles : -->s1=[0;1;2;3]

s1 =

! 0. !

! 1. !

! 2. !

! 3. !

-->s1=[0:3]' s1 =

! 0. !

! 1. !

! 2. !

! 3. !

-->s1=[0:1:3]' s1 =

! 0. !

! 1. !

! 2. !

! 3. !

-->s1=s' s1 =

! 0. !

! 1. !

! 2. !

! 3. ! Mettre des vecteurs bout à bout, former des matrices

-->s2=[0 1 2 3; 0 1 2 3]

s2 =

! 0. 1. 2. 3. !

! 0. 1. 2. 3. !

-->s2=[s;s]

s2 =

! 0. 1. 2. 3. !

! 0. 1. 2. 3. !

-->s2=[s1';s1']

s2 =

! 0. 1. 2. 3. !

! 0. 1. 2. 3. ! Accéder aux éléments d’une matrice

-->s(0)

!--error 21 invalid index

-->s(1) ans = 0.

-->s(1:2:4) ans =

! 0. 2. !

-->s2(2,3) ans = 2.

Les deux premières syntaxes montrent que le premier indice d’une matrice est toujours « 1 » dans Scilab, et non « 0 ».

La troisième syntaxe permet d’accéder aux éléments de rang 1 à 4 de « s » par pas de 2.

Matrices particulières -->zeros(2,3)

ans =

! 0. 0. 0. !

! 0. 0. 0. !

-->ones(3,2) ans =

! 1. 1. !

! 1. 1. !

! 1. 1. !

-->eye(3,4) ans =

! 1. 0. 0. 0. !

! 0. 1. 0. 0. !

! 0. 0. 1. 0. !

-->rand(3,2) ans =

! .0683740 .7263507 !

! .5608486 .1985144 !

! .6623569 .5442573 !

On précise à chaque fois, dans l’ordre le nombre de lignes et de colonnes souhaitées. La première écriture donne une matrice de « 0 », la seconde de « 1 », la troisième une matrice dont les éléments de la diagonale sont des « 1 » et les autres des « 0 », et la dernière donne des éléments aléatoire entre « 0 » et « 1 ».

Données particulières

Elles sont précédées du symbole « % ». Citons : - le nombre π, soit %pi,

(19)

- l’imaginaire pur, soit %i,

- et très utiles pour lever certaines indéterminations, le plus petit nombre manipulable par Scilab (2,22 10-16), soit %eps, ainsi que les type vrai, %t, et faux, %f.

Opérations particulières On trouve évidemment :

- les opérations d’addition « + » (les matrices doivent alors avoir même dimension), - de soustraction « - » (les matrices doivent alors avoir même dimension),

- de multiplication « * » entre matrices (le nombre de colonnes de la première matrice doit alors être égal au nombre de lignes de la seconde), de même que la multiplication de tous les éléments de la matrice par un nombre,

- de division « / »,

- la mise à puissance de 10, avec « e », par exemple 10e3 (soit 1000).

A ne pas confondre avec ces deux dernières les multiplications et divisions éléments par éléments, notées respectivement « .* » et « ./ ». Les matrices doivent alors avoir même dimension.

Observons l’exemple ci-après (à lire de gauche à droite) :

-->A=[0,1;2,3]

A =

! 0. 1. !

! 2. 3. !

-->B=[4,5;6,7]

B =

! 4. 5. !

! 6. 7. !

-->C=A*B C =

! 6. 7. !

! 26. 31. !

-->D=A .*B D =

! 0. 5. !

! 12. 21. ! On trouvera le même mode de fonctionnement avec la fonction élévation à la puissance et les symboles « ^ » et « .^ ».

Citons également quelques opérations spécifiques :

- size (A) qui donne le nombre de ligne et colonnes de A, - length (A) qui donne le nombre d’éléments de A,

- matrix (A, m, n) qui redimensionne A sur m ligne et n colonnes (la lecture se fait colonne par colonne),

- sum(A) qui renvoie un nombre correspondant à la somme de tous les éléments de la matrice, - sum(A,’r’) qui renvoie un vecteur ligne (‘r’ pour row) dont chaque élément est la somme des

éléments de la colonne correspondante de A,

- sum(A,’c’) qui renvoie un vecteur colonne (‘c’ pour column) dont chaque élément est la somme des éléments de la ligne correspondante de A,

- triu(A) qui ne garde que la valeur des éléments du triangle (« tri » pour triangle) supérieur (« u » pour up) de la matrice (diagonal comprise) et place des « 0 » ailleurs,

- tril(A) qui ne garde que la valeur des éléments du triangle (« tri » pour triangle) inférieur (« l » pour low) de la matrice (diagonal comprise) et place des « 0 » ailleurs,

- A’ qui renvoie la matrice A transposée et conjuguée, - conj(A) qui renvoie la matrice A conjuguée.

Fonctions particulières Citons les principales : - sqrt( ), la racine carrée,

- sin( ), cos( ), tan( ) les sinus, cosinus et tangente,

- asin( ), acos( ), atan( ) les fonctions inverses des précédentes, - exp( ), log( ) les fonctions exponentielle et logarithme népérien, - 10^( ), log10( ) les fonctions puissance de 10 et logarithme décimal, - real( ), imag( ) les fonctions partie réelle et imaginaire d’un complexe, - abs( ), phasemag( ) les fonctions module et phase d’un complexe.

Exemple

Voici un exemple de tracé de la représentation temporelle et fréquentielle d’une sinusoïde.

(20)

clear

// définition des constantes, nombre de points, période d’échantillonnage et fréquence du signal N=1000 ; Te=0.1e-3 ; F=100 ;

//

// description du vecteur temps t=Te*(0:N-1);

//

// description du vecteur signal s=5*sin(2*%pi*F*t);

//

// définition d'une variable fréquence pour l'affichage du spectre

// le premier point correspond au continu, le dernier à la fréquence d'échantillonnage au pas près f=1/(N*Te)*( 0 : N-1) ;

//

// calcul du module de la transformée de Fourrier sf=1/N* abs(fft(s,-1)) ;

//

// initialisation de l'affichage xbasc(); xset("font size",4);

//

// affichage de la représentation temporelle

// dans le coin en haut à gauche de la fenëtre graphique (coordonnées 0,0) // sur toute la largeur et sur une demi-hauteur

xsetech([0,0,1,1/2]) ; plot2d(t,s);

xtitle(“représentation temporelle”,”temps (s)”,”amplitude (V)”) //

// affichage du module corrigé de 0 à fe/2

// à gauche à la moitié de la hauteur de la fenêtre graphique (coordonnées 0,1/2) // sur toute la largeur et sur une demi-hauteur

xsetech([0,1/2,1,1/2]) ; plot2d3(f(1:N/2), sf(1:N/2)) ;

xtitle("module corrigé en fonction de la fréquence de 0 à fe/2","fréquence (Hz)","amplitude (Vs)");

0 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.10

-5 -4 -3 -2 -1 0 1 2 3 4 5

représentation tem porelle

tem ps (s) amplitude (V)

0 1e3 2e3 3e3 4e3 5e3

0 0.4 0.8 1.2 1.6 2.0 2.4 2.8

m odule corrigé en fonction de la fréquence de 0 à fe/2

fréquence (H z) amplitude (Vs)

(21)

Annexe 3 : Modulations angulaires

Rappels théoriques

L’expression ci-après rappelle l’équation d’un signal modulé en fréquence : ] t m(t)) K (F sin[2π U

(t)

um = P 0 + F

La fréquence instantanée vaut alors :

) t ( m K F ) t (

f = 0+ F tandis que la phase instantanée vaut :

π + π

=

ϕ(t) 2 F0t 2 KF m(t)dt

L’indice de modulation δ est défini comme l’écart de phase ∆ϕ autour de la phase 2πF0t de la porteuse.

Dans le cas d’un signal modulant sinusoïdal, soit m(t)=Ui sin(2π fi t), l’intégration due au passage de la fréquence à la phase du signal, nous amène à l’expression :

i i F

f U

=K δ

Comme on peut le constater, l’indice de modulation dépend de l’amplitude et de la fréquence du signal informatif. Lorsque plusieurs fréquences sont mises en jeu, on prend la plus élevée pour définir cet indice (qui sera alors d’autant plus faible).

L’expression d’un signal modulé en phase est la suivante :

] m(t) K t F sin[2π U

(t)

um = P 0 + P

La fréquence instantanée a pour expression :

dt ) t ( m K d 2 F 1 ) t (

f 0 P

+ π

= tandis que la phase instantanée vaut :

) t ( m K t F 2

(t)= π 0 + p ϕ

L’indice de modulation, toujours défini comme l’écart de phase autour de la phase de la porteuse, a pour expression dans le cas du signal informatif sinusoïdal précédent :

i P U

=K δ

Ce bref rappel permet de mettre en évidence que pour faire une modulation de phase avec un modulateur de fréquence, il suffit de dériver d’abord le signal informatif.

De même, pour faire une modulation de phase avec un modulateur de fréquence, il faut d’abord intégrer le signal modulant.

Transmission d’informations numériques

Modulation à déplacement de fréquence MDF ou FSK (Frequency Shift Keying)

Le principe consiste à associer autour de la fréquence porteuse FP une fréquence FP+∆F pour le niveau logique 1 et FP-∆F pour le niveau logique 0.

Si D est le débit binaire, l’indice de modulation est généralement défini par δ=2∆F/D.

Les valeurs de cet indice classiquement utilisées pour leur bon compromis « débit numérique / encombrement spectral » sont 2/π et 1/2.

Modulation à déplacement de phase MDP ou PSK (Phase Shift Keying)

Le principe consiste à associer une phase (0 et π) particulière de la porteuse pour chaque niveau logique. Ce principe se prête bien à la transmission de plusieurs bits par phase, ce qui peut être représenté par une constellation comme celle qui suit où 3 bits sont envoyés par phase.

(22)

axe des réels axe des

imaginaires

000 001

111 110

100

101

010 011

Chaque point représente l’extrémité du vecteur de Fresnel de la porteuse, en fonction du « tribit » envoyé.

La modulation est généralement de type différentiel, la référence n’étant pas une phase absolue, mais celle du symbole précédent ; dans la constellation de l’exemple, un écart de phase de +3π/4 par rapport au symbole précédent correspond au tribit 100.

Le passage d’un symbole au symbole le plus proche sur la constellation se fait par un code Gray (un seul bit change à la fois), de manière à limiter les erreurs en cas de confusion entre deux symboles voisins.

Modulation d’amplitude en quadrature MAQ ou QAM (Quadrature Amplitude Modulation)

La modulation à déplacement de phase devient peu performante lorsque le nombre de bits transmis par phase augmente, la lecture des phases devenant problématique. Aussi utilise t-on aussi une modulation d’amplitude en plus, pour obtenir par exemple la constellation suivante où 4 bits sont transmis à chaque symbole :

axe des réels axe des

imaginaires

Ce type de modulation peut être vu comme la somme de deux modulations d’amplitude, dont les porteuses de même fréquence, serait en quadrature. On en déduit alors le schéma du modulateur.

Horloge bit HB

signal modulé registre

à décalage

D données

division par 4 de fréquence

déphaseur 90°

+

X X registre

parallèle

Oscillateur (fréquence porteuse) CNA 2 bits

CNA 2 bits Q3

Q2

Q0 Q1

Q3 Q2

Q0 Q1 D3 D2

D0 D1

Ck Ck

Références

Documents relatifs

&RPPHQWPHVXUHWRQOD FDSDFLWp" 7kFKHGHGpWHFWLRQGHVWUDLWV7RZQVHQGHWDODOWHUQDQW DYHFODWkFKHGHUHFKHUFKHYLVXHOOHORUVGHVSUHPLqUHV VHVVLRQV 'HX[TXHVWLRQV

[r]

Compléter les pointillés de la définition ci-dessus en choisissant le mot qui convient parmi les deux propositions suivantes1.

Pour rappel : Voici le tableau donnant les tables de soustraction utiles pour poser une soustraction. (qui sont donc à

[r]

[r]

[r]

Déterminer par le calcul les antécédents