Mehrere LED-Ausgänge auf FPGA mit Verilog

Ich habe mit Verilog einen einfachen Zähler von 0 bis 9 erstellt. Der Ausgang sind 4 LEDs, die eingeschaltet werden, wenn ihr entsprechendes Bit 1 ist. Der Code synthetisiert gut, aber auf dem FPGA leuchtet nur eine LED wiederholt ein und aus. Die anderen drei LEDs leuchten überhaupt nicht. Hier ist mein Code:

module counter(
   input wire clock,
   input wire reset,

   output wire [3:0] o_number
);

reg [3:0] cur_state;
reg [3:0] next_state;

always @(posedge clock or posedge reset) begin
   if (reset) cur_state <= 4'b0;
   else 
    cur_state <= next_state;
end

// Next state function
always @(*) begin
   if (cur_state == 4'b1001) next_state = 4'b0000;
   else next_state = cur_state + 4'b0001;
end

 // Output function
assign o_number = cur_state;

endmodule

module display(
   input wire [3:0] inumber,

   output wire [3:0] LEDs
);

assign LEDs = inumber;

endmodule

Keine der LEDs ist defekt, da sie alle leuchten, wenn sie einzeln getestet werden. Die Uhr wurde so eingestellt, dass ihre Periode etwa 2 Sekunden beträgt.

Bitte hilf mir. Danke schön.

Ich habe das Zählermodul überarbeitet. Hier sind alle Dateien, die ich verwendet habe:

oben.v

module top ( input wire clock, input wire reset, output wire [3:0] LEDs);
counter c1 (.clock(clock), .reset(reset), .o_number(number));
display d1 (.inumber(number), .LEDs(LEDs));
endmodule

Zähler.v

module counter ( input wire clock, input wire reset, output wire [3:0] o_number);
reg [3:0] cur_state;
always @ (posedge clock or posedge reset) begin
    if (reset) cur_state[3:0] <= 4'b0000;
    else begin
        if (cur_state[3:0]==4'b1001) cur_state[3:0] <= 4'b0000;
        else cur_state[3:0] <= cur_state[3:0] + 4'b0001;
    end
end
assign o_number[3:0]=cur_state[3:0];
endmodule

Anzeige.v

module display( input wire[3:0] inumber, output wire [3:0] LEDs);
assign LEDs[3:0] = inumber[3:0];
endmodule

top.ucf

NET "LEDs[0]" LOC = K12;
NET "LEDs[1]" LOC = P14;
NET "LEDs[2]" LOC = L12;
NET "LEDs[3]" LOC = N14;

NET "clock" LOC = T9;
NET "reset" LOC = L14;
Möchten Sie nicht, dass sich der nächste Zustand beim Taktsignal ändert, anstatt * ??
Es ändert sich an der positiven Flanke der Uhr.
Sie wechseln in den nächsten Zustand auf Uhr, aber Sie ändern den Zustand von nextState auf *
Wäre das ein großes Problem?
Vielleicht nicht, aber fühlt sich für mich nicht richtig an
Ich folge eigentlich einer Richtlinie, die mir sagt, eine FSM in sequentielle Logik, nächste Zustandsfunktion und Ausgabefunktion zu unterteilen.
Aus Sicht von Verilog ist nichts falsch. Ich vermute, dass nur die zugeordnete LED LEDs[3]die einzige ist, die aufleuchtet. Wenn dies der Fall ist, versuchen Sie, Ihre Uhr auf 1/4 ihrer aktuellen Frequenz zu verlangsamen. Wenn das nicht funktioniert, überprüfen Sie die Zuordnung in Ihrer top.ucf
Ach, noch was. Die meisten FPGAs haben eine begrenzte Anzahl von Flops mit asynchronem Reset/Preset. Da Ihr Code korrekt synthetisiert wird, sollten Sie kein Problem haben, aber Sie sollten in Betracht ziehen, auf synchrones Zurücksetzen umzusteigen. Entfernen or posedge reset, um es zu einem synchronen Reset zu machen. Ich bezweifle, dass die Asynchronität das Problem ist, ich glaube, es ist die Taktfrequenz, die wahrscheinlich das Problem ist.

Antworten (2)

Es gab ein Problem mit dem oberen Modul. Ich habe den Draht, der zum Verbinden des Anzeige- und Zählermoduls verwendet wird, nicht deklariert.

Hier ist die überarbeitete top.v:

module top ( input wire clock, input wire reset, output wire [3:0] LEDs);
wire [3:0] number;
counter c1 (.clock(clock), .reset(reset), .o_number(number));
display d1 (.inumber(number), .LEDs(LEDs));
endmodule

Die LEDs leuchten jetzt je nach Zustand korrekt.

Es hätte Warnungen oder Fehler darüber geben müssen. Können Sie bitte mit dieser Deklaration und ohne sie kompilieren und den Unterschied in Compiler/Synthesizer-Meldungen sehen.
Tatsächlich gab es keine Warnungen oder Meldungen, die auf dieses Problem hinweisen. Die Dokumentation besagt, dass, wenn im oberen Modul kein Draht angegeben ist, automatisch ein Ein-Bit-Draht angenommen wird. Daher bekam ich das Ergebnis, wo nur eine LED funktionierte.

Ich vermute, das Problem kann in der Verwendung cur_stateund next_stateohne Indizes liegen. Versuchen

always @(posedge clock or posedge reset) begin
    if (reset) cur_state[3:0] <= 4'b0;
    else begin
        cur_state[3:0] <= next_state[3:0];
end

always @(*) begin
    if (cur_state[3:0] == 4'b1001) next_state[3:0] <= 4'b0000;
    else next_state[3:0] <= cur_state[3:0] + 4'b0001;
end

Und

assign o_number[3:0] = cur_state[3:0];

Und

assign LEDs[3:0] = inumber[3:0];

Beachten Sie, dass ich [3:0]überall hinzufüge und im zweiten Konstrukt =zu ändere .<=always

Das Ziel kann durch eine viel einfachere Konfiguration erreicht werden:

module counter(
input wire clock,
input wire reset,
output wire [3:0] LEDs
);

reg [3:0] cur_state;
wire reset_n=~reset;
assign LEDs[3:0] = cur_state[3:0];

always @(posedge clock or negedge reset_n) begin
    if (!reset_n) cur_state[3:0] <= {4{1'b0}};
    else begin
        if (cur_state[3:0] == 4'b1001) cur_state[3:0] <= {4{1'b0}};
        else cur_state[3:0] <= cur_state[3:0] + 4'b1;
    end
end

Update:LEDs[3:0] Hat nicht geholfen - dann erstmal nur mit zuordnen 4'b1111und schauen ob alle LEDs leuchten.

Die nächste mögliche Ursache für das Problem ist, always @(*) begindass es beim Ändern von Eingangsleitungen für das Inhaltskonstrukt ausgelöst wird always. Das einzige Ereignis, das passiert, wenn Sie Reset ausgeben, cur_stateändert sich auf 0 und wird somit zu cur_state4'b0001 und behält diesen Wert.

Update 1: Sie haben also LSB, andere 3 Bits funktionieren nicht. Sie haben getestet, dass alle LEDs leuchten, wenn Sie 4'b1111 in die Drähte der LEDs schreiben. Ich denke, der Code ist korrekt, da ist etwas anderes falsch. Folgendes berücksichtigen:

  • vereinfachen den Wechsel von Dezimal zu Hexadezimal. In diesem Fall müssen Sie nur cur_state[3:0] <= cur_state[3:0] + 4'b1;ohne Bedingungen nach Zustand #10 suchen

    always @ (posedge clock or posedge reset) begin if (reset) cur_state[3:0] <= 4'b0000; else cur_state[3:0] <= cur_state[3:0] + 4'b0001; end

  • Überlegen Sie, was resetwährend des Tests passiert. Bist du sicher, dass es konstant niedrig ist? Alternativ entfernen Sie es überhaupt aus der Konfiguration:

    always @ (posedge clock) begin cur_state[3:0] <= cur_state[3:0] + 4'b0001; end

  • synthetisiere meinen obigen Code mit nur einem Modul und reset_num zu sehen, ob es auch nicht funktioniert.

  • versuchen Sie es mit anderen LEDs:

    always @ (posedge clock) begin cur_state[3:1] <= cur_state[3:1] + 3'b001; end

Danke für deine Antwort, aber sie hat das Problem nicht gelöst. Ich möchte es auch mit zwei Modulen implementieren, daher ist keine Vereinfachung erforderlich. Ich verwende übrigens das Spartan 3 FPGA-Board.
Ich habe die Antwort aktualisiert. Ich denke, die Ursache des Problems ist always @(*). Sie können zwei Module behalten, aber es sollte keine Notwendigkeit bestehen, das erste Modul mit zwei Always-Konstrukten zu verkomplizieren. Die Implementierung sollte so prägnant und lesbar wie möglich sein – dies ist ein Ziel jeder Programmiersprache, einschließlich Verilog.
Den letzten Absatz deiner Antwort kann ich nicht ganz nachvollziehen. Kannst du es bitte nochmal erklären?
Ich habe alle Ihre Vorschläge ausprobiert, aber nichts davon hat funktioniert.
Fügen Sie der Frage Ihren neuen Code hinzu (aber entfernen Sie nicht den alten). Ich kann nicht erraten, was Sie versucht haben. Haben Sie bewiesen, dass alle LEDs funktionieren, indem Sie alle 1s in das Ausgangsregister geschrieben haben? Mein letzter Absatz sagt, dass es always @(*)anscheinend nicht das leistet, was Sie davon erwarten. RTFM darüber, was es tut und vor allem wann.
Ich habe bewiesen, dass alle LEDs so funktionieren, wie Sie es wollten. Ich habe alle Codes gepostet, die ich verwendet habe, also wäre es toll, wenn Sie sie sich ansehen könnten.
Gut, wenn Sie sich meinen Code ansehen würden, können Sie sehen, dass ich Negedge des invertierten Resets verwende. Bitte versuchen Sie es auf diese Weise. Meiner Meinung nach alwayssollte Ihre aktuelle Bedingung dazu führen, dass Operand(en) in der Bedingung nicht mit den entsprechenden Kanten in der umschließenden Ereignissteuerung des Always-Construct- Fehlers übereinstimmen können. Erklären Sie auch, wie es jetzt nicht funktioniert.
Ich habe es versucht, aber ich bekomme keinerlei Fehler und der Code wird gut synthetisiert. Auf der FPGA-Platine schaltet sich die LSB-LED jedoch nach dem ersten Takt ein und beim nächsten Takt aus, wenn keine anderen LEDs eingeschaltet sind. Daher schaltet sich nur die LSB-LED (LEDs[0]) wiederholt ein und aus.
Ich habe die Antwort mit Update Nr. 1 aktualisiert. Ihr letzter Code sieht für mich in Ordnung aus, daher sollten Sie Anweisung für Anweisung ausschließen, um zu sehen, wann Sie damit beginnen, wie erwartet zu funktionieren.
Danke für deine Hilfe. Das Problem war, dass ich im oberen Modul kein zusätzliches Kabel deklariert habe. Danke schön.