Stap 15: VM 3.3: hoe om te instantiëren van een Module
In de vorige module vermeld ik gelijkenissen tussen modules in Verilog instantiëren en aanroepen van functies in C/C++.Laten we eens kijken hoe we een module in Verilog zou instantiëren.
Hier is de module die we met werken:
' tijdschaal 1ns / 1ps
module srlatch)
input S,
input R,
uitvoer Q
);
draad Q_int, Qn_int;
toewijzen van Q_int = ~ (S & Qn_int);
toewijzen van Qn_int = ~ (R & Q_int);
toewijzen van Q = Q_int;
endmodule
Door nu niet mag er Verilog in deze module kon niet u verklaren.
Dus laten we zeggen we wilden een circuit met twee SR-sloten (ongeacht hoe onzinnig dit circuit is in werkelijkheid), elk met een schakelaar voor hun operatie 'set' en een gedeelde reset-knop. De output van elk klink zullen een LED.
Met deze specs in gedachten, laten we de definitie van de bovenste module. Vergeet niet, bovenste module verklaringen bevat alleen in- en uitgangen die komen en gaan van de echte wereld.
' tijdschaal 1ns / 1ps
Uitdaging: Herschrijven deze verklaring van de module met behulp van bussen
top () module
invoer switch0,
invoer switch1,
invoer btn0,
uitvoer led0,
uitvoer led1
);
endmodule
Geweldig! Nu moeten we twee SR-hendels toevoegen aan onze schakeling. Hoe zouden we dit doen?
Don't say "Hard code van het gedrag van twee SR-sloten en toewijzen van hun in- en uitgangen respectievelijk." We zullen het instantiëren van twee exemplaren van een SR-Latch. Hier is hoe onze bovenste module eruit zal zien na de instantiëren:
' tijdschaal 1ns / 1ps
top () module
invoer switch0,
invoer switch1,
invoer btn0,
uitvoer led0,
uitvoer led1
);
srlatch sr0)
. S(switch0),
. R(btn0),
. Q(LED0)
);
srlatch sr1)
. S(switch1),
. R(btn0),
. Q(LED1)
);
endmodule
Dus wat is links te doen? Niets; helemaal niets (ervan uitgaande dat u al een UCF bestand klaar). Waarom?
De reden ligt in de module instantiëren. Neem een dichtere blik bij één.
srlatch sr0)
. S(switch0),
. R(btn0),
. Q(LED0)
);
Eerste regel: srlatch sr0 (
Dit is een zeer belangrijke lijn waarvan formulier dat u moet inzetten voor geheugen. Eerst komt srlatch. Dit is de naam van de basismodule die zijn we instantiëren. sr0 is de naam van het exemplaar. Het haakje opent de instantiëren. Elke instantiëren zal beginnen als dat; "< module worden geïnstantieerd >< instantienaam >(".
Er zijn sommige minder voorkomende gevallen waarin instantiëren zal enigszins afwijken, maar zelfs dan dit formulier nog steeds aanwezig zal zijn.
De volgende drie regels:
. S(switch0),
. R(btn0),
. Q(LED0)
Neem een kijkje op de srlatch module poortnamen en kijk dan terug naar deze drie lijnen. Dit is, in een omweg, vergelijkbaar met hoe we noemen een functie in C/C++; Dit is waar we de parameters.
Het verschil is dat in Verilog we langs beide ingangen naar de module en uitgangen aan de module. Dat wil zeggen, vertellen wij dat specifieke exemplaar van de module waar haar ingangen vandaan en waar we willen de uitgangen te gaan.
Een andere manier te kijken is dat we voorbij de module een reeks ingangen en uitgangen, elk waarvan de waarde voortdurend is bijgewerkt binnen de module (outputs) of buiten de module (ingangen).
Laten we breken de verklaring: . S(switch0)
Elke module-instantiëren zal hebben een reeks instructies vergelijkbaar met dit één, één instructie per invoer/uitvoer. De ". S"verwijst naar de ingang S in de module van de srlatch, en de (switch0) verwijst naar input switch0 gelegen in de bovenste module. Zie een patroon?
. < naam van de poort in exemplaar module > (< poortnaam in de huidige module >)
Dit concept is ook vergelijkbaar met het aanroepen van functies in andere programmeertalen zoals C/C++; in de functie-aanroep geven we waarden (die wij weten de naam van de variabele) naar de functie. We noemen dit een ding van waarde in, bijvoorbeeld, voornaamste, maar in de functie heet het iets anders. In dit voorbeeld Verilog we een inbreng hebben in de bovenste module met de naam "swtich0", en we willen de waarde van de "S" van "sr0" gelijk te zijn aan wat "switch0" is.
Zoals ik eerder al noemde, moet u een verklaring van de initialisatie van de poort per poort in de module die u zijn instantiëren, maar als u zijn het instantiëren van een module die, bijvoorbeeld heeft een bus [7:0] input genaamd "T", u hoeft te maken van 8 uitspraken als ". T[0](input[0]) ". U kunt doorgeven hele bussen door te verwijzen naar de namen alleen, zodat u kan overgaan "Input" in "T"door te verklaren". T(input) ". Houd in mening niettemin dat bus afmetingen moeten overeenkomen met up (d.w.z. kunt u niet overgaan een 5 poortbus in een module die een 3 poortbus heeft).
Bovendien moeten poorttypen overeenkomen. U kunt alleen het doorgeven van een bijdrage aan een ingang en een uitgang (of een draad; daarover later meer) op een uitgang.
De verklaringen van de initialisatie van het afzonderlijke poort met een komma. Goede codeerstijl dicteert dat elke regel slechts één instantiëren bevat. Hieruit moet je kunnen begrijpen die drie regels code.
Sluit de instantiëren met een bijpassende haakje en een puntkomma.
Nadat de instantiatie is met succes gedaan, de uitgangen van het exemplaar van de module, in wezen zullen toegankelijk binnen de huidige module. Vervolgens kunt u deze uitgangen routeren naar hoogste niveau havens of zelfs de ingangen van het andere exemplaar modules.
Voordat we deze discussie beëindigen, laten we eens samenvatten starten van een module (Onthoud dat "huidige module" verwijst naar de module die het instantiëren doet):
< naam van module >< (naam van exemplaar >
. < naam van de poort in de module worden geïnstantieerd > (< poort/draad naam in de huidige module >),
... < herhalen boven zo vaak als nodig >...
. < naam van de poort in de module worden geïnstantieerd > (< poort/draad naam in de huidige module >)
);