lundi 14 avril 2014

Comment fonctionne un décodeur d'instruction

Dans un article précédent j'ai expliqué comment fonctionne l'unitée arithmétique et logique d'un microcontrôleur. Dans cette article j'explique comment fonctionne le décodeur d'instruction. On va prendre pour exemple le coeur PIC baseline.

Voici le cycle d'instruction d'un coeur baseline.

Il faut 4 cycles d'oscillateur pour exécuter une instruction. Ces cycles sont appelés Q1,Q2,Q3,Q4 sur le diagramme ci-haut. Commençons par un circuit qui permet de généner ce clocking 4 phases:
Il s'agit d'un compteur binaire à 2 bits réalisé avec 2 bascules JK configurées en mode toggle. Ce compteur boucle de 0 à 3. Il suffit de décoder le code binaire de sorte que la sortie Qx est à 1 seulement lorsque le compteur est à sa valeur correspondante x. A chaque transition montante de Fosc, la sortie Q de FF1 change d'état. La sortie ~Q est le complémentaire de Q et sert à clocker FF2. Il faut 2 cycles de Fosc pour faire basculer FF1 mais il en faut 4 pour FF2. Ça donne la table de vérité suivante.
comptephases
b1b0Q1Q2Q3Q4
001000
010100
100010
110001

Si on regarde encore le diagramme décrivant le cycle d'instruction on constate que le compteur ordinal est incrémenté par la transition montante de la phase Q1. Sur les PIC baseline les instructions sont toutes de la même longueurs soit 1 location mémoire. Donc à chaque instruction le compteur ordinal est augmenté de 1. Dans une telle situation on peut utiliser un compteur binaire synchrone comme compteur ordinal. Cependant pour effectuer des branchements il faut qu'on puisse charger ce compteur avec la valeur de l'adresse de destination. Un tel compteur binaire s'appelle loadable counter. Celui ci-dessous a 4 bits mais le principe peut-être étendu à autant de bits que nécessaires, (9 bits pour les PIC10F202).

Maintenant on a 2 éléments essentiels de notre coeur baseline. Le circuit qui génère les 4 phases et le compteur ordinal.

On va prendre en exemple 2 instructions, GOTO et ADDWF. Commençons par le GOTO. Le code opérationnel de cette instruction est encodée sur les 3 bits les plus significatifs (les instructions sont encodées sur 12 bits) et correspond à 101. Voici comment elle pourrait-être décodée.

Bien que je ne les ai pas représentés sur le schéma il y a des portes de sélection sur tous les bus entre les registres. Les signaux Qx ouvrent et ferment ses portes pour assurer le transfert au moment approprié. Voiçi les étapes pour le GOTO, les étapes 1 et 2 sont communes à toutes les instructions:
  1. Sur la transition Q1 montante on peut transférer le contenu du registre fetch register dans le registre décodeur d'instruction (instructon register). En même temps le compteur ordinal est incrémenté.
  2. Sur la transition descendante de Q1 le contenu du bus data de la mémoire programme peut-être transféré dans le fetch register. Puisque le compteur ordinal été incrémenté l'instruction chargée est celle à l'adresse PC+1
  3. Il s'agit d'un GOTO il faut donc remplacé le contenu du compteur ordinal par les 9 bits faibles du registre d'instruction. On peut faire ce transfert sur la transition montante de Q2. l'instruction qui a été chargée dans le fetch register n'est plus bonne puisqu'il y a changement d'adresse. Il faut donc mettre ce regisre à zéro qui est le code opérationnel pour l'instruction NOP (ne fait rien). Car au prochain cycle on doit charger l'instruction qui se trouve à la nouvelle addresse. On peut-faire cette mise à zéro aussi sur Q2 montante.
  4. Là on a un petit problème. Puisque le compteur ordinal pointe sur la prochaine instruction à exécuter et que celle-ci n'est pas dans le fetch register et puisque que le compteur ordinal est incrémenté dès le début du cycle d'instruction, si on le laisse tel quel il va chargé l'instruction qui se trouve après celle du GOTO. On va donc décrémenter le compteur ordinal avant de terminer ce cycle d'instruction. Cette opération ce fait sur la transition montante de Q3.
  5. La phase Q4 n'est pas utilisée par cette instruction.

ADDWF

Voici un schéma partiel d'un décodeur pour cette instruction.

Comme mentionné précédemment la phase Q1 est identique pour toutes les instructions.

  1. Pendant la phase Q2 la valeur contenu à l'adresse indiqué dans le code opérationnel (5 bits faibles) est utilisé pour adresser le file register. S'il y a indirection, le file register doit-être adressé une deuxième fois avec le contenu du registre FSR
  2. Pendant la phase Q3 la valeur de W et le contenus adressé dans le file register sont présentés aux entrées de l'UAL et l'addition effectuée.
  3. Durant la phase Q4 le résultat de l'opération est retourné soit dans W soit dans le file register. Notez la façon dont le bit d du code opérationnel est utilisé pour sélectionner la destination. Si d est zéro le résultat est retourné dans W sinon il est retourné dans le file register. Un petit rond à l'entrée d'une porte indique que le signal est inversé (active low) il faut donc que W soit à zéro pour que le signal de contrôle passe.

décodeur ROM

Créer un décodeur pour chaque instruction peut nécessité beaucoup de portes logiques même si les instructions peuvent partager des portes, par exemples les inverseurs sont communs à tous les décodeurs. Il y a une autre façon de procéder, il s'agit d'utiliser un décodeur ROM (Read Only Memory). Les bits data de la ROM sont fabriqués avec un masque métallique plutôt que des portes et ont un faible coût. L'idée est simple à implanter, les bits de l'instruction register qui contiennent le code opérationnel sont utilisés comme adresse d'une mémoire ROM. Les lignes de sortie de donnée de la ROM sont utilisés comme signaux pour contrôler les portes, en plus certaines lignes de données sont retournées vers le bus d'adresse de la ROM ce qui permet de faire évoluer l'automate de manière simple d'une étape à l'autre.

Supposons que le opcode est 5 et que les bits à la sortie du latch sont toujours à zéro au début du cycle d'instruction. À l'adresse 5 de la mémoire ROM on met les bits data aux valeurs qu'on a besoin sur le bus de contrôle et on envoie dans le latch les bits qui combinés avec les bits qui proviennent de l'instruction register vont donner l'adresse en ROM qui contient les valeurs de bits qu'on aura besoin à la prochaine étape du décodage. Ce genre de state machine est fréquemment utilisé, particulièrement dans les FPGA.