Étape 16 : VM 3.3 : instanciation questions avancées
(Image initialement créé par Digilent Inc., modifié par moi, pour cela, ce tutoriel)
Le module précédent introduit et j’espère que conduit la maison, le concept de l’instanciation en Verilog. Maintenant, nous prendrons un regard sur quelques sujets avancés (second thème seront ajoutées prochainement) en ce qui concerne l’instanciation de module.
Contrer l’instanciation contrôlée :
Que se passe-t-il si nous avions besoin générer un tas (prendre 50 à titre d’exemple) de DFFs qui étaient tous reliés entre eux dans un circuit diviseur d’horloge... Nous savons déjà comment faire un module général de DFF, alors maintenant que nous devons instancier 50 fois et la broche horloge de chacun d’eux à la sortie de facto qui précède dans l’ordre, connecter remis à un reset global et le D en pin à l’inverse de la sortie du DFF (Q). Utilisez le diagramme ci-joint pour référence.
Ce serait beaucoup d’instanciations pour vous écrire (50 instanciations fois 6 lignes par instanciation est 300 lignes!) à la main. Mais en Verilog, nous pouvons utiliser un contrôleur de compteur de boucle, plus précisément, une boucle « for », pour instancier (générer) tous ces modules (à l’exception de la première) pour nous en très peu de lignes de code. Mais il y a une mise en garde ; Nous devons planifier soigneusement notre conception afin que nous puissions utiliser un « générer une boucle » correctement.
Notez que la façon dont nous connectons chaque forces de facto à l’autre est uniforme et prévisible. Bien sûr, horloge la première DFF sera l’horloge d’entrée de notre module de haut niveau et la sortie de facto dernier ira quelque part dans le module de haut niveau, mais nous pouvons traiter ceux individuellement ; au cours de la génération, chaque fil interne dans la conception, à l’exception de la première horloge qui nous désignera manuellement et le dernier fil de sortie explicitement donnera une source et un drain. Le logiciel sait que les deux fils restants ont besoin d’une source (première horloge) ou drain (dernières données) et c’est la responsabilité de l’ingénieur d’en fournir une.
Comme mentionné précédemment, vous devez configurer la conception adéquatement afin d’utiliser une boucle de générer. En quoi cela consiste ? Eh bien, il est logique que puisque chaque DFF va avoir une horloge en dépendant sur le précédent (non compris le premierà!) que nous pouvons regrouper ces signaux semblables dans un bus ! Cela nous permet de faire référence à des groupes de signal comme un tableau en C/C++ et appel des fils individuels par index à l’aide de l’opérateur [].
La broche de remise à zéro pour chaque DFF viendra une réinitialisation commune, puisque chaque DFF doit être en mesure de réinitialiser en même temps.
Sans connaître les spécificités d’une boucle de générer encore, nous pouvons toujours faire notre bus qui seront utilisés lors de la conception. Quel type de bus va nous faire ? Puisque ceux-ci transportent uniquement un signal provenant d’une source à une vidange, nous allons faire des fils.
fil des bus large [49:0] //50 bit pour DFF d’entrée/sortie
Nous pouvons également instancier notre premier DFF. En utilisant le module de facto de tutoriel Module 3.2, en supposant que notre diviseur d’horloge possède une entrée clk (un NIP de l’horloge), une entrée rst (une broche de remise à zéro) et une sortie out (disons il conduira une diode, créant un effet de clignotement).
(DFF) dff0
.CLK(CLK),
.RST(RST),
. D(~out[0]),
. Q(out[0])
);
Maintenant, la boucle de générer. Il est semblable à une boucle en C/C++, mais a ses propres nuances. Tout d’abord nous devons créer une variable de compteur. En Verilog, le type de variable est appelé « genvar » et il est utilisé pour déclarer une variable, appelez-le « y », comme suit :
genvar y ;
La boucle de générer commence avec le mot clé « générer » et se termine par « endgenerate ».
Remarque : Vous devez déclarer toutes les variables genvar hors de la portée de la boucle de générer.
Nous avons maintenant :
genvar y ; endgenerate
générer des
Immédiatement après le mot-clé « générer » est la véritable boucle. Sa déclaration ressemble à une boucle en C/C++, mais en Verilog, nous n’avons pas le luxe de gauche et droite bouclés entre accolades ({et}) mais nous n’avons pas l’équivalent de Verilog : commencent et se terminent. En outre, Verilog ne supporte pas des opérations de postfix, donc on ne peut pas déclarer « y ++ » et doit indiquer à la place "y = y + 1". Lors de la construction la boucle for, gardez à l’esprit que nous avons déjà créé le DFF première (DFF0) donc on va générer de 1 à 49 (inférieur à 50).
genvar y ; fin
générer des
pour (y = 1; y < 50; y = y + 1) //spaces peut être omise
commencer
endgenerate
Avec une boucle de générer, nous allons à « commencer » une boucle de l’instanciation et doit donner à ce processus un nom. On n’utilisera pas ce nom à d’autres fins et ne fera pas référence à elle plus tard dans notre conception (il est utilisé en interne dans le synthétiseur). Nous faisons cela en ajoutant une instruction qui suit le format ":" et le placer sur la même ligne que le « début » pour le bon style. Appelons cette « dff_generation » :
genvar y ; fin
générer des
pour (y = 1; y < 50; y = y + 1) //spaces peut être omise
commencer : dff_generation
endgenerate
Voici la partie cruciale et la plus difficile : création du modèle d’instanciation. Cela ressemblera à l’instar de n’importe quel autre instanciation sauf que les fils que vous passez le module sont autorisés à utiliser le genvar comme une valeur ou une modification de la valeur. Rappelons que la valeur de la genvar changera en un dans ce cas après chaque instanciation.
Plutôt que de parcourir chaque ligne de l’instanciation, je vais vous donner l’ensemble du bloc de code et souligner les choses que vous ne pouvez pas reconnaître. N’oubliez pas de se référer à l’image fournie pour voir comment ce circuit est mis en œuvre.
genvar y ;
générer des
pour (y = 1; y < 50; y = y + 1) //spaces peut être omise
commencer : dff_generation
les dessous d’instance nom n’est pas grave
(DFF) dff_insts
.CLK(out[y-1]), //clk dans des forces de facto « y » est de "y-1"
.RST(RST), //each DFF obtient la même remise à zéro
. D(~out[y]), le //input est alimenté la sortie inversée
. Q(out[y]) //output
);
fin
endgenerate
Je vous encourage à main trace quelques itérations de la boucle pour voir comment la génération processus fonctionne. Le synthétiseur donnera chaque instance il crée un nom unique indexé comme "dff_insts1" et "dff_insts2".