Fonctionnement d'un ordinateur/Les circuits synchrones et asynchrones

Un livre de Wikilivres.

Les bascules sont rarement utilisées seules. Elles sont combinées avec des circuits combinatoires pour former des circuits qui possèdent une capacité de mémorisation, appelés circuits séquentiels. L'ensemble des informations mémorisées dans un circuit séquentiel, le contenu de ses bascules, forme ce qu'on appelle l'état du circuit, aussi appelé la mémoire du circuit séquentiel. Un circuit séquentiel peut ainsi être découpé en deux morceaux : des bascules qui stockent l'état du circuit, et des circuits combinatoires pour mettre à jour l'état du circuit et sa sortie. Suivant la méthode utilisée pour déterminer la sortie, on peut classer les circuits séquentiels en deux catégories :

  • les automates de Moore, où la sortie ne dépend que de l'état mémorisé ;
  • et les automates de Mealy, où la sortie dépend de l'état du circuit et de ses entrées.
Ces derniers ont tendance à utiliser moins de portes logiques que les automates de Moore.
Automate de Moore et de Mealy

Concevoir des circuits séquentiels demande d'utiliser un formalisme assez complexe et des outils comme des machines à état finis (finite state machine). Mais nous ne parlerons pas de cela dans ce cours, car nous n'aurons heureusement pas à les utiliser.

La majorité des circuits séquentiels possèdent plusieurs bascules, dont certaines doivent être synchronisées entre elles. Sauf qu'un léger détail vient mettre son grain de sel : tous les circuits combinatoires ne vont pas à la même vitesse ! Si on change l'entrée d'un circuit combinatoire, cela se répercutera sur ses sorties. Mais toutes les sorties ne sont pas mises en même temps et certaines sorties seront mises à jour avant les autres ! Cela ne pose pas de problèmes avec un circuit combinatoire, mais ce n'est pas le cas si une boucle est impliquée, comme dans les circuits séquentiels. Si les sorties sont renvoyées sur les entrées, alors le résultat sur l'entrée sera un mix entre certaines sorties en avance et certaines sorties non-mises à jour. Le circuit combinatoire donnera alors un résultat erroné en sortie. Certes, la présence de l'entrée Enable permet de limiter ce problème, mais rien ne garantit qu'elle soit mise à jour au bon moment. En conséquence, les bascules ne sont pas mises à jour en même temps, ce qui pose quelques problèmes relativement fâcheux si aucune mesure n'est prise.

Le temps de propagation[modifier | modifier le wikicode]

Pour commencer, il nous faut expliquer pourquoi tous les circuits combinatoires ne vont pas à la même vitesse. Tout circuit, quel qu'il soit, va mettre un petit peu de temps avant de réagir. Ce temps mis par le circuit pour propager un changement sur les entrées vers la sortie s'appelle le temps de propagation. Pour faire simple, c'est le temps que met un circuit à faire ce qu'on lui demande : plus ce temps de propagation est élevé, plus le circuit est lent. Ce temps de propagation dépend de pas mal de paramètres, aussi je ne vais citer que les principaux.

Le temps de propagation des portes logiques[modifier | modifier le wikicode]

Une porte logique n'est pas un système parfait et reste soumis aux lois de la physique. Notamment, il n'a pas une évolution instantanée et met toujours un petit peu de temps avant de changer d'état. Quand un bit à l'entrée d'une porte logique change, elle met du temps avant de changer sa sortie. Ce temps de réaction pour propager un changement fait sur les entrées vers la sortie s'appelle le temps de propagation de la porte logique. Pour être plus précis, il existe deux temps de propagation : un temps pour passer la sortie de 0 à 1, et un temps pour la passer de 1 à 0. Les électroniciens utilisent souvent la moyenne entre ces deux temps de propagation, et la nomment le retard de propagation, noté .

Temps de propagation d'une porte logique.

Le chemin critique[modifier | modifier le wikicode]

Délai de propagation dans un circuit simple.

Si le temps de propagation de chaque porte logique a son importance, il faut aussi tenir compte de la manière dont elles sont reliées. La relation entre "temps de propagation d'un circuit" et "temps de propagation de ses portes" n'est pas simple. Deux paramètres vont venir jouer les trouble-fêtes : le chemin critique et la sortance des portes logiques. Commençons par voir le chemin critique, qui n'est autre que le nombre maximal de portes logiques entre une entrée et une sortie de notre circuit. Pour donner un exemple, nous allons prendre le schéma ci-contre. Pour ce circuit, le chemin critique est dessiné en rouge. En suivant ce chemin, on va traverser trois portes logiques, contre deux ou une dans les autres chemins.

Le temps de propagation total, lié au chemin critique, se calcule à partie de plusieurs paramètres. Premièrement, il faut déterminer quel est le temps de propagation pour chaque porte logique du circuit. En effet, chaque porte logique met un certain temps avant de fournir son résultat en sortie : quand les entrées sont modifiées, il faut un peu de temps pour que sa sortie change. Ensuite, pour chaque porte, il faut ajouter le temps de propagation des portes qui précédent. Si plusieurs portes sont reliées sur les entrées, on prend le temps le plus élevé. Enfin, il faut identifier le chemin critique, le plus long : le temps de propagation de ce chemin est le temps qui donne le tempo maximal du circuit.

Temps de propagation par porte logique.
Temps de propagation pour chaque chemin.
Identification du chemin critique.

La sortance des portes logiques[modifier | modifier le wikicode]

Passons maintenant au second paramètre lié à l'interconnexion entre portes logiques : la sortance. Dans les circuits complexes, il n'est pas rare que la sortie d'une porte logique soit reliée à plusieurs entrées (d'autre portes logiques). Le nombre d'entrées connectées à une sortie est appelé la sortance de la sortie. Il se trouve que plus on connecte de portes logiques sur une sortie, (plus sa sortance est élevée), plus il faudra du temps pour que la tension à l'entrée de ces portes passe de 1 à 0 (ou inversement). La raison en est que la porte logique fournit un courant fixe sur sa sortie, qui charge les entrées en tension électrique. Un courant positif assez fort charge les entrées à 1, alors qu'un courant nul ne charge pas les entrées qui retombent à 0. Avec plusieurs entrées, la répartition est approximativement équitable et chaque entrée reçoit seulement une partie du courant de sortie. Elles mettent plus de temps à se remplir de charges, ce qui fait que la tension met plus de temps à monter jusqu'à 1.

Influence de la sortance d'un circuit sur sa fréquence-période

Le temps de latence des fils[modifier | modifier le wikicode]

Enfin, il faut tenir compte du temps de propagation dans les fils, celui mis par notre tension pour se propager dans les fils qui relient les portes logiques entre elles. Ce temps perdu dans les fils devient de plus en plus important au cours du temps, les transistors et portes logiques devenant de plus en plus rapides à force de les miniaturiser. Par exemple, si vous comptez créer un circuit avec des entrées de 256 à 512 bits, il vaut mieux le modifier pour minimiser le temps perdu dans les interconnexions que de diminuer le chemin critique.

Les circuits synchrones et asynchrones[modifier | modifier le wikicode]

Sur les circuits purement combinatoires, le temps de propagation n'est que rarement un souci, à moins de rencontrer des soucis de métastabilité assez compliqués. Par contre, le temps de propagation doit être pris en compte quand on crée un circuit séquentiel : sans ça on ne sait pas quand mettre à jour les bascules du circuit. Si on le fait trop tôt, le circuit combinatoire peut sauter des états : il se peut parfaitement qu'on change le bit placé sur l'entrée avant qu'il ne soit mémorisé. De plus, les différents circuits d'un composant électronique n'ont pas tous le même temps de propagation, et ceux-ci vont fonctionner à des vitesses différentes. Si l'on ne fait rien, on peut se retrouver avec des dysfonctionnements : par exemple, un circuit lent peut rater deux ou trois nombres envoyés par un composant un peu trop rapide.

Pour éviter les ennuis dus à l'existence de ce temps de propagation, il existe deux grandes solutions, qui permettent de faire la différence entre circuits asynchrones et synchrones. Les circuits asynchrones préviennent les bascules quand ils veulent la mettre à jour. Quand le circuit combinatoire et les bascules sont tous les deux prêts, on autorise l'écriture dans les bascules. Mais ce n'est pas cette solution qui est utilisée dans les circuits de nos ordinateurs, qui sont des circuits synchrones. Dans les circuits synchrones, les bascules sont mises à jour en même temps.

Les circuits synchrones[modifier | modifier le wikicode]

Les circuits synchrones mettent à jour leurs bascules à intervalles réguliers. La durée entre deux mises à jour est constante et doit être plus grande que le temps de propagation le plus long du circuit : on se cale donc sur le circuit combinatoire le plus lent. Les concepteurs d'un circuit doivent estimer le pire temps de propagation possible pour le circuit et ajouter une marge de sûreté. Pour mettre à jour les circuits à intervalles réguliers, le signal d'autorisation d'écriture est une tension qui varie de façon cyclique : on parle alors de signal d'horloge. Le temps que met la tension pour effectuer un cycle est ce qu'on appelle la période. Le nombre de périodes par seconde est appelé la fréquence. Elle se mesure en hertz. On voit sur ce schéma que la tension ne peut pas varier instantanément : elle met un certain temps pour passer de 0 à 1 et de 1 à 0. On appelle cela un front. Le passage de 0 à 1 est appelé un front montant et le passage de 1 à 0 un front descendant.

Fréquence et période.

Un point important est que le signal d'horloge passe régulièrement de 0 à 1. Dans le cas idéal, 50% de la période est à l'état 1 et les 50% restants à l'état 0. On a alors un signal carré. Mais il arrive que le temps passé à l'état 1 ne soit pas forcément le même que le temps passé à 0. Par exemple, le signal peut passer 10% de la période à l'état 1 et 90% du temps à l'état 0. C'est assez rare, mais possible et même parfois utile. Le signal n'est alors pas appelé un signal carré, mais un signal rectangulaire. Le signal d'horloge est donc à 1 durant un certain pourcentage de la période. Ce pourcentage est appelé le rapport cyclique (duty cycle).

Signaux d'horloge asymétriques

En faisant cela, le circuit mettra ses sorties à jour lors d'un front montant (ou descendant) sur son entrée d'horloge. Entre deux fronts montants (ou descendants), le circuit ne réagit pas aux variations des entrées. Rappelons que seuls les circuits séquentiels doivent être synchronisés ainsi, les circuits combinatoires étant épargnés par les problématiques de synchronisation. Pour que les circuits séquentiels soient cadencés par une horloge, les bascules du circuit sont modifiées de manière à réagir aux fronts montants et/ou aux fronts descendants, ce qui fait que la mise à jour de l'état interne du circuit est synchronisée sur l'horloge. Évidemment, l’horloge est envoyée au circuit via une entrée spéciale : l'entrée d'horloge. L'horloge est ensuite distribuée à l'intérieur du composant, jusqu'aux bascules, par un ensemble de connexions qui relient l'entrée d'horloge aux bascules.

Circuit séquentiel synchrone.

En théorie, plus un composant utilise une fréquence élevée, plus il est rapide. C'est assez intuitif : plus un composant peut changer d'état un grand nombre de fois par seconde, plus, il peut faire de calculs, et plus il est performant. Cela n'est toutefois pas un élément déterminant : un processeur de 4 gigahertz peut être bien plus rapide qu'un processeur de 200 gigahertz, pour des raisons techniques qu'on verra plus tard dans ce cours. Mais dans les grandes lignes, une hausse de la fréquence signifie une performance plus élevée. Les processeurs et mémoires ont vu leur fréquence augmenter au fil du temps, ce qui explique en partie pourquoi leur performance a augmenté au cours du temps. Pour donner un ordre de grandeur, le premier microprocesseur avait une fréquence de 740 kilohertz (740 000 hertz), alors que les processeurs actuels montent jusqu'à plusieurs gigahertz : plusieurs milliards de fronts par secondes ! Mais cela a eu pour défaut d'augmenter la consommation d'énergie des processeurs, et la chaleur qu'ils émettent. Car, comme on le verra dans plusieurs chapitres, un composant chauffe d'autant plus qu'il a une fréquence élevée. Les premiers processeurs étaient refroidis par un simple radiateur, alors que les processeurs modernes demandent un radiateur, un ventilateur et une pâte thermique de qualité pour dissiper leur chaleur. Pour limiter la catastrophe, les fabricants de processeurs ont inventé diverses techniques permettant de diminuer la consommation énergétique et la dissipation thermique d'un processeur, mais cela est un sujet pour un autre chapitre. Toujours est-il que l'augmentation en fréquence des processeurs modernes est de plus en plus contrainte par la dissipation de chaleur et la consommation d'énergie.

Dans un ordinateur moderne, chaque composant a sa propre horloge, qui peut être plus ou moins rapide que les autres. Par exemple, le processeur fonctionne avec une horloge différente de l'horloge de la mémoire RAM ou des périphériques. La présence de plusieurs horloges vient du fait que certains composants sont plus lents que d'autres. Plutôt que de caler tous les composants d'un ordinateur sur le plus lent en utilisant une seule horloge, il vaut mieux utiliser une horloge différente pour chaque composant : les mises à jour des circuits sont synchronisées à l'intérieur d'un composant (dans un processeur, ou une mémoire), alors que les composants eux-mêmes synchronisent leurs communications avec d'autres mécanismes. Ces multiples signaux d'horloge dérivent d'une horloge de base qui est « transformée » en plusieurs horloges, grâce à des montages électroniques spécialisés (des PLL ou des montages à portes logiques un peu particuliers).

Les circuits asynchrones[modifier | modifier le wikicode]

Les circuits asynchrones n'utilisent pas d'horloge pour synchroniser leurs composants/sous-circuits. L’asynchrone permet à deux circuits/composants de se synchroniser, l'un des deux étant un émetteur, l'autre étant un récepteur. Pour se synchroniser, l’émetteur indique au récepteur qu'il lui a envoyé une donnée. Le récepteur réceptionne alors la donnée et indique qu'il a pris en compte les données envoyées. Cette synchronisation se fait grâce à des fils spécialisés du bus de commande, qui transmettent des bits particuliers.

Communication asynchrone

La transmission des données/requêtes peut se faire de deux manières différentes : la première utilise un signal de requête qui indique que de nouvelles données sont disponibles, la seconde n'envoie que des données dupliquées. Ces deux méthodes portent les noms de Bundled Encoding et de Multi-Rail Encoding. La première est la plus intuitive, car elle correspond à l'encodage des bits que nous utilisons depuis le début de ce cours, alors que la seconde est inédite à ce point du cours.

Le Bundled Encoding[modifier | modifier le wikicode]

Avec la méthode du Bundled Encoding, aussi appelée codage simple-track, la synchronisation utilise deux fils : REQ et ACK (des mots anglais request =demande et acknowledg(e)ment =accusé de réception). Le fil REQ indique au récepteur que l'émetteur lui a envoyé une donnée, tandis que le fil ACK indique que le récepteur a fini son travail et a accepté la donnée entrante.

Plus rarement, un seul fil est utilisé à la fois pour la requête et l'acquittement, ce qui limite le nombre de fils. Un 1 sur ce fil signifie qu'une requête est en attente (le second composant est occupé), tandis qu'un 0 indique que le second composant est libre. Ce fil est manipulé aussi bien par l'émetteur que par le récepteur. L'émetteur met ce fil à 1 pour envoyer une donnée, le récepteur le remet à 0 une fois qu'il est libre.

Signaux de commande d'un bus asynchrone

Si l'on utilise deux fils séparés, le codage des requêtes et acquittements peut se faire de plusieurs manières. Deux d'entre elles sont très utilisées et sont souvent introduites dans les cours sur les circuits asynchrones. Elles portent les noms de protocole à 4 phases et protocole à 2 phases. Elles ne sont cependant pas les seules et beaucoup de protocoles asynchrones utilisent des méthodes alternatives, mais ces deux méthodes sont très pédagogiques, d'où le fait qu'on les introduise ici.

Protocoles de transmission asynchrone à 2 et 4 phases. Les chiffres correspondent au nombre de fronts de la transmission.

Avec le protocole à 4 phases, les requêtes d'acquittement sont codées par un bit et/ou un front montant. Les signaux REQ/ACK sont mis à 1 en cas de requête/acquittement et repassent 0 s'il n'y en a pas. Le protocole assure que les deux signaux sont remis à zéro à la fin d'une transmission, ce qui est très important pour le fonctionnement du protocole. Lorsque l'émetteur envoie une donnée au récepteur, il fait passer le fil REQ de 0 à 1. Cela dit au récepteur : « attention, j'ai besoin que tu me fasses quelque chose ». Le récepteur réagit au front montant et/ou au bit REQ et fait ce qu'on lui a demandé. Une fois qu'il a terminé, il positionne le fil ACK à 1 histoire de dire : j'ai terminé ! les deux signaux reviennent ensuite à 0, avant de pouvoir démarrer une nouvelle transaction.

Avec le protocole à deux phases, tout changement des signaux REQ et ACK indique une nouvelle transmission, peu importe que le signal passe de 0 à 1 ou de 1 à 0. En clair, les signaux sont codés par des fronts montants et descendants, et non par le niveau des bits ou par un front unique. Il n'y a donc pas de retour à 0 des signaux REQ et ACK à la fin d'une transmission. Une transmission a lieu entre deux fronts de même nature, deux fronts montants ou deux fronts descendants.

Le tout est illustré ci-contre. On voit que le protocole à 4 phases demande 4 fronts pour une transmission : un front montant sur REQ pour le mettre à 1, un autre sur ACk pour indiquer l'acquittement, et deux fronts descendants pour remettre les deux signaux à 0. Avec le protocole à 2 phases, on n'a que deux fronts : deux fronts montants pour la première transmission, deux fronts descendants pour la suivante. D'où le nom des deux protocoles : 4 et 2 phases.

Le Multi-Rail Encoding[modifier | modifier le wikicode]

Les circuits asynchrones précédents, qui le Bundled Encoding, utilisent un fil par bit de données et un fil pour le signal REQ. Mais cette manière de faire a quelques défauts, le principal étant la sensibilité aux délais. Pour faire simple, la conception du circuit doit prendre en compte le temps de propagation dans les fils : il faut garantir que le signal REQ arrive au second circuit après les données, ce qui est loin d'être trivial. Pour éviter cela, d'autres circuits utilisent plusieurs fils pour coder un seul bit, ce qui donne un codage multiple-rails.

Le cas le plus simple utilise deux fils par bit, ce qui lui vaut le nom de codage dual-rail.

Dual-rail protocol

Il en existe plusieurs sous-types, qui différent selon ce qu'on envoie sur les deux fils qui codent un bit.

  • Certains circuits asynchrones utilisent un signal REQ par bit, d'où la présence de deux fils par bit : un pour le bit de données, et l'autre pour le signal REQ.
  • D'autres codent un bit de données sur deux bits, certaines valeurs indiquant un bit invalide.
Protocole 3 états

Les bascules synchrones[modifier | modifier le wikicode]

Utiliser une horloge demande cependant d'adapter les circuits vus précédemment, les bascules devant être modifiées. En effet, les bascules précédentes sont mises à jour quand un signal d'autorisation est mis à 1. Mais avec un signal d'horloge, les bascules doivent être mises à jour lors d'un front, montant ou descendant, peu importe. Pour cela, les bascules ont une entrée d'autorisation d'écriture modifiée, qui réagit au signal d'horloge. Les bascules commandées par une horloge sont appelées des bascules synchrones.

Les bascules synchrones peuvent mettre à jour leur contenu soit lors d'un front montant, soit d'un front descendant, soit les deux, soit lorsque la tension d'horloge est à 1. Suivant le cas, le symbole utilisé pour représenter l'entrée d'horloge est différent, comme illustré ci-dessous.

Symboles des bascules synchrones.
Notons qu'en anglais, le terme bascule se dit flip-flop ou latch. De nos jours, le terme latch étant utilisé pour les bascules non-synchrones, alors que le terme flip-flop est utilisé pour désigner les bascules synchrones.

Les types de bascules synchrones[modifier | modifier le wikicode]

Il existe plusieurs types de bascules synchrones, qu'on peut classer en fonction de leurs entrées-sorties.

Symbole d'une bascule D synchrone.

La plus simple est la bascule D synchrone est une bascule D modifiée de manière à mettre à jour son contenu sur un front (montant). Celle-ci possède deux entrées : une entrée D sur laquelle on envoie la donnée à mémoriser (entrée d'écriture), et une autre pour l'horloge. Elle contient entre une et deux sorties : une pour la donnée mémorisée (sortie de lecture) et éventuellement une autre pour son opposé. Son fonctionnement est simple : son contenu est mis à jour avec ce qu'il y a sur l'entrée D, mais seulement lors d'un front (montant ou descendant suivant la bascule). Plus rares, certaines bascules D contiennent des entrées R et S pour les mettre à zéro ou à 1. La plupart des bascules D ont une entrée R pour les remettre à zéro, tandis que l'entrée S est absente, celle-ci étant peu utile.

Entrée CLK Entrée D Sortie Q
Front montant (ou descendant, suivant la bascule) 0 0
1 1
Pas de front montant 0 ou 1 Pas de changement
Bascule SR synchrone.

Il existe aussi des versions synchrones des bascules RS à entrée Enable. Sur celles-ci, l'entrée Enable est juste remplacée par une entrée pour l’horloge. On les appelle des bascules RS synchrones.

Entrée CLK Entrée R Entrée S Sortie Q
Front montant (ou descendant, suivant la bascule) 0 0 Pas de changement
0 1 Mise à 1
1 0 Mise à 0
1 1 Indéterminé.
Pas de front montant 0 ou 1 0 ou 1 Pas de changement
Bascule synchrone JK.

Les bascules JK ont aussi leur version synchrone, les bascules JK synchrones.

Entrée CLK Entrée R Entrée S Sortie Q
Front montant (ou descendant, suivant la bascule) 0 0 Pas de changement
0 1 Mise à 1
1 0 Mise à 0
1 1 Inversion du bit mémorisé
Pas de front montant 0 ou 1 0 ou 1 Pas de changement
Bascule T.

La bascule T est une bascule qui n'existe que comme bascule synchrone. Elle possède deux entrées : une entrée d'horloge et une entrée nommée T. Cette bascule inverse son contenu quand l'entrée T est à 1, mais à condition qu'il y ait un front sur le signal d'horloge. En clair, l'inversion a lieu quand il y a à la fois un front et un 1 sur l'entrée T. Si l'entrée T est maintenu à 1 pendant longtemps, cette bascule inverse son contenu à chaque cycle d'horloge. À ce propos, l'entrée T tire son nom du mot anglais Toggle, qui veut dite inverser.

Entrée CLK Entrée T Sortie Q
Front montant (ou descendant, suivant la bascule) 0 Pas de changement
1 Inversion du contenu de la bascule
Pas de front montant 0 ou 1 Pas de changement
Chronogramme qui montre le fonctionnement d'une bascule T. Le chronogramme montre comment évolue la sortie Q en fonction du temps, en fonction de l'entrée d'horloge C et de l'entrée T.
Cette bascule est utilisée pour fabriquer des compteurs, des circuits dans lesquels des bits doivent régulièrement être inversées.
Bascule T simplifiée.

La bascule T simplifiée est une bascule T dont l'entrée T a été retiré. Cette bascule change d'état à chaque cycle d'horloge, sans besoin d'autorisation de la part d'une entrée T.

Entrée CLK Sortie Q
Front montant (ou descendant, suivant la bascule) Inversion du bit mémorisé
Pas de front montant Pas de changement

L'intérieur d'une bascule synchrone[modifier | modifier le wikicode]

Pour fabriquer une bascule synchrone, les solutions sont nombreuses et dépendent de si l'on parle d'une bascule D ou d'une bascule RS. Néanmoins, une méthode assez courante, et assez simple, est de partir d'une bascule non-synchrone, puis de la modifier pour la rendre synchrone. Les bascules les plus indiquées pour cela sont les bascules avec une entrée Enable : il suffit de transformer l’entrée Enable en entrée d'horloge. Évidemment, cela demande de faire quelques modifications. Il ne suffit pas d'envoyer le signal d'horloge sur l'entrée Enable pour que cela marche.

La méthode la plus simple consiste à placer deux bascules D l'une à la suite de l'autre. De plus, l'entrée Enable de la seconde bascule est précédée d'une porte NON. Avec cette méthode, la première bascule est mise à jour quand l’horloge est à 0, la seconde étant mise à jour avec le contenu de la première quand l'horloge est à 1. Dans ces conditions, la sortie finale de la bascule est mise à jour après un front montant.

Negative-edge triggered master slave D flip-flop

On peut faire exactement la même chose avec deux bascules asynchrones RS l'une à la suite de l'autre.

Bascule R synchrone basée sur des bascules RS non-synchrones.
Bascule D cadencée par une horloge.

Une autre méthode associe trois bascules RS normales, les deux premières formant une couche d'entrée qui commande la troisième bascule. Ces deux bascules d'entrée vont en quelque sorte traiter le signal à envoyer à la troisième bascule. Quand le signal d'horloge est à 0, les deux bascules d'entrée fournissent un 1 sur leur sortie : la troisième bascule reste donc dans son état précédent, sans aucune modification. Quand l'horloge passe à 1 (front montant), seule une des deux bascules va fournir un 1 en sortie, l'autre voyant sa sortie passer à 0. La bascule en question dépend de la valeur de D : un 0 sur l'entrée D force l'entrée R de la troisième bascule, un 1 forçant l'entrée S. Dit autrement, le contenu de la troisième bascule est mis à jour. Quand l'entrée d'horloge passe à 1, les bascules se figent toutes dans leur état précédent. Ainsi, la troisième bascule reste commandée par les deux bascules précédentes, qui maintiennent son contenu (les entrées R et S restent à leur valeur obtenue lors du front montant).

Il est aussi possible de créer une bascule D synchrone avec des transistors. Nous n'étudierons pas ce cas, qui est franchement compliqué et relève plus de l'état de l'art que d’autre chose. Tout au plus, nous pouvons nous contenter de vous donner le circuit obtenu, pour le plaisir de vos yeux.

True single-phase edge-triggered flip-flop with reset

Fabriquer des bascules synchrones à partir d'autres bascules synchrones[modifier | modifier le wikicode]

Une bascule JK synchrone se fabrique facilement à partir d'une bascule RS synchrones, ce qui n'est pas étonnant quand on sait que leur comportement est presque identique, la seule différence étant ce qui se passe quand les entrées RS sont toutes les deux à 1. Il suffit, comme pour une bascule JK asynchrone, d'ajouter quelques circuits pour convertir les entrées JK en entrées RS.

Bascule JK synchrone, conçue à partir d'une bascule RS synchrone.

La bascule D synchrone peut se fabriquer partir d'une bascule JK ou RS synchrone. Il suffit alors d'ajouter un circuit combinatoire pour traduire les entrées D et E en entrées RS ou JK.

Bascule D fabriquée avec une bascule JK synchrone. Bascule D fabriquée avec une bascule RS synchrone.

La bascule T simplifiée est la version la plus simple de bascule T, celle qui n'a pas d'entrée T et se contente d'inverser son contenu à chaque cycle d'horloge. La fabriquer est assez simple : il suffit de prendre une bascule D synchrone et de relier sa sortie /Q à son entrée D. On peut aussi faire la même chose avec une bascule JK synchrone ou une bascule RS synchrone.

Bascule T simplifiée fabriquée avec une bascule D synchrone. Bascule T simplifiée fabriquée avec une bascule RS synchrone. Bascule T simplifiée fabriquée avec une bascule JK synchrone.

Une bascule T normale peut s’implémenter une bascule T simplifiée, une bascule RS synchrone ou une bascule JK synchrone. Pour le circuit basé sur une bascule T simplifiée, l'idée est de faire un ET entre l'entrée T et le signal d'horloge, ce ET garantissant que le signal d’horloge est mis à 0 si l'entrée T est à zéro.

Bascule T simplifiée, fabriquée avec une bascule T simplifiée. Bascule T simplifiée, fabriquée avec une bascule RS synchrone. Bascule T fabriquée avec une bascule JK.

L'utilisation de l'horloge pour les circuits combinatoires : la logique dynamique MOS[modifier | modifier le wikicode]

La logique dynamique permet de créer des portes logiques ou des bascules d'une manière assez intéressante. Logiquement, nous aurions dû la voir dans le chapitre sur les transistors et les portes logiques, mais le problème est que cette logique fait appel à un signal d'horloge. Et aussi étonnant que cela puisse paraître, le signal d’horloge est alors utilisé pour fabriquer des circuits combinatoires !

Un transistor MOS peut servir de condensateur[modifier | modifier le wikicode]

Les technologies CMOS conventionnelles mettent la sortie d'une porte logique à 0/1 en la connectant à la tension d'alimentation ou à la masse. La logique pass transistor transfère la tension et le courant de l'entrée vers la sortie. Dans les deux cas, la sortie est connectée directement ou indirectement à la tension d'alimentation quand on veut lui faire sortie un 1. Avec la logique dynamique, ce n'est pas le cas. La sortie est maintenue à 0 ou à 1 en utilisant un réservoir d'électron qui remplace la tension d'alimentation.

En électronique, il existe un composant qui sert de réservoir à électricité : il s'agit du condensateur. On peut le charger en électricité, ou le vider pour fournir un courant durant une petite durée de temps. Par convention, un condensateur stocke un 1 s'il est rempli, un 0 s'il est vide. L'intérieur d'un condensateur est formé de deux couches de métal conducteur, séparées par un isolant électrique. Les deux plaques de conducteur sont appelées les armatures du condensateur. C'est sur celles-ci que les charges électriques s'accumulent lors de la charge/décharge d'un condensateur. L'isolant empêche la fuite des charges d'une armature à l'autre, ce qui permet au condensateur de fonctionner comme un réservoir, et non comme un simple fil.

Il est possible de fabriquer un pseudo-condensateur avec un transistor MOS. En effet, tout transistor MOS a un pseudo-condensateur caché entre la grille et la liaison source-drain. Pour comprendre ce qui se passe dans ce transistor de mémorisation, il faut savoir ce qu'il y a dans un transistor CMOS. À l'intérieur, on trouve une plaque en métal appelée l'armature, un bout de semi-conducteur entre la source et le drain, et un morceau d'isolant entre les deux. L'ensemble forme donc un condensateur, certes imparfait, qui porte le nom de capacité parasite du transistor. Suivant la tension qu'on envoie sur la grille, l'armature va se remplir d’électrons ou se vider, ce qui permet de stocker un bit : une grille pleine compte pour un 1, une grille vide compte pour un 0.

Anatomie d'un transistor CMOS

L'utilisation de transistors MOS comme condensateur n'est pas spécifique à la logique dynamique. Certains mémoires RAM le font, comme nous le verrons dans le chapitre sur les cellules mémoires. Aussi, il est intéressant d'en parler maintenant, histoire de préparer le terrain. D'ailleurs, les mémoires RAM sont remplies de logique dynamique.

L'utilisation des pseudo-condensateurs en logique dynamique[modifier | modifier le wikicode]

Un circuit conçu en logique dynamique contient un transistor est utilisé comme condensateur. Il s’insère entre la tension d'alimentation et la sortie du circuit. Son rôle est simple : lorsqu'on utilise la sortie, le condensateur se vide, ce qui place la sortie à 1. le reste du temps, le condensateur est relié à la tension d'alimentation et se charge. Un circuit en logique dynamique effectue son travail en deux phases : une phase d'inactivité où il remplit ses condensateurs, et une phase où sa sortie fonctionne. Les deux phases sont appelées la phase de précharge et la phase d'évaluation. La succession de ces deux phases est réalisée par le signal d'horloge : la première pahse a lieu quand le signal d'horloge est à 1, l'autre quand il est à 0.

Une porte NAND en logique dynamique CMOS[modifier | modifier le wikicode]

Voici un exemple de porte NAND en logique dynamique MOS. La porte est alors réalisée avec des transistors NMOS et PMOS, le circuit ressemble à ce qu'on a en logique NMOS. En bas, on trouve les transistors NMOS pour relier la sortie au 0 volt. Mais au-dessus, on trouve un transistor CMOS qui remplace la résistance. Le fonctionnement du circuit est simple. Quand l'entrée clock est à 1, le condensateur se charge, les deux transistors NMOS sont déconnectés de la masse et le circuit est inactif. Puis, quand clock passe à 0, Le transistor PMOS se comporte en circuit ouvert, ce qui déconnecte la tension d'alimentation. Et son pseudo-condensateur se vide, ce qui fournit une tension d'alimentation de remplacement temporaire. Le transistor NMOS du bas se ferme, ce qui fait que les deux transistors A et B décident de si la sortie est connectée au 0 volt ou non. Si c'est le cas, le pseudo-condensateur se vide dans le 0 volt et la sortie est à 0. Sinon, le pseudo-condensateur se vide dans la sortie, ce qui la met à 1.

Porte NAND en logique CMOS.

Une bascule D en logique dynamique CMOS[modifier | modifier le wikicode]

Il est possible de créer une bascule D en utilisant la logique dynamique. L'idée est de prendre une bascule D normale, mais d'ajouter un fonctionnement en deux étapes en ajoutant des transistors/interrupteurs. Pour rappel, une bascule D normale est composée de deux inverseurs reliés l'un à l'autre en formant une boucle, avec un multiplexeur pour permettre les écritures dans la boucle.

Implémentation conceptuelle d'une bascule D
Animation du fonctionnement de la bascule précédente.

Le circuit final ajoute deux transistors entre les inverseurs tête-bêche. Les transistors en question sont reliés à l'horloge, l'un étant ouvert quand l'autre est fermé. Grâce à eux, le bit mémorisé circule d'un inverseur à l'autre : il est dans le premier inverseur quand le signal d'horloge est à 1, dans l'autre inverseur quand il est à 0 (en fait son inverse, comme vous l'aurez compris). Le tout est illustré ci-contre. Cette implémentation a été utilisée autrefois, notamment dans le processeur Intel 8086.

Bascule D en logique Dynamique, avec entrée Enable

Il existe une variante très utilisée, qui permet de remplacer le multiplexeur par un circuit légèrement plus simple. Avec elle, on a deux entrées pour commander la bascule, et non une seule entrée Enable. L'entrée Enable autorise les écriture, l'entrée Hold ferme la boucle qui relie la sortie du second inverseur au premier. Chaque entrée est associé à un transistor/interrupteur. Le transistor sur lequel on envoie l'entrée Enable se ferme uniquement lors des écritures et reste fermé sinon. A l'inverse, le transistor relié au signal Hold est fermé en permanence, sauf lors des écritures. En clair, les deux signaux sont l'inverse l'un de l'autre. Il permet de fermer le circuit, de bien relier les deux inverseurs en tête-bêche, sauf lors des écritures. On envoie donc l'inverse de l'entrée Enable sur ce transistor.

Bascule D en logique dynamique

Une manière de comprendre le circuit précédent est de le comparer à celui avec le multiplexeur. Le multiplexeur est composé d'une porte NON et de deux transistors. Il se trouve que les deux transistors en question sont placés au même endroit que les transistors connectés aux signaux Hold et Enable. En prenant retirant la porte NON du multiplexeur, on se retrouve avec le circuit. Au lieu de prendre un Signal Enable qui commande les deux transistors, ce qui demande d'ajouter une porte NON vu que les deux transistors doivent faire l'inverse l'un de l'autre, on se contente d'envoyer deux signaux séparés pour commander chaque transistor indépendamment.

Avantages et inconvénients[modifier | modifier le wikicode]

Les circuits en logique dynamique sont opposés aux circuits en logique statique, ces derniers étant les circuits CMOS, PMOS, NMOS ou TTL vu jusqu'à présent. Les circuits dynamiques et statiques ont des différences notables, ainsi que des avantages et inconvénients divers. Si on devait résumer :

  • la logique dynamique utilise généralement un peu plus de transistors qu'un circuit CMOS normal ;
  • la logique dynamique est souvent très rapide par rapport à la concurrence, car elle n'utilise que des transistors NMOS, plus rapides ;
  • la consommation d'énergie est généralement supérieure comparé au CMOS.

Un désavantage de la logique dynamique est qu'elle utilise plus de transistors. On économise certes des transistors MOS, mais il faut rajouter les transistors pour déconnecter les transistors NMOS de la masse (0 volt). Le second surcompense le premier.

Un autre désavantage est que le signal d'horloge ne doit pas tomber en-dessous d'une fréquence minimale. Avec une logique statique, on a une fréquence maximale, mais pas de fréquence minimale. Avec un circuit statique peut réduire la fréquence d'un circuit pour économiser de l'énergie, pour améliorer sa stabilité, et de nombreux processeurs modernes ne s'en privent pas. On peut même stopper le signal d'horloge et figer le circuit, ce qui permet de le mettre en veille, d'en stopper le fonctionnement, etc. Impossible avec la logique dynamique, qui demande de ne pas tomber sous la fréquence minimale. Cela a un impact sur la consommation d'énergie, sans compter que cela se marie assez mal avec certaines applications. Un processeur moderne ne peut pas être totalement fabriqué en logique dynamique, car il a besoin d'être mis en veille et qu'il a besoin de varier sa fréquence en fonction des besoins.

La distribution de l'horloge dans un circuit complexe[modifier | modifier le wikicode]

L’horloge est distribuée aux bascules et autres circuits à travers un réseau de connexions électriques qu'on appelle l'arbre d'horloge. L'arbre d'horloge le plus simple, illustré dans la première image ci-dessous, relie directement l'horloge à tous les composants à cadencer.

Arbre d’horloge simple.
Arbre d'horloge avec des buffers (les triangles sur le schéma).

Il va de soit que l'arbre d'horloge est beaucoup plus compliqué avec la logique dynamique qu'avec la logique statique. Avec la logique statique, seules les bascules doivent recevoir le signal d'horloge, avec éventuellement quelques rares circuits annexes. Mais avec la logique dynamique, toutes les portes logiques doivent recevoir le signal d'horloge, ce qui rend la distribution de l'hrologe beaucoup plus compliquée. C'est un point qui fait que la logique dynamique est assez peu utilisée, et souvent limitée à quelques portions bien précise d'un processeur.

Les défauts inhérents aux arbres d’horloge[modifier | modifier le wikicode]

Un problème avec cette approche est la sortance de l'horloge. Cette dernière est connectée à trop de composants, ce qui la ralentit. Pour éviter tout problème, on peut ajouter des buffers, de petits répéteurs de signal. S'ils sont bien placés, ils réduisent la sortance nécessaire et empêchent que le signal de l'horloge s'atténue en parcourant les fils.

Un autre problème très fréquent sur les circuits à haute performance est qu'une bonne partie de la consommation d'énergie a lieu dans l'arbre d'horloge. Ce n'était pas le cas avec les anciens transistors dits bipolaires, ou les anciennes technologies de fabrication de circuits imprimés, mais c'est devenu un problème depuis l'arrivée des transistors CMOS. Nous en reparlerons dans le chapitre sur la consommation énergétique des ordinateurs, mais il est intéressant de mettre quelques chiffres sur ce phénomène. Entre 20 à 30% de la consommation énergétique des processeurs modernes a lieu dans l'arbre d'horloge. En comparaison, les circuits asynchrones se passent de cette consommation d'énergie, sans compter que leurs mécanismes de synchronisations sont moins gourmands en courant. Ils sont donc beaucoup plus économes en énergie et chauffent moins. Malheureusement, leur difficulté de conception les rend peu courants.

Le décalage d’horloge (clock skew)[modifier | modifier le wikicode]

Clock skew lié aux temps de transmission dans les fils.

Un problème courant sur les circuits à haute fréquence est que les fils qui transmettent l’horloge ont chacun des délais de transmission différents. La raison principale à cela est qu'ils n'ont pas la même longueur, ce qui fait que l'électricité met plus de temps à traverser les quelques micromètres de différence entre fils. En conséquence, les composants sont temporellement décalés les uns d'avec les autres, même si ce n'est que légèrement. Ce phénomène est appelé le décalage d'horloge, traduction du terme clock skew utilisé en langue anglaise. Il ne pose pas de problème à faible fréquence et/ou pour des fils assez courts, mais c'est autre chose pour les circuits à haute fréquence. Pour éviter les effets néfastes du clock skew sur les circuits haute-fréquence, on doit concevoir l'arbre d'horloge avec des techniques assez complexes.

Par exemple, on peut jouer sur la forme de l'arbre d'horloge. Dans les schémas du dessus, l'arbre d'horloge part d'un côté du processeur, de là où se trouve la broche pour l'horloge. En faisant cela, un côté du processeur recevra l'horloge avant l'autre, entraînant l'apparition d'un délai entre la gauche du processeur et sa droite. Pour éviter cela, on peut faire partir l'horloge du centre du processeur. Le fil de l'horloge part de la broche d'horloge, va jusqu’au centre du processeur, puis se ramifie de plus en plus en direction des composants. En faisant cela, on garantit que les délais sont équilibrés entre les deux côtés du processeur. Cependant, il existera quand même un délai entre les composants proches du centre et ceux sur les bords du processeur. Mais le délai maximal est minimisé. Entre un délai proportionnel à la largeur du processeur, et un délai proportionnel à la distance maximale centre-bord (environ la moitié de la diagonale), le second est plus faible.

Il arrive que le clock skew soit utilisé volontairement pour compenser d'autres délais de transmission. Pour comprendre pourquoi, imaginons que deux composants soient reliés l'une avec l'autre, le premier envoyant ses données au second. Il y a évidemment un petit délai de transmission entre les deux. Mais sans clock skew, les deux composants recevront l'horloge en même temps : le receveur captera un front montant de l'horloge avant les données de l'émetteur. En théorie, on devrait cadencer l'horloge de manière à ce que ce délai inter-composants ne pose pas de problème. Mais cela n'est pas forcément la meilleure solution si on veut fabriquer un circuit à haute fréquence. Pour éviter cela, on peut ajouter un clock skew, qui retardera l’horloge du receveur. Si le clock skew est supérieur ou égal au temps de transmission inter-composants, alors le receveur réceptionnera bien le signal de l'horloge après les données envoyées par l'émetteur. On peut ainsi conserver un fonctionnement à haute fréquence, sans que les délais de transmission de données ne posent problème. Cette technique porte le nom barbare de source-synchronous clocking.

Interaction entre le clock skew et le délai de transmission entre deux circuits.

Les domaines d'horloge[modifier | modifier le wikicode]

Il existe des composants électroniques qui sont divisés en plusieurs morceaux cadencés à des fréquences différentes. Par exemple, les processeurs modernes contiennent plusieurs cœurs (pour simplifier, on a regroupé plusieurs processeurs dans un même boitier, et chaque processeur a été renommé cœur), chacun capable d’exécuter un programme/logiciel. Chaque cœur a sa propre fréquence, et il est possible que deux cœurs différents aillent à des fréquences différentes. Par exemple, il est possible de faire varier dynamiquement la fréquence de chaque cœur suivant leur charge de travail : les cœurs très utilisés iront à haute fréquence, alors que ceux ayant peu de calculs à faire iront à basse fréquence. Comme autre possibilité, il est possible de créer un processeur avec des cœurs puissants à haute fréquence et des cœurs basse-consommation à basse fréquence. C'est le cas sur certaines puces ARM et sur les processeurs Intel Core de 12e génération, de micro-architecture "Alder Lake". Comme autre exemple, les processeurs modernes intègrent tous une carte graphique, les deux étant sur la même puce de silicium, dans le même boitier. Mais le processeur va à une fréquence plus élevée que la carte graphique : plusieurs gigahertz pour le processeur, plusieurs centaines de mégahertz pour la carte graphique. De tels composants sont très fréquents et nous en verrons quelques autres dans la suite du cours. Et pour parler de ces composants, il est très utile d'introduire la notion de domaine d'horloge.

Un domaine d'horloge est l'ensemble des registres qui sont reliés au même signal d'horloge, associé aux circuits combinatoires associés. Il n'incorpore pas l'arbre d'horloge ni même le circuit de génération du signal d'horloge, mais c'est là un détail. La plupart des composants électroniques ont un seul domaine d'horloge, ce qui veut dire que tout le circuit est cadencé à une fréquence unique, la même pour toute la puce. D'autres ont plusieurs domaines d'horloge qui vont à des fréquences distinctes. Les raisons à cela sont multiples, mais la principale est que autant certains circuits ont besoin d'être performants et donc d'avoir une haute fréquence, d'autres peuvent très bine faire leur travail à une fréquence plus faible. L'usage de plusieurs domaines d'horloge permet à une portion critique de la puce d'être très rapide, tandis que le reste de la puce va à une fréquence inférieure. Une autre raison est l’interfaçage entre deux composants allant à des vitesses différentes, par exemple pour faire communiquer un processeur avec un périphérique.

Il arrive que deux domaines d'horloge doivent communiquer ensemble et s'échanger des données, et l'on parle alors de clock domain crossing. Et cela pose de nombreux problèmes, du fait de la différence de fréquence. Les deux domaines d'horloge ne sont pas synchronisés, n'ont pas la même fréquence, la même phase, rien ne colle. Dans les explications qui suivent, on va prendre l'exemple de l'échange d'un bit entre deux domaines d'horloge, qui va d'un domaine d'horloge source vers un domaine d'horloge de destination. Dans ce cas, on peut passer par l'intermédiaire d'une bascule inséré entre les deux domaines d'horloge, bascule cadencée à la fréquence du domaine d'horloge source.

Mais pour l'échange d'un nombre, les choses sont plus compliquées et insérer un registre entre les deux domaines d'horloge ne marche pas. En effet, lors d'un changement de valeur du nombre à transmettre, tous les bits du nombre n'arrivent pas au même moment dans le registre. Il est possible que le domaine d'horloge de destination voit un état transitoire, où seule une partie des bits a été mise à jour. Le résultat est que le domaine d'horloge de destination utilisera une valeur transitoire faussée, causa tout un tas de problèmes. Pour éviter cela, les nombres transmis entre deux domaines d'horloge sont encodés en code Gray, dans lequel les états transitoires n'existent pas. Pour rappel, entre deux nombres consécutifs en code Gray, seul un bit change.