Leçon 8 : instruction MOV avec Fizzim

Vous allez mettre en place la première instruction de votre processeur S3. Seuls les accès aux registres en entrée et en sortie seront sollicités. Vous allez devoir mettre en place votre FSM qui assure non seulement le chargement de votre instruction à exécuter, mais aussi le déclenchement des commandes qui permettent la réalisation de cette instruction pour tous les transferts de registres possibles. La construction de votre FSM telle que nous l’avons introduite au TP5, assure un fonctionnement pipe-line en deux étages. Vous l’avez sans doute remarqué dans la question 2 de la leçon précédente. Le premier étage décode la prochaine instruction à exécuter, alors que le second étage exécute l’instruction en cours d’exécution. Ce pipe-line permet d’avoir deux instructions en traitement en même temps dans deux états d’avancement différents.

L'ancienne version avec VHDL est disponible ici

Le transfert de données d’un registre vers un autre provoque une duplication de l’information dans le registre destination. Pour votre processeur S3 cette instruction est indispensable. Le fonctionnement de S3 est si simple qu’il faut toujours générer les instructions de transfert de registre avant de pouvoir déclencher un calcul ou un accès mémoire. Le transfert de registres tel qu’il a été testé dans la leçon précédente peut être généralisé pour tous les registres. Il faut alors proposer une instruction qui déclenche un de ces transferts : c’est l’instruction MOV qui va le réaliser !

Connaissances requises

Registre, bus, automates, mode d’adressage

Objectif

Vous allez mettre en place la première instruction de votre processeur S3. Seuls les accès aux registres en entrée et en sortie seront sollicités. Vous allez devoir mettre en place votre FSM qui assure non seulement le chargement de votre instruction à exécuter, mais aussi le déclenchement des commandes qui permettent la réalisation de cette instruction pour tous les transferts de registres possibles. La construction de votre FSM telle que nous l’avons introduite au TP5, assure un fonctionnement pipe-line en deux étages. Vous l’avez sans doute remarqué dans la question 2 de la leçon précédente. Le premier étage décode la prochaine instruction à exécuter, alors que le second étage exécute l’instruction en cours d’exécution. Ce pipe-line permet d’avoir deux instructions en traitement en même temps dans deux états d’avancement différents.

Le projet

Après avoir choisi une codification de l’instruction MOV, vous allez décoder l’instruction dans votre FSM. Si cette instruction est un MOV, vous devez alors ouvrir le bon registre source sur le bus de données ainsi que le bon registre destination en écriture depuis ce même bus. Seuls certains registres acceptent des écritures depuis le bus. Par contre tous les registres peuvent s’ouvrir vers le bus, si aucun ne s’ouvre, la constante x0000 est alors véhiculée sur le bus et éventuellement recopiée dans le registre destination. Cela équivaut à un reset du registre.

Les connexions au bus

Ouvrez le TP8 que vous avez copié à la fin de la leçon précédente. Pour commencer, sélectionnez tous les GND que vous aviez placés sur les entrées des connecteur16 et supprimez-les. Sur chaque entrée ainsi libérée, placez un fil et nommez les dans l’ordre du haut vers le bas et sans erreur (Nom_du_registre to Bus) : R12B, R22B, R32B, R42B, R52B, Rled2B, Rsw2B, R7seg2B, Rsrc12B, Rsrc22B, Rdest2B, Ram2B, Rdm2B, CO2B. RI2B est déjà créé. Sur les registres, il faut ajoutez un fil sur les CE non encore connectés. Voici les noms à placer sur ces fils et dans le même ordre : B2R1, B2R2, B2R3, B2R4, B2R5, B2Rled, Rswload, B2Rsrc1, B2Rsrc2, Rdestload, B2Ram, Rdmload. Les CE de CO RI et R7seg sont déjà connectés. Voici une partie des connexions que vous devriez obtenir.

Figure 97 Les contrôles bus vers registre et registre vers bus

L’instruction MOV

Les instructions du processeur S3 sont donc codées sur 16 bits. Les 4 premiers bits seront utilisés pour coder le code opération. Il reste 3 champs de 4 bits pour les opérandes ou également pour spécialiser un code opération.

L’instruction MOV aura comme code opération b0000. Le second champ n’est pas utilisé, le troisième champ code l’adresse du registre source, le quatrième champ code l’adresse du registre destination. Le codage des registres se fera dans l’ordre de placement sur le schéma :

Par exemple l’instruction b0000_0000_0011_1100 soit x003C correspond à MOV R3 Ram. Les registres Rsw, RI et Rdest ne peuvent être la destination d’un MOV. Ils ne sont pas connectés au bus de données en entrée. Pour le registre Rsw, placez sur le port CE un Vcc (=1) pour forcer le chargement à chaque top d’horloge. Ce registre procure une copie des switches à chaque top d’horloge.

C’est votre FSM qui va décoder la prochaine instruction à exécuter. Par conséquent la prochaine instruction à exécuter devient une entrée de la FSM. En sortie la FSM doit produire le numéro du registre à transférer sur le bus et le numéro du registre à charger depuis le bus. Le numéro b0000 permet de ne rien déclencher, c’est pour cela que le processeur S3 ne possède que 15 registres. Pour passer du numéro produit par la FSM aux fils de sélection que vous venez d’ajouter, vous utiliserez deux décodeurs 4 x 16 qui activent le fil dont le numéro est placé en entrée : b0101 activerait le fil 5 soit R52B en source ou B2R5 en destination.

Modification de votre FSM

Pour commencer il faut créer un nouveau fichier fsm.vhd dans TP8. Créez ensuite le fichier fsm.fzm avec Fizzim dans TP8. Il faut respecter la syntaxe, sinon ça ne compilera pas en VHDL!!!

Avec un Page Setup changez la taille à 1500 x 2000 pixels.On prévoit ainsi pour la suite...

    1. Créez l'état chargement , agrandissez le rond pour cet état , il y aura beaucoup de transitions TP après TP.
    2. Ensuite dans Global Attributes vous pouvez dans State Machine
      • changez le nom en fsm
      • ajoutez par l'onglet User une ligne reset_state avec comme Default Value chargement
      • puis une seconde ligne User pour insert_at_top_of_module avec comme Default Value alias CodeOp : std_logic_vector(3 downto 0) is instr(15 downto 12); Cela nous permettra d’utiliser le nom CodeOP pour référencer les 4 bits de poids forts qui serviront à coder le code opération de nos instructions.
  1. Dans Inputs ajouter clk et instr[15:0] en multibit
  1. Dans transitions ajoutez par l'onglet Ouput source[3:0] et dest[3:0], visibility à NO par défaut , vous pouvez aussi ajouter une priority visibility à YES par défaut
    1. Dans Outputs ajouter les deux Ouput COinc et RIload avec des Default Value à 0, puis les deux Multibit Output source[3:0] et dest[3:0]. Pour ces deux sorties il faut aussi changer le Type en mode flag
  1. Dans States ajoutez par User dest[3:0] et source[3:0], vous pouvez valider.
  1. Ajoutez une Loopback Transition sur chargement, elle sera active quand le code opération de l 'instruction sera celui du MOV:
    • name MOV, Comment MOV ( permet de suivre dans le code produit.)
    • equation prend la valeur CodeOp ="0000"
    • source prend la valeur instr[7:4], Visibility YES
    • dest prend la valur instr[3:0], Visibility YES
    • et priority à 1
  1. En cliquant sur l'état chargement placez un 1 sur COinc et RIload pour les rendre actifs et placez "0000" dans source et dest.
  1. Ajoutez une autre Loopback sur chargement pour les autres cas:
  • name NOP, comment NOP
  • equation prend la valeur 1
  • source est dest reste vide et invisible
  • priority à 1000

Vous avez toute les copies d'écran, la prohaine fois je ne mettrai que l'essentiel... Revenez ici si besoin.

Vous êtes prêt pour la construction de la nouvelle FSM. Lancez la commande Perl fizzim.pl afin de produire le fichier fsm.vhd, il devrait se mettre à jour automatiquement dans ISE.

Vous êtes prêt pour générer le symbole associé à cette FSM. Une fois généré, il faut ensuite venir le mettre à jour dans S3, il remplacera le symbole créé lors du TP précèdent. ISE devrait vous le demander d’office. Vérifiez que clk, COinc et RIload sont toujours connectés. Connectez l’entrée instr(15:0) au bus sortant de insmem sur le port spo(15:0). Ajoutez deux bus horizontaux sur les ports source et dest et nommez les source(3:0) et dest(3:0). Il faut maintenant décoder les numéros véhiculés par sources et dest afin d’activer le fil correspondant qui est connecté soit aux connect des connecteur16 et soit aux CE des registres. Bien sûr il faut respecter la codification choisie précédemment. ISE propose un décodeur D4_16E qui va vous réaliser ce décodage.

Placer un premier D4_16E sous la FSM après l’avoir fait pivoter de 90°. Ajouter 16 petits fils sur les sorties. A ce moment faites un copier-coller pour en créer un second D4_16E que vous placerez à sa droite. Avec 4 Bus Tap vous devez connecter dest(3:0) sur les 4 entrées A3 A2 A1 A0 en respectant les poids des fils. Faites la même chose pour le second avec source(3:0).

Il ne vous reste plus qu’à nommer les sorties de vos deux D4_16E. Aucune erreur n’est permise. Aidez-vous du schéma suivant pour suivre l’ordre de nos registres R12B, R22B … sur les sorties 1, 2 … du décodeur source, B2R1, B2R2 …. sur les sorties 1, 2 … du décodeur dest. Pour terminer placez un Vcc sur les deux entrées E des décodeurs afin de les rendre actifs.

Figure 98 FSM connectée au RI et ses deux décodeurs

Figure 99 Zoom sur le décodeur destination

Figure 100 Zoom sur le décodeur source

Votre processeur S3 est prêt pour exécuter son premier programme.

Le premier programme va récupérer la valeur saisie sur les switches, celle-ci est automatiquement copiée dans le registre Rsw. Pour tester quelques transferts de registres vous allez la recopier dans le registre R3, puis R3 est recopié dans R4 enfin R4 est recopié dans R7seg pour affichage. Si la source d’un MOV n’est pas sélectionnée (code b0000) de par notre hypothèse sur les connecteurs, la valeur véhiculée sur le bus de donnée est x0000. MOV 0 R5 copie la valeur x0000 dans le registre R5.

Il suffit de mettre ce programme dans votre mémoire d’instruction insmem. Pour cela vous devez éditer le fichier prog.coe et copier les 4 premières instructions hexa suivantes. Il faudra toujours placer une première instruction b0000 0000 0000 0000 en début de programme. La raison de cette contrainte est liée à la simplicité du processeur S3 : il n’y a pas de signal de reset qui initialise le processeur. Par la suite on appellera cette instruction NOP : elle ne fait aucun transfert et ne déclenche aucune opération. Vous pouvez aussi laisser une instruction autre que MOV à la fin du programme. Normalement votre case ne la prendra pas en compte.

Une fois le fichier mis à jour et sauvé, il faut ouvrir l’IP_Core insmem et venir mettre à jour le fichier d’initialisation sur le troisième écran de saisie. Faites un show pour être certain de rentrer le bon fichier. Enfin il faut regénérer le composant par Generate. Une fois cette tâche ISE terminée, venez mettre à jour le schéma S3 par un clic sur le schéma, des symboles ont dû changer, recréez le composant S3 et mettez-le à jour dans toplevel.

Vous pouvez simuler toplevel en utilisant toplevel_tb , changez dans ce fichier la valeur initiale de CLK à '1'. Choisissez les ports q(15:0) des registres que vous voulez observer (RI, CO, R3, R4, R7seg dans l’ordre sur la fenêtre de simulation). La valeur x12 est toujours initialisée pour les switches dans toplevel_tb. (Les UUUU sont dus à une mauvaise initialisation de DEST par la FSM produite par Fizzim, mais celà ne gène pas le fonctionnement)

Figure 101 Simulation de votre premier programme

Lancez la génération finale et testez le programme sur la carte. Faites une copie du projet et nommez le TP9.

Un assembleur en deux minutes

Effectivement copier des codes hexadécimaux dans un fichier, c’est fastidieux et source d’erreur. Le jeu d’instructions du processeur S3 est assez simple pour créer un assembleur lui aussi très simple avec la commande sed. Cette commande linux est aussi disponible sous windows. Il vous suffit d’installer la dernière version. Voici celle que j’ai utilisée lors de la rédaction de ces TPs.

http://sourceforge.net/projects/gnuwin32/files/sed/4.2.1/sed-4.2.1-setup.exe/download

Ensuite il vous suffit de créer un fichier S3asm.bat qui contient toutes vos commandes sed. Les S/xxx/yyy/ produisent des substitutions de toutes les chaines xxx par une chaîne yyy.

ATTENTION la ligne 3 et 4 s/BEGIN/ .... doit être sur une seule ligne !!

Dans une fenêtre dos lancez alors la commande sur un fichier texte contenant le code assembleur de votre programme. Modifiez votre path si besoin est.

commande SED

sed -f S3asm.bat mon_fichier.S3 >mon_fichier.coe

Le format de mon_fichier.S3 ne doit utiliser que les mots clefs de votre fichier S3asm.bat, ou des hexadécimaux tout cela entre un begin et end. Vous pouvez remarquer que la première instruction x0000 est générée automatiquement par la traduction du begin. Inutile de le réécrire dans votre code assembleur. Tous les mots clefs sont en majuscule, mais la première commande de S3asm.bat convertit toutes les minuscules en majuscules, les deux sont donc équivalents. La seconde commande sed supprime les lignes commençant par --, ce sont des lignes commentaire.Voici le code mon_fichier.s3 de votre premier programme S3.

A vous de jouer

Question 1 : Modifier le programme pour afficher également la valeur sur les Led (Rled est le registre 6).

Question 2 : Pourquoi le programme tourne à l’infini et non pas une seule fois? Que fait votre CO ???

Réponses

name NOP, comment NOP