IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

FPGA - Que fait ce code Verilog/SystemVerilog ?
Un billet blog de f-leb

Le , par f-leb

0PARTAGES

En Verilog/SystemVerilog, on peut trouver ce genre de code:
a <= b;
b <= a;
Mais que fait ce code? Il renvoie Vrai si a est inférieur ou égal à b... Non, ce n'est pas ça. Le signe <= est surement un opérateur d'affectation: je mets b dans a... puis a dans b? C'est pour échanger les valeurs de a et b (swap):koi:? Mais ça ne peut pas fonctionner, car «normalement» pour faire l'échange, il faut passer par une variable temporaire:
temp = a; a = b; b = temp;
À moins que cela fonctionne comme une sorte d'affectation simultanée (ou parallèle) comme en Python: a, b = b, a.
Il y a de l'idée, mais ce n'est pas encore cela. Car en HDL (Hardware Description Language), il n'y a pas de «variables» comme dans les langages de programmation, mais il y a une notion qui semble s'en rapprocher, celle des registres.

Voyons une démonstration avec deux registres 3bits synchrones (out1 et out2) dont on peut charger le contenu en mettant le signal de contrôle enable à l'état haut, et que l'on peut permuter en mettant le signal de contrôle swap à l'état haut:
module essai
(
input logic clk, enable, swap,
input logic[2:0] in1, in2,
output logic[2:0] out1, out2
);

always_ff @(posedge clk) begin // sensibilité au front montant de l'horloge

if (enable) begin // si chargement des registres
out1 <= in1;
out2 <= in2;
end
else if (swap) begin // permutation des sorties
out2 <= out1;
out1 <= out2;
end

end

endmodule

La simulation fonctionnelle ci-dessous montre un exemple avec le chargement des registres out1 et out2 avec les valeurs 3 et 5 présentées en entrée, sur le premier front montant de l'horloge clk repéré en rouge. Ces valeurs sont maintenues en sortie après ce front, comme mémorisées. On voit ensuite l'effet de la permutation des valeurs de sortie au 2è front montant repéré en rouge:

643172

L'analyse RTL donne le schéma suivant, où j'ai mis en surbrillance le flot des transferts lorsque le signal swap est activé (swap=1, enable=0):

643193
swap=1, enable=0

On voit en rouge et en bleu que la sortie de chaque registre (3bits) est dirigée vers l'entrée de l'autre registre, ce qui permet la permutation attendue des signaux en sortie.

Une fois le transfert effectué au front d'horloge, on peut voir ci-dessous le flot formant une boucle où la sortie de chaque registre est redirigée vers son entrée pour maintenir son état:

643194
swap=0, enable=0

Alors comment bien interpréter cette écriture quelque peu déroutante?
out2 <= out1;
out1 <= out2;

La sémantique de l'affectation dans les blocs always_ff

L'opérateur <= est donc bien un opérateur d'«affectation».


  • Le signal du bus en sortie du registre évoqué à droite du signe <= porte l'état du registre à un instant présent. Et cet état est transmis à l'entrée du registre évoqué à gauche du signe <=, et sera pris en compte au front d'horloge suivant. Une ligne comme out2 <= out1; est donc une opération de transfert entre registres.
  • Il n'y a pas d'ordre d'exécution des affectations dans un bloc always_ff. Toutes les instructions d'affectation sont concurrentes et exécutées sur le même front d'horloge.
    On peut aussi bien écrire:
    out2 <= out1;
    out1 <= out2;

    ou
    out1 <= out2;
    out2 <= out1;


Ce dernier point souligné en gras est fondamental.

Mais alors... Que fait cet autre code ci-dessous?
module quefaitcetruc
(
input logic clk, in_serial,
output logic[3:0] Q
);

always_ff @(posedge clk) begin // sensibilité au front montant de l'horloge
Q <= in_serial;
Q <= Q;
Q <= Q;
Q <= Q;
end

endmodule

Réponse:
Ce module décrit le comportement d'un registre à décalage SIPO (Serial Input - Parallel Output):

644390
Simulation registre à décalage 4 bits SIPO

On voit que le bit présenté sur l'entrée série (en jaune) est «décalé» dans le registre 4 bits Q à chaque front montant de l'horloge.
On utilise ce principe lorsque l'on a besoin de convertir des données série sur une entrée (in_serial) en des données présentes sur une sortie parallèle (bus Q).

Exemple en simulation:

644391

On voit que la séquence série 1011 (bit de poids faible en premier) est disponible sur le bus QQQQ au 4è front d'horloge.

Les quatre transferts avec l'opérateur <= ci-dessous sont effectifs sur le même front d'horloge pour que le décalage puisse s'opérer.
Q <= in_serial;
Q <= Q;
Q <= Q;
Q <= Q;


Structurellement, quatre bascules D synchrones sont chaînées comme sur le schéma ci-dessous:

644351
Map view Quartus Pro Lite

Vous avez lu gratuitement 3 683 articles depuis plus d'un an.
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer à vous proposer des publications.

Une erreur dans cette actualité ? Signalez-nous-la !