Forum: FPGA, VHDL & Co. FSM funktioniert nicht wie ich will


von Signalisierer (Gast)


Lesenswert?

Hallo guten Tag,

ich versuche eine Mealy Maschine zum Laufen zu bringen, die Muster eines 
Datensstroms erkennen soll.

* Zuerst möchte ich "0x5a50dad0d1d2d3d4" (64 Bit) erkennen

* wenn ich das separat in einem process mache klappt das ohne weiteres
* Das ist auch relativ einfach, da bei rising edge dieses Signal 
auftauchen kann
```
testcheck : process  (Daten)
WHEN WAIT_FOR_ADR1 =>
                -- check first addres
                case FRAME_PART1v2  is
    when X"5a50dad0d1d2d3d4" => DETECTED_ADR1 <= '1';
    when others =>
end process testcheck;
```
* Mit meiner State Machine klappt das nicht

* Sie scheint zu spät zu prüfen oder so

* Erst wenn ich die "next state output "logic sensibel mache detektiert 
sie dieses Muster...

* Wird nicht bei clk-rising edge der "next_state" aktualisiert und 
deswegen gleichzeitig die FSM aufgerufen?

* Dort müsste doch erkannt werden, dass zu diesem Zeitpunkt dieser 
Vektor (0x5a50dad0d1d2d3d4) anliegt!

* Bei dem Mealy Beispiel von Xilinx stand noch ein x  neben dem 
current_state. Ich könnte das für den Input verwenden...
 Finde ich aber seltsam aber ok.
Wenn sich die state machine gerade in diesem Zustand befindet und dafür 
sensibel sein muss ...


```
--- hier übergebe ich meine Eingangsdaten:
FRAME_PART1v2 <= m_axis_tdata;

-- Das ist meine "reset logic"
-- sie wird bei jedem m_axis_clk  ausgeführt
-- current state wird dabei immer aktualisert

    SYNC_PROC2 : PROCESS (m_axis_clk)
    BEGIN
        IF rising_edge(m_axis_clk) THEN
            IF (axi_reset = '1') THEN
            -- reset..
                current_state <= IDLE;
            ELSE
                current_state <= next_state;
            END IF;
        END IF;
    END PROCESS;


-- next state & Output logic:
-- dadurch, dass current_state bei jedem risign edge aktualisiert wird,
-- wird zeitgleich(?) die next state output logic ausgeführt.
-- es soll eine bestimmte Adresse in dem signal "FRAME_PART1v2" 
detektiert werden.
-- dann soll DETECTED_ADR1 auf 1 gesetzt werden.
-- allerdings klappt das nicht
-- habe dann einfach m_axis_clk in die Sensibilitätsliste eingefügt.. 
und dann geht es
 -- könnte evtl. noch den datenstream selber in in die 
Sensibilitätsliste einfügen . Im xilinx beispiel war dort ein x... habe 
ich weggemacht :D

    NEXT_STATE_DECODE : PROCESS (current_state,m_axis_clk)
    BEGIN

        CASE (next_state) IS
        WHEN IDLE =>
        next_state<= WAIT_FOR_ADR1;
        -- do nothing


        WHEN WAIT_FOR_ADR1 =>
                -- check first addres
                case FRAME_PART1v2  is
    when X"5a50dad0d1d2d3d4" => DETECTED_ADR1 <= '1';
    when others =>
  end case;
```

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


Lesenswert?

Signalisierer schrieb:
> die FSM aufgerufen?
Du hast die falsche Denkweise und "programmierst" Hardware.

Denn in der Hardware wird nichts "aufgerufen", eine FSM wird nicht 
"aufgerufen". Jedes Flipflop, das deine VHDL-Beschreibung in einem FPGA 
oder einem ASIC erzeugt, ist immer da. Und bei der entsprechenden Flanke 
wird einfach der Pegel vom Eingang des Flipflops auf dessen Ausgang 
abgespeichert.

Signalisierer schrieb:
1
testcheck : process  (Daten)
2
   WHEN WAIT_FOR_ADR1 =>
3
                -- check first addres
4
                case FRAME_PART1v2  is
5
    when X"5a50dad0d1d2d3d4" => DETECTED_ADR1 <= '1';
6
    when others => 
7
end process testcheck;
Die Sensitivliste ist falsch. Siehe auch das:
1
    NEXT_STATE_DECODE : PROCESS (current_state,m_axis_clk)
2
    BEGIN
3
        CASE (next_state) IS
4
        WHEN IDLE => 
5
        next_state<= WAIT_FOR_ADR1;
6
        -- do nothing
7
        WHEN WAIT_FOR_ADR1 =>
8
                -- check first addres
9
                case FRAME_PART1v2  is
10
    when X"5a50dad0d1d2d3d4" => DETECTED_ADR1 <= '1';
11
    when others => 
12
  end case;
In dieser Sensitivliste sind unnötigerweise "current_state" und 
"m_axis_clk" drin. Dafür fehlen aber "next_state" und "FRAME_PART1v2".

Deshalb wird deine Simulation nicht zur erzeugten Hardware passen.
Das sagt dir der Synthesizer aber auch...

Über die Sensitivliste kannst du lediglich das Verhalten der Simulation 
steuern. Der Synthesizer kümmert sich nicht um die Sensitivliste. Er 
wird deshalb die Signale "next_state" und "FRAME_PART1v2" schlicht 
ignorieren.

Signalisierer schrieb:
> Erst wenn ich die "next state output "logic sensibel mache detektiert
> sie dieses Muster...
Wer detektiert da was zu spät? Wie stellst du das fest? Im Simulator? Im 
echten Leben? Kann man da mal irgendwelche 
Grafiken/Screenshots/Messungen sehen?

von Signalisierer (Gast)


Lesenswert?

Vielen Dank für das Feedback!

Habe nicht beachtet wie eine Sensitivitätsliste synthetisiert wird.

Sehe gerade einen Beitrag:

>Christian R. (supachris)
>30.05.2013 22:18

>Die Sensitivitätsliste ist ausschließlich für den Simulator relevant
>und gibt an, welche Signale auf Änderungen überwacht werden sollen.
>Jedes mal wenn sich ein Signal aus der Liste ändert, wird das Ergebnis
>des Prozesses vom Simulator neu berechnet. Trotzdem sollte man die Liste
>immer ordentlich beschreiben, da sonst Simulation und Realität nicht
>übereinstimmen. In deinem Fall müsste dann x in die Liste, denn bei
>einer Änderung von x soll sofort der Ausgang neu berechnet werden. Der
>Synthese ist die Liste egal, die spuckt in der Regel nur eine Warnung
>aus, wenn sie nicht vollständig ist.



* Habe mich außerdem an diesem Beispiel orientiert.
* Muss eigentlich nicht synthetisierbar sein
* Möchte es aber trotzdem als Übung machen
* Möchte außerdem eine passende State-Machine wählen um AXI-Stream zu 
checken
 - In der Simulation passt das schon einigermaßen


https://www.xilinx.com/support/documents/university/Vivado-Teaching/HDL-Design/2015x/VHDL/docs-pdf/lab10.pdf
1
TYPE state_type IS (S0, S1);
2
SIGNAL state, next_state : state_type;
3
BEGIN
4
  SYNC_PROC : PROCESS (clk)
5
  BEGIN
6
    IF rising_edge(clk) THEN
7
      IF (reset = '1') THEN
8
        state <= S0;
9
      ELSE
10
        state <= next_state;
11
      END IF;
12
    END IF;
13
  END PROCESS;
14
15
  NEXT_STATE_DECODE : PROCESS (state, x)
16
  BEGIN
17
    parity <= '0';
18
    CASE (state) IS
19
      WHEN S0 => 
20
        IF (x = '1') THEN
21
          parity <= '1';
22
          next_state <= S1;
23
        ELSE
24
          next_state <= S0;
25
        END IF;
26
      WHEN S1 => 
27
        IF (x = '1') THEN
28
          next_state <= S0;
29
        ELSE
30
          parity <= '1';
31
          next_state <= S1;
32
        END IF;
33
      WHEN OTHERS => 
34
        next_state <= S0;
35
    END CASE;
36
END PROCESS;

von Signalisierer (Gast)


Lesenswert?

Also ok die Simulation benötigt die Angabe der Sensitivitätsliste dafür, 
dass sie sich so wie das Enddesign verhält.
Sonst würde die Simulation bei bestimmten Signaländerungen nicht 
reagieren, während das echte Design dann aber reagieren würde.


Ah hier sehe das auch noch mal...


Entwurf von digitalen Schaltungen und Systemen mit HDLs und FPGAs ...
von Frank Kesel, Ruben Bartholomä s.344

[link]https://books.google.de/books?id=D0_pBQAAQBAJ&pg=PA344&lpg=PA344&dq=sensitivit%C3%A4tsliste+ignoriert&source=bl&ots=17g0iiDcvm&sig=ACfU3U1VRRD-Uuxk-XXuXxPVM-ERN24A-Q&hl=de&sa=X&ved=2ahUKEwiwm7e39qb3AhXYuKQKHazECpUQ6AF6BAgdEAM#v=onepage&q=sensitivit%C3%A4tsliste%20ignoriert&f=false 
[/link]

von Signalisierer (Gast)


Lesenswert?

* weiß grade nicht wieso ich anstatt.


1
  CASE (state) IS


das hier geschrieben habe
1
  CASE (next_state) IS

* Auf jeden Fall werde ich das ganze überarbeiten
  - vor allem da ich Sensibilitätslisten jetzt ein bisschen anders sehe!

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


Lesenswert?

Signalisierer schrieb:
> weiß grade nicht wieso ich anstatt
>   CASE (state) IS
> das hier geschrieben habe
>   CASE (next_state) IS
Mein Tipp: schreib synchrone FSM in der 1-Prozess-Schreibweise, dann 
passiert sowas nie wieder.
Siehe dazu auch den Thread Beitrag "FSM Beschreibung in VHDL (registered, combinatorial)" 
und die Links darin.

: Bearbeitet durch Moderator
von Signalisierer (Gast)


Lesenswert?

* Ich weiß jetzt gerade gar nicht, was ich wählen soll.
* 1 Prozess klingt gut
* Aber ich hätte überhaupt kein Problem Kombinatorik und Synchrones zu 
trennen



Wollte eigentlich mit einem Zähler arbeiten, der bei jeden Takt prüft, 
ob das aktuelle Signal einen validen Code enthält.

* Also  64 Bit Signal = valide dann  counter++ bei rising edge
   - 64 Bit  kann dabei auch konstant bleiben.
   - Kombinatorisch nicht erkennbar, weil Takt einzige Änderung.

* Also angenommen ich möchte bei dem Xilinx Beispiel bleiben.
  - Mit 2 Prozessen.
* Wo soll ich dann diesen Counter hinschreiben?
  - In den ersten oder in den 2ten Prozess.
  - Oder einen neuen Prozess dafür erstellen?

von Signalisierer (Gast)


Lesenswert?

Lothar M. schrieb:
> synchrone FSM in der 1-Prozess-Schreibweise

axi-s ist ja synchron zum Takt..
von daher könnte das sogar passen für einen simplen pattern checker 
oder?

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


Lesenswert?

Signalisierer schrieb:
> Also angenommen ich möchte bei dem Xilinx Beispiel bleiben.
> Mit 2 Prozessen.
> Wo soll ich dann diesen Counter hinschreiben?
> In den ersten oder in den 2ten Prozess.
Du musst nach reiner Lehre den Counter aufteilen in Register z.B. 
namens "cnt" und einen Addierer, der "cnt_next" ausrechnet.

Das wollte ich vorhin eigentlich auch noch verlinken, da steht das drin:
http://www.lothar-miller.de/s9y/archives/43-Ein-oder-Zwei-Prozess-Schreibweise-fuer-FSM.html

: Bearbeitet durch Moderator
von Signalisierer (Gast)


Lesenswert?

Ah vielen Dank für den Link!
Würde das nämlich mindestens gerne nachvollziehen :D

(Habe vorhin schon mal nach "FSM" in dem Suchfeld gesucht, aber es kam 
nichts!)



Was meinst du damit:

Lother M. schrieb:
> ein synchroner und ein kombinatorischer Prozess gemergt in einer
> process-Umgebung.
Die kurze Schreibweise dafür ist "Murks!"

von Signalisierer (Gast)


Lesenswert?

Hab  das sogar bei meinem pattern generator ( nicht der gerade erwähnte 
pattern checker) auf deine Weise gemacht:


#### Hier der Ausschnitt:

Anmerkungen:

* Der SYNC_PROC ist einfach nur da, weil ich das aus dem Beispiel hatte 
und nicht wusste, ob ich das mit reinbringen soll oder nicht...
* next_state und state passen hier aber von der Namensgebung evtl. 
nicht..
* sm_pr : PROCESS (m_axis_clk) beschreibt dann die states..
* Funktioniert auch soweit ich das nachvollziehen konnte..


1
 SYNC_PROC : PROCESS (m_axis_clk)
2
    BEGIN
3
        IF rising_edge (m_axis_clk) THEN
4
            IF (axi_reset = '1') THEN
5
                current_state <= IDLE; -- its like reset
6
            ELSE
7
                current_state <= next_state;
8
            END IF;
9
        END IF;
10
    END PROCESS SYNC_PROC;
11
    -- connect data
12
    axi_data (63 DOWNTO 0) <= axi_data_content(63 DOWNTO 0); -- axi data
13
    m_axis_tdata <= STD_LOGIC_VECTOR(axi_data); -- data is converted to std logic vector and layed onto signal!
14
    ------------------------------------------------
15
    --- FSM: 
16
    sm_pr : PROCESS (m_axis_clk)
17
    BEGIN
18
        IF (rising_edge (m_axis_clk)) THEN
19
            CASE (next_state) IS
20
                    --- 
21
                WHEN IDLE => -- its like reset
22
23
.
24
.
25
.

von Signalisierer (Gast)


Lesenswert?

current_state wird da nicht mal verwendet xD

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


Lesenswert?

Signalisierer schrieb:
> Was meinst du damit
Man schreibt entweder einen kombinatorischen Prozess ohne Takt, oder 
man schreibt einen synchronen Prozess, wo neben dem Takt 
schlimmstenfalls nur noch ein Reset in der Sensitivliste steht.

Aber man fasst nicht die Kombinatorik und die Register einer 
2-Prozess-Beschreibung hintereinander im selben Prozess zusammen.

Beitrag #7043085 wurde von einem Moderator gelöscht.
von Nils D. (Gast)


Lesenswert?

Man braucht kein next Städte und current state. Es reicht ein state 
signal, was du in deinem synchronen Prozess änderst. Sonst hast du immer 
zwei Zyklen Verzögerung.

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.