Forum: FPGA, VHDL & Co. Takt herunterteilen


von Küchenhilfe (Gast)


Lesenswert?

Ich bin noch recht unerfahren mit VHDL und brauche eure Hilfe.
Ich soll mit Hilfe von VHDL einen 1Mhz-Takt herunterteilen auf 
verschiedene Werte: 1Hz, 10 Hz, 100 Hz, 1kHz, 10 kHz, 100 kHz und 1 Mhz.
Mir fehlt der richtige Ansatz. Wie fange ich dabei richtig an?

von Christian R. (supachris)


Lesenswert?

Das macht man mit Clock Enable. Nicht den Takkt teilen, sondern nur alle 
x Takte das Clock Enable auf 1 setzen, damit die Schaltung was macht. 
Oder musst du einen symetrischen Takt ausgeben?

von Küchenhilfe (Gast)


Lesenswert?

Der Takt sollte schon symmetrisch sein.

von Boris M. (borism)


Lesenswert?

Na das sollte doch kein Problem sein...
Ich geb dir mal einen Gedankenanstoß, kannst es ja versuchen zu 
programmieren. Wenn du fragen zu deinem Code hast kannst du die ja gerne 
hier stellen!

Du hast deine CLK (Grundtakt = 1 MHz) aus dieser erzeugst du dir ein 
Enable-Signal, welches doppelt so schnell ist wie dein gewünschter Takt 
(z. B. mit einem Zähler). Mit deiner Clock und dem Ansteigen deines 
Enable-Signal hast du dann den Zeitpunkt für eine Flanken deiner 
gewünschte Clock (hiere musst du nur zwischen 0 und 1 toggeln wenn die 
CLK von 0 auf 1 geht und wenn Enable-Signal 1 ist).
(Ich hoffe ich habe mich einigermaßen verständlich ausgedrückt...
Wenn nicht frag einfach...

von Küchenhilfe (Gast)


Lesenswert?

Das mit dem enable habe ich verstanden, aber was meinst du mit dem 
Begriff Toggeln?

von Klaus (Gast)


Lesenswert?

Mit toggeln meint er den Wechsel zwischen 0 und 1. Also du nutzt einen 
Zähler der mit dem Ursprungstakt läuft. Wenn Zählerstand erreicht -- 
Zähler rücksetzen und neues Taktsignal toggeln...

schlecht erklärt ;-)

von Martin K. (mkohler)


Lesenswert?

Küchenhilfe schrieb:
> Das mit dem enable habe ich verstanden, aber was meinst du mit dem
> Begriff Toggeln?
Mit Toggeln wird gesagt, dass das Signal zum Schaltzeitpunkt (wenn Clock 
Enable gesetzt ist) einfach invertiert wird, 0->1 resp. 1->0, unabhängig 
davon, was für einen Zustand es vorher hatte.

von Christian R. (supachris)


Lesenswert?

Als Beispiel: Du hast 10MHz Grundtakt und willst 1MHz erzeugen.
Dann beschreibst du einen synchronen Zähler, und einen Komparator, der 
beim Zählerstand 4 ein FlipFlop umschaltet (toggle) und außerdem 
synchron den Zähler zurücksetzt. Somit zählt der immer von 0 bis 4 und 
dein Signal wechselt alle 5 Takte die Polarität und du hast einen 
schönen symetrischen Takt am Ausgang des Toggle-FlipFlops mit 1Mhz. 
Durch Variation der Zählerwerte kannst du dann bei entsprechend langem 
Zähler alle möglichen Frequenzen einstellen. Der Zählerwert ist immer 
der halbe Teilerwert minus 1.

von Küchenhilfe (Gast)


Lesenswert?

Übrigens soll das Signal an einen Drehschalter an dem die Taktsignale 
eingestellt werden.

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


Lesenswert?

> Übrigens soll das Signal an einen Drehschalter an dem die Taktsignale
> eingestellt werden.
Ich würde mit einem Drehschalter den Teiler am CPLD/FPGA einstellen und 
das fertige Signal ausgeben.
Also nicht alle diese Frequenzen ausgeben
>>> 1Hz, 10 Hz, 100 Hz, 1kHz, 10 kHz, 100 kHz und 1 Mhz
und daraus auswählen.
Sondern nur eine Frequenz erzeugen, und zwar die, die vom Schalter 
ausgewählt ist.

Das ist eine einfache Aufgabe, aber mach erst mal 1 Frequenz:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
entity Taktteiler is
6
  port(CLK_10M     : in  std_logic;
7
       CLK_OUT     : out std_logic);
8
end Taktteiler;
9
10
architecture BEHAVE of Taktteiler is
11
constant div1MHZ    : integer := (10/2)-1; -- 10MHz/10 = 1MHz --> zählen von 0..4
12
signal cnt          : integer range 0 to div1MHZ  := 0;
13
signal clkout       : std_logic := '0';
14
15
begin
16
  process begin 
17
     wait until rising_edge(clk_10M);
18
     if (cnt < div1MHZ) then
19
        cnt    <= cnt+1;
20
     else 
21
        clkout <= not clkout;
22
        cnt    <= 0;
23
     end if;
24
  end process;
25
  CLK_OUT <= clkout;
26
end BEHAVE;

von Küchenhilfe (Gast)


Lesenswert?

>Ich würde mit einem Drehschalter den Teiler am CPLD/FPGA einstellen und
>das fertige Signal ausgeben.
Das würde ich nur im Notfall machen, weil ich zu wenig Anschlüsse am 
CPLD (XC9572 PC44) habe. Hier würden denke ich 3 Pins belegt werden. 
(GCK, In und OUT)
ODER wenn natürlich zu viele Makrozellen ausgelastet sind, würde ich auf 
den nächst größeren CPLD setzen, dann könnte ich diese Methode 
durchführen.

von Küchenhilfe (Gast)


Lesenswert?

Ich habe noch mal nachgedacht: Die Idee mit dem Drehschalter finde ich 
doch nicht so schlecht. Dann müsste aber der Drehschalter einen Code 
erzeugen. ODER?

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


Lesenswert?

> Hier würden denke ich 3 Pins belegt werden. (GCK, In und OUT)
Was ist "hier"? Wie kommst du auf 3 Pins?
Zum Ausgeben der o.a. Frequenzen bräuchtest du 7 Ausgangspins. Beim 
Anschluss eines BCD-Schalters bräuchtest du 3 für den Schalter und 1 für 
den Ausgang.

> Dann müsste aber der Drehschalter einen Code erzeugen. ODER?
Das wäre wohl das beste.

BTW: die ganzen Teiler brauchen recht viel Platz im CPLD...

von Chef (Gast)


Lesenswert?

>Der Takt sollte schon symmetrisch sein.
Einfach jeweils den doppelten Takt nehmen und auf ein JK-FF (toggle FF).

von Klaus (Gast)


Lesenswert?

Hallo,

bin neu in VHDL und FPGA und komme eigentlich ziemlich flott voran. Zum 
Thema synchroner Takt habe ich aber noch einige Unklarheiten, die mir an 
dieser Stelle evtl genommen werden können.
Unter synchronem Takt verstehe ich, dass die heruntergeteilten 
Taktsignale die Flanken exakt zum gleichen Zeitpunkt haben wie der 
Haupttakt, von welchem die heruntergeteilten abgeleitet sind (die 
Flanken natürlich seltener, da kleinere Frequenz). Es soll also nicht 
ein Zählerstand mit Kombinatorik mit einen bestimmten Zählerwert 
verglichen werden, da durch die Kombinatorik wieder eine Verzögerung 
hinzukommt. Wenn nun der Vergleichswert jedoch in ein FF gespeichert 
wird (das das Ergebnis des Vergleichs übernimmt), dann müsste dies doch 
wieder synchron mit dem Haupttakt laufen oder?

Stellt das Beispiel von:
Autor: Lothar Miller (lkmiller)
Datum: 13.11.2009 09:35

mit CLK_OUT einen synchronen Takt zur Verfügung? der ohne weiteres in 
weiterverwendet werden kann?

Die im Artikel 
http://www.mikrocontroller.net/articles/Taktung_FPGA/CPLD#Clock_Enable 
verwendete Methode läuft ja eigentlich auf das gleiche heraus (wobei das 
CLK_OUT aus dem Beispiel von Lothar dem ce aus dem Artikel entspricht). 
Daraus schliesse ich, dass es auch mit dem Beispiel von Lothar nötig 
ist, nochmals mit dem Haupttakt zu synchronisieren? Oder liege ich da 
falsch?

Das ganze ist mir noch ein bisschen schleierhaft... Wer hilft, bekommt 
42 Jungfrauen im Paradies, versprochen !

von Klaus Falser (Gast)


Lesenswert?

> Wenn nun der Vergleichswert jedoch in ein FF gespeichert
> wird (das das Ergebnis des Vergleichs übernimmt), dann müsste dies doch
> wieder synchron mit dem Haupttakt laufen oder?

Nein, weil der Ausgang des FFs erst mit einer bestimmten Verzögerung 
erscheint. Der Ausgang kommt also später als der Takt.
Die Flanken des "Derived Clock" sind also phasenverschoben zum schnellen 
Takt. Man kann so einen abgeleiteten Takt verwenden, es kann aber 
Probleme geben:
- Wenn man z.B. Ausgänge von FFs, die mit dem schnellen Takt arbeiten, 
an FFs führt, die mit dem abgeleiteten arbeiten, dann schalten deren 
Eingänge während der Taktflanke um. Es kommt zu Setup-Zeit Verletzungen.
- Im FPGA gibt es eigene schnelle Leitungen für den Takt, welche 
garantieren, dass alle angeschlossenen FFs den Takt mehr oder weniger 
gleichzeitig sehen. Diese werden aber für angeleitete Takte nicht 
unbedingt verwendet, sodass die FFs am abgeleiteten Takt eventuell nicht 
100% synchron schalten. In jedem Fall sollte man sicherstellen, dass der 
abgeleitete Takt wieder auf eine schnelle Leitung geführt wird (BUFG 
Komponente).

Bei der (besten) Lösung mit CE Signal muss nichts nochmals synchronisert 
werden, weil alle FFs mit nur einem Takt laufen.

von Klaus (Gast)


Lesenswert?

OK, vielen Dank. Das mit der Verzögerung leuchtet mir ein.
D.h. aber auch, dass die Lösung von Lothar ein paar Beiträge weiter oben 
nicht absolut synchron ist und die einzige absolut Synchrone Variante 
ist, dass man das Haupttaktsignal und das CE-Signal in einen Block 
gibt (welcher mit langsamem Takt laufen soll) und dort die steigende 
Flanke des Haupttaktes auswertet und wenn das CE = 1 ist, dann eine 
Aktion ausführt?
Ich hoffe, dass das so ungefähr hinkommt...

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


Lesenswert?

> D.h. aber auch, dass die Lösung von Lothar ein paar Beiträge weiter oben
> nicht absolut synchron ist
Die Aufgabe war, ein Ausgangssignal mit einem Tastverhältnis von 50% zu 
erzeugen. Dass dieses Ausgangssignal CLK_OUT heißt, ist ein Teil der 
Aufgabenstellung.
Niemals (sag niemals Nie) würde ich diesen CLK_OUT innerhalb eines 
FPGA-Designs weiterverwenden. Allerdings hat dieser CLK_OUT wenigstens 
keine Glitches, Spikes und ähnliche unschöne Effekte, weil das Signal 
registriert ist.

> D.h. aber auch, dass die Lösung von Lothar ein paar Beiträge weiter oben
> nicht absolut synchron ist
Ein synchrones Design ist so definiert, dass sich Signale nur aufgrund 
eines (in Zahlen 1) Taktes ändern können.

Sowas z.B. ist garantiert synchron:
1
  process begin 
2
     wait until rising_edge(clk_10M); -- Alles hört auf den Takt
3
     if (counter=99) then
4
        counter <= 0;
5
     else
6
        counter <= counter+1;
7
     end if;
8
  end process;
9
  
10
  process begin 
11
     wait until rising_edge(clk_10M); -- Alles hört auf den Takt
12
     if (counter=0) then
13
        led <= '0';
14
     end if;
15
     if (counter=50) then
16
        led <= '1';
17
     end if;
18
  end process;

Das hier ist nicht synchron:
1
  process (counter, clk) begin 
2
     if (counter=100) then        -- asynchroner Reset
3
        counter <= 0;
4
     elsif rising_edge(clk) then
5
        counter <= counter+1;
6
     end if;
7
  end process;
8
9
  process (counter) begin         -- Kombinatorik und Latch
10
     if (counter=0) then            
11
        led <= '0';
12
     end if;
13
     if (counter=50) then
14
        led <= '1';
15
     end if;
16
 end process;
Simulieren tut beides (in etwa) gleich: Es wird ein Zähler von 0 bis 
99 erzeugt. Bei Zählerstand 0 wird eine LED aus- und bei 50 
eingeschaltet. Allerdings ist die zweite Variante in der Realität 
extrem empfindlich auf Glitches und Spikes bei Zählerübergängen von 
counter.

In der ersten Variante wird der counter quasi als Enable für das Setzen 
und Zurücksetzen der LED verwendet.

von Klaus (Gast)


Lesenswert?

Vielen Dank für die Erläuterung!
Wenn ich das Beispiel aus dem Clock Enable Artikel nochmals hernehme:
1
process(clk)
2
begin
3
  if rising_edge(clk) then
4
    if ce='1' then
5
 
6
    -- Aktionen hier einfügen, welche mit langsamen Takt laufen
7
    -- ***1
8
 
9
    end if;
10
  end if;
11
end process;
1
process(clk)
2
begin
3
  if rising_edge(clk) then
4
 
5
    -- Aktionen hier einfügen, welche mit schnellem Takt laufen
6
    -- ***2
7
 
8
  end if;
9
end process;

Die Aktionen, welche an den Stellen -- ***1 und -- ***2 stehen laufen 
also absolut synchron (also ohne Taktversetzung und ohne die Gefahr von 
Spikes/Glitches) und das if ce='1' then bildet ebenfalls keine 
Verzögerung?

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


Lesenswert?

Ja. Sie laufen absolut synchron zum clk.

> das if ce='1' then bildet ebenfalls keine Verzögerung?
Nein, denn das ist ja nur eine weitere Bedingung, die in die 
Weiterschaltlogik dort eingefügt werden:
>>    -- Aktionen hier einfügen, welche mit langsamen Takt laufen
>>    -- ***1

von Klaus (Gast)


Lesenswert?

OK, vielen Dank für die Nachhilfe ;)

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.