Menu

Verilog wire vs reg : quand utiliser chacun (avec exemples)

Les deux principaux types de données en Verilog - wire pour les connexions continues et reg pour le stockage procédural - et la règle pour choisir entre les deux à chaque fois.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

Deux noms, un seul job

Chaque signal en Verilog a un type. Les deux types que tu rencontreras en premier sont wire et reg. Les deux peuvent retenir une valeur. Les deux peuvent être sur un bit ou multi-bits. La différence ne porte pas sur ce que le signal est - mais sur qui le pilote.

  • Les signaux wire sont pilotés en dehors des blocs procéduraux - par des instructions assign, par les sorties de sous-modules, ou par les ports d'entrée du module.
  • Les signaux reg sont pilotés à l'intérieur des blocs procéduraux - initial ou always.

Voilà toute la règle. Les noms des mots-clés sont maladroits parce qu'ils précèdent la façon moderne d'écrire du Verilog. reg ne devient pas toujours un registre dans le matériel. Lis la suite pour comprendre pourquoi.

Wire : la connexion continue

Un wire est un fil électrique. Il transporte ce que son pilote produit, en permanence. Deux façons qu'un wire soit piloté :

Trois choses à remarquer :

  • y et z sont déclarés wire dans le module et wire à nouveau dans le testbench.
  • Ils sont pilotés par assign - c'est la forme assignation continue. La partie droite du = est recalculée chaque fois qu'un signal qu'elle contient change.
  • On ne peut pas écrire y = a & b à l'intérieur d'un bloc always tout en gardant y comme wire. Le compilateur refuserait.

Si tu oublies le mot-clé wire, Verilog déclare implicitement le signal comme un wire 1 bit à ta place - ce qui est parfois pratique et parfois un bug silencieux. La plupart des équipes activent une option d'outil qui erreur sur les wires implicites. Sois explicite et évite le piège.

Reg : du stockage à l'intérieur d'un bloc procédural

Un reg est un signal que tu assignes à l'intérieur de initial ou always. Le nom est un vestige des débuts du langage où « reg » sonnait comme « register » ; dans l'usage moderne, un reg est juste le type de tout signal que du code procédural écrit.

count est reg à l'intérieur du module (parce que le bloc always y écrit) et wire dans le testbench (parce que le port de sortie du DUT le pilote). Même signal, rôles différents, types différents selon le contexte.

Pourquoi « reg » ne veut pas toujours dire « registre »

Voici le piège le plus courant chez les débutants. Ce module déclare y comme reg - mais le matériel synthétisé ne contient pas de flip-flop :

Le bloc always @(*) est sensible à n'importe quel changement d'entrée. C'est combinatoire. Un outil de synthèse voit ce motif et produit une porte AND - pas de flip-flop, pas d'horloge, juste de la logique. Le mot-clé reg est purement une exigence syntaxique parce que y est assigné à l'intérieur d'un always.

Pour obtenir un vrai flip-flop, le bloc always doit être sensible à un front d'horloge :

always @(posedge clk) begin
    q <= d;
end

C'est le motif synthèse-outil-fais-moi-un-flip-flop : liste de sensibilité cadencée, assignation non-blocking. Même mot-clé reg, matériel complètement différent. On couvre la distinction dans Always Block et Blocking vs Non-blocking.

La décision en pratique

Chaque fois que tu déclares un signal, demande-toi : comment vais-je le piloter ?

  • Piloté avec assign ? → wire.
  • Connecté au port de sortie d'un sous-module ? → wire.
  • Port d'entrée d'un module ? → wire. (Les entrées sont toujours des wire.)
  • Piloté depuis initial ou always ? → reg.
  • Port de sortie d'un module piloté par du code procédural ? → output reg.
  • Port de sortie d'un module piloté par assign ? → output wire. (Ou juste output - la direction seule par défaut donne wire.)

Cet arbre de décision couvre chaque situation que tu rencontreras en Verilog classique.

Conflits de pilotage

Les signaux wire peuvent avoir plusieurs pilotes en théorie - c'est comme ça que fonctionnent les bus tri-state, où plusieurs modules peuvent piloter le même wire et les inactifs passent en haute impédance (z). Pour la logique ordinaire, deux instructions assign écrivant le même wire produisent un comportement indéfini :

assign y = a;
assign y = b;   // MAUVAIS - y a deux pilotes

Le simulateur peut en choisir un, peut X-er le signal, ça dépend de l'outil. Quoi qu'il en soit c'est un bug. Un pilote par wire sauf si tu construis explicitement un bus.

Les signaux reg ne peuvent être pilotés que par un seul bloc procédural. Deux blocs always assignant tous deux le même reg est une erreur de synthèse et un comportement bizarre en simulation. Même règle : un seul pilote.

La mise à jour SystemVerilog : logic

SystemVerilog (le sur-ensemble vers lequel Verilog a évolué) ajoute un seul mot-clé qui remplace les deux : logic. Un signal logic peut être piloté par assign ou par un bloc procédural - mais pas les deux - et le compilateur t'empêche de créer accidentellement un bug multi-pilotes.

module modern(input logic a, input logic b, output logic y);
    assign y = a ^ b;
endmodule

Si tu démarres un projet from scratch et que ton outil supporte SystemVerilog (ce qui est le cas de l'éditeur sur cette page, avec -g2012), utiliser logic partout simplifie les règles. Les fichiers .v classiques ont toujours besoin du split wire/reg, et tu verras les deux styles dans la nature pour toujours.

La suite

Le prochain document - Vecteurs et tableaux - prend ces mêmes deux types et montre comment les rendre multi-bits. Largeurs de bus, plages, dimensions packées, la différence entre un vecteur de bits et un tableau de vecteurs. Tout ce dont tu as besoin avant de construire quoi que ce soit de plus gros qu'un additionneur 1 bit.

Questions fréquentes

Quelle est la différence entre wire et reg en Verilog ?

wire et reg retiennent tous deux une valeur de signal à chaque instant de la simulation, mais tu choisis entre les deux selon qui pilote le signal. Un wire est piloté depuis l'extérieur d'un bloc procédural - par un assign ou la sortie d'un sous-module. Un reg est piloté depuis l'intérieur d'un bloc initial ou always. Les noms sont historiques et trompeurs ; reg ne veut pas toujours dire « registre ».

Un reg en Verilog veut-il dire flip-flop ?

Pas forcément. Un reg ne se synthétise en flip-flop que lorsque son bloc always est sensible à un front d'horloge et utilise une assignation non-blocking. Un reg assigné dans un bloc combinatoire always @(*) se synthétise en simple logique combinatoire. Le mot-clé choisit le type de données Verilog, pas le matériel.

Quand utiliser wire vs reg ?

Règle simple : si tu pilotes le signal avec assign ou si tu le connectes à un port de sortie d'un sous-module, utilise wire. Si tu l'assignes à l'intérieur d'un bloc always ou initial, utilise reg. Les entrées d'un module sont toujours des wire. Les sorties sont des wire si pilotées par assign et des reg si pilotées par un bloc procédural.

Peut-on assigner un wire à l'intérieur d'un bloc always ?

Non - c'est une erreur de syntaxe. Les signaux wire ne peuvent être pilotés que par des assignations continues (assign) ou en étant connectés comme sortie d'une instance de sous-module. Tout ce qui est à l'intérieur de initial ou always doit cibler un reg (ou en SystemVerilog, un logic). Le compilateur attrapera ça et se plaindra d'un « left-hand side type mismatch ».

Qu'est-ce que logic en SystemVerilog ?

logic est l'unification SystemVerilog de wire et reg. Il peut être piloté soit par une assignation continue soit par un bloc procédural (mais pas les deux en même temps). Le code moderne utilise de plus en plus logic partout et oublie la distinction wire/reg. Les fichiers Verilog classiques doivent encore choisir.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER