Licence CC BY

Les compteurs numériques

Comment fabriquer un circuit qui compte à partir de bascules et de circuits combinatoires

Publié :
Auteurs :

Catégorie :

Ce cours demande les pré-requis suivants pour être compris :

  • savoir compter en binaire ;
  • savoir ce qu'est un multiplexeur ;
  • savoir ce qu'est une bascule , et notamment une bascule D ;
  • savoir ce qu'est une porte logique ET, OU, OU exclusif, etc.

Les compteurs sont des circuits électroniques qui … comptent. Ils mémorisent un nombre qu'ils mettent à jour soit à chaque cycle d'horloge, soit à la demande. Suivant le compteur, la représentation du nombre mémorisé change : certains utilisent le binaire traditionnel, d'autres le BCD, d'autre le code Gray, etc. Il existe plusieurs types de compteurs, qui se basent tous sur le même principe : ils utilisent des bascules pour mémoriser les bits du nombre (le contenu du compteur), ainsi que des multiplexeurs et des portes logiques pour mettre à jour ces bascules.

Ces compteurs peuvent être classés suivant plusieurs critères :

  • le sens de mise à jour du compteur (augmentation ou diminution) ;
  • la possibilité d'initialiser le compteur avec une valeur différente de zéro ;
  • leur comportement une fois la valeur maximale atteinte ;
  • leur fréquence de mise à jour ;
  • etc.

Premièrement, certains compteurs comptent, alors que d'autres décomptent : les compteurs augmentent le contenu du compteur à chaque mise à jour, alors que les décompteurs le diminuent. Certains circuits, les compteurs-décompteurs peuvent faire les deux : on peut leur demander d'augmenter ou de diminuer leur contenu avec une entrée de commande.

Certains compteurs commencent à compter à partir de zéro, tandis que les compteurs initialisables peuvent être initialisés avec la valeur de notre choix : ces derniers possèdent une entrée d'initialisation sur laquelle on peut placer le nombre initial. Cette entrée d'initialisation est couplée avec une entrée Reset, qui indique si le compteur doit compter, ou être réinitialisé avec la valeur présente sur l'entrée d'initialisation.

Tout compteur ne peut plus compter au-delà d'une certaine limite, et les compteurs se comportent différemment une fois cette limite atteinte. Certains restent bloqués sur cette valeur maximale tant qu'on ne les remet pas à zéro "manuellement" : de sont des compteurs à saturation. D'autres recommencent à compter naturellement à partir de zéro : ce sont des compteurs modulaires.

Un compteur mémorise un nombre codé sur plusieurs bits. Certains compteurs font un usage maximal de ces bits et peuvent compter de zéro à un nombre de la forme 2n - 1 (2, 4, 8, 16, etc). Mais d'autres compteurs ne comptent pas jusque-là : certains ne comptent que jusqu'à 10, 150, etc : ce sont des compteurs modulo.

Ensuite, il faut faire la différence entre compteurs synchrones et asynchrones. Les compteurs synchrones sont commandés par un signal d’horloge, un signal périodique généralement utilisé pour synchroniser les composants d'un circuit électronique : le compteur/décompteur est mis à jour à chaque cycle d'horloge. Les compteurs asynchrones sont commandés non pas par un signal d'horloge périodique, mais à la demande : ils possèdent une entrée Enable, qui ordonne la mise à jour du compteur quand celle-ci est à 1 (ou 0 sur certains compteurs), la valeur de cette entrée étant calculée par un autre circuit.

Compteurs asynchrones

Nous allons aborder un premier type de compteur : les compteurs asynchrones. Ces compteurs sont des compteurs qui augmentent ou diminuent leur contenu (le nombre mémorisé) à la demande : ils possèdent une entrée sur laquelle on envoie un ordre de mise à jour du contenu du compteur.

Compteur

Nous allons commencer par un compteur qui compte normalement : celui-ci compte de 0 à un certain nombre : le nombre maximum que peut contenir un registre. Puis, il recommence à partir de zéro une fois ce maximum atteint.

Compteur simple

Pour comprendre comment créer ces compteurs, il suffit de regarder la séquence des premiers entiers, puis de prendre des paires de colonnes adjacentes :

Nombre mémorisé dans le compteur Première et seconde colonne Seconde et troisième colonne Troisième colonne et quatrième colonne
0000 00 00 00
0001 01 00 00
0010 10 01 00
0011 11 01 00
0100 00 10 01
0101 01 10 01
0110 10 11 01
0111 11 11 01
1000 00 00 10
1001 01 00 10
1010 10 01 10
1011 11 01 10
1100 00 11 11
1101 01 10 11
1110 10 11 11
1111 11 11 11

On remarque que le bit sur une colonne change quand le bit de la précédente passe de 1 à 0. C'est assez simple à comprendre : en binaire, 1 + 1 = 0 plus une retenue prise en compte sur la colonne suivante. Quand on passe de 1 à 0 dans une colonne, cela signifie que la retenue précédente, ajoutée au bit de cette colonne, donne 10 : la retenue à propager à la colonne suivante vaut 1. Si cette colonne suivante contient un 0, alors il passe à 1 : 0 + 1 = 1. Si elle contient un 1, alors il passe à 0, car 1+1 = (1)0. En clair : le bit s'inverse.

Maintenant que l'on sait cela, on peut facilement créer un compteur avec quelques bascules. Pour la colonne la plus à droite (celle des bits de poids faible), on remarque que celle-ci inverse son contenu à chaque cycle d'horloge : pour inverser le contenu, on a évidemment besoin d'une porte NON, qui boucle la sortie de la bascule sur son entrée.

Bascule qui mémorise le bit de poids faible du compteur

On peut aussi ruser en se souvenant que certaines bascules contiennent une sortie nommée $\overline{Q}$, qui fournit l'inverse du bit stocké dans la bascule. Dans ce cas, la porte NON devient inutile : il suffit de boucler la sortie $\overline{Q}$ sur l'entrée.

Bascule qui mémorise le bit de poids faible du compteur, en version "optimisée"

Pour les autres colonnes, il suffit de trouver un moyen pour faire en sorte que l'inversion du bit ne se produise que lorsque le bit de la bascule précédente passe de 1 à 0. Le mieux est d'autoriser la mise à jour une fois la transition de la colonne précédente effectuée, c'est à dire quand le bit de la colonne précédente vaut 0. Ainsi, la méthode vue au-dessus reste valable à un changement près : l'entrée Enable/Clock de la bascule n'est pas reliée au signal d'horloge, mais à l'inverse de la sortie de la bascule de la colonne précédente (ou à la sortie $\overline{Q}$). On obtient le circuit décrit dans le schéma qui suit.

Circuit final d'un compteur

Compteurs initialisables

Maintenant que l'on sait créer un compteur simple, nous allons l'améliorer pour fabriquer un compteur initialisable. Pour cela, il suffit de rajouter des multiplexeurs à deux entrées devant chaque entrée d'une bascule : une entrée du multiplexeur est reliée à la mise à jour du compteur, et l'autre au bit de la valeur initiale.

Pour préciser au compteur quand faire une initialisation, il suffit de rajouter une entrée Init : cette entrée vaudra 1 si on veut initialiser le compteur, et zéro sinon. Cette entrée sera reliée aux entrées de commande des multiplexeurs deux entrées mentionnés plus haut.

Compteur initialisable

Compteurs Modulo

On peut aussi faire en sorte que le compteur compte jusqu'à une limite de notre choix, qu'on va appeler N. Le principe est simple : si la valeur du compteur atteint N + 1, on remet le compteur à zéro. Pour cela, on a besoin d'un circuit qui compare le contenu du compteur avec N+1 : si ce comparateur sort un 1 (le compteur vaut N+1), il faut mettre toutes les bascules à zéro. En utilisant des bascules qui possèdent une entrée de Reset, il suffit alors de relier la sortie de ce comparateur aux entrées Reset des bascules.

Décompteur

Fabriquer un décompteur ressemble à la même chose que ce qu'on a fait avec le compteur plus haut, en regardant la séquence des nombres et en analysant des colonnes successives. Pour simplifier le propos, nous allons juste comparer la séquence d'un compteur, et la séquence d'un décompteur :

1111

0000

1110

0001

1101

0010

1100

0011

1011

0100

1010

0101

1001

0110

1000

0111

0111

1000

0110

1001

0101

1010

0100

1011

0011

1100

0010

1101

0001

1110

0000

1111

On ne peut pas faire plus clair : un décompteur est strictement identique à un compteur auquel on a inversé tous les bits. On peut donc réutiliser le compteur du dessus, à part que les sorties du compteurs sont reliées aux sorties Q des bascules.

Compteurs synchrones

Les compteurs asynchrone ont un léger problème : le temps de propagation des "retenues" à travers les bascules est assez élevé. Ainsi, dans certains cas, il faut que la retenue générée par le premier étage passe jusqu'à dernier étage pour modifier convenablement le compteur : pensez à la transition 1111 -> 0000. Et ce temps pose un problème : si on travaille à haute fréquence, il devient supérieur à la durée d'un cycle d'horloge. Le compteur ne fonctionne pas !

Pour résoudre ce problème, on doit utiliser des compteurs que l'on appelle des compteurs synchrones, où la mise à jour des bascules est commandée par un signal d'horloge. Avec ces compteurs, toutes les bascules sont reliées à la même horloge et sont donc mises à jour simultanément, réduisant à néant le problème mentionné plus haut. Pour créer des compteurs synchrones, on prend un registre qui mémorise la valeur du compteur, et un circuit combinatoire qui se charge de mettre à jour le compteur/décompteur.

Compteur

On peut créer un compteur de plusieurs manières, certaines étant plus générales que d'autres. Les différences entre compteurs synchrones se localisent toutes dans le circuit combinatoire utilisé, qui va d'un additionneur à un circuit beaucoup simplifié (et moins flexible).

Compteur à additionneur

Dans le cas le plus simple, le circuit combinatoire est un additionneur. Cette solution est très souple : elle ne se limite pas à des compteurs qui comptent de 1 en 1, mais peut s'adapter à des compteurs qui comptent de 3 en 3, de 6 en 6, etc : il suffit de mémoriser la constante quelque part et de l'envoyer en entrée de l'additionneur.

Compteur à additionneur

Seul problème : l'additionneur utilise beaucoup de circuits. Pour éviter cela, on peut le remplacer par un circuit qui se charge de faire +1 (ou +3, +5, etc., selon la constante choisie). Si le compteur comprend peu de bits, on peut créer ce circuit avec une table de Karnaugh.

Compteur à incrémenteur

Dans ce qui va suivre, nous allons créer un circuit qui compte de 1 en 1, sans utiliser d'additionneur. Pour comprendre comment créer un tel compteur, nous allons reprendre la séquence d'un compteur, déjà vue dans le premier extrait :

  • 0000
  • 0001
  • 0010
  • 0011
  • 0100
  • 0101
  • 0110
  • 0111
  • 1000
  • 1001
  • 1010
  • 1011
  • 1100
  • 1101
  • 1110
  • 1111

On peut remarquer quelque chose dans ce tableau : peu importe la colonne, un bit s'inversera au prochain cycle d’horloge quand tous les bits des colonnes précédentes valent 1. Ainsi, prenons le cas où le compteur vaut 110111 :

  • les deux premiers 1 sont respectivement précédés par la séquence 10111 et 0111 : vu qu'il y a un zéro dans ces séquences, ils ne s'inverseront pas au cycle suivant ;
  • le bit qui vaut zéro est précédé de la séquence de bit 111 : il s'inversera au cycle suivant ;
  • le troisième 1 en partant de la gauche est précédé de la séquence de bits 11 : il s'inversera aussi ;
  • même raisonnement pour le quatrième 1 en partant de la gauche ;
  • le 1 le plus à droite correspond au bit de poids faible, qui s'inverse tous les cycles.

Au final, on en déduit que la prochaine valeur sera de 1000, ce que confirme la séquence d'entier du compteur.

Pour implanter cela en circuit, on a besoin de deux micro-circuits par bascules :

  • un circuit qui détermine si tous les bits des colonnes précédentes (en lisant de droite à gauche) sont à 1 ;
  • et un circuit qui inverse le contenu de la bascule.

Le circuit qui détermine si tous les bits précédents sont à 1 est un simple ET entre les bits en question.

L'autre circuit a besoin de deux entrées :

  • le contenu de la bascule ;
  • et l'ordre d'inversion.

On peut alors écrire sa table de vérité, qui est identique à celle d'une porte OU exclusif (XOR) :

Inversion

Contenu de la bascule

-

Sortie

0

0

-

0

0

1

-

1

1

0

-

1

1

1

-

0

Au final, le circuit ressemble à ceci :

Compteur synchrone à incrémenteur

Comme pour les compteurs asynchrones, on peut faire en sorte que les compteurs synchrones soient initialisables. Le principe est exactement le même : il suffit d'ajouter quelques multiplexeurs, dont l'entrée de commande est reliée à une entrée Init. On peut aussi faire en sorte que ces compteurs synchrones ne soient pas limités que par la taille du registre : on peut changer la limite supérieure de la même manière que pour les compteurs asynchrones.

Décompteur

Pour créer un décompteur, même topo : on peut faire la même chose que pour un compteur, à savoir relier un registre à un soustracteur. Comme pour les autres compteurs, le soustracteur peut être remplacé par un simple circuit décrémenteur (qui fait -1, -2, -3, etc., suivant le compteur) similaire à celui vu plus haut.

Décompteurs à soustracteur

Mais on peut aussi utiliser le même genre de ruses que celles utilisées pour le compteur. Prenons la séquence de décomptage :

  • 1111
  • 1110
  • 1101
  • 1100
  • 1011
  • 1010
  • 1001
  • 1000
  • 0111
  • 0110
  • 0101
  • 0100
  • 0011
  • 0010
  • 0001
  • 0000

On remarque qu'un bit s'inverse lorsque tous les bits précédents sont à zéro. En utilisant le même raisonnement que celui utilisé pour concevoir un compteur synchrone à incrémenteur, on obtient un circuit presque identique, si ce n'est que les sorties des bascules doivent être inversées avant d'être traitées par le comparateur. On peut directement réutiliser le circuit d'un compteur, à la seule différence que les portes logiques doivent être reliées aux entrées $\overline{Q}$, et non aux entrées $Q$.

Décompteur synchrone

Compteur/décompteur

Maintenant, il peut être utile de créer un circuit compte ou décompte, suivant la situation. Par exemple, prenons un compteur d'entrées/sorties de parking. Ce compteur compte le nombre de voiture qui sont actuellement dans le parking. A chaque entrée de voiture, on doit incrémenter celui-ci. A chaque sortie, ce compteur est décrémenté. Ainsi, suivant la situation, le compteur est soit incrémenté, soit décrémenté. Comment construire un tel compteur ?

Tout d'abord, il faut se rendre compte que ce compteur a besoin de savoir s'il faut compter ou décompter. Pour cela, on lui rajoute une nouvelle entrée Count : si celle-ci vaut 1, le circuit compte, sinon il décompte.

Pour créer ce circuit, on peut relier un registre à un additionneur/soustracteur. Il faut ajouter une entrée Count, pour indiquer s'il faut ajouter ou retirer la constante : cette entrée Count correspond à l'entrée ADD/SUB de l'additionneur soustracteur. Comme pour les compteurs et les décompteurs, l'additionneur/soustracteur peut être remplacé par un circuit spécialisé qui incrémente ou décrémente avec le bon "pas de calcul".

Compteur/décompteur

Les autres compteurs

En plus des compteurs asynchrones et synchrones, on trouve deux autres types de compteur : les compteurs en anneau, et les compteurs de Johnson. Ces compteurs sont beaucoup plus simples à fabriquer que les compteurs vus plus haut, ce qui fait qu'ils ont tendance à être plus rapides que leurs concurrents.

Compteurs en anneau

Dans le cas le plus simple, ces compteurs en anneau sont simplement des registres à décalage SIPO dont on a bouclé la sortie sur l'entrée.

Compteur en anneau de 4 bits

La séquence de ce compteur 4 bits est celle-ci :

  • 1000
  • 0100
  • 0010
  • 0001

Avec n bits, ce compteur peut compter avec n nombres différents, qui ont tous un seul bit à 1. Petit détail : on peut créer un compteur "normal" en reliant un compteur en anneau avec un encodeur : la sortie de l'encodeur nous donne la valeur normale du compteur.

Compteurs de Johnson

Dans d'autres cas, le bit de sortie est inversé avant d'être bouclé sur l'entrée : ce sont des compteurs de Johnson. Ce compteur a une limite supérieure double de celle d'un compteur en anneau.

Compteur de Johnson

La séquence d'un tel compteur est :

  • 1000
  • 1100
  • 1110
  • 1111
  • 0111
  • 0011
  • 0001
  • 0000

5 commentaires

Ah, c'est donc toi qui a écrit ce tutoriel. Je l'avais vu sur OC à l'époque, sans vraiment m'y attarder, par manque de temps… Je vais m'y mettre sans tarder ;) Au fait, merci et bravo pour tous les tutoriels que tu publies, tu fais un travail remarquable!

Un jour j'irai vivre en Théorie, car en théorie tout se passe bien.

+0 -0

question de clarté, sur la plupart de tes schémas, la grandeur à compter, c'est ce qu'il y a dans les fils rouges (que tu appelle "horloge ou enable"), ou alors c'est plutôt un signal de commande qui active/désactive l'incrémentation (ou décrémentation)? enfin… comme on pourrait trouver dans un ADC à rampe, en sortie de comparateur, par exemple? (je sais pas si je suis clair, et j'en suis désolé d'avance).

sinon, bah c'est encore un tuto sympa sur "comment c'est fait là dedans", personnellement j'aime bien. bravo et merci!

Oui. Non. Attends, je regarde mieux et je te dis.

+0 -0

Le signal en rouge dans les schémas, c'est un signal de commande qui active ou désactive la mise à jour du compteur. Pour les compteurs synchrones, c'est un signal d'horloge.

Chaque bit de la grandeur à compter est mémorisée dans une bascule du compteur.

Édité

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte