Forum: FPGA, VHDL & Co. Design - Faustregeln


von Pat R. (patrik)


Angehängte Dateien:

Lesenswert?

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

von Joko (Gast)


Lesenswert?

>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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> 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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

>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;

....

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

... 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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

... 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.

von Pat R. (patrik)


Lesenswert?

Hallo Leute,
Hut ab und 10^6 x DANKE!!! :-))

Patrik

von mac4ever (Gast)


Lesenswert?

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 ?

von Pat R. (patrik)


Lesenswert?

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.

von Joko (Gast)


Lesenswert?

@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..

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> 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.

von mac4ever (Gast)


Lesenswert?

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

von Mike (Gast)


Lesenswert?

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.

von Morin (Gast)


Lesenswert?

> 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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> 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... ;-)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> 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.

von Pat R. (patrik)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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.

von Pat R. (patrik)


Lesenswert?

ok, jetzt werd' ich mir es schon merken ;-)

von Dida (Gast)


Lesenswert?

@ Lothar Miller (lkmiller): verschone uns mit deiner Krümmelkackerei!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.