Frage zu synthetisierbarer For-Schleife und Generieren

Ich verwende die Verilog-Sprache und Zedboard als Zieltafel.

Soweit ich weiß, kann die for-Schleife synthetisiert werden, und das Synthesetool übersetzt die for-Schleife als eine Folge duplizierter Anweisungen wie das Abrollen der Schleife.

Zum Beispiel,

for ( i = 0; i < 4; i=i+1) begin
  mem[i] = i;
end

will be translated to 
mem[0] = 0;
mem[1] = 1;
mem[2] = 2;
mem[3] = 3;

Soweit ich weiß, kann daher die for-Schleife verwendet werden, wenn die Ressource verfügbar ist, um auf die mehreren, aber gleichen Gatter zu schließen.

Es scheint jedoch, dass das Generieren in Verilog verwendet werden kann, um nicht nur die mehreren Instanzen, sondern auch die mehreren Anweisungen wie die for-Schleife zu implizieren.

Ich verstehe, dass das Generieren nur die mehreren Instanzen des Moduls implizieren kann und die for-Schleife nicht für diesen Zweck verwendet werden kann.

Was ist dann der Unterschied zwischen der Generate + For-Schleife und der Nur-For-Schleife? Ich denke, beides funktioniert wie das Abrollen der Schleife. Gibt es einen merklichen Unterschied? Wenn es keinen Unterschied gibt, welcher ist der bevorzugte Codierungsstil, um das Abrollen der Schleife zu induzieren?

Nur zur Verdeutlichung, es ist: Ich impliziere, du folgerst. zB implizieren Sie einen RAM in Verilog/VHDL, die Synthesesoftware leitet diesen RAM aus Ihrem Verilog/VHDL ab. Sehr häufiger Fehler, lernenswert.

Antworten (1)

Verilog for-Schleifen sind unter bestimmten Bedingungen perfekt synthetisierbar:

  • Sie können jede prozedurale Anweisung innerhalb einer Schleife verwenden (z. B. if-else).
  • Die Anzahl der Schleifen muss vorgegeben werden .
    • Der einschränkende Ausdruck muss ein Vergleich zwischen der Schleifenvariablen und entweder einer Konstanten oder einem Parameter sein.
    • Die Schrittzuweisung muss den Schleifenwert um einen konstanten Betrag erhöhen.
  • Sie können der gleichen Variablen in jeder Schleife einen anderen Wert zuweisen (z. B. einen Index aus der Schleifenvariablen berechnen).
  • Für Synthesezwecke wird die Schleife in Nullzeit ausgewertet – dh wenn Sie versuchen würden, einen Zähler zu erstellen, würden Sie immer nur den Endwert sehen.

Dieselben Regeln gelten unabhängig davon, ob Sie eine for-Schleife in einem prozeduralen Block oder in einem generierten Block verwenden.

initialWenn Sie in einem prozeduralen Block fertig sind, alwayskönnen Sie eine for-Schleife verwenden, um Elemente in einem Array zu ändern (genau wie in Ihrem Beispiel), oder Sie können denselben Wert mehrmals ändern, zum Beispiel:

for (idx = 0; idx < 4; idx=idx+1) begin
    a = a + b[idx];
    c = c + 2;     //You can change more than one variable in a for loop
end

In diesem Beispiel ist die resultierende Hardware eine Kette von Addierern, die die Werte von vier Array-Indizes summieren.

Das Wichtigste ist, dass Sie in einer prozeduralen for-Schleife keine neuen Variablen oder Module erstellen können. Diese Regel gilt allgemein für prozedurale Blöcke, nicht nur für Schleifen (dh Sie können keine Variablen in einem prozeduralen Block deklarieren).

 

Generate-Blöcke hingegen ermöglichen die Erstellung von Variablen und die Instanziierung von Modulen. Das bedeutet, dass Sie in einem Generate-Block eine Generate-For-Schleife verwenden können, um Module abzuleiten. Das ist so ziemlich der einzige Unterschied.

genvarZum Erzeugen von for-Schleifen müssen Sie a als Schleifenvariable verwenden (dh den Wert, mit dem Sie durch jede Schleife zählen). Sie müssen der for-Schleife auch einen Namen geben:

for (loopVal = 0; loopVal < 4; loopVal = loopVal + 1) begin : loopName

Dieser Name wird jedem Hardwareteil vorangestellt, das Sie in der Schleife instanziieren. Wenn Sie also eine Instanz mit dem Namen erstellen bob, würde die obige Schleife Instanzen erstellen:

loopName[0]|bob
loopName[1]|bob
loopName[2]|bob
loopName[3]|bob

Dies führt zu mehreren Instanzen mit eindeutigen Namen.

 

Sowohl generierte als auch prozedurale For-Schleifen führen das Abrollen der Schleife durch, wie Sie sagen. Der Unterschied besteht einfach darin, wie Sie sie verwenden können. Procedural kann in prozeduralen Blöcken verwendet werden (z. B. zum Initialisieren eines Speichers). Generate kann nur in Generate-Blöcken verwendet werden.

Sie sind sowohl nützlich als auch bevorzugt. Das eine kann das andere nicht ersetzen.

Eine andere Möglichkeit, sich Generate vorzustellen, ist als eine Art Vorprozessor. Ihr Verilog-Compiler führt Dinge in Generate-Blöcken an dem Punkt aus, an dem er den Block mit den Generates instanziiert - sie geschehen nicht zur Laufzeit (im Gegensatz zu prozeduralen Schleifen).
@Taniwha Prozedurschleifen werden auch nicht zur Laufzeit ausgeführt. Sie werden vom Compiler entrollt. Am Ende läuft alles auf die Hardware hinaus. Verwechseln Sie den Präprozessor auch nicht mit Generate-Anweisungen, sie sind nicht dasselbe Konzept - Verilog hat einen Präprozessor, der if-else-Anweisungen enthält.
@TomCarpenter Ich schätze eine großartige Antwort. Ich konnte alle Ihre Punkte außer der generierten For-Schleife verstehen. Es scheint, dass begin: Etwas sollte direkt vor der for-Schleife hinzugefügt werden, kann aber nicht verstehen, wie es beim Instanziieren von Modulen funktioniert. Ist der LoopName eine Variable oder nur eine Zeichenfolge? Und wie sie von [1] bis [4] indiziert werden können.
@JaeHyukLee loopNameist nur Text, wie ein Instanzname oder ein Signalname. Es kann alles sein, was Sie wollen.
@TomCarpenter - es hängt vom Compiler ab - wenn Sie Gates kompilieren, ja, werden sie entrollt, wenn Sie Code für die Simulation kompilieren, eher nicht (Haftungsausschluss, ich habe einen Verilog-Compiler geschrieben)