Forum: FPGA, VHDL & Co. VHDL: kurzen Impuls halten, um State Machine zu steuern


von Klaus (Gast)


Lesenswert?

Hi,

ich habe in VHDl eine State Machine mit zwei Prozessen gebaut.
Der erste ist getaktet und schaltet vom alten zum neuen state. Der 
andere ist ungetaktet und definiert die Ausgänge im jeweiligen state.

Ich habe jetzt einen idle state, der wartet bis irgendwas passiert. Bis 
jetzt war das das Signal von einem Taster. Wenn dieses 1 wurde, ist die 
state machine angelaufen. Soweit so gut.

Jetzt möchte ich den Taster ersetzen. Eine andere Komponente schickt 
dabei für einen Takt lang (beide Komponenten laufen auf dem gleichen 
Takt) einen Impuls. Mit diesem Impuls soll meine state machine starten. 
Wenn ich jetzt einfach in meinem idle state
1
if impuls = '1' then
2
   state_neu <= next_state;
3
else
4
   state_neu <= idle;
5
end if;

so abfrage, dann kann es ja passieren, dass der neue state nicht 
übernommen wird, weil der Impuls nicht während einer steigenden Flanke 1 
ist.


Mein Ansatz war jetzt, dass ich in einem extra Prozess die steigende 
Flanke des externen Impulses abfrage, damit dann ein Signal setze 
(dieses wird dann im idle state auf 1 geprüft) und dieses Signal erst 
zurücksetze, wenn meine state machine auch wirklich im nächsten Zustand 
ist.


Die Umsetzung bereitet mir allerdings Probleme. Mein grober Plan sieht 
so aus:
1
process (rdy)
2
begin
3
if rising_edge(rdy) then
4
   start <= '1';
5
elsif state = w2 then
6
   start <= '0';
7
end if;
8
end process;


Allerdings habe ichd ann ein Problem, dass das Signal laut Fehlermeldung 
nicht gehalten wird. Eine Zurücksetzung im getakteten Teil der state 
machien geht ja auch nicht wegen dem multiple driver Problem.

Kann mir da jemand bitte helfen?

Beste Grüße

von Johannes O. (jojo_2)


Lesenswert?

Poste mal mehr Code.
Was ist dein Signal rdy? Ist das ein clock? Schau dir mal an, für was 
man rising_edge verwenden soll und für was nicht.


Du hast also zwei Prozesse, einen ungetakteten und einen getakteten. Du 
schreibst was von Taster.
Ich gehe mal davon aus, dass dein Clock DEUTLICH schneller ist als du 
auf den Taster drücken kannst. Dann mach am besten beide Prozesse 
synchron zum Takt. Dann wärs doch deutlich einfacher!

von Klaus (Gast)


Lesenswert?

Das Signal rdy kommt von meinem FIR Filter. Dieser Filter läuft mit 4MHz 
und deshalb ist das rdy signal auch eine Taktperiode des 4MHz Taktes 
lang 1. Das Signal rdy widerholt sich mit einer Frequenz von 16kHz.

Die Daten des FIR Filters sollen dann in einem RAM gespeichert werden. 
Dafür die State machine.


Das ist mein getakteter Prozess. Er läuft mit der gleichen Frequenz wie 
der FIR Filter. cnt ist ein counter, der eine gewisse zeit wartet, bis 
er vom init ind en idle Zustand wechselt. in state w5 wird die Adresse 
hochgezählt.
1
  process (CLKRAM)
2
  begin
3
    if rising_edge(CLKRAM) then
4
      statealt <= stateneu;
5
      
6
      case statealt is
7
        when init => cnt <= cnt + 1;
8
        
9
        when w5 => addr <= std_logic_vector(unsigned(addr) + 1);
10
        when idle => cnt <= 0;
11
        
12
        when others => null;
13
      end case;
14
    end if;
15
  end process;

Das folgende sind dann meine states. Die Zuweisungen sind uninteressant 
und deswegen xx <= xx. Wichtig ist state idle, der zu w1 wechselt, wenn 
der entprellte Button BTNd(0) gedrückt wird. Das war auch kein Problem, 
da man ja länger als 250ns auf den Button drückt und das auch auf jeden 
Fall die steigende Flanke von CLKRAM erkennt.

Ich möchte jetzt aber BTNd(0) durch das signal rdy ersetzen, welches nur 
250ns lang ist. Wie kann ich sicherstellen, dass es auch vom getakteten 
prozess erkannt wird (Periodendauer auch 250ns) und somit mein state 
idle zu w1 wechselt?
1
  WRITE: process (BTNd(0),statealt,cnt,DATA,addr)
2
  begin
3
    case statealt is
4
      when init =>    xx <= xx --zuweisungen
5
                      if cnt > 500 then
6
                        stateneu <= idle;
7
                      else
8
                        stateneu <= init;
9
                      end if;
10
            
11
        when idle =>  xx <= xx --zuweisungen
12
                      if BTNd(0) = '1' then
13
                        stateneu <= w1;
14
                      else
15
                        stateneu <= idle;
16
                      end if;
17
  
18
        when w1 =>    xx <= xx --zuweisungen
19
                      stateneu <= w2;
20
21
        when w2 =>    xx <= xx --zuweisungen
22
                      stateneu <= w3;
23
24
        when w3 =>    xx <= xx --zuweisungen
25
                      stateneu <= w4;
26
27
        when w4 =>    xx <= xx --zuweisungen
28
                      stateneu <= w5;
29
                      
30
        when w5 =>    xx <= xx --zuweisungen
31
                      stateneu <= idle;
32
  
33
        when others =>  xx <= xx --zuweisungen
34
                            stateneu <= idle;
35
        
36
  end case;
37
end process;

: Bearbeitet durch Moderator
von Alexander F. (alexf91)


Lesenswert?

Tritt tatsächlich ein Problem auf?
Wenn beide Komponenten den gleichen Takt haben, dann sollte das schon 
funktionieren.
Die Synthesetools sind ja im Allgemeinen auch nicht dumm.

von Klaus (Gast)


Lesenswert?

Hmm ich habe es ehrlich gesagt noch nicht getestet, weil ich davon 
ausgegangen bin, dass es dann ab und zu klappt und ab und zu nicht. Je 
nachdem ob rdy zur rising edge schon 1 ist oder eben nicht. Wollte da 
eigentlich auf Nummer sicher gehen. Oder ist das wirklich ohne Probleme 
umsetzbar?

von Hunz (Gast)


Lesenswert?

Das Synthesetool sorgt dafür dass alle synchronen Prozesse zur gleichen 
Zeit/Taktflanke schalten. Laufzeiten im Chip werden dabei berücksichtigt 
und solange das Timing (max. Taktfrequenz <> Laufzeiten) eingehalten 
wird sollte es auch funktionieren. Dies bedeutet dass alle Prozesse 
gültige Daten "sehen" - du musst daher nicht manuell was dazu beitragen.

Anders sieht es aus wenn asynchrone Eingangssignale direkt in der FSM 
abgefragt werden. Dies kann dann sehr wohl zu undefinierten 
Zustandsübergängen führen, weshalb man die externen Signale zuerst 
einsychronisieren sollte.

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


Lesenswert?

Klaus schrieb:
> Je nachdem ob rdy zur rising edge schon 1 ist oder eben nicht. Wollte
> da eigentlich auf Nummer sicher gehen. Oder ist das wirklich ohne
> Probleme umsetzbar?
Das Grundprinzip jedes synchronen Designs ist so: nach einer Taktflanke 
herrscht im FPGA große Unruhe. Neue Zählerstände werden berechnet, Logik 
ermittelt aktuelle Werte und die Folgezustände von FSM werden berechnet. 
Und rechtzeitig vor der nächsten Taktflanke müssen die Werte wieder 
stabil sein. Denn dann kommt wieder der Takt und das Spiel geht von 
vorne los.

Und deshalb sollte es im Idealfall nur 1 Takt im Sytem geben, und immer 
auf die selbe Flanke dieses Taktes reagiert werden.

Wenn rdy mit dem selben Takt erzeugt und ausgewertet wird, dann geht da 
nichts schief, wenn du ein Constraint auf den Eingangstakt gesetzt hast.

BTW: wie wird der CLKRAM erzeugt? Und wie viele andere Takte hast du 
noch in deinem Design?

von Chris (Gast)


Lesenswert?

Alles klar, das klingt alles sehr logisch und räumt meine Zweifel aus. 
Zwischenzeitlich hatte ich , um auf Nummer sicher zu gehen, den Takt 
meiner State Machine auf 10Mhz erhöht um auf Nummer sicher zu gehen.

Ich arbeite teilweise schon mit unterschiedlichen Takten. Dazu habe ich 
mittels dem Clocking Wizard von Xilinx einen IP Core erstellt und 
erzeuge mir aus 100MHz dann 10 und 4 MHz. Sind hier mehrere Takte 
wirklich schädlich? Ich hatte eventuell vor noch mehrere Takte zu 
implementieren...

von alex (Gast)


Lesenswert?

Chris schrieb:
Sind hier mehrere Takte
> wirklich schädlich? Ich hatte eventuell vor noch mehrere Takte zu
> implementieren...

Wofür genau?

von Klaus (Gast)


Lesenswert?

Sorry, habe mit dem Laptop von meinem Kollegen nebenan geantwortet und 
nicht auf den Namen geachtet!

von Klaus (Gast)


Lesenswert?

alex schrieb:
> Chris schrieb:
> Sind hier mehrere Takte
>> wirklich schädlich? Ich hatte eventuell vor noch mehrere Takte zu
>> implementieren...
>
> Wofür genau?



Ich möchte das System mit mehreren Takten testen und deswegen möchte ich 
später einen IP Core haben, der 100, 80, 40, 20, 10 und 4 MHz ausgibt 
und ichd ann flexibel wählen kann. Je nach Anwendung würde ich 
vielleicht 3 Takte verwenden.
Am Eingang ein System mit dem hohen Takt, dann wird dezimiert(clk des 
CIC cores wäre gleich), der FIR Filter läuft dann wohl mit 4 MHz und den 
RAM würde ich immer mit 10 MHz betreiben wollen.

von Duke Scarring (Gast)


Lesenswert?

Klaus schrieb:
> der 100, 80, 40, 20, 10 und 4 MHz ausgibt
> und ichd ann flexibel wählen kann.
Dann muß Dein Design mit maximal 100 MHz laufen können. Ich verwende ein 
'enable' was mir gültige Daten anzeigt. Wenn die Daten nur mit 10 MHz 
anfallen, dann ist das 'enable' auch nur alle 10 Takte mal auf '1'. 
Trotzdem brauche ich nur einen Takt im System: den Schnellsten.

Duke

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.