Ich versuche, ein Verilog-Modul zu schreiben, das für einige Taktzyklen ein Einschalt-Rücksetzsignal erzeugt. Ich synthetisiere mit Lattice iCEcube2 + Synplify Pro, das auf einen iCE40 HX1K auf dem Nandland Go Board abzielt .
Wenn ich das Modul so schreibe, wird es optimiert:
`default_nettype none
module reset_generator #(
parameter COUNT_WIDTH = 2
) (
input wire i_clk,
output wire o_rst
);
reg [COUNT_WIDTH:0] rst_count;
assign o_rst = !rst_count[COUNT_WIDTH];
always @(posedge i_clk) begin
if (o_rst == 1) begin
rst_count <= rst_count + 1;
end
end
endmodule
iCEcube2 gibt diese Warnung aus:
...
@N:CL189 : reset_generator.v(13) | Register bit rst_count[4] is always 1.
@N:CL159 : reset_generator.v(6) | Input i_clk is unused.
...
@N:BN115 : ball_absolute_mv_vga_top.v(19) | Removing instance reset_gen (in view: work.ball_absolute_mv_vga_top(verilog)) of type view:work.reset_generator_4s(verilog) because it does not drive other instances.
...
Und ich kann überprüfen, dass das o_rst
Signal tatsächlich nie auf gesetzt ist 1
. Ich dachte, alle Register wurden initialisiert 0
, also bin ich mir nicht sicher, warum es denkt rst_count[4] is always 1
.
Wenn ich jedoch explizit rst_count
auf setze 0
, so:
reg [COUNT_WIDTH:0] rst_count = 0;
Jetzt wird es nicht mehr optimiert und funktioniert wie erwartet, aber iCEcube2 zeigt diese Warnung:
@W:FX1039 : reset_generator.v(13) | User-specified initial value defined for instance reset_gen.rst_count[4:0] is being ignored.
Diese Warnung impliziert auch, dass die Anfangswerte 0 sind. Warum wird also die erste Version optimiert? Und warum ändert das Hinzufügen eines anfänglichen Werts, der ignoriert wird, das Verhalten? Ist das nur eine Eigenart von iCEcube2 und/oder Synplify Pro?
BEARBEITEN 1 : Ich verwende einen Einschalt-Reset, da Lattice Register nur auf Null initialisieren kann und ich möchte, dass einige mit Werten ungleich Null beginnen.
Die o_rst
dieser reset_generator
Komponente ist wie folgt mit einer anderen Komponente auf einer höheren Ebene verbunden:
wire w_reset;
reset_generator #(
.COUNT_WIDTH(4)
) reset_gen (
.i_clk(i_clk),
.o_rst(w_reset)
);
ball_absolute ball_absolute (
.clk(i_clk),
.reset(w_reset),
.vsync(o_vga_vsync),
// ...
);
Der Grund dafür ist, dass es ball_absolute
ein Paar X/Y-Register für die Position des Balls auf dem Bildschirm hat. Ich möchte, dass der Ball in der Mitte des Bildschirms beginnt, nicht bei (0, 0)
. Und da Lattice Register nur auf initialisieren kann 0
, möchte ich ein Power-On-Reset-Signal verwenden, um X/Y auf Werte ungleich Null zu setzen.
Das vollständige Projekt ist tatsächlich auf GitHub verfügbar .
EDIT 2 : Ich verstehe auch, dass ein PLL-Lock-Signal als Power-On-Reset verwendet werden könnte, aber leider hat der HX1K keine PLLs. Das Go Board verwendet einen externen Kristall für die Uhr.
Dies ist wahrscheinlich eine Eigenart in synplify. Synplify ist für die Synthese von Designs für ASICs, nicht für FPGAs gedacht, und ist daher ziemlich eigensinnig. Bei ASICs ist es üblich, überhaupt nichts zu initialisieren und stattdessen explizite Resets zu verwenden. Infolgedessen behandelt synplify Initialblöcke und Inline-Initialisierer anders als FPGA-Tools – insbesondere ignoriert es sie meistens, selbst wenn es zu seltsamem, unerwartetem Verhalten kommt. Alle nicht explizit initialisierten Signale beginnen jedenfalls nicht bei 0, sondern bei X (unbestimmter Logikpegel). Und dann können die Tools während der Synthese einen beliebigen Wert auswählen, wenn dies die Logik vereinfachen kann. Es scheint also, was synplify hier tut ... Es bemerkt, dass es dieses bestimmte X in eine 1 auflösen kann und als Ergebnis eine Menge Logik löscht. Wenn Sie diese Registrierung auf 0 initialisieren, dann kann synplify diese Optimierung nicht vornehmen, aber es warnt Sie, dass der Initialisierer ignoriert wird, da synplify nicht versteht, wie die Register tatsächlich initialisiert werden, da Sie dies auf einem ASIC nicht tun können. Was Sie tun sollten, ist, den Inline-Init auf Null zu halten, aber auch einen externen Reset-Eingang hinzuzufügen, der dieses Register ebenfalls zurücksetzen kann.
rst_count = 0
die Warnung zu setzen und zu ignorieren.
Mitu Raj
Benutzer253751
Christian B.
David Dribin
0
Einschalten und zählt aufwärts. Sobaldo_rst
er niedrig ist,rst_count
bleibt er für immer auf dem gleichen Wert ungleich Null.David Dribin
Das Photon
David Dribin
Das Photon
Das Photon
rst_count[4]
Ohne dies können wir nicht beantworten, warum Sie die Meldung "...treibt keine anderen Instanzen" erhalten haben, und wir können auch nicht erkennen, warum ein standardmäßig mit 3 Bits deklarierter Zähler ein 5. Bit ( ) haben würde.David Dribin