2012-09-20 13 views
11

Ich versuche, ein Modul zu erhalten, um die Syntaxprüfung in ISE 12.4 zu bestehen, und es gibt mir einen Fehler, den ich nicht verstehe. Zunächst wird ein Code-Schnipsel:Verilog generate/genvar in einem immer Block

parameter ROWBITS = 4; 

reg [ROWBITS-1:0] temp; 

genvar c; 
generate 
    always @(posedge sysclk) begin 
     for (c = 0; c < ROWBITS; c = c + 1) begin: test 
      temp[c] <= 1'b0; 
     end 
    end 
endgenerate 

Wenn ich versuche, eine Syntaxprüfung, erhalte ich die folgende Fehlermeldung:

ERROR:HDLCompiler:731 - "test.v" Line 46: Procedural assignment to a non-register <c> is not permitted.

ich wirklich nicht verstehen, warum es zu beschweren. "c" ist kein Draht, es ist ein Genvar. Dies sollte das Äquivalent der völlig legal Syntax sein:

reg [3:0] temp; 

always @(posedge sysclk) begin 
    temp[0] <= 1'b0; 
    temp[1] <= 1'b0; 
    temp[2] <= 1'b0; 
    temp[3] <= 1'b0; 
end 

Bitte keine Kommentare darüber, wie es einfacher sein würde, dies zu schreiben, ohne die zu erzeugen. Dies ist ein reduziertes Beispiel für einen viel komplexeren Code, der mehrere Wenns und nicht blockierende Zuweisungen an "temp" enthält. Sagen Sie mir auch nicht, dass es neuere Versionen von ISE gibt, das weiß ich schon. OTOH, wenn Sie wissen, es in einer späteren Version von ISE festgelegt ist, lassen Sie es mich wissen, welche Version Sie Werke kennen.

Antwort

15

Sie müssen die Verschachtelung innerhalb des erzeugen Block umkehren:

genvar c; 
generate 
    for (c = 0; c < ROWBITS; c = c + 1) begin: test 
     always @(posedge sysclk) begin 
      temp[c] <= 1'b0; 
     end 
    end 
endgenerate 

Technisch ist diese vier immer Blöcke erzeugt:

always @(posedge sysclk) temp[0] <= 1'b0; 
always @(posedge sysclk) temp[1] <= 1'b0; 
always @(posedge sysclk) temp[2] <= 1'b0; 
always @(posedge sysclk) temp[3] <= 1'b0; 

In diesem einfachen Beispiel, gibt es keinen Unterschied im Verhalten zwischen den vier immer blockt und ein einziger immer Block mit vier Zuweisungen, aber in anderen Fällen könnte es sein.

Die genvarabhängige Operation muss aufgelöst werden, wenn die In-Memory-Darstellung des Designs (im Falle eines Simulators) oder bei der Zuordnung zu Logikgattern (im Falle eines Synthesewerkzeugs) erstellt wird. Das always @posedge hat keine Bedeutung, bis das Design funktioniert.

Mit gewissen Einschränkungen können Sie eine for-Schleife in den always-Block setzen, auch für synthetisierbaren Code. Zur Synthese wird die Schleife abgerollt. In diesem Fall muss die for-Schleife jedoch mit reg, integer oder ähnlichem arbeiten. Es kann kein genvar verwendet werden, da die for-Schleife innerhalb des always-Blocks eine Operation beschreibt, die an jeder Kante der Uhr auftritt, keine Operation, die während der Ausarbeitung des Entwurfs statisch expandiert werden kann.

+0

Danke für die schnelle Antwort. Ich hatte Angst, es wäre so etwas. Ein Teil des Problems bestand darin, eine Sequenz von if-Anweisungen oder Case-Selektoren mit der for-Schleife zu generieren, die nicht in separaten always-Blöcken ausgeführt werden kann. – user1684538

+0

Gibt es eine Möglichkeit, den gesamten Code in einem einzigen Block zu erzeugen, oder ist Genvar einfach nicht dazu in der Lage? – user2569332

2

Innerhalb eines Moduls enthält Verilog im Wesentlichen zwei Konstrukte: Elemente und Anweisungen. Anweisungen werden immer in prozeduralen Kontexten gefunden, die alles dazwischen beinhalten: Begin ... end, Funktionen, Aufgaben, immer Blöcke und Anfangsblöcke. Elemente wie Generate-Konstrukte werden direkt im Modul aufgelistet. For-Schleifen und die meisten Variablen/Konstanten-Deklarationen können in beiden Kontexten existieren.

In Ihrem Code scheint es, dass Sie möchten, dass die for-Schleife als generisches Element ausgewertet wird, aber die Schleife ist tatsächlich Teil des prozeduralen Kontexts des always-Blocks. Damit eine for-Schleife als generierte Schleife behandelt wird, muss sie sich im Modulkontext befinden. Die generate..endgenerate-Schlüsselwörter sind vollständig optional (einige Tools benötigen sie) und haben keine Auswirkungen. Ein Beispiel dafür, wie generierte Schleifen ausgewertet werden, finden Sie unter this answer.

//Compiler sees this 
parameter ROWBITS = 4; 
reg [ROWBITS-1:0] temp; 
genvar c; 

    always @(posedge sysclk) //Procedural context starts here 
    begin 
     for (c = 0; c < ROWBITS; c = c + 1) begin: test 
      temp[c] <= 1'b0; //Still a genvar 
     end 
    end 
2

Wenn es Ihnen nichts ausmacht, die Datei zu kompilieren/generieren, dann könnten Sie eine Vorverarbeitungstechnik verwenden. Dies gibt Ihnen die Kraft des Generierens, führt aber zu einer sauberen Verilog-Datei, die oft leichter zu debuggen ist und zu weniger Simulatorproblemen führt.

Ich verwende RubyIt, um Verilog-Dateien aus Vorlagen mit ERB (Embedded Ruby) zu generieren.

parameter ROWBITS = <%= ROWBITS %> ; 
always @(posedge sysclk) begin 
    <% (0...ROWBITS).each do |addr| -%> 
    temp[<%= addr %>] <= 1'b0; 
    <% end -%> 
end 

Generieren der module_name.v Datei mit:

$ ruby_it --parameter ROWBITS=4 --outpath ./ --file ./module_name.rv 

Die erzeugte module_name.v

parameter ROWBITS = 4 ; 
always @(posedge sysclk) begin 
    temp[0] <= 1'b0; 
    temp[1] <= 1'b0; 
    temp[2] <= 1'b0; 
    temp[3] <= 1'b0; 
end 
4

Sie brauchen keinen bock erzeugen müssen, wenn Sie die Bits temp alle wollen im selben always Block zugewiesen.

parameter ROWBITS = 4; 
reg [ROWBITS-1:0] temp; 
always @(posedge sysclk) begin 
    for (integer c=0; c<ROWBITS; c=c+1) begin: test 
     temp[c] <= 1'b0; 
    end 
end 

Alternativ, wenn Ihr Simulator unterstützt IEEE 1800 (SytemVerilog), dann

parameter ROWBITS = 4; 
reg [ROWBITS-1:0] temp; 
always @(posedge sysclk) begin 
     temp <= '0; // fill with 0 
    end 
end 
0

für Verilog tun nur

parameter ROWBITS = 4; 
reg [ROWBITS-1:0] temp; 
always @(posedge sysclk) begin 
    temp <= {ROWBITS{1'b0}}; // fill with 0 
end