Hallo Leute, ich versuche einen Spartan3E XC3S500E auf dem StarterKit mit Xilinx ISE 10.1 zu programmieren. Im Anhang ist eine Schaltung zu finden, die einen digitalen Signal (Low=0V, High=3.3V) liefert. Das Signal ist cca. 7ms High und dann cca. 70ms Low und das wiederholt sich. Und ich möchte den FPGA so programmieren, dass ich auf einem anderen Pin eine 'Kopie' von diesem Eingangssignal bekomme. Das Eingangssignal bereitet mir aber grosse Kopfschmerzen und bringt den FPGA durcheinander. Ich habe folgendes versucht: proc: process(clk, reset) begin if reset = '1' then CHANGED_SIGNAL <= '0'; fsm_p <= wait_for_start_p; elsif clk'event and clk = '1' then case fsm_p is when wait_for_start_p => if SIGNAL_ORIG = '1' then CHANGED_SIGNAL <= '1'; fsm_p <= process_neutral; end if; when process_neutral => if SIGNAL_ORIG = '0' then CHANGED_SIGNAL <= '0'; fsm_p <= inj_p_debounce; end if; when inj_p_debounce => fsm_p <= wait_for_start_p; end case; end if; end process; Wenn ich das an Osci anschliesse, dann bleibt ab und zu mal das Ausgangssignal 'hängen'. Es kopiert das Eingangssignal nicht, sondern bleibt ab und zu mal eine ganze Periode(77ms) auf High oder Low und dann geht es wieder kurz ordentlich und dann bleibt es wieder hängen usw. Ausserdem, wenn ich in den FSM Zuständen anderen Signalen einen Wert zuweise, wird dieser ab und zu nicht richtig übernommen. Manchmal kommt der FSM in einen undefinierten Zustand und dann geht auch gar Nichts mehr. Ich weiss, dieser FSM ist unsafe, aber selbst wenn ich zusätzlichen Zustand hinzufüge und den FSM safe mache, bringt es nichts. Ich habe viel rumexperimentiert und habe herausgefunden, dass wenn das Eingangssignal gelesen wird oder das Ausgangssignal gesetzt wird, sollte nichts anderes gemacht werden, ausser den FSM auf den nächsten Zustand setzen. Dann scheint es auf dem Osci zu funcen. Hier ein Beispiel das zu funktionieren scheint: proc: process(clk, reset) begin if reset = '1' then CHANGED_SIGNAL <= '0'; s0 <= '1'; s1 <= '0'; s2 <= '0'; s3 <= '0'; is_start <= '1'; elsif clk'event and clk = '1' then if s0 = '1' then is_start <= '1'; if SIGNAL_ORIG = '1' then s0 <= '0'; s1 <= '1'; end if; elsif s1 = '1' then s1 <= '0'; s2 <= '1'; CHANGED_SIGNAL <= '1'; elsif s2 = '1' then is_start <= '0'; if SIGNAL_ORIG = '0' then s2 <= '0'; s3 <= '1'; end if; elsif s3 <= '1' then CHANGED_SIGNAL <= '0'; s3 <= '0'; s0 <= '1'; else leds(3) <= '1'; end if; end if; end process; Aber wieder, wenn ich versuche, CHANGED_SIGNAL dort zu setzen wo SIGNAL_ORIG gelesen wird, geht das ganze nach kurzer Zeit in den else Zweig und dann geht nichts mehr. Ich weiss, CHANGED_SIGNAL <= SIGNAL_ORIG; funktioniert vorzüglich, ich möchte aber verstehen, warum die erste Lösung nicht funktioniert und sich so merkwürdig verhält(bzw. auch die zweite Lösung wenn CHANGED_SIGNAL dort gesetzt wird wo SIGNAL_ORIG gelesen wird)? Gibt es faustregel die man beim Design beachten muss, wie z.B. dass das Eingangssignal in einem anderen FSM/Prozess gelesen werden muss, oder muss ich die Eigenschaften des Eingangspins anders setzen (PullUp und PullDown habe ich schon versucht, den I/O Standard Des Eingangspins habe ich auf LVTTL gesetzt)? Hat jemand eine andere Idee warum das merkwürdige Verhalten oder wie ich das Problem ZUVERLÄSSIG lösen kann? Ich bin für jede Idee dankbar da ich nicht weiterarbeiten will, solange ich das nicht verstehe. Danke Patrik
>Hat jemand eine andere Idee warum das merkwürdige Verhalten oder >wie ich das Problem ZUVERLÄSSIG lösen kann? ja >Gibt es faustregel die man beim Design beachten muss, ja >wie z.B. dass das Eingangssignal in einem anderen FSM/Prozess >gelesen werden muss nein ---------- Dein "Problem" ist ein grundlegendes: man MUß synchron arbeiten ! d.h.: alle Signale müssen auf den Arbeitstakt synchonisiert sein! Dein Eingangssignal ist jedoch asynchron ! :-((( Deine Statemachine besteht aus mehr 2 States, d.h. sie besteht aus mehr als einem FlipFlop Dadurch kann es passieren, daß bei einem Zustandswechsel des Eingangssignals ein (oder mehrere) FF(s) einen anderen Wert 'sieht/sehen', als die anderen und dadurch die FSM in einen undefinierten Zustand gerät. (Metastabilität - die im Prinzip bei Dir auch auftreten kann - ist dabei unwahrscheinlicher als der o.a. Effekt) >Ich weiss, dieser FSM ist unsafe, aber selbst wenn ich zusätzlichen >Zustand hinzufüge und den FSM safe mache, bringt es nichts. Bist Du Dir sicher, daß die FSM 'safe' ist? vielleicht wurde sie auch als 'one hot' implementiert, dann ist sie (in Deinem Fall) immer noch 'unsafe' Die einzig 'richtige' Vorgehensweise: Taste Dein Eingangssignal mit zwei (2) hintereinander geschalteten FFs (mit der FSM-clock) ab und führe das Ausgangssignal an Deine FSM... Gruß Jochen
> faustregel die man beim Design beachten muss - ein (1) Takt - keine unnötigen State-Machines - synchroner Reset - externe Signale einsynchronisieren Und wie bei allen Faustregeln gilt, dass an der geeigneten/nötigen Stelle davon abgewichen werden darf/soll/muß. Zu deinem Problem sieh mal dort: Beitrag "Re: 1 clk impuls erzeugen" Ganz schlimme Sachen passieren, wenn du das externe Signal direkt auf mehrere FFs in einer SM legst. Dann gibt es wirklich mal unerwartete und nicht nachvollziehbare Sprünge zwischen den Zuständen. Bei einer One-Hot-Implementierung kann es dann sogar sein, dass mehrere FFs hot sind :-o
>Ich weiss, dieser FSM ist unsafe, aber selbst wenn ich zusätzlichen >Zustand hinzufüge und den FSM safe mache, bringt es nichts. Es ist Unsinn, eine SM "safe" machen zu wollen. Das heißt ja nichts anderes als: "Ich rechne damit, dass etwas schiefgeht, und definiere daher alle Zustände. Dann findet die SM immer einen Weg zurück." Augen zu und durch :-( Wichtiger ist es, die Eingangssignale für die SM "safe" zu machen. Und in der Praxis heißt das "Einsynchronisieren". In den Synthese-Properties gibt es die Möglichkeit, die SM safe codieren zu lassen (Bild). Diese (scheinbare) Sicherheit kostet aber ganz enorm Ressourcen. Als Beispiel:
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use IEEE.NUMERIC_STD.ALL; |
4 | |
5 | entity StateMachine is |
6 | Port ( clk : in STD_LOGIC; |
7 | inp : in STD_LOGIC; |
8 | outp : out STD_LOGIC); |
9 | end StateMachine; |
10 | |
11 | |
12 | architecture Behavioral of StateMachine is |
13 | type State_Type is (S0, S1, S2, S3); |
14 | signal state : State_Type := S0; |
15 | |
16 | signal inpsr : unsigned(1 downto 0); -- Schieberegister zur Synchronisation |
17 | signal inploc : STD_LOGIC; -- synchronisierter Eingang |
18 | |
19 | begin
|
20 | -- SM arbeitet komplett nur mit synchronen Signalen
|
21 | process begin |
22 | wait until rising_edge(clk); |
23 | case (state) is |
24 | when S0 => if (inploc='0') then |
25 | state <= S1; |
26 | end if; |
27 | when S1 => if (inploc='1') then |
28 | state <= S2; |
29 | end if; |
30 | when S2 => if (inploc='0') then |
31 | state <= S3; |
32 | end if; |
33 | when S3 => if (inploc='1') then |
34 | state <= S0; |
35 | end if; |
36 | end case; |
37 | end process; |
38 | |
39 | -- Eingang einsynchronisieren und auf lokales Signal abbilden
|
40 | process begin |
41 | wait until rising_edge(clk); |
42 | inpsr <= inpsr(0) & inp; |
43 | if (inpsr="00") then inploc<='0'; end if; |
44 | if (inpsr="11") then inploc<='1'; end if; |
45 | end process; |
46 | |
47 | outp <= '1' when state=S0 or state=S1 else '0'; |
48 | |
49 | end Behavioral; |
....
... Daraus wird mit One-Hot ohne die Safe-Implementation sowas wie im Bild. (hier ist nur die eigentliche SM, das Synchronisieren geschieht ausserhalb, es ist also das Signal In0 = inploc) Es könnten hier durch asynchrone Signale, die dirket auf mehrere FFs gehen, durchaus auch mal 2 der FFs aktiv werden. Ab dann rennt die SM komplett neben der Kappe :-o
... Mit One-Hot "safe" wird sowas synthetisiert. Das Abfangen der unzulässigen Zustände (mehrere FFs auf '1') kostet ziemlichen Aufwand. Wer für diese "Sicherheit" soviel Logik verheizen will, der soll das ruhig tun. Wenn hier mit einem asynchronen Signal hineingefahren wird, gibt es zwar keinen "verbotenen" Zustand mehr, aber es kann trotzdem sein, dass ungültige Transitionen durchgeführt werden. Und das ist im Ergebnis genauso falsch :-o Fazit: eine SM an sich muß nicht "safe" sein. Die Eingangssignale zur SM müssen "safe" sein. Das werden sie durch das Eintakten/Einsynchronisieren.
Die SM vollständig auskodieren würde ich sicherlich auch nicht, aber warum sehe ich nirgends ein "when others =>" ? Falls die SM dann in einen nicht definierten Zustand springt, kann man das wenigstens abfangen. Oder ist das bei One-Hot-Kodierung überflüssig ?
Ich habe an vielen Stellen gelesen, dass when others nicht alle theoretisch möglichen Zustände abdeckt, sondern nur diejenigen, die in der Aufzählung definiert sind, nicht aber durch when Klausel behandelt werden. Somit kann die FSM selbst mit when others in einem undefinierten Zustand geraten.
@mac4ever >[..] ich nirgends ein "when others =>" ? Falls die SM dann in >einen nicht definierten Zustand springt, kann man das wenigstens >abfangen. eben nicht: um Ressourcen zu sparen ignoriert die Synthese per default den "when others"-Zweig komplett ! um einen undefinierten abzufangen, muß man den safe-modus manuell einschalten - kostet aber wie bereits ausführlich beschrieben eine Unmenge an Ressourcen. Dies macht man nur, wenn man um ggf. die Auswirkungen von SEU zu beeinflussen - glaube aber kaum, daß de OP daran denkt, seine Schaltung in den Anden oder im Weltraum zu betreiben..
> when others .... > ist das bei One-Hot-Kodierung überflüssig ? Wenn jeder Zustand auscodiert wurde, macht when-others bei der One-Hot-Codierung mit abgeschalteter "Safe-Implementierung" gar keinen Sinn. Da ist jeder definierte Zustand ein (1) FF. Der hier "gemeinte" when-others-Fall wäre also, wenn mehr als 1 FF aktiv wäre. Und diese Abfrage kostet immensen Aufwand, da dann ja alle FFs mit in die entscheidung einfliessen müssen (siehe dazu meine Screenshots). Die Safe-Option ist bei binär codierten SM einfacher zu implementieren, aber Mehraufwand ist es immer. Grundlegend ist ja wohl, dass üblicherweise when-others niemals erreicht werden darf. Und falls es doch dazu kommt, wie sollte denn dann reagiert werden? Und wie oft darf es dazu kommen? Darf dann einfach so weiter gemacht werden? Ein lustiger Trick ist übrigens bei Designs, die ab und zu nicht funktionieren, einfach mal eine andere Implementierung (z.B. binär statt one-hot) zu erzwingen. Wenn sich dann am Verhalten was ändert, sind idR. asynchrone Signale und Glitches dafür verantwortlich, nicht die SM an sich.
Ok, danke für die Infos. Ich hab vorhin auch mal ein wenig herum gesucht und bin dabei auf ein Dokument der Nasa gestoßen. Dort werden genau Themen wie SEU und "Safe-Mode" bzw. Fehlererkennung angesprochen. Es wird empfohlen eine One-Hot-Kodierung durch ein XNOR aller Zustand-FFs zur Fehlererkennung zu benutzen. Aber wie Joko schon treffend fragte: Wollen wir ins All ? :D
Du bekommst durch den Kondensator nicht wirklich steile Flanken an den Eingang. Das verschärft die Probleme mit der Metastabilität (die Zeit die der Eingang im verbotenen Bereich verbringt wird länger). Ich würde daher auf jeden Fall noch ein Schmidt Trigger Gatter davor hängen - natürlich zusätzlich zu den restlichen Empfehlungen.
> Ich habe an vielen Stellen gelesen, dass when others nicht alle > theoretisch möglichen Zustände abdeckt, sondern nur diejenigen, die in > der Aufzählung definiert sind, nicht aber durch when Klausel behandelt > werden. Somit kann die FSM selbst mit when others in einem undefinierten > Zustand geraten. Die Sache ist etwas komplexer. Rein formal deckt "when others" alle nicht explizit aufgeführten Fälle ab; rein formal sind aber nur die im Datentyp aufgelisteten Fälle überhaupt möglich. "When others" deckt also tatsächlich nur die im Typ aufgelisteten Fälle ab, weil die andern aus Sicht des VHDL-Codes nicht möglich sind und deshalb weder auftreten können noch behandelt werden können. Problem bei der Sache ist, dass die Synthese gar nicht den eingegebenen VHDL-Code synthetisiert, sondern einen abgewandelten Code mit kleineren Änderungen, in dem zum Beispiel noch andere als die aufgelisteten Fälle möglich sind. Wie diese zusätzlichen Fälle behandelt werden, hängt dann davon ab, wie diese Code-Transformation im Detail passiert. Die ist Teil des Synthesetools, und man kann per Parameter steuern, wie die Transformation abläuft. Einer dieser Schalter ist der erwähnte "safe"-Schalter, welcher im wesentlichen einen Übergang der neu eingeführten Zustände in einen definierten Startzustand einfügt. Man kann also, sobald eine solche Transformation im Spiel ist, nicht mehr genau sagen, ob "when others" die neu eingeführten Fälle abdeckt. Das ist abhängig vom Synthesetool. In VHDL-Manuals wird dazu nichts zu finden sein, weil diese nur die Semantik eines VHDL-"Programms" festlegen, aber nicht, wie dieses Programm bei der Synthese verändert werden soll. Im Manual zum Synthesetool gibt es evtl. Informationen dazu. Desweiteren gibt es auch gewisse Standards, wie die Code-Transformation bei der Synthese abzulaufen hat, aber da kenne ich mich leider nicht aus.
> Ich würde daher auf jeden Fall noch ein Schmidt Trigger Gatter davor > hängen - natürlich zusätzlich zu den restlichen Empfehlungen. Das war Herr Otto Schmitt, der mit dem Trigger. Und dieses Schmitttrigger davorhängen ist absolut unnötig. Wenns fürs Gewissen und das Gefühl unbedingt sein muß, dann häng doch einfach noch ein Register dahinter. Im FPGA gibts genug davon. Aber dann sind wir schon fast auf dem Niveau vom sauerstofffreiem Kupfer für Leiterbahnen... ;-)
> rein formal sind aber nur die im Datentyp aufgelisteten Fälle > überhaupt möglich. Und genau auf dieser formalen Ebene läuft dann auch eine Verhaltens-Simulation ab. D.h. hier können wir dann auch gleich den Aberglauben aufräumen, in einer Verhaltens-Simulation so ein Verhalten nachstellen und finden zu können.
Eigentlich geht der Pin nicht in FPGA sondern in einen Schmidt-Trigger und erst danach in FPGA, mein Fehler! Ob er jetzt nötig ist oder nicht, das kann ich nicht beurteilen, da kenne ich mich viel zu wenig aus. Ich könnte es aber ohne den ausprobieren, denn die Entprellung, die im FPGA stattfindet(nicht in dem Beispiel von mir enthalten), ist dann meiner Meinung nach ausreichend.
Lothar Miller (lkmiller) wrote: > Das war Herr Otto Schmitt, der mit dem Trigger. Patrik Krizan wrote: > ... Schmidt-Trigger ... Lernresistent? ;-) Für das FPGA ist ein Signal erst dann interessant, wenns am IO-Buffer ankommt. Ob davor noch irgendwelche Signalkonditionierungen stattfinden ist für das FPGA komplett uninteressant. Egal wie steilflankig dieses asynchrone Signal ist: es muss auf den Takt (der SM) einsynchronisiert werden. Stichworte dazu sind Setup-Zeit, Hold-Zeit und Metastabilität. BTW: der Pin geht nirgendwohin, der ist fest am Gehäuse angebracht.
Dida wrote:
> @ Lothar Miller (lkmiller): verschone uns mit deiner Krümmelkackerei!
Dito.
Krümel... ;-)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.