Eine Verständnisfrage:
Am FPGA liegt ein externer 150-Mhz-Takt an. Per DCM wird daraus ein
interner 150Mhz-Takt und ein halbierter phasensynchroner 75MHz-Takt
generiert.
Beispiel:
1
signalflipflop:std_logic,
2
process(Clk150)
3
begin
4
if(rising_edge(Clk150))then
5
if(Clk75=1)then
6
flipflop<='1';
7
else
8
flipflop<='0';
9
endif;
10
endif;
11
endprocess;
Nun kommen beide Taktflanken ja gleichzeitig.
Meine Befürchtung wäre, daß das "flipflop" mit der steigenden Flanke an
seinem Takteingang (CLk150) an seinem Dateneingang gerade einen
Zustandswechsel (Clk75) sieht und dadurch die Setup- bzw. Hold-Zeit
verletzt ist.
Stimmt das? Oder ergibt dies ein ClockEnable?
Hallo,
dein Signal fllipflop ist für 2 Takte des 150 MHz Taktes 1 und für die
nächsten zwei Takte 0. Das kann man auch wunderbar mit einem 2 Bit
langen Counter realisieren. Dann gibt es auch keine Fragen mehr
hinsichtlich Setup/Hold-Zeiten.
Tom
Ich nehme mal an, dass Dein Beispiel stark vereinfacht war.
Eine beliebte Lösung ist die Erzeugung eines Signals, z.B. CLK75EN, dass
der 150MHz Domain mitteilt, ob innerhalb der nächsten Phase eine CLK75
Flanke folgt. Dadurch weiß CLK150, wann Ausgänge geändert und Eingänge
abgetastet werden dürfen.
1
_ _ _ _ _ _ _
2
CLK150 _| |_| |_| |_| |_| |_| |_| |
3
_ ___ ___ ___
4
CLK75 |___| |___| |___| |__
5
___ ___ ___ __
6
CLK75EN _| |___| |___| |___|
Bei halbiertem Takt sieht das zwar trivial aus, aber bei anderen
Verhältnissen macht sich der Vorteil schnell bemerkbar.
Dieses Verfahren wird beispielsweise bei ARM Kernen eingesetzt, um
langsamere Busse anzuschließen:
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0438e/CJHFFIHH.html
Gruß
Marcus
Udo Weizenheim schrieb:> Stimmt das?
Ja.
> Oder ergibt dies ein ClockEnable?
Ich frage mich: warum eigentlich so umständlich? Warum verwendest du
das 75MHz-Signal als Clock-Enable für den 150MHz-Takt? Warum verwendest
du nicht den 75MHz-Takt direkt?
Ich würde dein Beispiel so schreiben:
1
flipflop<=clk75;
Ach, so hattest du das nicht gemeint?
Was fehlt dann an deinem Beispiel, damit man dein Problem nachvollziehen
könnte?
1
process(Clk75)begin
2
ifrising_edge(Clk75)then
3
flipflop<=notflipflop;
4
endif;
5
endprocess;
6
7
8
process(Clk150)begin
9
ifrising_edge(Clk150)then
10
ausgang<=flipflop;-- kein Problem, weil keine "echte" zweite Taktdomäne
11
endif;
12
endprocess;
Denn du kannst ganz problemlos Signale zwischen zwei per DCM
erzeugten Domänen hin- und her übertragen. Die Toolchain sorgt (bei
angegebenem Constraint auf den Basistakt) für die Überwachung der
Laufzeiten...
Marcus Harnisch schrieb:> Dieses Verfahren wird beispielsweise bei ARM Kernen eingesetzt, um> langsamere Busse anzuschließen:
Damit ist aber die die Richtung klar: die "schnelle" Domäne gibt den
Takt vor. Denn dieses Enable-Signal ist ja zur "schnellen" Domäne
synchron. Das sieht mir wie "voreilendes Einsynchronisieren" aus...
Danke für die Antworten.
Mein Beispiel war natürlich stark vereinfacht, sorry!
Meine Anwendung sieht so aus:
In mein Modul kommen 8-Bit-Daten mit 150Mhz rein und sollen als
16Bit-Daten mit 75MHz raus. Die 8-Bit-Daten kommen als Pakete und können
mit jeder steigenden 150MHz-Flanke beginnen.
Das Problem ist jetzt folgendes:
Wenn ein 8-Bit-Daten-Paket dann beginnt, wenn auch der 75MHz-Clock eine
steigende Flanke hat, ist alles gut.
Wenn ein 8-Bit-Daten-Paket aber dann beginnt, wenn der 75MHz-Clock
gerade eine fallende Flanke hat, muß ich die Daten zwischenpuffern und
quasi einen "Wait-State" einlegen.
Daher meine Idee:
Mit jeder steigenden 150MHz-Flanke frage ich den Zustand des 75MHz-Takts
ab.
Dann mein Zweifel:
Hab ich zum Zeitpunkt der 150MHz-Flanke überhaupt einen stabilen Zustand
am 75MHz-Takt?
Offensichtlich nicht.
Eigentlich müßte der Code so aussehen:
Lothar Miller schrieb:> Denn du kannst ganz problemlos Signale zwischen zwei per DCM> erzeugten Domänen hin- und her übertragen. Die Toolchain sorgt (bei> angegebenem Constraint auf den Basistakt) für die Überwachung der> Laufzeiten...
Wenn ich Dich richtig verstehe, heißt das:
Eigentlich hab ich eine Setup/Hold-Verletzung, aber die Toolchain ist
clever genug, um das zu berücksichtigen.
Ich vermute, eigentlich müsste dein Code so aussehen:
1
ifrising_edge(Clk75)then...
2
elsiffalling_edge(Clk75)then...
3
endif;
Und der Witz: das geht sogar, wenn man weiß, was dabei erlaubt ist...
;-)
Das hatten wir letzhin im
Beitrag "Re: Seriell-Parallel-Wandlung mit VHDL"Udo Weizenheim schrieb:> Das Problem ist jetzt folgendes:> Wenn ein 8-Bit-Daten-Paket dann beginnt, wenn auch der 75MHz-Clock eine> steigende Flanke hat, ist alles gut.> Wenn ein 8-Bit-Daten-Paket aber dann beginnt, wenn der 75MHz-Clock> gerade eine fallende Flanke hat, muß ich die Daten zwischenpuffern und> quasi einen "Wait-State" einlegen.
Dann hast du eigentlich kein Problem, nur ist eben der betroffene 75MHz
Pfad ebenfalls mit 150MHz zu constrainen. Dann haben eben die "zweiten"
8-Bit nur 6,6ns (statt der 13,3ns) Zeit bis zum Ausgang.
Allerdings ist es bei solchen Taktraten eh' sinnvoll, sowohl den Eingang
wie auch den Ausgang zu registieren, damit die FFs im IOB verwendet
werden. Sonst bekommst du da nie ein brauchbares Timing hin...
> Lothar Miller schrieb:>> Denn du kannst ganz problemlos Signale zwischen zwei per DCM>> erzeugten Domänen hin- und her übertragen. Die Toolchain sorgt (bei>> angegebenem Constraint auf den Basistakt) für die Überwachung der>> Laufzeiten...> Wenn ich Dich richtig verstehe, heißt das: Eigentlich hab ich eine> Setup/Hold-Verletzung, aber die Toolchain ist clever genug, um das> zu berücksichtigen.
Richtig, zum Preis einer viel höheren "virtuellen" Taktfrequenz bei
ungünstigen Verhältnissen: wenn du z.B. 150MHz (6,666ns) über einen DCM
auf 100MHz (10ns) wandelst (3:2), dann hast du beim Domänenübergang eine
"virtuelle" Taktfrequenz von 300MHz (10ns-6,666ns). Und da tut sich die
Toolchain dann schon mal schwer...
> Und der Witz: das geht sogar, wenn man weiß, was dabei erlaubt ist...> ;-)
Ja natürlich, Du hast absolut recht!
Ich bin überhaupt nicht auf die Idee gekommen, daß ich ja wirklich auf
die fallende Flanke triggern kann (obwohl ich es auch noch
hingeschrieben hab, schön blöd...).
Aus irgendeinem Grund dachte ich, daß immer nur auf die steigende Flanke
triggern kann und daher den doppelte Takt (150MHz) nehmen muß.
> Richtig, zum Preis einer viel höheren "virtuellen" Taktfrequenz bei> ungünstigen Verhältnissen: wenn du z.B. 150MHz (6,666ns) über einen DCM> auf 100MHz (10ns) wandelst (3:2), dann hast du beim Domänenübergang eine> "virtuelle" Taktfrequenz von 300MHz (10ns-6,666ns). Und da tut sich die> Toolchain dann schon mal schwer...
Das war mir so auch noch nicht bewußt.
Danke Dir!
Lothar Miller schrieb:> Denn du kannst ganz problemlos Signale zwischen zwei per DCM>> erzeugten Domänen hin- und her übertragen. Die Toolchain sorgt (bei>> angegebenem Constraint auf den Basistakt) für die Überwachung der>> Laufzeiten...
Ich hätte erwartet, dass du aus Deiner Erfahrung heraus eher das
Gegenteil empfiehlst, denn bei der (unnötigen!) clock-domain crosserei
kommt der Jitter zweimal ins Spiel und liefert am Ende ein Design mit
etwas reduzierter Frequenz.
R. K. schrieb:> dass du aus Deiner Erfahrung heraus eher das Gegenteil empfiehlst
Das war nicht die zugrundeliegende Frage. Meine Postulate gelten nach
wie vor. Es ging mir hier um die prinzipielle Machbarkeit...
> denn bei der (unnötigen!) clock-domain crosserei
Bei den angegebenen Frequenzen (150MHz und 75MHz) wird doch nirgends
eine Taktdomäne gekreuzt. Die beiden sind voneinander
abgeleitet/abhängig und soweit recht gut bekannt. Das bisschen Jitter,
das der DCM da reinbringt, fällt nicht nennenwert ins Gewicht...