Forum: FPGA, VHDL & Co. Zustandsautomat


von VHDL-Beginner (Gast)


Angehängte Dateien:

Lesenswert?

Tag Zusammen,

ich(VHDL Neuling) versuche gerade einen Automaten zu schreiben, der 4
Zustände annehmen soll.
Solange kein reset anliegt, sollen die Zustanände A_Auslesen,
B_Auslesen. C_Auslesen, A_Auslesen,... der Reihe nach ausgeführt
werden.
Da es verschiedene Arten von Automaten gibt, möchte ich wissen, ob
dieser Automat so voll funktionsfähig ist.
Meine zweite Frage wäre: Wie kann ich DIESEN Automaten im Zustand
A_Auslesen starten, wenn ich meine Schaltung mit Strom versorge?

Die Aufgabe des Automaten ist es, 3x8 Bit aus einem UART-Modul
auszulesen und diese einem nachfolgenden Auswertemodul zur Verfügung zu
stellen (Signal Daten_abholen_out="1").

Kann sich jemand dies bitte mal anschauen und mir mögliche Fehler in
diesem Automaten nennen? Habe noch Probleme damit :(

Danke!

von CoolRunner (Gast)


Lesenswert?

Es gibt auch andere Wege aus einem UART-Modul 3 Bytes auszulesen, auch
wenn dieser nur 1Byte am Stück auslesen kann.

Hierfür brauchst du keinen Automaten, sondern ein Register und einen
Zähler.

von VHDL-Beginner (Gast)


Lesenswert?

Danke. Ich bin überzeugt, dass es verschiedene Lösungswege gibt. Wäre
ich so gut in VHDL könnte ich mir selber ein paar Sachen einfallen
lassen. DOch kann ich meine Modelle nicht in die praxis umsetzen,
mangels Kenntisse :(

Ich würde mich sehr freuen, wenn Ihr zu euren Lösungswegen einen
Code-Schnipsel posten würdet oder meine State-Machine euch anschauen
würdet.

Vielen Dank

von VHDL-Beginner (Gast)


Lesenswert?

Hallo nochmals,

ich habe ein paar Fehler herausgefiltert.
Leider komme ich aber nicht mehr weiter.

LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.std_logic_signed.ALL;

---------------------------------------------------------------------
--- ENTITY   Deklaration des Automaten
---------------------------------------------------------------------

entity DATEN_AUSLESEN is
  port (
    CLK        : in std_logic;            -- Takt
    Daten_abholen_in: in std_logic;            -- Signalisiert das
Vorhandensein neuer Daten
    Data_In_8    : in std_logic_vector(7 downto 0);  -- Eingangsdaten 
aus
Receiver-Modul
    Reset      : in std_logic;            -- Resetsignal für
Automat(Zustand=Idle)

    Flag      : out std_logic;          -- Daten abgeholt --> Receiver 
resetten
für neue Daten
    Data_Out_24    : out std_logic_vector(23 downto 0); -- 3x8 Bit a 
Daten
    Daten_abholen_out: out std_logic
    );
end entity DATEN_AUSLESEN;

-------------------------------------------------------------------
-- ARCHITECTURE  Beschreibung des Automaten
-------------------------------------------------------------------

architecture DATEN_AUSLESEN_ARCH of DATEN_AUSLESEN is
   -- States definieren
  type Zustaende is (IDLE, A_AUSLESEN, B_AUSLESEN, C_AUSLESEN);
  attribute enum_encoding : string;
  attribute enum_encoding of Zustaende: type is "00, 01, 10, 11";
  Signal Aktueller_Zustand : Zustaende;
  Signal A :std_logic_vector(7 downto 0);
  Signal B :std_logic_vector(7 downto 0);
  Signal C :std_logic_vector(7 downto 0);

begin

-------------------------------------------------------------------
-- Ermittlung des neuen Zustandes
-------------------------------------------------------------------

    Zustandsfolge : PROCESS( Daten_Abholen_In, Reset )
  begin

    if Reset ='1'
      then Aktueller_Zustand<=IDLE;

    elsif rising_edge(Daten_Abholen_In) then

      CASE Aktueller_Zustand IS

              WHEN A_AUSLESEN =>
          Aktueller_Zustand <= B_AUSLESEN;

        WHEN B_AUSLESEN =>
          Aktueller_Zustand <= C_AUSLESEN;

        WHEN C_AUSLESEN =>
          Aktueller_Zustand <= A_AUSLESEN;

        WHEN IDLE =>
          Aktueller_Zustand <= A_AUSLESEN;

      END CASE;
        END IF;
    END PROCESS;

--------------------------------------------------------
-- Berechnung der Ausgänge
-------------------------------------------------------

OUTPUT: Process (Aktueller_Zustand)
begin

  CASE Aktueller_Zustand is

    WHEN IDLE =>
      A<="00000000";
      B<="00000000";
      C<="00000000";
      Flag<='0';
      Daten_abholen_out<= '0';


    WHEN A_AUSLESEN =>
      A<=Data_In_8;
      Flag<='1';
      Daten_abholen_out<= '0';

    WHEN B_AUSLESEN =>
      B<=Data_In_8;
      Flag<='1';
      Daten_abholen_out<= '0';

    WHEN C_AUSLESEN =>
      C<=Data_In_8;
      Flag<='1';
      Daten_abholen_out<= '1';

  End CASE;
END Process;

END DATEN_AUSLESEN_ARCH;

von VHDL-Beginner (Gast)


Lesenswert?

Hallo nochmals!

Ich habe versucht durch google weitere Foren zu finden, die sich auch
mit VHDL befassen und so belebt wie dieser sind. Leider habe ich keine
ähnlichen gefunden.

Hat einer von euch zufällig ein ähnliches Forum entdckt auch in
englischer Sprache?

Wenn ja, könnt ihr die Adresse posten?

Thanks!

von VHDL-Beginner (Gast)


Lesenswert?

Hallo Leute,

ich würde gerne wissen, wie eine Frage aussehen muss, damit auf diese
eine Antwort erfolgen kann.

Kann es sein, dass ich zu banale Fragen stelle, auf die niemand
antworten möchte?

Ich würde nicht in dieses Forum schreiben, wenn ich weiss, dass auf
VHDL-spezifische Fragen keine Antworten erfolgen. Und diese würde ich
nicht stellen, wenn ich selber eine Antwort drauf parat hätte...

{Kommentar eines Verzweifelten :(   }


Schönen Tag!

von Tobias (Gast)


Lesenswert?

@vhdl_beginner
>Kann es sein, dass ich zu banale Fragen stelle, auf die niemand
>antworten möchte?

Es ist manchmal hilfreich die Fragen zu nummerieren. So kann man auch
gezielt und schnell darauf Antworten.

Ich versuche mal die Fragen zu beantworten:

(1)
>Da es verschiedene Arten von Automaten gibt, möchte ich wissen, ob
>dieser Automat so voll funktionsfähig ist.

Nein


(2)
>Meine zweite Frage wäre: Wie kann ich DIESEN Automaten im Zustand
>A_Auslesen starten, wenn ich meine Schaltung mit Strom versorge?

Indem du im asynchronen Reset dem signal "Zustand" den Wert
A_Auslesen
zuweist.

(3)
>Ich würde mich sehr freuen, wenn Ihr zu euren Lösungswegen einen
>Code-Schnipsel posten würdet oder meine State-Machine euch anschauen
>würdet.

Dieser Automat ist in dieser Form nicht funktionsfähig. Eine
Überarbeitung würde mehr Zeit kosten als ihn komplett neu zu schreiben.
Du versuchst eine Art Mix aus Ein- und Zweiprozess- Zustandsautomat zu
schreiben.


Hier mal ein Beispiel an dem du dich orientieren kannst.

Eingangssignale: sig1_i,sig2_i,clock,reset
Ausgangssignale: sig1_o,sig2_o


type state_type is (IDLE,S1,S2)
signal state_reg,next_state;
signal temp_reg,next_temp;

process (clock) is begin
 if(rising_edge(clock) then
   if(reset = '1')  then
      state_reg <= next_state;
   else
      state_reg <= next_state;
      temp_reg <= next_temp;
   end if;
 end if;
end process;

process (state_reg,sig1_i,sig2_i,temp_reg) is begin
   next_temp <= temp_reg;
   next_state <= state_reg;
   sig1_o <= '0';
   sig2_o <= '0';
 case state_reg is
   when IDLE =>
                if(sig1_i = '1') then
                   next_state <= s1;
                end if;
   when s1   =>
                 sig1_o <= '1';
                if(sig2_i = '1') then
                   sig2_o <= temp_reg;
                   next_state <= s2;
                end if;
   when s2   =>
                if(sig2_i = '1') then
                   next_temp <= '1';
                 end if;
                next_state <= IDLE;

   when others =>
             next_state <= idle;
   end case;
end process;


Versuch mal das ganze in dieser oder ähnlicher Form zu schreiben. Ich
glaube dann wird man auch in diesem Forum  schnell zu einer
funktionsfähigen Lösung kommen.

Mein Lösungsansatz wäre:
4 Zustände (IDLE,WR1,WR2,WR3,OUTPUT)
ein 24 Bit Register in dem die Daten von der UART aufgenommen werden.


Urzustand nach reset: IDLE danach sofortiger Übergang zu WR1
WR1,WR2,WR3: Zustände in denen das 24 Bit Register gefüllt wird.
Zustand OUTPUT auslesen des 24 Bit Registers mit Handshake.

Gruß Tobias















Die einzige "Frage" die ich aus deinem ersten Posting extrahieren
konnte war:
>Kann sich jemand dies bitte mal anschauen und mir mögliche Fehler in
>diesem Automaten nennen? Habe noch Probleme damit :(

In meinen Augen ist das auch keine Frage sondern eine Bitte sich mal
den VHDL Text anzusehen und auf Fehler zu überprüfen.

Jetzt zu deiner "Frage" von deinem zweiten Posting.

>Ich würde mich sehr freuen, wenn Ihr zu euren Lösungswegen einen
>Code-Schnipsel posten würdet oder meine State-Machine euch anschauen
>würdet.

Na klar mach ich doch gerne.

In deinem Code benutzt du für den Zustandsübergang das Signal
Daten_Abholen_In und bestimmst in dem Prozess auch noch den
Folgezustand. Für getaktete Prozesse benutze für die Zustandszuweisung
das Taktsignal "clk".
CLK sowie Data_Out_24 wird überhaupt nicht benutzt.


entity DATEN_AUSLESEN is
  port (
    CLK              : in std_logic;            -- Takt
    Daten_abholen_in : in std_logic;
    Data_In_8        : in std_logic_vector(7 downto 0);  --
    Reset            : in std_logic;
    Flag             : out std_logic;          -- Daten abgeholt -->
    Data_Out_24      : out std_logic_vector(23 downto 0); -- 3x8 Bit a
    Daten_abholen_out: out std_logic
    );
end entity DATEN_AUSLESEN;

von Tobias (Gast)


Lesenswert?

Ein bisschen zuviel geschickt. Der untere Teil gehört nicht mehr zum
Posting

Gruß Tobias

von VHDL-Beginner (Gast)


Lesenswert?

Hi Tobias

Das hilft mir bestimmt weiter.

Vielen herzlichen Dank!

von VHDL-Beginner (Gast)


Lesenswert?

Hi,

ich habe an meiner FSM weitergearbeitet, Trotz mehrerer Änderungen
bekomme ich Sie dennoch nicht sauber zum Laufen.

Kann bitte hier jemand mal einen Blick reinwerfen und mir sagen, was
hier falsch läuft, bzw. wie es aussehen müsste?

Danke!




LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.std_logic_signed.ALL;

---------------------------------------------------------------------
--- ENTITY   Deklaration des Automaten
---------------------------------------------------------------------

entity DATEN_AUSLESEN is
  port (
    Clk        : in std_logic;            -- Takt
    Daten_abholen_in: in std_logic;            -- Signalisiert das
Vorhandensein neuer Daten
    Data_In_8    : in std_logic_vector(7 downto 0);  -- Eingangsdaten 
aus
Receiver-Modul
    Reset      : in std_logic;            -- Resetsignal für
Automat(Zustand=Idle)

    Flag      : out std_logic;          -- Daten abgeholt --> Receiver 
resetten
für neue Daten
    Data_Out_24    : out std_logic_vector(23 downto 0); -- 3x8 Bit a 
Daten
    Daten_abholen_out: out std_logic
    );
end DATEN_AUSLESEN;

-------------------------------------------------------------------
-- ARCHITECTURE  Beschreibung des Automaten
-------------------------------------------------------------------

architecture ARCH of DATEN_AUSLESEN is
  -- States definieren
  type Zustaende is (IDLE, A_AUSLESEN, B_AUSLESEN, C_AUSLESEN);
  Signal Naechster_Zustand : Zustaende;
  Signal A,B,C :std_logic_vector(7 downto 0);

begin

-------------------------------------------------------------------
-- Ermittlung des neuen Zustandes
-------------------------------------------------------------------

    Zustandsfolge : PROCESS( Daten_Abholen_In, Reset, Clk )
  begin

    if (Reset ='0')
      then Naechster_Zustand<=IDLE;

    elsif rising_edge(Daten_Abholen_In) then

      CASE Naechster_Zustand IS

        WHEN IDLE =>
          Naechster_Zustand <= A_AUSLESEN;

              WHEN A_AUSLESEN =>
          Naechster_Zustand <= B_AUSLESEN;

        WHEN B_AUSLESEN =>
          Naechster_Zustand <= C_AUSLESEN;

        WHEN C_AUSLESEN =>
          Naechster_Zustand <= A_AUSLESEN;

        WHEN others =>
          Naechster_Zustand <= IDLE;

      END CASE;
        END IF;
    END PROCESS;

--------------------------------------------------------
-- Berechnung der Ausgänge
-------------------------------------------------------

OUTPUT: Process (Naechster_Zustand)
begin

  CASE Naechster_Zustand is

    WHEN IDLE =>
      A<="00000000";
      B<="00000000";
      C<="00000000";
      Flag<='0';
      Daten_abholen_out<= '0';


    WHEN A_AUSLESEN =>
      A<=Data_In_8;
      Flag<='1';
      Daten_abholen_out<= '0';

    WHEN B_AUSLESEN =>
      B<=Data_In_8;
      Flag<='1';
      Daten_abholen_out<= '0';

    WHEN C_AUSLESEN =>
      C<=Data_In_8;
      Flag<='1';
      Daten_abholen_out<= '1';

  End CASE;
END Process;

END ARCH;

von Xenu (Gast)


Lesenswert?

Zwei Punkte:

1. Alles was getaktet wird (d.h. alles was Flip-Flops darstellt),
sollte mit dem Systemtakt (clk) getaktet werden. Du nimmst aber
"Daten_Abholen_In" als Takt für Deinen Automaten. Benutze dieses
Signal als Taktfreigabesignal:

  elsif rising_edge(clk) then
    if(Daten_Abholen_In = '1') then
      -- blabla
    end if;
  end if;

Dann musst Du aber sicherstellen dass "Daten_Abholen_In" auch nur für
einen clk-Zyklus auf '1' ist.

2. Der zweite Prozess beschreibt Latches (= pegelgesteuerte
Flip-Flops). Ich bezweifle dass Du das willst. Falls die Signale die
dort vorkommen rein kombinatorische Logik darstellen sollen, musst Du
jedem Signal auch in jedem when-Abschnitt auch etwas zuweisen.
Falls Du Flip-Flops daraus machen willst, musst Du das ganze in einen
"if rising_edge(clk)"-Block einbetten.

von VHDL-Beginner (Gast)


Lesenswert?

Leider ist das Daten_Abholen_In so lange auf High, bis ich diesen mit
dieser State-Machine auf Low setze, d.h mit Flag=1 wird es wieder
asynchron resettet.

Daten_Abholen_In geht auf High, wenn Daten zum Abholen bereitstehen.
Damit man weitere Daten erwarten und abholen kann, muss der Automat,
der dieses Signal(Daten_Abholen_In) steuert resettet werden

von Xenu (Gast)


Lesenswert?

Du kannst aus jedem Signal das längere Zeit auf '1' liegt eins
machen,
das für einen clk-Zyklus auf '1' liegt. Das ist sozusagen eine
Standard-Problem.

Dafür machst Du Dir einfach eine zweiten Automaten:

---------------------------------------------------
process(reset,clk)
begin

if(reset = '0') then

  state <= s0;

elsif(rising_edge(clk)) then

  case state is

    when s0 =>
      if(Daten_Abholen_In = '0') then
        state <= s1;
      end if;

    when s1 =>
      if(Daten_Abholen_In = '1') then
        state <= s2;
      end if;

    when s2 =>
      state <= s0;

  end case;

end if;
end process;
---------------------------------------------------
  sig_one <= '1' when (state = s2) else '0';
---------------------------------------------------


Anstatt "Daten_Abholen_In" kannst Du jetzt "sig_one" als
Taktfreigabe benutzen.

von VHDL (Gast)


Lesenswert?

Super nett von dir. Danke Xenu!

von Daniel R. (daniel_r)


Lesenswert?

Das halte ich für keine gute Idee.
Besser ist es, die Signale gleich bei ihrer "Entstehung" so zu
generieren, dass sie nur einen Takt lang high sind. Das dürfte kein
Problem sein, kostet weniger Resourcen und ist einfacher.

Daniel

von VHDL-Beginner (Gast)


Lesenswert?

Da hast du ja vollkommen Recht damit, aber ich verwende ein fertiges
Core, welches mir leider ein Signall, dass mehrere Takte lang ist
bereitstellt.
Es würde viel mehr Zeit und Arbeit kosten, dieses Core zu ändern,
anstelle ein neues zu designen.

Ich weiss aber immer noch nicht so recht, ob mir weitere Arbeiten mit
dem alten Core auch bei den nächsten Programmschritten Schwierigkeiten
bereiten würden. Muss diese mal klarstellen.

Resourcen sind zur Zeit das kleinste Problem.

von Daniel R. (daniel_r)


Lesenswert?

OK, dann ist Xenu's Lösung vollkommen in Ordnung.

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.