Datum:
Hallo, ich stehe da irgendwie auf dem Schlauch. Folgender VHDL Code entity ResetGenerator is Port ( RESET_IN : in STD_LOGIC; CLK_IN : in STD_LOGIC; STATE_OUT: out std_logic_vector(1 downto 0); RESET_OUT : out STD_LOGIC); end ResetGenerator; architecture Behavioral of ResetGenerator is signal state: bit_vector(1 downto 0); begin process(state, RESET_IN, CLK_IN) begin if rising_edge(CLK_IN) then case state is when "00" => state <= "00"; RESET_OUT <= '0'; if RESET_IN = '1' then state <= "01"; RESET_OUT <= '1'; end if; when "01" => state <= "11"; RESET_OUT <= '1'; when "11" => state <= "10"; RESET_OUT <= '0'; when "10" => state <= "10"; RESET_OUT <= '0'; if RESET_IN = '0' then state <= "00"; RESET_OUT <= '0'; end if; when others => state <= "00"; end case; end if; end process; STATE_OUT <= to_stdlogicvector(state); end Behavioral; Soll ein RESET_IN Signal entgegennehmen, für zwei CLK_IN Zyklen eine '1' auf das Ausgangssignal RESET_OUT legen und danach warten, bis das Eingangssignal wieder auf Null geht, damit das ganze wieder von vorn beginnen kann. Board ist ein Spartan 3AN Prototypenboard von DIGILENT, ich benutze ISE 13.2. CLK_IN ist der 50MHz Quarz, RESET_IN einer der Taster. RESET_OUT, STATE_OUT und auch der Taster sind auf LEDs gelegt, das RESET_OUT-Signal wird zusätzlich noch mit einem Oszi überprüft. Wenn ich jetzt das ganze ausprobiere: Taste gedrückt: LED für Taste an, STATE_OUT ist "10" Taste losgelassen: LED für Taste aus, STATE_OUT ist "00" Es wird beim Drücken der Taste ein 40ns Impuls erzeugt. So weit so gut... Tippe ich jetzt mehrfach auf den Taster hängt das ganze nach kurzer Zeit. Wenn es hängt: Taste gedrückt: LED für Taste an, STATE_OUT ist _"00"_ Taste losgelassen: LED für Taste aus, STATE_OUT ist "00" Es wird beim Drücken der Taste KEIN 40ns Impuls erzeugt. Wie kann das sein? Was habe ich da nicht begriffen? Gruß, Patric
Datum:
so kann man das besser lesen
entity ResetGenerator is Port ( RESET_IN : in STD_LOGIC; CLK_IN : in STD_LOGIC; STATE_OUT: out std_logic_vector(1 downto 0); RESET_OUT : out STD_LOGIC); end ResetGenerator; architecture Behavioral of ResetGenerator is signal state: bit_vector(1 downto 0); begin process(state, RESET_IN, CLK_IN) begin if rising_edge(CLK_IN) then case state is when "00" => state <= "00"; RESET_OUT <= '0'; if RESET_IN = '1' then state <= "01"; RESET_OUT <= '1'; end if; when "01" => state <= "11"; RESET_OUT <= '1'; when "11" => state <= "10"; RESET_OUT <= '0'; when "10" => state <= "10"; RESET_OUT <= '0'; if RESET_IN = '0' then state <= "00"; RESET_OUT <= '0'; end if; when others => state <= "00"; end case; end if; end process; STATE_OUT <= to_stdlogicvector(state); end Behavioral; |
keine fundierten Tipps, aber: 1. hast du das ganze mal simuliert? 2. die Fehlerbeschreibung klingt, als ob du irgendwo Probleme mit einem prellenden Taster hättest
Datum:
Ok, wie geht das mit der Lesbarkeit? Und Danke erstmal für die Antwort. zu 1. nein ich habe es nicht simuliert (kenne mich da mit den Tools (noch) nicht so ganz aus. zu 2. Müsste es nicht egal sein, ob der Taster prellt? Das Ding hängt komplett. Selbst wenn der Taster irgendwo prellt müsste sich das ganze doch wieder fangen, da es keinen Zustand gibt, der als Sackgasse in Frage kommt? Der Taster funktioniert laut LED und die 50MHz sind auch weiterhin da (Oszi geprüft).
Datum:
Gibts bei der Synthese irgendwelche Warnungen?
Datum:
Warnungen: Ja, jede Menge, die aber nichts mit dem entsprechenden Fetzen Hardware zu tun haben. Nur für den ResetGenerator beschwert sich das Tool über den default case (zu recht) und schmeisst ihn weg. Ich habe das Ganze noch eben mal mit einem globalen asynchronen Reset versehen (weiterer Taster). Es dauert gefühlt 5* so lang bis das Ganze hängt. Aber es lässt sich wieder zum Leben erwecken indem man state auf "00" zwingt und RESET_OUT auf '0'. Kann ein bit_vector noch andere Zustände annehmen als "00" "01" "11" "10"? Derzeitiger Code:
entity ResetGenerator is Port ( RESET_IN : in STD_LOGIC; RESET: in STD_LOGIC; CLK_IN : in STD_LOGIC; STATE_OUT: out std_logic_vector(1 downto 0); RESET_OUT : out STD_LOGIC); end ResetGenerator; architecture Behavioral of ResetGenerator is signal state: bit_vector(1 downto 0); begin process(RESET, state, RESET_IN, CLK_IN) begin if RESET = '1' then state <= "00"; RESET_OUT <= '0'; else if rising_edge(CLK_IN) then case state is when "00" => state <= "00"; RESET_OUT <= '0'; if RESET_IN = '1' then state <= "01"; RESET_OUT <= '1'; end if; when "01" => state <= "11"; RESET_OUT <= '1'; when "11" => state <= "10"; RESET_OUT <= '0'; when "10" => state <= "10"; RESET_OUT <= '0'; if RESET_IN = '0' then state <= "00"; RESET_OUT <= '0'; end if; when others => state <= "00"; end case; end if; end if; end process; STATE_OUT <= to_stdlogicvector(state); end Behavioral; |
Toll die Formatierung funktioniert ziemlich gut :)
Datum:
Hallo Patric, > Kann ein bit_vector noch andere Zustände annehmen als "00" "01" "11" > "10"? Nein, der bit_vector(1 downto 0) kennt keine anderen Werte. Aber dein Synthesetool erkennt, dass du eine Statemachine baust, und es kann die interne Codierung der States anders wählen, als du im VHDL-Code angibst. Die Ausgänge müssen mit den Werten im Code übereinstimmen, aber die internen Zustände können eine andere Codierung aufweisen. Du kannst in der ISE die Codierung der SM vorgeben. Evtl ist dort eine Codierung wie "one hot" eingestellt, dann werden deine vier Zustände mit 4 Flipflops codiert, und dann kann es verbotene Zustände geben, in denen sich die SM aufhängt. Reset_in ein ansynchrones Signal von außen, das du zunächst einsynchronisieren musst. Andernfalls kann es passieren, dass Reset_in genau bei einer Taktflanke schaltet. Ein Teil der Logik wertet noch den alten Wert von Reset_in aus, ein anderer Teil sieht schon den neuen Wert, und insgesamt erhältst du ein verbotenes Ergebnis (SM hängt sich auf). viele Grüße Achim S.
Datum:
Na, jetzt hab ich auch den passenden Link dazu gefunden :-) http://www.lothar-miller.de/s9y/categories/35-Eins...
Datum:
Danke Achim! Also die Antwort auf meine Frage mit den Zuständen des bit_vectors wäre dann ein nein, aber das Synthesetool weiss es besser? Ich dachte ich hätte das RESET_IN Signal über die Statemachine einsynchronisiert. Nun gut dann werde ich mir morgen mal ISE genauer ansehen, oder kannst Du mir sagen wo ich Einfluss auf die SM-Generation nehmen kann? Ach Quartus war irgendwie einfacher :) Aber das werde ich mir mal genauer zu Gemüte führen, ich habe schon an meinem Verstand gezweifelt. Immerhin ist es ja schon ein Gray-Code.
Datum:
also statemachinen kann man auch so angeben type state_type is (idle, zustand1, zustand2, zustand3); signal state : state_type;
Datum:
Angehängte Dateien:> Nun gut dann werde ich mir morgen mal ISE genauer > ansehen, oder kannst Du mir sagen wo ich Einfluss auf die SM-Generation > nehmen kann? auf dem Rechner hier habe ich nur die 10.1 installiert. Dort kannst du die Einstellung über einen Rechtsklick auf Synthesize XST -> Properties -> HDL Options einstellen. In anderen Versionen muss es nicht genau so heißen, aber ähnlich. > Ich dachte ich hätte das RESET_IN Signal über die Statemachine > einsynchronisiert. Nö: du wertest das Signal zwar nur bei der steigenden Taktflanke aus, aber das Signals kann sich genau zu diesem Zeitpunkt ändern. Um es einzusynchronisieren musst du es mit der steigenden Taktflanke einem internen Signal zuweisen. Und dieses interne Signal nutzt du dann (mit einem Takt Verzögerung) zur Steuerung der SM. Wenn sich dann das externe Signal genau bei der Taktflanke ändert, erhält das interne Signal den neuen Wert entweder gleich oder erst einen Takt später, aber es hat auf jeden Fall kurz nach der Taktflanke einen eindeutigen Wert. Und alle Teile der Logik der SM sehen den identischen, eindeutigen Wert und schalten mit dem nächsten Takt "in die selbe Richtung". viele Grüße Achim S.
Datum:
Achim S. schrieb: > Nö: du wertest das Signal zwar nur bei der steigenden Taktflanke aus, > aber das Signals kann sich genau zu diesem Zeitpunkt ändern. Und noch nicht mal das ist das Problem. Das kommt nämlich gleich danach: nicht alle Flipflops der FSM sehen den selben Pegel. Das ist der eigentliche Knackpunkt.
process(RESET, state, RESET_IN, CLK_IN) begin if RESET = '1' then state <= "00"; RESET_OUT <= '0'; else if rising_edge(CLK_IN) then |
Diese Sensitivliste ist überbestimmt. Da muss der Simulator zu viel tun, denn er wird unnötigerweise bei einer Änderung von state und RESET_IN zu einer Neuberechnung genötigt! Patric vL schrieb: > Ach Quartus war irgendwie einfacher :) Das hat nichts mit Quartus zu tun. Auch Altera kocht da mit dem selben Wasser: unterschiedliche Laufzeiten von asynchronen Signalen, die direkt in eine FSM gehen, führen per Definition zu Fehlern. > Nun gut dann werde ich mir morgen mal ISE genauer ansehen, oder kannst > Du mir sagen wo ich Einfluss auf die SM-Generation nehmen kann? Als Faustformel: wenn du durch eine geänderte FSM-Implementierung ein anderes Verhalten der FSM bekommst, dann hast du mit an Sicherheit grenzender Wahrscheinlichkeit einen Designfehler, der irgendwas mit Laufzeiten und/oder der Verdrahtung zu tun hat. Patric vL schrieb: > Ich habe das Ganze noch eben mal mit einem globalen asynchronen Reset > versehen (weiterer Taster). Es dauert gefühlt 5* so lang bis das Ganze > hängt. Wie gesagt: andere Verdrahtung, anderes Verhalten. Ursache: nicht einsynchronisierter Eingang, der direkt in die FSM geht. Ein asynchroner Reset, wieder mal...
process(RESET, state, RESET_IN, CLK_IN) begin if RESET = '1' then |
Dazu den Klassiker im Beitrag "Xilinx und die Resets" Und das lesenswerte WP272 von Xilinx.
Datum:
Hallo Achim S., hallo Lothar M., zu dem Punkt Synthesetool erkennt Statemachine: Beim Schematic sind tatsächlich 4 FlipFlops zu erkennen. Ich durchschaue das Schematic nicht ganz, aber es sieht nach einer OneHot-Codierung aus. Beim Menuepunkt "FSM Encoding Algorithm" war "Auto" eingetragen. Ich habe das RESET-Signal erstmal wieder rausgenommen (war eh nur um zu prüfen, ob man einen augenscheinlichen "00" state auf "00" resetten kann) und ich habe "FSM Encoding Algorithm" auf "None" gesetzt damit funktioniert der folgende Code:
process(CLK_IN) begin if rising_edge(CLK_IN) then case state is when "00" => state <= "00"; RESET_OUT <= '0'; if RESET_IN = '1' then state <= "01"; RESET_OUT <= '1'; end if; when "01" => state <= "11"; RESET_OUT <= '1'; when "11" => state <= "10"; RESET_OUT <= '0'; when "10" => state <= "10"; RESET_OUT <= '0'; if RESET_IN = '0' then state <= "00"; RESET_OUT <= '0'; end if; when others => state <= "00"; end case; end if; end process; |
zumindest habe ich nach 5min Finger wundtippen keinen Hänger gehabt (ich weiss, dass dies kein Beweis ist). zum Punkt einsynchronisieren des RESET_IN Signales: Ich habe in einem zweiten process das RESET_IN Signal mit CLK_IN synchronisiert und dabei das Signal synced_reset generiert und dieses statt RESET_IN verwendet. Code:
process (CLK_IN) begin if rising_edge(CLK_IN) then synced_reset <= RESET_IN; end if; end process; process(CLK_IN) begin if rising_edge(CLK_IN) then case state is when "00" => state <= "00"; RESET_OUT <= '0'; if synced_reset = '1' then state <= "01"; RESET_OUT <= '1'; end if; when "01" => state <= "11"; RESET_OUT <= '1'; when "11" => state <= "10"; RESET_OUT <= '0'; when "10" => state <= "10"; RESET_OUT <= '0'; if synced_reset = '0' then state <= "00"; RESET_OUT <= '0'; end if; when others => state <= "00"; end case; end if; end process; |
"FSM Encoding Algorithm" wurde wieder auf "Auto" gesetzt. Im Schematic konnte ich jetzt keine OneHot-Codierung finden. Daher habe ich "FSM Encoding Algorithm" auf "OneHot" gesetzt ich konnte aber immer noch keine OneHot-Codierung im Schematic finden. Die "Auto" und "OneHot" Versionen habe ich getestet (diesmal mit Funktionsgenerator) und auch diesmal hängt nichts. Fazit: An sich war die Gray-Codierung nicht falsch, aber das Synthesetool hat eine OneHot-Codierung daraus gemacht und die knirscht, weil das RESET_IN-Signal dadurch nicht (mehr?) synchronisiert war. Ich danke Euch, ich war nämlich kurz davor meinen Verstand zu verlieren, abgesehen davon fallen mir spontan drei Stellen ein, bei denen diese Art Fehler auch noch dazwischen funkt. Gruß, Patric
Datum:
bitteschön, und schön dass es jetzt klappt. > An sich war die Gray-Codierung nicht falsch, aber das Synthesetool > hat eine OneHot-Codierung daraus gemacht und die knirscht, weil das > RESET_IN-Signal dadurch nicht (mehr?) synchronisiert war. Ich würde eher formulieren: das Reset_in ist seiner Natur nach ein asynchrones Signal, und du musst erst ein synchrones Signal daraus machen. In der One-hot SM führt das asynchrone Eingangssignal zu Fehlern bis hin zum Aufhängen. In deiner Gray-codierten SM, bei der alle Zustände genutzt werden, führt das asynchrone Eingangssignal "nur" zu einem falschen Durchlaufen der States (der Ausgangspuls kann z.B. mal zu kurz oder zu lang werden), aber nicht zum Aufhängen der SM. Das ist zwar schon mal eine Verbesserung, und bei flüchtigem Darübersehen fallen verbleibende Fehler vielleicht nicht mal auf. Aber die richtige Lösung besteht allein darin, das Signal einzusynchronisieren. viele Grüße Achim S.
Datum:
und ich würde Dir dringend dazu raten deine FSM wie oben beschrieben zu definieren und dem Synthesetool die Entscheidung der Codierung zu überlassen >type state_type is (idle, zustand1, zustand2, zustand3); >signal state : state_type; da kann man dem state nämlich gleich noch einwenig Info mit geben, wie "idle", "reset_active", "wait_for_reset_low" oder ähnlich ;-) Gruß
Datum:
Kann es ein dass alle INterpretationen falsch waren und
der Code
state <= "00";
RESET_OUT <= '0';
if RESET_IN = '1' then
state <= "01";
RESET_OUT <= '1';
end if;
einfach Mist ist?
Könnte das Problem des Hängens nicht besser mit
if RESET_IN = '1' then
state <= "01";
RESET_OUT <= '1';
else
state <= "00";
RESET_OUT <= '0';
end if;
gefixt werden?
Zwei verschiedene Zuweisungen auf 'state' , welche soll
denn bitteschön gelten? MIt 'else' eindeutig
Datum:
@Martin Soweit ich das verstanden habe wird bei der Synthese
RESET_OUT <= '0';
if RESET_IN = '1' then
state <= "01";
RESET_OUT <= '1';
end if;
|
Der Anweisungsblock von oben nach unten interpretiert und der letzte Zustand "gilt". Das macht den Code lesbarer, weil man oben quasi erstmal den Default-Zustand definieren kann und unten auf die Einzelfälle eingehen kann. In einem meiner Bücher wurde das als guter Stil propagiert.
Datum:
martin schrieb: > Zwei verschiedene Zuweisungen auf 'state' , welche soll > denn bitteschön gelten? Solange wie die bei VHDL im Prozess stehen, gewinnt die letzte Zuweisung. > MIt 'else' eindeutig Ja, aber: Es wird gern vergessen alle Signale, die ein Prozess treibt, in jedem möglichen Zweig zu setzten (zumindest bei komplexeren Sachen). Daher ist es nicht verkehrt erstmal allen Signalen einen default-Wert zuzuweisen und den dann ggf. zu "überschreiben". Duke
Datum:
@Achim S. Spontan hätte ich ja gesagt, dass, da beim Gray-Code ja immer nur ein Bit kippt alles in Ordnung sein sollte, aber nach längerem Meditieren kommen mir Zweifel. Ich habe dass jetzt noch mal mit Funktionsgenerator, "None", Gray-Codierung und ohne Synchronisierung durchlaufen lassen, mit Oszi auf Nachleuchten unendlich und siehe da: manche Impulse sind nur 20ns lang. Also es scheint ein "Durchrutschen" von "00" auf "11" zu geben. Ich ziehe mein Fazit zurück :( War zugegebenermassen nur ein Versuch wenigstens ein wenig Recht zu haben ;) ABER meine Gray-Version würde wenigstens nicht hängenbleiben (jaja ich weiss unsauber ist unsauber). @martin (Gast) Lesbarkeit ist immer gut. Würde denn eine solche Codierung auch hängenbleiben können? Die bit_vector[2]-Gray-Version hat ja durch die Synthese als OneHot zusätzliche "illegale" States erzeugt, die sich mit when others nicht abfangen liessen, weil es semantisch vollständig auscodiert war.
Datum:
martin schrieb: > Zwei verschiedene Zuweisungen auf 'state' , welche soll > denn bitteschön gelten? Wie üblich beim Prozess: die letzte Zuweisung an ein Signal gewinnt... Der "Zwischenzustand" existiert in diesm Fall gar nicht. Nehmen wir mal diese (etwas unsinnige und umständliche) Beschreibung:
process (clk) begin if rising_edge(clk) then Ausgang <= '0'; if Eingang='1' then Ausgang <= '1'; end if; end if; end process; |
Frage: Was macht bei einer Taktflanke der Ausgang, wenn der Eingang '1' ist? Antwort: Der Ausgang ist fest auf '1'. Da gibt es keine auch noch so kurzen Spikes nach '0', obwohl da eine Defaultzuweisung (Ausgang <= '0') steht. Patric vL schrieb: > ABER meine Gray-Version würde wenigstens nicht hängenbleiben (jaja > ich weiss unsauber ist unsauber). Glück gehabt, denn du hast alle Zustände verwendet. Wenn das jetzt aber nicht sowas simples wäre, sondern eine FSM, die z.B. einen Getränkeautomaten steuert, dann käme z.B. der Kaffee und dann wäre Ende. Oder es käme nur ein Becher, oder kein Pulver... EDIT: Zweiter! Duke hatte das mit dem "gewinnen" schon erwähnt... ;-)

