Verilog blockiert immer
Ein always
block ist einer der prozeduralen Blöcke in Verilog. Anweisungen innerhalb eines Always-Blocks werden sequentiell ausgeführt.
Syntax
always @ (event)
[statement]
always @ (event) begin
[multiple statements]
end
Die always
Block wird bei einem bestimmten Ereignis ausgeführt. Das Ereignis wird durch eine Sensitivitätsliste definiert.
Was ist die Sensibilitätsliste?
Eine Empfindlichkeit list ist der Ausdruck, der definiert, wann der Always-Block ausgeführt werden soll, und wird nach @
angegeben Operator in Klammern ( )
. Diese Liste kann entweder ein oder eine Gruppe von Signalen enthalten, deren Wertänderung den Always-Block ausführt.
Im unten gezeigten Code sind alle Anweisungen innerhalb des always
Block wird immer dann ausgeführt, wenn sich der Wert der Signale a oder b ändert.
// Execute always block whenever value of "a" or "b" change
always @ (a or b) begin
[statements]
end
Wofür wird der Always-Block verwendet?
Ein always
Block kann verwendet werden, um kombinatorische oder sequentielle Elemente zu realisieren. Ein sequentielles Element wie ein Flip-Flop wird aktiv, wenn es mit einem Takt versorgt und zurückgesetzt wird. In ähnlicher Weise wird ein Kombinationsblock aktiv, wenn sich einer seiner Eingangswerte ändert. Diese Hardwareblöcke arbeiten alle gleichzeitig und unabhängig voneinander. Die Verbindung zwischen ihnen bestimmt den Datenfluss. Um dieses Verhalten zu modellieren, wird ein always
block wird als kontinuierlicher Prozess erstellt, der ausgelöst wird und eine Aktion ausführt, wenn ein Signal in der Sensitivitätsliste aktiv wird.
Im folgenden Beispiel werden alle Anweisungen innerhalb des Always-Blocks bei jeder positiven Flanke des Signals clk ausgeführt.
// Execute always block at positive edge of signal "clk"
always @ (posedge clk) begin
[statements]
end
Was passiert, wenn es keine Sensitivitätsliste gibt?
Die always
Block wiederholt sich kontinuierlich während der gesamten Dauer einer Simulation. Die Sensitivitätsliste bringt ein gewisses Timing mit sich, d.h. wann immer sich irgendein Signal in der Sensitivitätsliste ändert, wird der Always-Block ausgelöst. Wenn innerhalb eines Always-Blocks keine Timing-Control-Anweisungen vorhanden sind, hängt die Simulation wegen einer verzögerungsfreien Endlosschleife !
Beispiel
Das unten gezeigte Beispiel ist ein Always-Block, der versucht, den Wert des Signals clk zu invertieren. Die Anweisung wird alle 0 Zeiteinheiten ausgeführt. Daher wird es aufgrund des Fehlens einer Verzögerung in der Anweisung für immer ausgeführt.
// always block is started at time 0 units
// But when is it supposed to be repeated ?
// There is no time control, and hence it will stay and
// be repeated at 0 time units only. This continues
// in a loop and simulation will hang !
always clk = ~clk;
Auch wenn die Empfindlichkeitsliste leer ist, sollte es eine andere Form der Zeitverzögerung geben. Die Simulationszeit wird durch eine Verzögerungsanweisung innerhalb des always
vorgezogen wie unten gezeigt konstruieren. Jetzt wird die Uhrumstellung alle 10 Zeiteinheiten durchgeführt.
always #10 clk = ~clk;
Hinweis: Explizite Verzögerungen können nicht in Logikgatter synthetisiert werden !
Daher erfordert echter Verilog-Designcode immer eine Sensitivitätsliste.
Beispiel für ein sequenzielles Elementdesign
Der unten gezeigte Code definiert ein Modul namens tff, das einen Dateneingang, eine Uhr und einen Active-Low-Reset akzeptiert. Der Ausgang wird invertiert, wenn festgestellt wird, dass d an der positiven Flanke des Takts 1 ist. Hier die always
Der Block wird entweder bei der positiven Flanke von clk oder der negativen Flanke von rstn getriggert.
Was passiert bei der positiven Flanke der Uhr ?
Die folgenden Ereignisse finden an der positiven Taktflanke statt und werden für alle positiven Taktflanken wiederholt.
- Erster
if
Block prüft den Wert von Active-Low-Reset rstn - Wenn rstn Null ist, dann sollte der Ausgang q auf den Standardwert 0 zurückgesetzt werden
- Wenn rstn eins ist, bedeutet dies, dass Reset nicht angewendet wird und dem Standardverhalten folgen sollte
- Wenn der vorherige Schritt falsch ist:
- Überprüfe den Wert von d und invertiere den Wert von q, wenn er eins ist
- Wenn d 0 ist, dann Wert von q beibehalten
module tff (input d,
clk,
rstn,
output reg q);
always @ (posedge clk or negedge rstn) begin
if (!rstn)
q <= 0;
else
if (d)
q <= ~q;
else
q <= q;
end
endmodule
Was passiert bei der negativen Flanke von Reset?
Die folgenden Ereignisse treten an der negativen Flanke von rstn auf und treten bei allen solchen Ereignissen auf.
- Erste
if
Block prüft Wert von aktiv-low Reset rstn. Bei negativer Flanke des Signals ist sein Wert 0. - Wenn der Wert von rstn 0 ist, bedeutet dies, dass ein Reset angewendet wird und die Ausgabe auf den Standardwert von 0 zurückgesetzt werden sollte
- Der Fall, in dem der Wert von rstn 1 ist, wird nicht berücksichtigt, da das aktuelle Ereignis eine negative Flanke ist des rstn
Beispiel für kombiniertes Elementdesign
Ein always
Block kann auch beim Entwurf von Kombinationsblöcken verwendet werden. Beispielsweise stellt die folgende digitale Schaltung eine Kombination aus drei verschiedenen Logikgattern dar, die bei Signal o eine bestimmte Ausgabe liefern.
Der unten gezeigte Code ist ein module
mit vier Eingabeports und einem einzigen Ausgabeport namens o. Die always
Der Block wird immer dann ausgelöst, wenn eines der Signale in der Empfindlichkeitsliste seinen Wert ändert. Das Ausgangssignal wird als Typ reg
deklariert in der Modulportliste, weil es in einem Verfahrensblock verwendet wird. Alle in einem Prozedurblock verwendeten Signale sollten als Typ reg
deklariert werden .
module combo ( input a,
input b,
input c,
input d,
output reg o);
always @ (a or b or c or d) begin
o <= ~((a & b) | (c^d));
end
endmodule
Sehen Sie, dass das Signal o immer dann 1 wird, wenn der kombinatorische Ausdruck auf der RHS wahr wird. Ebenso wird o zu 0, wenn RHS falsch ist.
SimulationsausgabeKlicken Sie hier für eine Diashow mit Simulationsbeispiel !
Verilog