Un circuit qui se souvient du dernier numéro
Un circuit séquentiel est un circuit dont la sortie dépend de ce qu’il a vu avant, et pas seulement de ses entrées du moment. Un compteur en est le plus simple exemple : il se souvient du dernier nombre pour donner le suivant.
La machine à tickets d’une boulangerie en contient un. À chaque appui, le numéro monte de un. Ici, c’est une horloge qui donne le signal.
À la fin de cette leçon
Remarque
Je peux décrire un compteur qui change à chaque front montant de l’horloge.
Mots-clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Horloge | un signal qui monte et descend à un rythme régulier | clk |
| Front montant | l’instant où l’horloge passe de 0 à 1 | |
| Bascule | un circuit qui mémorise un bit jusqu’au front suivant | |
| Remise à zéro | un signal qui remet la mémoire à 0 | rst |
| Compteur | des bascules qui comptent les fronts reçus | |
| Valeur inconnue | un bit que rien n’a encore fixé, noté x |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une bascule mémorise un bit par front
Une bascule est la plus petite mémoire d’un circuit : elle garde un bit. Elle ne change que sur un front montant de l’horloge, jamais entre deux fronts.
Un compteur de 3 bits a trois bascules. À chaque front, il lit sa valeur, calcule la suivante et la mémorise.
Un compteur qui va de 0 à 5
module compteur6(input clk, input rst, output reg [2:0] q);
always @(posedge clk)
if (rst) q <= 0;
else if (q == 5) q <= 0;
else q <= q + 1;
endmodule
Que veut dire always @(posedge clk) ?
Le bloc always @(posedge clk) décrit ce qui se passe à chaque front montant de clk. Le signe <= écrit la nouvelle valeur de q : toutes les bascules lisent leurs entrées d’abord, puis changent ensemble.
Les lignes if se lisent dans l’ordre. La remise à zéro passe en premier, car elle est la plus forte. Ici elle est synchrone : elle n’agit qu’au front suivant, pas tout de suite.
Aller dans le dossier de travail
cd ~/hdlAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire compteur6.v
printf 'module compteur6(input clk, input rst, output reg [2:0] q);\n always @(posedge clk)\n if (rst) q <= 0;\n else if (q == 5) q <= 0;\n else q <= q + 1;\nendmodule\n' > compteur6.vAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire son banc de test
printf 'module compteur6_tb;\n reg clk = 0, rst = 0;\n wire [2:0] q;\n compteur6 dut(.clk(clk), .rst(rst), .q(q));\n always #5 clk = ~clk;\n initial begin\n $monitor("t=%%0d rst=%%b q=%%0d", $time, rst, q);\n #12 rst = 1;\n #10 rst = 0;\n #80 $finish;\n end\nendmodule\n' > compteur6_tb.vAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Compiler les deux fichiers
iverilog -o /tmp/compteur6 compteur6.v compteur6_tb.vAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Lancer la simulation
vvp /tmp/compteur6Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
La remise à zéro supprime le x
Au début, aucune bascule n’a de valeur : q affiche x, la valeur inconnue. Compter à partir d’une valeur inconnue donne encore x, et x ne disparaît jamais tout seul.
C’est pourquoi un compteur a une remise à zéro. Elle fixe q à 0, et le compteur peut alors compter pour de bon.
Exemple travaillé : ce que la simulation montre
| Instant | rst | q affiché | Pourquoi |
|---|---|---|---|
| 0 | 0 | x | Aucun front encore, q est inconnue |
| 15 | 1 | 0 | Le front lit rst à 1 : q devient 0 |
| 25 | 0 | 1 | Premier front avec rst à 0 : q passe à 1 |
| 65 | 0 | 5 | q atteint la dernière valeur |
| 75 | 0 | 0 | Le front suivant ramène q à 0 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Erreur fréquente
Attention
Beaucoup de gens pensent que q change à l’instant où rst ou en change. Ce n’est vrai que pour un fil comme assign. Une bascule ne regarde ses entrées qu’au front : si rst monte à 12, q ne devient 0 qu’au front de 15.
Pour aller plus loin
Dans le labo, counter4.v attend un compteur de 4 bits avec une validation en et une remise à zéro synchrone. Son commentaire dit comment il doit se comporter.
Écrivez d’abord sur papier ce que q doit valoir à chaque front pour une suite de valeurs de rst et en. Puis écrivez le module.