Forum: FPGA, VHDL & Co. Zwei Taktflanken synchronisieren


von chris (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

kurze Frage an die VHDL Profis. Wie kann ich in meinem Programm s.o. die 
fallenden Taktflanken CLK_1_MHZ und INIT_BUTTON synchronisieren und dann 
beim Zutreffen der Bedingung RW_INIT auf gleich 1 setzten?
Also wenn INIT_BUTTON gleich 1 ist soll dessen fallende Flanke den 
Zustand Y1 bereitsstellen. Im Zustand Y1 sollte dann in der If Abfrage 
durch einen Zwischenwert ZW_ZUSTAND solange gewartet werden bis dieser 
Aufgrund von falling_edge (CLK_1_MHZ) wahr ist. Anschließend wird der 
Zustand Y2 zugewiesen und RW_INIT wird auf gleich 1 gesetzt. So richtig 
funktioniert es nicht und es ist auch sehr umständlich geschrieben, so 
denke ich zumindest.
Ggf. kann mir jemand Tipps geben wie man dies sauberer Lösen, sowie die 
gewünschte Funktion realisieren kann.

Vielen Dank

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


Lesenswert?

> So richtig funktioniert es nicht...
Und das nicht mal in der Simulation...
So ein Bauteil existiert nicht:
1
TIMING_SPEICHER: process (INIT_BUTTON)
2
  begin
3
       if INIT_BUTTON = '0' then 
4
          ZUSTAND <= Y0;   --INIT_BUTTON -> nicht gedrueckt
5
       elsif falling_edge (INIT_BUTTON) then 
6
          ZUSTAND <= Y1;
7
          if falling_edge (CLK_1_MHZ)  then 
8
             :
9
             ZUSTAND <= FOLGE_Y;    
10
          end if;
11
       end if;
Das wäre ja ein Flipflop mit zwei Takteingängen...

Ich werde aus deiner Beschreibung nicht schlau. Zeichne einfach mal ein 
Timingdiagramm.

Zu den Grundlagen:
In einem FPGA-Design hast du im Idealfall (und insbesondere als 
Anfänger) genau 1 Takt, der auf eine Flankenrichtung sensitiv ist. Das 
nennt man dann ein synchrones Design. Alles andere erfolgt z.B. wie in 
VHDL Flankenerkennung beschrieben.

von Schrotty (Gast)


Lesenswert?

du musst dir darüber im Klaren sein, dass du in VHDL eine Hardware 
beschreibst.
Was du hier machst, ist mehr oder weniger an die "Denke" von 
µC-Programmierung angelehnt. Sowas ist aber nicht synthetisierbar.

Dein Problem ist nicht nur die Flankenerkennung, sondern generell dein 
Design. z.B. würden für ZUSTAND keine Register angelegt, sondern 
Latches.


Auch ist mir die Funktionalität nicht ganz klar, was du erreichen 
willst.
Ich hab es so verstanden:

Dein Taster ist auf High und wenn er auf Low geht, dann springst du in 
einen Wartezustand, den du aber sofort mit der nächsten negativen Flanke 
des Taktes wieder verlässt.. Das Resultat wäre ein kurzer Impuls der 
unabhängig davon ist, wie lange du deinen Finger auf dem Taster lässt. 
Ist das so richtig?

von chris (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

vielen Dank für eure Antworten. Danke für den Link, ist eine sehr gute 
VHDL Codesammlung.
Schrotty du hast es richtig verstanden.

Ich habe es nun so wie im Bsp "VHDL Flankenerkennung" gemacht.
Danke für den Tipp.

Es haben sich jedoch schon wieder andere Fragen aufgetan. Vielleicht 
könnt ihr mir da als Anfänger und Lernwilligen auch weiterhelfen.
Ich will einen IC initialisieren (TEA 5880 TS FM-Empfänger). Dieser hat 
3 Datenleitungen die für die Beschreibung notwendig sind (RW_ENABLE, 
DATA_TX und CLK). Ebenso hat dieser 4 Register um ihn zu initialisieren. 
So, ich habe nun ein Programm geschrieben das genau das tun soll. Es 
funktioniert auch soweit, ich habe eine Testbench geschrieben und es in 
ModelSim simuliert. Jedoch habe ich wohl irgendwo ein Latch!

Die Daten zur Initialisierung habe ich als "constant std_logic_vector" 
definiert s. Anhang. Mit dem Tastendruck SET_BUTTON in der VHDL 
Flankenerkennung (Prozess: EDGE_DETECT) und CLK_ENABLE initialisiere ich 
nun meine State Maschine STATE_INIT.
Mit der eigentlichen State Maschine FSM_DATA_R_W, laufe ich nun meine 
Zustände durch. Ich setzte den RW_ENABLE = 1 und starte die 
Datenübertragung (15 Bit). Ich zähle die Bits durch 0..14, wenn Bit 14 
erreicht ist, dann setze ich ein Flag (Zustandsauswahl) und springe 
zurück in den Zustand WRITE_MODE. In diesem setze ich RW_ENABLE = 0, da 
RW_ENABLE nur während der  Übertragung der 15 Bit aktiv sein darf. Mit 
RW_ENABLE = 0 übernimmt der IC den jeweiligen 15 Bit String in das 
Register. Das mache ich nun 4 mal. Das funktioniert auch soweit, jedoch 
habe ich im Zustand   "CTL_REG_B" das Problem, das statt den letzten 
beiden Bits "01" in dem Vector "CONTROL_REG_A" eine "111" Folge 
erscheint (rot eingekreist im Anhang ModelSim). Ich weiß nicht mehr 
weiter warum das so ist...Latch?
Für Hilfe wäre ich sehr dankbar, vielleicht könnte ich noch ein paar 
Tipps bekommen den Code robuster bzw. einfacher zu gestalten.

Vielen Dank

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


Lesenswert?

Ich habe mir das jetzt noch nicht sooo genau angeschaut, aber:
1) üblicherweise ist die Testbench ausserhalb des Designs, bindet das zu 
testende Modul als Komponente ein und hat keine Ports in der Entity.
2) dieser Prozess hier:
1
FSM_DATA_R_W : process (STATE, CLK, RW_ENABLE, FLAG_A, FLAG_B, FLAG_C, FLAG_D)  
2
variable i, j, k, l     : integer:= 0;
3
begin
4
   if falling_edge (CLK) then
5
   :
ist nur auf CLK sensitiv. Alle anderen Signale sind in der Liste 
überflüssig.

> Ich weiß nicht mehr weiter warum das so ist...Latch?
Nicht so richtig ein Latch, aber du bist dort bereits im Zustand 
WRITE_MODE. Wegen der Bitmuster ist schlecht zu sehen, dass das letzte 
Bit in keinem der Zustände CTL_REG_A...D korrekt ausgegeben wird   :-o
Und das wird klar, wenn du dir ansiehst, dass deine Variable nach dem 
indizieren incerementiert wird, und danach (wenn sie =14 ist) sofort der 
Zustand gewechselt wird. Das Bit 13 bleibt also jeweils in DATA_TX 
gespeichert.
Probiers mal so:
1
     RW_ENABLE <= '1';
2
     DATA_TX <= CONTROL_REG_A (i);
3
     i := i + 1;  
4
     if i = 15 then  
5
        RW_ENABLE <= '0';  -- bin mir hier nicht sicher
6
        i := 0;  -- eigentlich unnötig. Nur nötig, wenn i auch in den anderen Zuständen als Laufvariable verwendet werden soll
7
        FLAG_B <= '1';
8
        NEXT_STATE <= WRITE_MODE;
9
     end if;

von chris (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

erstmal vielen Dank für die schnelle Antwort und die super Tipps.
So, ich habe nun meine Bedingung in der if Abfrage auf i = 15 geändert, 
d.h gleichzeitig, dass ich auch meine Bitstrings auf 15 ändern muss. Ich 
habe dann jeweils den Bitstrings noch eine '0' angehängt. Aber leider 
bleibt das Verhalten das gleiche und mein Timing verändert sich um die 
Bitstelle '0'. Allerdings wird dann das Bit in CTL_REG_B sichtbar, nur 
eben mit falschem Timing :-) Hab dir nochmals das neue Timing Diagramm 
angehängt, vielleicht hast du noch eine Idee die mir weiterhelfen 
könnte, bzw. eine andere Möglichkeit dies zu unterbinden. Schon mal 
vielen Dank für die Hilfe.

Grüße

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.