Si j'ai un module Verilog 'top' et un module verilog 'subcomponent', comment puis-je instancier un sous-composant dans top?
haut:
module top(
input clk,
input rst_n,
input enable,
input [9:0] data_rx_1,
input [9:0] data_rx_2,
output [9:0] data_tx_2
);
sous-composant:
module subcomponent(
input clk,
input rst_n,
input [9:0] data_rx,
output [9:0] data_tx
);
Remarque
Ceci a été écrit comme une question générique qui ne cesse de revenir de temps en temps, il suit le format auto-réponse . Les réponses et mises à jour supplémentaires sont encouragées.
Tout cela est généralement couvert par la section 23.3.2 de SystemVerilog IEEE Std 1800-2012 .
Le moyen le plus simple consiste à instancier dans la section principale de top, en créant une instance nommée et en câblant les ports dans l'ordre:
module top(
input clk,
input rst_n,
input enable,
input [9:0] data_rx_1,
input [9:0] data_rx_2,
output [9:0] data_tx_2
);
subcomponent subcomponent_instance_name (
clk, rst_n, data_rx_1, data_tx );
endmodule
Ceci est décrit dans la section 23.3.2.1 de SystemVerilog IEEE Std 1800-2012 .
Cela présente quelques inconvénients, en particulier en ce qui concerne l'ordre des ports du code de sous-composant. une simple refactorisation ici peut interrompre la connectivité ou changer le comportement. par exemple, si quelqu'un d'autre corrige un bogue et réorganise les ports pour une raison quelconque, commute l'ordre clk et réinitialise. Il n'y aura pas de problème de connectivité de votre compilateur mais ne fonctionnera pas comme prévu.
module subcomponent(
input rst_n,
input clk,
...
Il est donc recommandé de se connecter à l'aide de ports nommés, cela permet également de retrouver la connectivité des fils dans le code.
module top(
input clk,
input rst_n,
input enable,
input [9:0] data_rx_1,
input [9:0] data_rx_2,
output [9:0] data_tx_2
);
subcomponent subcomponent_instance_name (
.clk(clk), .rst_n(rst_n), .data_rx(data_rx_1), .data_tx(data_tx) );
endmodule
Ceci est décrit dans la section 23.3.2.2 de SystemVerilog IEEE Std 1800-2012 .
Donner à chaque port sa propre ligne et indenter correctement ajoute à la lisibilité et à la qualité du code.
subcomponent subcomponent_instance_name (
.clk ( clk ), // input
.rst_n ( rst_n ), // input
.data_rx ( data_rx_1 ), // input [9:0]
.data_tx ( data_tx ) // output [9:0]
);
Jusqu'à présent, toutes les connexions établies ont réutilisé les entrées et les sorties du sous-module et aucun câble de connectivité n'a été créé. Que se passe-t-il si nous devons prendre les sorties d'un composant à un autre:
clk_gen(
.clk ( clk_sub ), // output
.en ( enable ) // input
subcomponent subcomponent_instance_name (
.clk ( clk_sub ), // input
.rst_n ( rst_n ), // input
.data_rx ( data_rx_1 ), // input [9:0]
.data_tx ( data_tx ) // output [9:0]
);
Cela fonctionne nominalement car un fil pour clk_sub est automatiquement créé, il y a un danger à se fier à cela. il ne créera qu'un fil 1 bit par défaut. Un exemple où c'est un problème serait pour les données:
Notez que le nom d'occurrence du deuxième composant a été modifié
subcomponent subcomponent_instance_name (
.clk ( clk_sub ), // input
.rst_n ( rst_n ), // input
.data_rx ( data_rx_1 ), // input [9:0]
.data_tx ( data_temp ) // output [9:0]
);
subcomponent subcomponent_instance_name2 (
.clk ( clk_sub ), // input
.rst_n ( rst_n ), // input
.data_rx ( data_temp ), // input [9:0]
.data_tx ( data_tx ) // output [9:0]
);
Le problème avec le code ci-dessus est que data_temp n'est que de 1 bit de large, il y aurait un avertissement de compilation sur la différence de largeur de port. Le câble de connectivité doit être créé et une largeur spécifiée. Je recommanderais que tous les fils de connectivité soient explicitement écrits.
wire [9:0] data_temp
subcomponent subcomponent_instance_name (
.clk ( clk_sub ), // input
.rst_n ( rst_n ), // input
.data_rx ( data_rx_1 ), // input [9:0]
.data_tx ( data_temp ) // output [9:0]
);
subcomponent subcomponent_instance_name2 (
.clk ( clk_sub ), // input
.rst_n ( rst_n ), // input
.data_rx ( data_temp ), // input [9:0]
.data_tx ( data_tx ) // output [9:0]
);
En passant à SystemVerilog, quelques astuces sont disponibles pour éviter de taper une poignée de caractères. Je pense qu'ils entravent la lisibilité du code et peuvent rendre la recherche de bogues plus difficile.
Utilisation .port
sans parenthèses pour se connecter à un fil/reg du même nom. Cela peut sembler soigné, en particulier avec beaucoup de clk et de réinitialisations, mais à certains niveaux, vous pouvez générer des horloges ou des réinitialisations différentes ou vous ne voulez pas vous connecter au signal du même nom mais modifié et cela peut conduire à des bogues de câblage qui sont pas évident à l'œil.
module top(
input clk,
input rst_n,
input enable,
input [9:0] data_rx_1,
input [9:0] data_rx_2,
output [9:0] data_tx_2
);
subcomponent subcomponent_instance_name (
.clk, // input **Auto connect**
.rst_n, // input **Auto connect**
.data_rx ( data_rx_1 ), // input [9:0]
.data_tx ( data_tx ) // output [9:0]
);
endmodule
Ceci est décrit dans la section 23.3.2.3 de SystemVerilog IEEE Std 1800-2012 .
Une autre astuce que je pense est encore pire que celle ci-dessus est .*
qui connecte les ports non mentionnés aux signaux du même fil. Je considère que c'est assez dangereux dans le code de production. Il n'est pas évident lorsque de nouveaux ports ont été ajoutés et sont manquants ou qu'ils pourraient accidentellement se connecter si le nouveau nom de port avait une contrepartie au niveau d'instanciation, ils se connectent automatiquement et aucun avertissement n'est généré.
subcomponent subcomponent_instance_name (
.*, // **Auto connect**
.data_rx ( data_rx_1 ), // input [9:0]
.data_tx ( data_tx ) // output [9:0]
);
Ceci est décrit dans la section 23.3.2.4 de SystemVerilog IEEE Std 1800-2012 .
Assurez-vous de vérifier le mode verilog et surtout verilog-auto. http://www.veripool.org/wiki/verilog-mode/ Il s'agit d'un mode verilog pour emacs, mais des plugins existent pour vi (m?) par exemple.
Une instanciation peut être automatisée avec AUTOINST. Le commentaire est développé avec M-x verilog-auto
et peut ensuite être modifié manuellement.
subcomponent subcomponent_instance_name(/*AUTOINST*/);
Étendu
subcomponent subcomponent_instance_name (/*AUTOINST*/
//Inputs
.clk, (clk)
.rst_n, (rst_n)
.data_rx (data_rx_1[9:0]),
//Outputs
.data_tx (data_tx[9:0])
);
Les fils implicites peuvent être automatisés avec /*AUTOWIRE*/
. Consultez le lien pour plus d'informations.