Ich habe mit einem sehr einfachen Verilog-Programm zu kämpfen. Es ist ein 4-Bit-Schieberegister, das bei jedem Taktzyklus gedreht wird und vier LEDs ansteuert. (Wie Sie sehen, bin ich neu bei FPAGs und HDLs.)
Das Problem : Untenstehender Code wird ohne Warnungen synthetisiert und erfolgreich in das FPGA programmiert. Beim Start passiert dann nichts, die LEDs bleiben dunkel. Der i_Switch_1
Eingang wurde hinzugefügt, um überhaupt etwas zu bewirken, und tatsächlich, wenn ich den Schalter drücke, beginnen die LEDs zu rotieren.
Hier ist der Verilog-Code:
Version 1 (fehlgeschlagen)
module top
(input i_Clk,
input i_Switch_1,
output o_LED_1,
output o_LED_2,
output o_LED_3,
output o_LED_4
);
reg [3:0]shift_reg;
initial
shift_reg = 4'b0001; // has no effect
always @(posedge i_Clk)
begin
shift_reg <= i_Switch_1 ? 4'b0001 : {shift_reg[2:0], shift_reg[3]};
end
assign o_LED_1 = shift_reg[0];
assign o_LED_2 = shift_reg[1];
assign o_LED_3 = shift_reg[2];
assign o_LED_4 = shift_reg[3];
endmodule
Bewertung : Meine bisherige Schlussfolgerung ist, dass shift_reg
nicht auf 1 initialisiert wird. Die RTL-Ansicht unten zeigt, dass keine Initialisierung synthetisiert wird.
Ich habe an vielen Stellen gelesen, dass der Anfangsblock synthetisierbar ist, also bin ich jetzt wirklich verwirrt.
Frage 1 : Ist meine Einschätzung richtig?
Frage 2 : Angenommen, meine Einschätzung ist richtig, was ist die Abhilfe? Ich habe verschiedene Dinge ausprobiert und nichts davon funktioniert:
shift_reg==0
Vergleich (Version 2 unten)is_init
Flagge (Version 3 unten)Ich fange an zu glauben, dass ich etwas grundlegend falsch mache. Was ist los??
Version 2 (fehlgeschlagen)
shift_reg <= (shift_reg==0 || i_Switch_1) ? 1 : {shift_reg[2:0], shift_reg[3]}
Version 3 (fehlgeschlagen)
reg is_init;
initial
is_init = 0; // Must have this or else the is_init gets optimized out!
always @(posedge i_Clk)
begin
if(~is_init || i_Switch_1) begin
is_init <= 1;
shift_reg <= 4'b0001;
end
else begin
is_init <= 1;
shift_reg <= {shift_reg[2:0], shift_reg[3]};
end
end
Setup : LatticeSemi iCE40HX1K (Nandland Go Board) mit iCEcube2, Synthesetool ist Synplify Pro.
--
Aktualisieren
Das hier funktioniert:
Version 4 (Erfolg)
reg [3:0]shift_reg = 0;
always @(posedge i_Clk)
begin
case(shift_reg)
1: shift_reg <= 2;
2: shift_reg <= 4;
4: shift_reg <= 8;
8: shift_reg <= 1;
default:
shift_reg <= 1;
endcase
end
In vielen Fällen unterstützen FPGAs keine Einschalt-Anfangswerte von etwas anderem als 0. Ich weiß, dass alle Altera-FPGAs, mit denen ich gearbeitet habe, dies nicht tun. Tatsächlich ist dies laut Datenblatt für Ihr FPGA tatsächlich der Fall:
Jedes DFF ist auch mit einem globalen Rücksetzsignal verbunden, das automatisch unmittelbar nach der Gerätekonfiguration geltend gemacht wird.
Globales Zurücksetzen schlägt 0 vor, es würde gesetzt werden, wenn es zu einer 1 führen würde.
Um dies zu umgehen, tun einige Synthesewerkzeuge etwas, das Bubble Pushing genannt wird - alles, was auf 1 initialisiert werden sollte, wird stattdessen auf 0 initialisiert und dem Ausgang wird ein Not-Gate hinzugefügt. Es scheint jedoch in Ihrem Fall, dass das Synthesetool dies nicht richtig macht. Sie können es tatsächlich manuell versuchen, wenn Sie möchten:
...
shift_reg <= {shift_reg[2:1], !shift_reg[0], shift_reg[3]};
...
assign o_LED_1 = !shift_reg[0];
Wobei das auf Dauer nicht besonders sinnvoll ist.
Sie können auch die alternative Methode zur Angabe des Anfangswerts ausprobieren und sehen, ob das Synthese-Tool einen besseren Job macht:
reg [3:0] shift_reg = 4'b0001;
--
Jedenfalls verlassen wir uns im Allgemeinen nicht auf einen Anfangswert für Register und Logik. Stattdessen haben wir ein globales Reset-Signal und Reset-Klauseln in der Logik. Dadurch können wir alle Register jederzeit auf einen bekannten Zustand setzen, ohne einen Power Cycle durchführen zu müssen.
In Ihrem Beispiel mit dem Schalter scheint Ihr Code mit dem darin enthaltenen Schalter ein Reset-Signal korrekt abgeleitet zu haben ( R_PAT
nehme ich an), das wie erwartet von angesteuert wird i_Switch_1
. Typischerweise verwenden wir jedoch ein etwas anderes Format für Reset-Signale:
always @ (posedge clock) begin
if (reset) begin
// Do stuff here when in reset
end else begin
// Do stuff here when not in reset
end
end
Die strukturierte prozedurale Anweisung „initial“ ist nicht synthetisierbar. Um den Wert zu initialisieren, wenn Ihr FPGA eingeschaltet wird, können Sie den Wert des Registers initialisieren, indem Sie den Wert zum Zeitpunkt der Deklaration angeben. z.B.
reg [3:0]shift_reg= 4'b0000;
Prakash Darji