web-dev-qa-db-fra.com

Verilog: comment instancier un module

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.

13
Morgan

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 .

38
Morgan

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.

3
Moberg