Hallo zusammen, mein Problem ist folgendes: Ich habe einen Zustandsautomaten in VHDL programmiert. Wenn sich der Automat nun in einem best. Zustand z.B "zähl" befindet, soll er einen counter auf drücken eines Tasters um eins erhöhen. Da der Automat allerdings mit einer sehr hohen Taktrate läuft (soll auch so bleiben) wird der counter pro Tastendrücken um viele Stellen erhöht. Hat von euch vielleicht jemand eine Lösung für dieses Problem? Ich habe schon überlegt, ob der Automat nach jedem Tastendruck in einen Wartezustand übergehen soll. Nach 50 ms dann wieder zurück. Aber ich wüsste jetzt auch nicht, wie man so etwas umsetzt. Ich wäre euch für jeden Tipp wirklich dankbar, Grüße, Hannes
Nach dem Zustand "zähl" einen Zustand "wart" einfügen, der auf das Loslassen der Taste wartet. Zusätzlich muss aber Dein Taster wahrscheinlich auch noch entprellt werden, am einfachsten extern. Gruß Jörg
@Johannes Ruder >Ich habe einen Zustandsautomaten in VHDL programmiert. Wenn sich der >Automat nun in einem best. Zustand z.B "zähl" befindet, soll er einen >counter auf drücken eines Tasters um eins erhöhen. Da der Automat >allerdings mit einer sehr hohen Taktrate läuft (soll auch so bleiben) >wird der counter pro Tastendrücken um viele Stellen erhöht. Du musst deinen Taster a) entprellen b) einen Einzelpuls erzeugen Geht alles in VHDL mittels Zähler. Mit dem Einzelimpuls kannst du dann deine State Machine füttern. MFG Falk
Nachdem das Tastensignal = 1 ist, gehst du in den Wartezustand. In dem bleibst du solange, wie Tastensignal = 1 gilt. Falls nicht, gehst du zurück in den Zählzustand. Die 50 ms kannst du z.B. warten, indem du einen Zähler hochzählst, der quasi die Takte seit Eintritt in den Zustand zählt. Je nachdem, wie schnell getaktet wird, muss der größer oder kleiner sein. -- stefan
@Stefan Hanke >Nachdem das Tastensignal = 1 ist, gehst du in den Wartezustand. In dem >bleibst du solange, wie Tastensignal = 1 gilt. Falls nicht, gehst du Und hoffentlich prellt der Taster nicht . . . >zurück in den Zählzustand. >Die 50 ms kannst du z.B. warten, indem du einen Zähler hochzählst, der >quasi die Takte seit Eintritt in den Zustand zählt. Je nachdem, wie >schnell getaktet wird, muss der größer oder kleiner sein. Und damit bremst du deine State Machine massiv aus. -> Nicht gut. Wie man es besser macht? Siehe mein anderes Posting. MFG Falk
Falk wrote: > Und hoffentlich prellt der Taster nicht . . . Wird schon schiefgehen ;-) > Und damit bremst du deine State Machine massiv aus. -> Nicht gut. Du meinst das Inkrementieren? OK, stimmt. -- stefan
Vielen Dank für eure schnellen und zahlreichen Antworten!!! Habe gerade die ersten Versuche mit euren Antworten ausprobiert. Beim Drücken einer Taste gehts in einen Wartezustand. Beim Loslassen derselben dann wieder zurück. Der Zähler zählt jetzt während dem Drücken nicht mehr hoch, der Wert erhöht sich aber trotzdem um mehr als eins. Denke das liegt am Prellen des Tasters, wie ihr bereits befürchtet habt. Der Taster ist auf dem Xilinx Starter Board, so dass ich ihn nicht extern Entprellen kann. Wie würdet Ihr denn den Taster in VHDL entprellen und dann einen Einzelimpuls erzeugen? Habe überhaupt keine Vorstellung. Vielen Dank nochmal, Hannes
Da hilft dann meistens Google. http://www.auto.tuwien.ac.at/~schi/LVAs/vhdl_beispiele1a.doc sieht doch ganz gut aus. Kurz: Der asynchrone Eingang wird auf das erste einer Kette von n (hier 3) FFs gelegt. Erst, wenn alle drei den gleichen Wert haben, wird ein Ausgang erzeugt. -- stefan
@Stefan Hanke >http://www.auto.tuwien.ac.at/~schi/LVAs/vhdl_beispiele1a.doc >sieht doch ganz gut aus. Naja . . . >Kurz: Der asynchrone Eingang wird auf das erste einer Kette von n (hier >3) FFs gelegt. Erst, wenn alle drei den gleichen Wert haben, wird ein >Ausgang erzeugt. Dumm nur wenn meine FSM mit 100MHz läuft und der Taster 5 ms prellt. Besser gehts so. Siehe Anhang. MFG Falk
Hallo nochmal, vielen Dank auch wieder für eure Antworten. Der Entpreller von Falk scheint mir sehr vernünftig. Trotzdem funktioniert mein Zustandsautomat leider immer noch nicht. Vielleicht habe ich aber auch einen Denkfehler im Automaten. Er sieht in etwa so aus: entity stateMachine is Port ( clk: in std_logic; button: in std_logic_vector(3 downto 0); switch: in std_logic_vector(7 downto 0); k1: out SIGNED(7 downto 0)); end stateMachine; architecture Behavioral of stateMachine is COMPONENT key_debounce Generic (debounce : integer := 1000); -- number of clks for debounce Port ( key : in std_logic; clk : in std_logic; key_up : out std_logic; key_down : out std_logic); END COMPONENT; type state_type is (st_standby, st_k1); signal state, next_state: state_type; signal k1_i: SIGNED(7 downto 0) := to_signed (-21,16); signal button_reg , button_up, button_down: std_logic_vector(3 downto 0); signal switch_reg : std_logic_vector (7 downto 0); begin KEY_DEBOUNCE0: key_debounce Generic Map (debounce => 1000) Port Map ( key => button_reg(0), clk => clk, key_up => button_up(0), key_down => button_down(0)); SYNC_PROC: process (clk) begin if (clk'event and clk = '1') then state <= next_state; k1 <= k1_i; -- Alle Eingangssignale, die Zustandsübergänge beeinflussen, -- müssen über zusätzliches Flip-Flop switch_reg <= switch; button_reg <= button; end if; end process; --MEALY State Machine - Outputs based on state and inputs OUTPUT_DECODE: process (state, button_down, switch_reg) begin if (state = st_k1) then case button_down(0) is when '1' => k1_i <= k1_i+1; when others => k1_i <= k1_i; end case; end if; end process; ------------------------------------------------------------------------ ------------------- NEXT_STATE_DECODE: process (state, button_down, switch_reg) begin next_state <= state; --default is to stay in current state case (state) is when st_standby => if switch_reg(0) = '1' then next_state <= st_k1; end if; when st_k1 => if switch_reg(0) = '0' then next_state <= st_standby; end if; when others => next_state <= st_standby; end case; end process; end Behavioral; Die eingangsseitige Clock läuft mit 3.125 MHz. k1 wird in einem anderen Modul dann über eine 7-Segmentanzeige ausgegeben. Die Initialisierung mit -21 funktioniert und wird auch richtig angezeigt. Sobald ich dann allerdings die Taste drücke, springt der Wert auf -1. Nochmaliges drücken der Taste ändert jetzt nichts mehr am Wert, der Zustandsautomat ist aber nicht abgestürzt, alles andere funktioniert noch. Ich weiß jetzt echt nicht mehr weiter. Habe das ganze Wochenende versucht, es hinzubekommen. Kann ja eigentlich nicht so schwer sein, oder? Es wäre wirklich sehr nett, wenn ihr mir nochmal weiterhelfen könntet. Grüße, Hannes
@Johannes Ruder >drücken der Taste ändert jetzt nichts mehr am Wert, der Zustandsautomat >ist aber nicht abgestürzt, alles andere funktioniert noch. Ich weiß Naja, diese getrennte Modellierung von Dekoderlogik und Zustandsregistern halte ich für wenig sinnvoll. Aber man kann es so machen. ALlerdings braucht es dazu immer doppelt soviele Variablen, was der Übersicht nicht unbedingt förderlich ist. Dort hast du dich auch verhauen. Hier steckt das Problem. >--MEALY State Machine - Outputs based on state and inputs >OUTPUT_DECODE: process (state, button_down, switch_reg) >begin > if (state = st_k1) then > case button_down(0) is > when '1' => k1_i <= k1_i+1; > when others => k1_i <= k1_i; > end case; > end if; >end process; Hier stecken zwei Fehler drin. 1.) Welchen Wert bekommt k1_i wenn state= st_k1 nicht erfüllt ist? Dort steht nix, also wird ein Latch generiert. -> Schlecht 2.) Du hast dich mit den Variablen verhauen. Das erzeugt wilde kombinatorische Schleifen, das müsste der Compiler eigentlich anmeckern. Siehe unten. OUTPUT_DECODE: process (state, button_down, k1) begin if (state = st_k1) then case button_down(0) is when '1' => k1_i <= k1+1; -- hier war der Fehler, der neue Wert muss immer aus dem alten berechnet werden! when others => k1_i <= k1; -- alten Wert behalten end case; else k1_i <= k1; -- alten Wert behalten end if; end process; Wobei man das sinnvoll anders schreibt OUTPUT_DECODE: process (state, button_down, k1) begin if (state = st_k1) and (button_down(0)='1') then k1_i <= k1+1; else k1_i <= k1; -- alten Wert behalten end if; end process; MfG Falk
Hallo und vielen dank für euren großartigen Support! Habe den Zustandsautomaten jetzt endlich mit eurer Hilfe hinbekommen und viel dabei gelernt! Funktioniert einwandfrei! Vielen Dank! Leider steht bereits das nächste Problem vor der Tür: Mein Design besteht aus mehreren Komponenten, wie z.B ein SPI-Controller, zwei Differenzierer, ein Zustandsregler, eine PWM-Komponente und dem Zustandsautomat! Nun ist mir allerdings schon mehrmals aufgefallen, dass die SPI-Komponente falsche Daten liefert, sobald ich in anderen Komponenten etwas ändere. Wenn ich z.B. den Zustandsautomaten mit einer geringeren Taktrate laufen lasse, gibt die SPI-Komponente falsche Werte aus. Oder wenn ich in statt dem Fehler, den um 12 Bits nach rechts geshifteten Fehler über die PWM-Komponente ausgeben will, liefert die SPI-Komponente falsche Werte. Diese Änderungen haben eigentlich überhaupt nichts mit der SPI-Komponente zu tun. Ich habe allerdings die Vermutung, dass ich mit dem DCM was falsch gemacht habe, da am Ende der Erstellung folgendes ausgegeben wird: WARNING:PhysDesignRules:372 - Gated clock. Clock net sclk_OBUF is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop. WARNING:PhysDesignRules:372 - Gated clock. Clock net SPICONTROLER1/SIMPLESPI1/sck_1 is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop. WARNING:PhysDesignRules:372 - Gated clock. Clock net SPICONTROLER1/SIMPLESPI1/rcv_load is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop. INFO:PhysDesignRules:772 - To achieve optimal frequency synthesis performance with the CLKFX and CLKFX180 outputs of the DCM comp DCM1_1/DCM_INST/DCM1_1/DCM_INST, consult the device Interactive Data Sheet. Im Anhang habe ich die gesamte Ausgabe des Compilers angehängt. Vielleicht sieht ja von euch jemand besser, was ich falsch gemacht habe. Das wäre wirklich super nett! Danke nochmal, Hannes
@ Johannes Ruder >Zustandsautomaten mit einer geringeren Taktrate laufen lasse, gibt die Geringere Taktrate? Lass mich raten, du nimmst einen wilden Teiler + Mux. >Im Anhang habe ich die gesamte Ausgabe des Compilers angehängt. >Vielleicht sieht ja von euch jemand besser, was ich falsch gemacht habe. Das sagt dir der Compiler doch schon. Des Englischen nicht so mächtig? Du verwendest einen Gated-Clock, sprich du schaltest irgendwie deinen Takt mittels kombinatorischer Logik um. Das macht man so nicht. Siehe hier. Beitrag "Clock Switching" MfG Falk
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.