Maîtriser l'instanciation de modules Verilog : Bonnes pratiques pour conception hiérarchique
Comme vu précédemment, les conceptions complexes s'intègrent en instanciant plusieurs modules hiérarchiquement. Les modules sont instanciés dans d'autres modules et leurs ports connectés à d'autres signaux du module parent.
Connexions de ports : liste ordonnée ou par nom.
Connexion par liste ordonnée
Connexion entre expressions de ports dans instanciation et signaux du module parent par liste ordonnée.
mydesign instancié comme d0 dans tb_top. Ports connectés dans l'ordre déterminé par position dans liste de ports de la déclaration du module. Exemple : b dans testbench connecté à y du design car tous deux en 2e position.
module mydesign (input x, y, z, output o); endmodule
module tb_top;
wire [1:0] a; wire b, c;
mydesign d0 (a[0], b, a[1], c); // a[0]->x, b->y, a[1]->z, c->o
endmodule
L'ordre des ports dans le module design doit être connu pour connexion correcte.
Inconvénient : ordre change si nouveau port ajouté ou si beaucoup de ports.
Connexion par nom
Meilleure méthode : lier explicitement ports des deux côtés par leur nom de port.
Le point . indique que le nom suivant appartient au design. Le nom de signal à connecter est donné entre parenthèses ( ).
module design_top;
wire [1:0] a; wire b, c;
mydesign d0 (
.x (a[0]), // "x" dans mydesign connecté à "a[0]" dans design_top
.y (b), // "y" connecté à "b"
.z (a[1]),
.o (c)
);
endmodule
Recommandé : chaque connexion de port sur ligne séparée pour que messages d'erreur pointent vers bon numéro de ligne. Plus facile à déboguer. Ordre d'apparition sans importance car connexions par nom. Connexions multiples de ports d'instance non autorisées.
module design_top;
mydesign d0 (
.x (a[0]),
.z (a[1]), // z en 2e position okay grâce connexion explicite
.y (a[1]),
.x (b), // illégal - x déjà connecté à a[0]
.o (c)
);
endmodule
Ports non connectés / flottants
Ports non connectés à un fil dans le module instanciant auront valeur haute impédance.
module design_top;
mydesign d0 (
// x input non connecté -> a[0] sera Z
.y (a[1]),
.z (a[1]),
.o () // o a valeur valide dans mydesign mais non connecté à "c" -> c sera Z
);
endmodule
Exemple
Reprenons l'exemple registre à décalage, laissons certains ports non connectés.
module shift_reg (input d, input clk, input rstn, output q);
wire [2:0] q_net;
dff u0 (.d(d), .clk(clk), .rstn(rstn), .q(q_net[0]));
dff u1 (.d(q_net[0]), .clk(clk), .rstn(rstn), .q()); // Output q flottant
dff u2 (.d(q_net[1]), .clk(clk), .rstn(rstn), .q()); // Output q flottant
dff u3 (.d(q_net[2]), .clk(clk), .rstn(rstn), .q(q));
endmodule
Les sorties des instances u1 et u2 sont non connectées dans le schéma RTL après synthèse. Comme entrées d de u2 et u3 connectées à nets non pilotés, elles sont mises à la masse.

En simulation, ports non connectés = haute impédance ('hZ), typiquement ligne orange verticale au milieu dans formes d'onde.

Toutes déclarations de ports implicitement wire ; direction suffit. Cependant ports output devant stocker valeurs doivent être déclarés reg et utilisables dans blocs procéduraux always/initial. Ports input/inout ne peuvent être reg (pilotés de l'extérieur en continu, doivent refléter changements immédiatement). Légal de connecter ports tailles vectorielles différentes : taille inférieure prévaut, bits restants du port plus large ignorés.
// Cas #1 : Inputs implicitement wire
module des0_1 (input wire clk ...); // wire optionnel
module des0_2 (input clk, ...); // par défaut wire
// Cas #2 : Inputs ne peuvent être reg
module des1 (input reg clk, ...); // Illégal
// Cas #3 : Largeurs de ports variables
module des2 (output [3:0] data, ...); // 4-bit output
module des3 (input [7:0] data, ...); // 8-bit input
module top ( ... );
wire [7:0] net;
des2 u0 ( .data(net) ... ); // 4 bits supérieurs de net non pilotés
des3 u1 ( .data(net) ... );
endmodule
// Cas #4 : Outputs ne peuvent connecter à reg dans module parent
module top_0 ( ... );
reg [3:0] data_reg;
des2 ( .data(data) ...); // Illégal: output port connecté à reg "data_reg"
endmodule
Verilog
- Maîtriser Verilog : Tutoriel complet pour la conception de circuits numériques
- Maîtriser la concaténation Verilog : Guide pratique
- Verilog Essentiel : Aperçu concis
- Comprendre les affectations Verilog : Types, Syntaxe et Bonnes Pratiques
- Verilog Blocking vs Non-Blocking : Différences Clés Expliquées
- Maîtriser les Fonctions Verilog pour une Conception RTL Efficace
- Comprendre les Tasks Verilog : Fonctions vs Tasks, Syntaxe et Utilisation
- Maîtriser la Portée de Référence Hiérarchique Verilog : Éviter les Collisions de Noms dans les Modules et Blocs
- Générateur d'Horloge Verilog : Guide de Conception et d'Implémentation