Registres et bus#

Nous savons maintenant retenir un bit avec une bascule. Pour construire un processeur, il faut retenir des octets entiers, et permettre à tous ses composants d'échanger ces octets. C'est le rôle des registres et du bus.

Le registre#

Reprenons la bascule D du chapitre précédent : elle ne mémorise qu'un seul bit, capturé au moment précis d'un front montant de l'horloge clk. Pour retenir plusieurs bits à la fois, il suffit d'aligner plusieurs bascules D côte à côte et de les brancher sur la même horloge. On appelle cela un registre. Un registre construit avec 8 bascules D mémorise ainsi un octet entier d'un seul coup.

On ajoute presque toujours au registre une entrée de commande supplémentaire, la charge (ou load, notée charger). Dans Logix, cette entrée porte l'étiquette LD (pour load). Elle décide si le registre doit réellement enregistrer une nouvelle valeur au prochain front montant, ou s'il doit plutôt conserver ce qu'il contient déjà :

  • si charger = 1, la valeur présentée à l'entrée est capturée au prochain front montant ;

  • si charger = 0, le registre garde son contenu, même si l'horloge continue de battre.

Sans cette entrée, un registre recopierait sa donnée d'entrée à chaque front montant, qu'on le veuille ou non. Avec elle, on choisit précisément le moment où une nouvelle valeur doit être mémorisée, et celui où l'ancienne doit être préservée.

On représente un registre par un symbole unique, une simple boîte, plutôt que de dessiner toutes les bascules D séparées : une entrée de donnée (sur plusieurs bits), l'horloge clk, l'entrée charger, et une sortie qui présente en permanence la valeur mémorisée.

Symbole d'un registre 8 bits : une entrée de donnée sur 8 bits à gauche, une entrée charger, une horloge clk avec son triangle, et une sortie Q sur 8 bits à droite

Le symbole d'un registre 8 bits. Le trait barré d'un 8 rappelle qu'il s'agit d'un faisceau de 8 fils.#

Important

  • Un registre de n bits, c'est n bascules D partageant la même horloge clk: elles capturent toutes leur bit au même front montant.

  • L'entrée charger décide si le registre enregistre une nouvelle valeur (charger = 1) ou conserve la précédente (charger = 0).

Essayez ci-dessous. Réglez la donnée, mettez charger à 1 ou 0, puis faites un front montant d'horloge : la sortie ne change qu'au front montant, et seulement si charger = 1.

Le banc de registres#

Un processeur regroupe souvent quelques registres en un banc de registres : par exemple quatre registres r0, r1, r2, r3 qui servent de mémoire de travail. On a alors besoin de deux choses : choisir dans lequel écrire, et choisir lequel lire. Ce sont exactement les deux briques du chapitre sur le multiplexage :

  • pour écrire, un décodeur transforme le numéro du registre voulu en un signal charger dirigé vers ce seul registre (les autres conservent leur valeur) ;

  • pour lire, un multiplexeur choisit, selon un numéro, quel registre présente sa valeur en sortie.

Un banc de registres n'est donc rien de plus que des registres, un décodeur et un multiplexeur assemblés. Nous nous en servirons pour construire le processeur.

Le bus#

En plus de ses registres, un processeur contient de nombreux autres composants. Tous ceux-ci doivent régulièrement s'échanger des octets. On pourrait imaginer tirer un fil dédié entre chaque paire de composants, mais, de cette manière, le nombre de fils exploserait et le câblage deviendrait ingérable.

La solution retenue dans presque tous les processeurs est de faire partager à tous les composants un même faisceau de fils, le bus. Au lieu de relier chaque composant à chaque autre, chacun se raccorde une seule fois à ce bus commun.

Trois registres R1, R2, R3 raccordés à un même faisceau de fils horizontal, le bus ; chaque registre possède une commande charger et une commande activer

Trois registres partageant un même bus. Chacun peut charger (lire le bus) ou activer sa sortie (poser sa valeur sur le bus).#

Mais partager un même fil pose un problème : que se passe-t-il si deux composants y déposent chacun une valeur différente au même instant ? Le bus se retrouverait avec deux tensions contradictoires, un vrai court-circuit. Une règle stricte s'impose donc :

Important

  • À chaque instant, un seul composant a le droit de poser sa valeur sur le bus, grâce à un signal qui lui est propre (une entrée "activer la sortie").

  • N'importe quel nombre de composants peuvent en revanche lire ce qui s'y trouve, en le capturant dans leur registre grâce à leur entrée charger, au prochain front montant d'horloge.

Essayez ci-dessous : deux registres partagent un même bus. Le bouton activer pose la valeur d'un registre sur le bus (un seul à la fois, sinon le bus signale un conflit) ; le bouton charger fait entrer la valeur du bus dans un registre au prochain front montant. En gardant activer r0 et charger r1 à 1, faites un front montant : la valeur passe de r0 à r1.

On peut comparer le bus à un micro qu'on se passe dans une réunion : une seule personne parle à la fois (elle "pose" sa voix sur le micro), mais tout le monde peut écouter en même temps. Si deux personnes attrapent le micro et parlent ensemble, plus personne ne comprend rien : c'est exactement le conflit qu'on interdit sur un bus.

Le Program Counter#

Un compteur est un registre un peu particulier : au lieu d'être chargé de l'extérieur, il réutilise l'additionneur vu au chapitre précédent pour ajouter 1 à sa propre valeur à chaque front montant d'horloge.

Dans notre processeur, ce compteur servira à repérer, une à une, les instructions du programme à exécuter : c'est pourquoi on l'appelle le program counter (ou compteur de programme en français). Il indique à tout moment la position, dans le programme, de la prochaine instruction. Comme n'importe quel registre, il garde tout de même son entrée charger : elle permet de lui imposer directement une valeur précise plutôt que de simplement ajouter 1, ce qui servira plus tard à "sauter" ailleurs dans le programme, par exemple pour une boucle.

Dans la démonstration ci-dessous, faites avancer l'horloge : le compteur ajoute 1 à chaque front montant.

Exercices#

Exercice 38#

Exercice 39#

À l'entrée du FriBowling, un afficheur montre le score de la partie en cours. Il est piloté par un registre R de 4 bits (valeurs de 0 à 15), muni d'une entrée charger : si charger = 1, R capture au prochain front montant la valeur présentée sur son entrée ; si charger = 0, R garde son contenu, quelle que soit la valeur présentée.

Voici, pour six fronts montants successifs, la valeur présentée à l'entrée et celle de charger. Au départ, avant le premier front montant, l'afficheur montre R = 0. Complétez le contenu de R après chaque front montant.

front montant

entrée

charger

R après le front montant

1

7

1

2

12

0

3

12

1

4

9

0

5

15

1

6

0

0

Exercice 40#

Trois registres R1, R2 et R3 du processeur sont reliés au même bus. Rappel : à chaque étape, un seul registre a le droit de poser sa valeur sur le bus ("activer sa sortie") ; en revanche, plusieurs registres peuvent charger cette même valeur en même temps.

Avant l'étape 1, les registres contiennent R1 = 9, R2 = 3, R3 = 0. Voici la suite des opérations :

Étape 1 : R1 active sa sortie ; R3 charge.
Étape 2 : R2 active sa sortie ; R1 charge.
Étape 3 : R3 active sa sortie ; R1 charge et R2 charge.
Étape 4 : R1 active sa sortie ; personne ne charge.

Complétez le contenu des trois registres après chaque étape.

étape

R1

R2

R3

avant

9

3

0

1

2

3

4

Exercice 41#

Le program counter (pc) est un registre spécial : à chaque front montant, s'il n'est pas chargé (charger = 0), il ajoute 1 à sa valeur. S'il est chargé (charger = 1), il prend directement la valeur imposée (un saut), au lieu de s'incrémenter.

Au départ, avant le premier front montant, pc = 0. Voici sept fronts montants successifs, avec la valeur de charger et, quand elle s'applique, la valeur de saut. Complétez pc après chaque front montant.

front montant

charger

valeur de saut

pc après le front montant

1

0

/

2

0

/

3

1

10

4

0

/

5

0

/

6

1

0

7

0

/

Une fois câblé, changez les di et faites un front montant : les quatre bits sont bien enregistrés en même temps. C'est cette idée, n bascules D sous une même horloge, qui définit un registre.

TP : registres, bus et banc de registres dans Logix#

Ouvrez Logix et construisez la mémoire de travail du processeur.

  1. Placez un registre (REG) et vérifiez son comportement : il ne capture la donnée que si charger (l'entrée LD) vaut 1, au front montant.

  2. Reliez deux registres à un composant BUS : donnez à chacun un signal activer (l'entrée en du bus) et un charger. Vérifiez qu'un seul peut poser sa valeur à la fois (sinon le bus signale un conflit), et faites passer une valeur d'un registre à l'autre.

  3. Construisez le banc de registres : quatre registres r0 à r3, un décodeur qui, à partir du numéro Rd, dirige le charger vers un seul registre, et deux multiplexeurs de lecture (commandés par Rd et Rs) qui présentent deux registres en sortie (pour alimenter l'ALU).

  4. Testez, puis encapsulez le banc de registres en un composant réutilisable nommé REGISTRES.

  5. Enregistrez votre travail.