Kuriose Zustandsübergänge in der RTL-Simulation von Zustandsmaschinen

Ich habe eine einfache Zustandsmaschine als Teil meines Verilog-Moduls:

localparam State_IDLE = 3'b000,
           State_WRITETOLANE1 = 3'b001;

reg [2:0] currentState;
reg [2:0] nextState;

always @(posedge TxByteClk) begin
if( rst ) begin
    currentState <= State_IDLE;
end else begin
    currentState <= nextState;
end
end

always @(*) begin
nextState = currentState;
case( currentState )
    State_IDLE: begin
        if( TxSync ) begin
            nextState = State_WRITETOLANE1;
        end
    end
    State_WRITETOLANE1: begin
        nextState = State_IDLE;
    end
endcase
end

TxSync ist ein Eingangssignal. Das bizarre Verhalten, das ich sehe, ist, dass an der positiven Flanke der Uhr, wenn TxSync hoch ist, currentState auf State_WRITETOLANE1 gesetzt wird und als Ergebnis nextState auf State_IDLE gesetzt wird. Aber nextState wurde nie auf State_WRITETOLANE1 gesetzt! Warum bekommt currentState einen Wert, der in nextState gar nicht vorhanden war? Ist die Zeile currentState <= nextState; implizieren, dass currentState die verzögerte Version von nextState ist?

Der FSM sieht korrekt aus. Könnten Sie den Code so bearbeiten, dass er kompilierbar ist? Es braucht nur die Parameterdefinitionen und die Modulanweisung, aber wenn ich es kompiliere, möchte ich denselben Code kompilieren, in dem Sie das Problem haben.
Wird nextState oder currentState von einem anderen Code gesteuert, der hier nicht aufgeführt ist?
Es kann hilfreich sein, eine Wellenform hochzuladen, die die relevanten Signale anzeigt.
Ich habe die Parameter hinzugefügt. currentState und nextState werden von nichts anderem angetrieben als dem, was hier gezeigt wird. Ich werde morgen eine Wellenform hinzufügen, wenn ich Zugriff habe, aber es ist eindeutig, dass sich der aktuelle Status auf einen Wert ändert, den der nächste Status nie gehalten hat.
nextState hätte auf State_WRITETOLANE1 gesetzt werden sollen, sobald TxSync hoch ging. Haben Sie ein Zeitdiagramm, das zeigt, dass dies nicht passiert ist? Welchen Wert sehen Sie in nextState vor der Taktflanke?

Antworten (1)

Ich ging voran und machte eine Testbank, um das Verhalten der Schaltung zu sehen. Bitte klicken Sie mit der rechten Maustaste auf das Bild, um es deutlicher zu sehen.

Geben Sie hier die Bildbeschreibung ein

Aus meiner Simulation ergibt sich nichts Unerwartetes oder Seltsames an der Wellenform. Der Zustand wird durch das Zurücksetzen korrekt initialisiert. Wenn TxSync hoch ist, schaltet der Zustand einmal pro Taktzyklus um. Wenn TxSync deaktiviert ist, hält der Zustand einen konstanten Wert.

Ich habe auch einen Flusenprüfer verwendet und es gibt keine größeren Probleme mit dem RTL. Ich muss feststellen, dass die Schaltung genau so simuliert, wie es in der RTL angegeben ist. Wenn Sie etwas anderes erwartet haben, sollten Sie das deutlicher machen, und ich werde Ihnen sagen, wie Sie das Modell ändern können.

Einige Anmerkungen zur Simulation:

  1. Das CurrentState-Register speichert den Wert von nextState an der steigenden Flanke von TxByteClk
  2. Die NextState-Logik wird nach einer infinitesimal kleinen Zeiteinheit nach der ansteigenden Flanke von TxByteClk (oder TxSync) aktualisiert, da dies ein 0-Verzögerungsmodell ist
  3. CurrentState und nextState scheinen sich gleichzeitig zu ändern, aber currentState wird zuerst aktualisiert

Fallstrick: Wenn Ihre Testbench den TxSync-Eingang genau an der steigenden Taktflanke aktualisiert, haben Sie nur einen Fehler in nextState. Ihr Simulator kann diesen Fehler beseitigen, sodass es so aussieht, als ob nextState nie in State_WRITETOLANE1 eingetreten ist, obwohl dies tatsächlich der Fall war, nur für einen sehr kurzen Moment. Dies würde es so aussehen lassen, als hätte currentState einen Wert zwischengespeichert, den nextState nie hatte.

Abhilfe: Aktualisieren Sie die Eingänge nicht exakt zur steigenden Taktflanke. Fügen Sie eine kleine Verzögerung hinzu, damit die Simulation besser verstanden werden kann. In meinem Fall habe ich den Eingang an der fallenden Taktflanke aktualisiert. Die Aktualisierungszeit ist jedoch willkürlich, wenn Sie eine 0-Verzögerungssimulation durchführen.

Das ist in der Tat die Antwort. Danke!. aber warum macht der simulator das? Es hat mit identischen Zustandsmaschinen funktioniert? Sollten Simulatoren nicht so reagieren, als ob alles an der steigenden Flanke geschehen wäre, und keine Störungen zulassen?
Das Zustandsregister wird nur an der steigenden Flanke des Takts aktualisiert. Denken Sie jedoch daran, dass Sie nicht nur den sequenziellen Zustand modellieren, sondern auch die Zustandsneuladelogik, die kombinatorisch ist. Diese beiden Komponenten sind jeweils der erste und der zweite Immer-Block. Für den sequentiellen Teil spielt es also keine Rolle, in welcher Phase des Taktzyklus Sie den Eingang ändern. Der kombinatorische Teil hängt jedoch davon ab, wann sich die Eingabe ändert, da er sofort aktualisiert wird. Wenn sich die Eingabe an der Posege-Uhr ändert, wird der Kombiteil zweimal zu schnell aktualisiert, um es auf der Sim zu sehen.