Forum: FPGA, VHDL & Co. FSM Problem(Ein zustand als Taktverzögerung)


von VHDL_Bginner (Gast)


Lesenswert?

Hallo zusammen!
Ich habe wieder ein Problem mit einem Zustandsautomat.Ein zustand will 
ich als eine 30 ns Taktverzögerung verwenden.Das heisst ich muss die 
zahl 3 da definieren und mit jedem clock(100 MHz)wird der zahl 
dekrementiert(!=0=>im aktuellen zustand bleiben) wenn ich die Null 
erreiche, dann kann ich zum nächsten zustand springen.Aber das programm 
macht total was anders sogar kann es die zahl auch nicht 
dekrementieren.Ich haoffe dass jemand mir bei diesem Problem helfen 
könnte.)ISE webpack(9.2i & 10.1).
MFG

von Mark (Gast)


Lesenswert?

@VHDL_Bginner

es wäre hilfreich, wenn Du den VHDL-Code mal posten würdest, oder willst 
Du gleich die fertige Lösung von jemand anders haben?

von Neuling_1 (Gast)


Lesenswert?

MARK!Es ist nett von Dir,dass du schnell darauf antwortest.Ich denke 
mein problem habe ich richtig beschrieben und wenn man sorgar keine 
Ahnung in VHDL kann er es verstehen denke ich mal.Das Problem haengt 
nicht davon ab wie man es in VHDL schreiben kann,Aber meine frage ist 
sowas in Hardware realisierbar.
Und hier ein code stück extra für Dich für 2 zustände aber die frage für 
Alle selbsverständlich:
begin
:
signal counter:std_logic_vector(2 downto 0):="000";
Eins:process(clk)  --Aktualisierung
begin
:
if rising_edge(clk) then
State_nxt<=S0;
end if;
end process(Eins);
zweitens;process(zustand)
begin
case zustand is
when s0 => state_nxt<=s1;      --counter ist schon initialisiert
when s1  => counter<=counter+1;-- hier ist eine Inkrementierung)
            if counter<4 then  --wieso counter zaehlt nicht hoch?
            state_nxt<=s1;--wenn ich ein extra zustand definiere wird
            end if;      --inkrementiert aber wenn ich so definiere
                         --macht er gar nichts
             else
            state_nxt<=s0;
end case;
end process zweitens;
:
Für jede Hilfe bin ich sehr Dankbar.
MFG

von Neuling_1 (Gast)


Lesenswert?

sorry!ich habe mich vertippt.im ersten prozess statt state_nxt<=s0 muss 
state_current<=state_nxt sein.

von Rick Dangerus (Gast)


Lesenswert?

Bau Dir eine Testbench dazu und teste das im Simulator!
Außerdem mußt Du dafür sorgen, das Dein counter auch mal wieder 
zurückgesetzt wird.

Rick

von Joachim S. (joachims)


Angehängte Dateien:

Lesenswert?

Eine Möglichkeit währe z.B.:
es wird nun jeder State um 3 Takte verzögert, ich habe allerdings die 
Statemachine hier in if else ausgeführt, das geht auch mir switch
und mit Signalen.
Ich bin selbst allerdings Anfänger (VHDL) und würde mich über
kommentare der VHDL Cracks freuen !

Gruß Joachim



library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity FSM is
 Port (  RESET   : IN std_logic;
      CLK      : IN std_logic;
      OUTPUT   : OUT std_logic_vector(3 downto 0)
    );
end FSM;
architecture Behavioral of FSM is
begin

process (RESET,CLK)
variable count   : integer range 0 to 2;
variable zustand  : integer range 0 to 3;
begin

  if RESET = '1' then
    count := 0;
  elsif rising_edge(CLK) then
  count := count +1;
    if count > 2 then
      count := 0;
      if zustand = 0 then
        OUTPUT <= "0001";
        zustand :=  zustand + 1;
      elsif zustand = 1 then
        OUTPUT <= "0010";
        zustand :=  zustand + 1;
      elsif zustand = 2 then
        OUTPUT <= "0100";
        zustand :=  zustand + 1;
      elsif zustand = 3 then
        OUTPUT <= "1000";
        zustand := 0;
      end if;
    end if;
  end if;
end process;
end Behavioral;

von Neuling_1 (Gast)


Lesenswert?

Hallo Joachim.Aber was Du da geschrieben hast ist ein 3 takt verzögerung 
für jeden zustand aber das will ich nicht.Mein problem liegt darin,dass 
Du 3 states hast nehmen wir an!und in einem  einzelnen State willst du 
eine verzögerung von 40 ns Z.B(clock 100MHz).Also in einem zustand musst 
Du ein defaultwert definieren fuer dein Counter und je nachdem wie Du 
den zähler zählen(ink. oder dekr.) willst .Counter hat den max oder min 
wert nicht erreicht bleibt in demselben zustand(UND HIER IST MEIN 
PROBLEM)sonst naechsten zustand wird erreicht.

von Neuling_1 (Gast)


Angehängte Dateien:

Lesenswert?

Hallo again!Hier ist ein source code Beispiel mit einem Testbench der 
mein problem zeigt.Cout ist als counter Pin für die Visualisierung.Aber 
bei der simulation kriege ich kein counter inkrementierung.

von Start-ING (Gast)


Lesenswert?

@neuling1
da das offensichtlich nicht Dein richtiger Code ist, denn er ist absolut 
nicht synthesefähig, können wir Dir bei Deinem Problem auch nur schlecht 
weiterhelfen. Der Fehler kann nahezu überall liegen. es geht los mit 
syntaxfehlern, fehlenden Signalen in der sensitivity list oder 
ähnlichem. Prinzipiell ist es recht leicht möglich, sowas zu 
realisieren...

von Neuling_1 (Gast)


Lesenswert?

Du hast recht:-)sorry aber hier ist der richtige Code:Diese Problem hat 
mich richtig geärgert.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity TEST is
port(clk:in std_logic;
     sort:out std_logic;
    Cout:out std_logic_vector(2 downto 0)
    );
end TEST;

architecture Behavioral of TEST is
type zustaende is (s0,s1);
signal zustand:zustaende:=s0;
signal folge:zustaende:=s0;
signal counter:std_logic_vector(2 downto 0):="000";

begin
erstens:process(clk)
begin
if rising_edge(clk) then
zustand<=folge;
end if;
end process erstens;
zweitens:process(zustand)
begin
case zustand is
when s0 => folge<= s1;
when s1 => counter<=counter+1;
           if counter<3 then
            folge<=s1;
     Cout<=counter;
           else
             folge<=s0;
      counter<=(others=>'0');
   end if;
end case;
end process zweitens;
Drittens:process(zustand)
begin
case zustand is
when s0 => sort<='0';
when others => sort<='1';
end case;
end process Drittens;


end Behavioral;

von lkmiller (Gast)


Lesenswert?

@Neuling_1

Was für ein Code und welche Testbench gehört zu der Waveform?

von Neuling_1 (Gast)


Angehängte Dateien:

Lesenswert?

Hier ist die Code + Testbench

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity TEST is
port(clk:in std_logic;
     sort:out std_logic;
    Cout:out std_logic_vector(2 downto 0)
    );
end TEST;

architecture Behavioral of TEST is
type zustaende is (s0,s1);
signal zustand:zustaende:=s0;
signal folge:zustaende:=s0;
signal counter:std_logic_vector(2 downto 0):="000";

begin
erstens:process(clk)
begin
if rising_edge(clk) then
zustand<=folge;
end if;
end process erstens;
zweitens:process(zustand)
begin
case zustand is
when s0 => folge<= s1;
when s1 => counter<=counter+1;
           if counter<3 then
            folge<=s1;
     Cout<=counter;
           else
             folge<=s0;
      counter<=(others=>'0');
   end if;
end case;
end process zweitens;
Drittens:process(zustand)
begin
case zustand is
when s0 => sort<='0';
when others => sort<='1';
end case;
end process Drittens;


end Behavioral;

von lkmiller (Gast)


Lesenswert?

Sowas:
1
:
2
counter<=counter+1;
3
:
darf nur in einem getakteten Prozess stehen.
Sonst gibt das eine kombinatorische Schleife.


In deinem Fall hat der Simulator Glück und reagiert nicht mehr auf eine
Änderung von counter, weil der nämlich in der sensitivity-list fehlt.

Wenn du den korrekterweise einfügst
1
:
2
zweitens:process(zustand,counter)
3
:
dann hängt der Simulator sich genauso auf wie deine Hardware.

Also:
Zähler immer taktabhängig.

von lkmiller (Gast)


Lesenswert?

Ich bevorzuge die Ein-Prozess-Statemachine.
Deine Aufgabe sieht dann so aus:
1
if rising_edge(clk) then
2
  case zustand is
3
     when s0 => zustand <= s1;
4
                sort    <= '0';
5
     when s1 => counter <= counter+1;
6
                if (counter<3) then
7
                   zustand <= s1;
8
                   Cout    <= counter;   -- Fehler? Cout wird nur hier aktualisiert!!
9
                else
10
                   zustand <= s0;
11
                   counter <= (others=>'0');
12
                end if;
13
                sort <= '1';
14
     when others ; -- könnte hier stehen
15
  end case;
16
end process;

Hier steht nur der Clock in der Sensitivity-List.
Ist irgendwie lesbarer als die Zwei- oder gar
Drei-Prozess-Schreibweise.
Man muß sich nur daran gewöhnen, dass sich hier
irgendwo ein Takt Latency einschleichen könnte,
aber Denken hält jung.

Alternativ könnte ich Schreiben:
1
if rising_edge(clk) then
2
  case zustand is
3
     when s0 => zustand <= s1;
4
     when s1 => counter <= counter+1;
5
                if (counter=3) then
6
                   zustand <= s0;
7
                   counter <= (others=>'0');
8
                end if;
9
  end case;
10
end process;
11
12
-- concurrent Zuweisungen
13
Cout <= counter;   
14
sort <= '0' when zustand=s0 else '1';

von Neuling_1 (Gast)


Lesenswert?

Danke schön für Deine Antwort.Du hast die ein prozessdarstellung 
verwendet.meine Frage:ist es nicht realisierbar wenn ich die 3 prozess 
darstellung benutze.IN dieser darstellung hab ich ein prozess für 
zustandsregister und zweiter für zustandübergänge und dritter für die 
Augänge.Bis jetzt ich weiss nicht woran liegt mein Fehler.In meinem Code 
werd ich mein state S1 natürlich mit einem positiven flanke erreichen 
und wenn ich drin bin muss counter inkrementiert werden. Also brauche 
ich keine zusätzliche takte für die Anweisungen was ich drin im meinem 
zustand definiert habe.(Device ist cpld coolrunnerII).

von lkmiller (Gast)


Lesenswert?

@Neuling_1
Du hast ein Verständnisproblem.

Zur Vereinfachung: ein Counter hat mehrere stabile Zustände und ist 
daher eine State-Machine (und umgekehrt).

Wenn du aber für eine State-Machine einen getakteten Prozess für die 
Übernahme des Folgezustands brauchst, dann brauchst du auch für das 
Weiterschalten des Counters einen getakteten Prozess.

Ins Unreine geschrieben könnte das evtl. so aussehen:
1
erstens:process(clk) begin
2
  if rising_edge(clk) then
3
    zustand <= folge;
4
    if(zustand=S1)  counter <= counter+1; 
5
    else            counter <= (others=>'0');
6
    end if;
7
  end if;
8
end process erstens;
9
10
zweitens:process(zustand, COUNTER) begin -- ALLE Signale in die Sensitivity-List!!!!!!!
11
  case zustand is
12
    when s0 => folge   <= s1;
13
    when s1 => if (counter<3) then
14
                  folge   <= s1;
15
                  Cout    <= counter; -- soll das so sein??
16
               else
17
                  folge   <= s0;
18
               end if;
19
  end case;
20
end process zweitens;
21
22
Drittens:process(zustand) begin
23
  case zustand is
24
     when s0 =>     sort<='0';
25
     when others => sort<='1';
26
  end case;
27
end process Drittens;

Aber ehrlich gesagt: ein halbes Jahr später würde (selbst) ich (selbst) 
das nicht mehr kapieren!!!!

von Joachim S. (joachims)


Angehängte Dateien:

Lesenswert?

Weshalb möchtest Du denn 3 Prozesse ?
Kannst Du das Problem Beschreiben ohne deine eigenen
Lösungsansätze in Spiel zu bringen?

So ganz Verstanden hab ich ja nicht was Du vorhast, aber eine 
Statemachine
in der ein Zustand um n Takt Counts verzögert wird, das ist auch so 
machbar:




library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;


entity stateTest2 is
 Port (  RESET   : IN std_logic;
      CLK      : IN std_logic;
      OUTPUT2   : OUT std_logic_vector(3 downto 0)
    );
end stateTest2;
architecture Behavioral of stateTest2 is
type zustaende is (s0,s1);
signal zustand:zustaende:=s0;

begin

process (RESET,CLK)
variable count   : integer range 0 to 2;

begin

  if RESET = '1' then
    count := 0;
    zustand <= s0;
  elsif rising_edge(CLK) then
    case zustand is
          when s0 =>   OUTPUT2 <= conv_std_logic_vector(count,4);
                  count := count +1;
                  if count > 2 then
                    count := 0;
                    zustand <= s1;
                  else
                    -- mach irgend etwas
                  end if;

          when s1 =>   OUTPUT2 <=conv_std_logic_vector(count,4);
                  zustand <=s0;
    end case;
  end if;
end process;
end Behavioral;

von lkmiller (Gast)


Lesenswert?

@ Joachim Schäfer

Ja, jetzt aber auch, wo kommt denn jetzt auf einmal der Reset her?

Als kleine Gedankenstütze:
ein FPGA braucht keinen Reset, das ist nach dem Laden schon definiert.
Z.B. so wie's Neuling_1 gemacht hat:
1
type zustaende is (s0,s1);
2
signal zustand:zustaende:=s0;
3
signal folge:zustaende:=s0;
4
signal counter:std_logic_vector(2 downto 0):="000";
Einen Reset-Eingang braucht nur der Entwickler für seinen Reset-Knopf.



Aber wenn schon ein Reset, dann bitte synchron.
Was haben wir schon für Dinge mit asynchronen Signalen erlebt...
Und ein Reset ist das Asynchronste überhaupt.
Dieser globale Reset mit seinem globalen Reset-Netzwerk kann
dir z.B. mit einem kleinen Spike das halbe FPGA zurücksetzen,
aber die andere Hälfte nicht.
Und das gibt lustige Fehler: jedesmal einen anderen.

Warum nicht so (wir alle lieben synchrone Designs):
1
process (RESET,CLK)
2
variable count   : integer range 0 to 2;
3
begin
4
  if rising_edge(CLK) then
5
    if RESET = '1' then
6
      count := 0;
7
      zustand <= s0;
8
    else
9
      case zustand is
10
          when s0 =>   OUTPUT2 <= conv_std_logic_vector(count,4);
11
                  count := count +1;
12
                  if count > 2 then
13
                    count := 0;
14
                    zustand <= s1;
15
                  else
16
                    -- mach irgend etwas
17
                  end if;
18
19
          when s1 =>   OUTPUT2 <=conv_std_logic_vector(count,4);
20
                  zustand <=s0;
21
      end case;
22
    end if;
23
  end if;
24
end process;
Vorher aber den Reset-Eingang wie üblich über zwei FFs auf den CLK 
synchronisieren.

von Joachim S. (joachims)


Lesenswert?

@lkmiller
Danke, ich hab ja in nem Beitrag weiter oben schon geschrieben, das ich 
noch nicht viel Erfahrung mit VHDL habe.
Ja den Reset braucht man hier sicher nicht, aber in der Simulation habe 
ich es schon benötigt um definierte Ausgangszustäbde zu bekommen.
Warscheinlich hätte ich das damals dort auch anders machen können aber
na ja wie gesagt ich lerne noch!
Auch der Tipp mit dem Syncronen Reset und den Folgefehlern
die entstehen könne , ist sehr interresannt.
Ja als Softwareentwickler muss mann mit dem parallelen Ablauf im FPGA
schon umdenken !

Gruß joachim

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.