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
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
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;
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.
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.
@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...
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;
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;
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.
Ich bevorzuge die Ein-Prozess-Statemachine.
Deine Aufgabe sieht dann so aus:
1
ifrising_edge(clk)then
2
casezustandis
3
whens0=>zustand<=s1;
4
sort<='0';
5
whens1=>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
endif;
13
sort<='1';
14
whenothers;-- könnte hier stehen
15
endcase;
16
endprocess;
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:
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).
@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
ifrising_edge(clk)then
3
zustand<=folge;
4
if(zustand=S1)counter<=counter+1;
5
elsecounter<=(others=>'0');
6
endif;
7
endif;
8
endprocesserstens;
9
10
zweitens:process(zustand,COUNTER)begin-- ALLE Signale in die Sensitivity-List!!!!!!!
11
casezustandis
12
whens0=>folge<=s1;
13
whens1=>if(counter<3)then
14
folge<=s1;
15
Cout<=counter;-- soll das so sein??
16
else
17
folge<=s0;
18
endif;
19
endcase;
20
endprocesszweitens;
21
22
Drittens:process(zustand)begin
23
casezustandis
24
whens0=>sort<='0';
25
whenothers=>sort<='1';
26
endcase;
27
endprocessDrittens;
Aber ehrlich gesagt: ein halbes Jahr später würde (selbst) ich (selbst)
das nicht mehr kapieren!!!!
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;
@ 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
typezustaendeis(s0,s1);
2
signalzustand:zustaende:=s0;
3
signalfolge:zustaende:=s0;
4
signalcounter:std_logic_vector(2downto0):="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
variablecount:integerrange0to2;
3
begin
4
ifrising_edge(CLK)then
5
ifRESET='1'then
6
count:=0;
7
zustand<=s0;
8
else
9
casezustandis
10
whens0=>OUTPUT2<=conv_std_logic_vector(count,4);
11
count:=count+1;
12
ifcount>2then
13
count:=0;
14
zustand<=s1;
15
else
16
-- mach irgend etwas
17
endif;
18
19
whens1=>OUTPUT2<=conv_std_logic_vector(count,4);
20
zustand<=s0;
21
endcase;
22
endif;
23
endif;
24
endprocess;
Vorher aber den Reset-Eingang wie üblich über zwei FFs auf den CLK
synchronisieren.
@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