réponses leçon 12
Question 1:
Question 1
Voici le code. Les fonctions sont placées en tête de programme. Le programme main ensuite appelle les fonctions: 2 fois saisie, calcule la somme puis appelle affichage.
-- fonction afficheur
-- attention les commentaires ne sont pas des lignes!!!!
Begin
mvi 0D Co
nop
-- saisie 16 bits
pause
mov Rsw Rsrc1
pause
mov Rsw Rsrc2
concat
pop CO
push Rdest zero
-- afficheur
pop R7seg
pop CO
pause
-- main
mvi 03 CO
pushi 0F zero
pop R1
MVI 03 CO
pushi 12 zero
pop Rsrc2
mov R1 Rsrc1
add
pushi 18 zero
mvi 0A CO
push Rdest zero
mvi 0D CO
nop
end
Question 2
Vous allez commencez par créer un composant LFSR. Je vous conseille de copier votre projet TP12 vers un nouveau projet TPRDM.
Vous avez bien sûr lu les informations sur LFSR. Pour un générateur 16 bits il suffit de 16 bascules D et de relier les sorties des bascules 3, 12, 14 et 15 par un Xor pour alimenter l'entrée de la bascule 0.
Comme vous voulez générer des nombres aléatoires seulement si l'instruction machine associée est exécutée, je vous propose d’instancier 16 bascules FDE qui seront activées par l'entrée CE seulement si une instruction RANDOM est décodée par la FSM.
Lorsque vous créez la première bascule, il faut impérativement placer la valeur initiale à 1! Il suffit d'ouvrir la fenêtre Object Properties de cette bascule et de changer la valeur INIT. Sans cela vos bascules produiront toujours x0000.
Ensuite copiez cette bascule et collez la 15 fois afin d'obtenir une grille de bascule 4x4. Placez un fil avec son I/O Marker clk sur tous les C, Placez un fil suivant et son I/O marker sur tous les CE. Reliez les bascules en cascade du Q vers le D de la suivante. Placez un XOR4 connecté aux 4 sorties des bascules 3, 11, 14 et 15. La sortie de ce XOR4 est directement connectée à l'entrée D de la bascule 0.
Il vous reste à récupérer le nombre aléatoire ainsi généré. Placez un bus RDN(15:0) avec son I/O Marker. Il vous suffit de nommer les sorties de chaque bascule RDN(0), RDN(1)..; RDN(15). Sauvez et créez le symbole associé.
Composant LFSR
Avant toute chose je vous propose de simuler ce composant . Utilisez Isim directement sur le LFSR.sch. Il vous suffit par un force clock d’initialiser clk et le signal suivant à 1 par un force constant. Vous devriez observer la séquence suivante.
Vous êtes prêt pour l'insertion dans le composant ALU. Il y reste plusieurs places libres. Pour simplifier la mise en oeuvre, je vous propose d'utiliser la dernière place dans l'arbre des mux2x16, en conséquence le code de cette instruction sera nécessairement x1F00. Afin de générer toujours la même suite de nombres aléatoires, indépendamment de la fréquence d'appel de l'instruction et donc de la clock du processeur, l'entrée suivant est active seulement lorsque le code OP(3:0) est égal à b1111. Placez une porte AND4 qui prend en compte cette configuration et valide l'entrée suivant du LFSR. Enfin ajoutez un fil clk avec son I/O Marker sur l'entrée correspondante de LFSR. Vous pouvez recréer le symbole associé à ALU.
LFSR dans ALU
Mettez à jour le composant ALU dans S3. Il doit y avoir un nouveau port clk sur ALU. Il suffit de le connecté au fil clk déjà en place.
Ajoutez le fil clk sur ALU
Mettez à jour votre assembleur, il suffit d'ajouter , avant la commande s/AND/ !! ( AND est inclus dans rANDom)
s/RANDOM/1F00/
Voici un premier programme testrdm.S3 qui vous permettra de tester votre nouvelle instruction. A chaque pression sur le bouton de la carte, le nombre aléatoire suivant dans la liste est affiché, c'est exactement le même ordre que ce que vous avez observé par simulation. Placez ce programme testrdm.coe dans insmem, mettez à jour S3 pour insmem, créez le symbole S3, mettre à jour toplevel. Vous pouvez générer toplevel.bit pour tester sur la carte.
-- test rdm
begin
random
mov rdest r7seg
mov 01 CO
PAUSE
end
Vous avez tout ce qu'il faut dans le processeur S3 pour maintenant écrire votre programme qui calcule PI par méthode Monté Carlo!
Voici un code que j'ai essayé. Il affiche la valeur du nombre de points dans le quart de cercle après xFF tirages et une précision de calcul sur 7 bits seulement afin de pouvoir calculer la somme des deux carrés sur 16 bits et de la comparer au carré du rayon du cercle de dimansion x7F. La valeur produite est xB7 et donne une valeur approchée de PI = xB7 / xFF * 4 = 2,87 !!! pas si mal avec aussi peut de précision.
-- Monte Carlo
begin
-- 3F01 dans R2
mvi 01 Rsrc1
mvi 3f Rsrc2
concat
mov Rdest R2
--8000 R3
mvi 00 Rsrc1
mvi 80 Rsrc2
concat
mov Rdest R3
-- 00 R4 nombre de points dans le cercle
mvi 00 R4
-- 01 init compteur de boucle à 255 tirages
mvi FF R1
--
random
mvi 7F Rsrc1
mov Rdest Rsrc2
and
mov Rdest Rsrc1
mov Rdest Rsrc2
mul8
mov Rdest R5
random
mvi 7F Rsrc1
mov Rdest Rsrc2
and
mov Rdest Rsrc1
mov Rdest Rsrc2
mul8
mov Rdest Rsrc1
mov R5 Rsrc2
add
mov R2 Rsrc1
mov Rdest Rsrc2
SUB
mov Rdest Rsrc1
mov R3 Rsrc2
and
miNZ 00 Rsrc1
miZ 01 Rsrc1
mov R4 Rsrc2
add
mov Rdest R4
mov R1 Rsrc1
dec
miNZ 0B CO
mov Rdest R1
mov R4 R7seg
pause
end
Vous pouvez facilement modifier le nombre de tirages, il suffit de changer la valeur initiale de R1. Attention l'adresse de boucle a changée!!!!
Avec x08FF tirages on obtient PI = 2,99.
Si le code est instable, il vous faudra baisser la clock du processeur S3!
Vous pouvez utiliser une bascule pour Nexys2, ou avec un IP_core and FPGA Features and Design>Clockin>Clocking Wizard pour Nexys3.
Pour Nexys3 voici les copies d'écrans: Créez une seconde sortie avec une fréquence de 50Mhz, puis supprimer reset et locked. Il vous suffit ensuite d'insérer une instance dans toplevel.