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?
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?
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...
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 ;-)
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.
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.
> Ü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
libraryieee;
2
useieee.std_logic_1164.all;
3
useieee.numeric_std.all;
4
5
entityTaktteileris
6
port(CLK_10M:instd_logic;
7
CLK_OUT:outstd_logic);
8
endTaktteiler;
9
10
architectureBEHAVEofTaktteileris
11
constantdiv1MHZ:integer:=(10/2)-1;-- 10MHz/10 = 1MHz --> zählen von 0..4
>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.
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?
> 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...
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 !
> 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.
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...
> 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
processbegin
2
waituntilrising_edge(clk_10M);-- Alles hört auf den Takt
3
if(counter=99)then
4
counter<=0;
5
else
6
counter<=counter+1;
7
endif;
8
endprocess;
9
10
processbegin
11
waituntilrising_edge(clk_10M);-- Alles hört auf den Takt
12
if(counter=0)then
13
led<='0';
14
endif;
15
if(counter=50)then
16
led<='1';
17
endif;
18
endprocess;
Das hier ist nicht synchron:
1
process(counter,clk)begin
2
if(counter=100)then-- asynchroner Reset
3
counter<=0;
4
elsifrising_edge(clk)then
5
counter<=counter+1;
6
endif;
7
endprocess;
8
9
process(counter)begin-- Kombinatorik und Latch
10
if(counter=0)then
11
led<='0';
12
endif;
13
if(counter=50)then
14
led<='1';
15
endif;
16
endprocess;
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.
Vielen Dank für die Erläuterung!
Wenn ich das Beispiel aus dem Clock Enable Artikel nochmals hernehme:
1
process(clk)
2
begin
3
ifrising_edge(clk)then
4
ifce='1'then
5
6
-- Aktionen hier einfügen, welche mit langsamen Takt laufen
7
-- ***1
8
9
endif;
10
endif;
11
endprocess;
1
process(clk)
2
begin
3
ifrising_edge(clk)then
4
5
-- Aktionen hier einfügen, welche mit schnellem Takt laufen
6
-- ***2
7
8
endif;
9
endprocess;
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?
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