Hallo,
ich möchte ein 13 MHz Taktsignal mit 500 ps Auflösung verzögern und habe
hierfür angedacht, mir die Laufzeit eines Inverters zu nutze zu machen.
Die Idee ist, das Signal auf eine Inverterkette (Serie mehrerer
Inverter) zu legen und zwischen den einzelnen Invertern abzugreifen.
Die Abgriffe sollen über einen Multiplexer ausgewählt und auf den
Ausgang gelegt werden können.
Bisher habe ich mich in Quartus und ISE mit Schematics versucht, aber
die Simulation gibt nichts sinnvolles aus.
Würde mich freuen, wenn ihr Tipps für mich hättet, welche
Optimierungsmechanismen ich deaktivieren muss oder wie ich das Ganze
angehen sollte, um tatsächlich die Laufzeit durch einen Inverter
ausnutzen zu können.
Danke schonmal!
Gruß Peter
PS: Das Delay könnte natürlich auch über Delay-Lines realisiert werden,
aber davon bräuchte ich dann recht viele.
also ich habe mal etwas ähnliches versucht im rahmen einer DCO (digital
clock oscillator). Leider war das dieses konzept wegen diversen
schwierigkeiten mit der inverterkette nicht realisierbar.
das haptsächliche problem was ich hatte war, das im FPGA die inverter ja
keine echten inverter sind, sondern im normalfall durch LUT's
dargestellt werden. und ich habe damals die sache auf basis eines
Spartan3E aufgebaut und mich an den FAE von Xilinx gewand. Dieser hat
mir das Problem bestätigt, dass, zumindest bei den xilinx bausteinen,
die LUT's nicht delaystabil arbeiten. sprich, man kann nich von einer
definiert festen verzögerung ausgehen. bei mir hatte das den effekt, das
die erzeugte frequenz schwankte. dadurch waren keine genauen frequenzen
einstellbar.
das zweite problem war, dass das synthesewerkzeug, die inverterkette für
die verzögerung als unnütze logik angesehen und einfach wegoptimiert
hat. hab dann die verzägerung über eine kombination aus UND und ODER
glieder realisiert und dem synthesewerkzeug gesagt "Keep hirarchie",
dann hat er es beibehalten.
vielleicht helfen dir diese beschreibungen meiner problematiken etwas.
Vielen Dank schonmal für Deine Antwort!
Ich dachte schon ich bin nur zu blöd die Optimierung komplett zu
deaktivieren.
Genau das Problem der LUT habe ich auch als Ursache für meine nicht
statischen Delayzeiten angesehen.
Das "wegoptimieren" konnte ich leider bisher weder bei Altera noch bei
Xilinx komplett verhindern. Scheint ähnlich wie bei Dir zu sein.
Könntest Du mir noch paar Details zu Deinem Ansatz "...Verzögerung über
eine Kombination aus UND und ODER Glieder..." verraten?
- Hast Du hierbei mit Schematic gearbeitet oder direkt VHDL?
- Welche Werte von Verzögerungen konntest Du so erreichen?
- Hast Du ebenfalls ausgewählt welches Delay auf den Ausgang soll, oder
fest eingestellte Werte durchgeschleift? (mein Delay soll im Betrieb
änderbar sein...)
Danke und Grüße
Peter
Ich weiß nicht genau ob das für deine Anwendung geht, aber hast du mal
darüber nachgedacht ob du ein DCM (gibts bei Xilinx FPGAs) nutzen
kannst? Weil damit kann man ein Clocksignal mit einem variablen Phase
Shift erzeugen.
so, hab mal das blockschaltbild reingestellt. hab aber selber alles
direkt in VHDL geschrieben.
das START-Singal ist dabei das "enable" der frequenzerzeugung. mit dem
L-Signal wählt man dann die Kettenlänge aus, darauf is zu beachten, das
nur eine einzige Stelle aktiviert sein darf. diese stelle ist dann das
letzte glied der kette.
ich habe es so aufgebaut, das ich 128 glieder aneinander schlaten
konnte, wobei ein glied aus jeweils einem UND und einem ODER besteht.
der periodische aufbau sollte erkennbar sein.
achim, DCM's sind zwar schön und machen eine stabile frequenz, aber
lassen sich leider nicht mehr zur laufzeit manipulieren. damit kann man
sich schön eine grundfrequenz erstellen, die man dann weiterbearbeitet,
aber dann kommt wieder die unregelmäßige gatterlaufzeit mit ins spiel.
DCM stellen keine hoch genuge Auflösung zur Verfügung und somit lässt
sich damit kein entsprechend kleines Delay realisieren. (Trotzdem DANKE
für die Idee!)
Danke Nephilim für das Blockschaltbild! Funktion ist klar und sieht
vielversprechend aus. Werde mich gleich mal dran machen und das
umsetzen!
Nochmal meine Frage: Was für ein Delay-Auflösung hast Du hiermit
erreichen können?
welchen delay man damit erzeugt ist natürlich bausteinabhängig und dann
noch in gewissen bereich schwankend. also ist das nich direkt
definierbar. ich hatte mit diesem ringoszillator frequenzen zwischen
120MHz und 20MHz herzeugt, aber tiefer geht immer. wenn man eine höhere
frequenz will bräuchte man einen anderen baustein. in kombination mit
der ganzen regelung (war ein teil einer vollständig digitalen PLL) war
nich mehr drin. aber war auch nur ein Spartan3E. mit nem virtex würde
man noch einiges mehr rauskitzeln können.
ach ja, und das ding mit dem simulieren wollt bei mir auch nich so
richtig. in einer behaviorsimulation gehts eh nich, weil dort ja keine
timing informationen enthalten sind, aber auch in einer Post-Route&Place
simulation kamen immer falsche werte raus. musste es dann direkt aufm
fpga mitm oszilloskop debuggen.
"keine hoch genuge " Was ist das für ein Konstrukt?
Meine Sprachsynthese optimiert das zu "keine ausreichend hohe" :D
Solche Delaygeschichten funktionieren eigentlich nur mit externen
Partnern zusammen wirklich stabil. Ich habe da auch einige Versuche
hinter mir.
Das einfachste ist ein HF-Quarz an einem Pin, das durch ein Signal
angetriggert wird und definiert zurückschwingt, was über einen Pin
wieder eingelesen und per kaskadierten SR gezählt wird: Jede Kaskade des
SR kriegt dabei den Ausgang vom vorherigen - verundet mit dem Quarztakt.
Dabei nutzt jedes 2.Register den negierten Takt. Den braucht man über
verschiedene Leitungen, damit die Synthese es nicht wegkillt.
Im Prinzip schalten dann für die Synthese alle Stufen innerhalb eines
Clocks, real rattert die Kombinatorik durch - aber eben synchronisiert
mit dem Quarz. So kriegt man es auf einige 10ppm genau. Habe das mit
einem 866MHz Quarz hinbekommen: Die Schaltfreuqenz je Stufe beträgt dann
0,6 ns. Das entspricht etwa der Verzögerung durch das SR-Gatter.
>"keine hoch genuge"
Süddeutsch, oder?
So würde ich auch reden... ;-)
Schreiben würde ich aber "keine genügend hohe"...
>...500 ps...
Die Gatterlaufzeiten und die zusammenaddierten Zeiten aus dem
Synthesereport sind Maximalzeiten. Bei den richtigen Temperaturen sind
die Bausteine wesentlich schneller.
Ich habe da mal einfach einen Oszillator über eine kombinatorische
Schleife gebaut und anschliessend ausgemessen. Die Frequenz hängt dann
im wesentlichen von den Gatterlaufzeiten ab, und war von FPGA zu FPGA
deutlich unterschiedlich. Insgesamt konnte damit dann auch sehr schön
die Temperatur gemessen werden. Wenn du also irgendwelche Zeiten über
Gatter- und Routinglaufzeiten einstellst, sollten deine Anforderungen an
die Genauigkeit nicht allzu hoch sein.
Hi zusammen,
Glaube, ich habe hier was verpaß, denn ich versteh' nicht,
wieso die DCM keine genügend hohe Auflösung bereitstellen soll ?
In der ersten Anfrage geht es NUR darum das Eingangssignal definiert zu
verzögern, oder ?
Ganau das nennt man "Phase Shifting"
Laut ds312-2 v3.7 Seite 37 läßt sich die Phase dynamisch in Schritten
von tPS = PHASESHIFT/256 (PHASESHIFT = -255..+255) einstellen !
Bei 13 MHz sind dies ca 150 ps !
OK, 500 ist kein ganzzahliges Vielfaches von 150 - aber Schritte von 450
ps sind auch nicht schlecht, oder?
da ganze läßt sich auch dynamisch (zur Laufzeit) ändern !
Gruß
Jochen
Hallo Jochen,
jetzt muss ich Dir Recht geben! Da hab ich wohl das Datenblatt etwas zu
schnell überflogen. Ich hatte nur etwas von
0° (no phase shift),
90° (¼ period),
180° (½ period),
270° (¾ period)
gelesen und war davon ausgegangen, dass nur Phaseshifts um jeweils eine
Viertelperiode möglich sind.
Da werde ich direkt mal weiter lesen, welche Delays hier tatsächlich
möglich sind!
Der Abschnitt
"Variable
Phase Shift increment or decrement unit" = 1/256th of CLKIN Period
(degrees)
Würde für mich von der Auflösung her ausreichen. Es geht auch nicht um
den Wert 500 ps, sondern lediglich um eine Genauigkeit in mindestens
diesem Bereich.
Also vielen Dank für diesen Tipp und verzeih, dass ich Deine Idee so
abgeschmettert habe :)
Grüße Peter
PS: Wir können alles, ausser Hochdeutsch :P
"Spartan-3E and Spartan-3A/3AN/3A DSP DLLs support input clock
frequencies as low as
5 MHz, whereas the Spartan-3 DLL requires at least 18 MHz."
Danach bin ich davon ausgegangen, dass zumindest die 3E Version bei 13
MHz funktionieren sollte. Oder verwechsel ich da mal wieder was?
Also bevor das hier ausartet :P möchte ich mich für eure hilfreichen
Tipps bedanken!
Ich habe inzwischen ein Spartan-3E Eval-Board bestellt und beschäftige
mich derzeit mit Datenblatt-Theorie.
Parallel dazu behalte ich die Kette aus AND und OR Gliedern im Auge -
diese habe ich jedoch leider nicht sinnvoll simulieren können - aber das
bekomme ich auch noch hin.
Also herzlichen Dank an dieser Stelle an alle Beitragenden!
Butter hab ich in den Kühlschrank gelegt, als kleines Dankeschön! (geh
nachschauen - da liegt wirklich Butter in Deinem Kühlschrank ;-)
Hallo zusammen,
Ich hab mich jetzt mal mit VHDL auseinander gesetzt und Nephilim's Idee
umgesetzt (oder der Versuch unternommen).
Leider bekomme ich weder den Compiler bei Altera Quartus noch bei Xilinx
ISE dazu, den von mir geschriebenen Code direkt zu übernehmen.
@Nephilim - falls Du noch mitließt würde ich mich freuen, wenn Du mir
bei dem Code Hilfestellung geben könntest.
Danke schonmal im Voraus
Grüße Peter
Im Anhang ein PDF mit meiner Idee und den Bezeichnungen für den
VHDL-Code
Und hier mein VHDL-Code:
oha, das sieht ja irgendwie aufwendiger aus als es eigentlich ist. ich
zeig dir mal wie ich es gemacht habe. also der teil, der sich quasi
immer wieder wiederholt habe ich extra geschrieben.
1
entityv_gliedis
2
Port(clk_in:inSTD_LOGIC;
3
ueberlauf:inSTD_LOGIC;
4
clk_out:outSTD_LOGIC;
5
enable:inSTD_LOGIC);
6
endv_glied;
7
8
architectureBehavioralofv_gliedis
9
signalint_1:std_logic;
10
begin
11
12
int_1<=clk_inandenable;
13
clk_out<=int_1orueberlauf;
14
15
endBehavioral;
diesen teil habe ich dann als Komponente über eine generic anweisung
eingebunden, da ich nicht manuell 127 instanzen schreiben wollte. ;)
1
v_glieder:foriin127downto0generate
2
gl1:ifi=127generate
3
u1:v_gliedPORTMAP(
4
clk_in=>clk_int,
5
ueberlauf=>'0',
6
clk_out=>clk_int_out(i),
7
enable=>Teiler_int(i)
8
);
9
endgenerate;
10
gl2:ifi<127generate
11
u2:v_gliedPORTMAP(
12
clk_in=>clk_int,
13
ueberlauf=>clk_int_out(i+1),
14
clk_out=>clk_int_out(i),
15
enable=>Teiler_int(i)
16
);
17
endgenerate;
18
endgeneratev_glieder;
und dazu dann noch das bissl logik aussen drum
1
clk_int<=not(RSTandclk_int_out(0));
2
Clk_out<=clk_out_2;
3
clk_out_2<=notclk_int;
jor, das wars im grunde auch schon. finde das übersichtlicher und auch
einfacher wenn man z.b. mal am verzögerungsglied (wie es bei mir heisst)
mal was ändern muss, dann muss mans nur einmal machen.
Ööööh wie Du vielleicht an meinem Code gesehen hast, bin ich alles
andere als fit in Sachen VHDL...
Ich hab das ganze so verstanden, wie hier als Schematic im Anhang
dargestellt.
Der "innere" Block wird mehrfach durchlaufen und abhängig vom externen
Teiler_int wird das Enable gesetzt.
Umsetzung um Deinen Code einzubauen sieht so aus:
1
LibraryIEEE;
2
useIEEE.Std_Logic_1164.all;
3
4
entityv_gliedis
5
Port(clk_in:inSTD_LOGIC;
6
ueberlauf:inSTD_LOGIC;
7
clk_out:outSTD_LOGIC;
8
enable:inSTD_LOGIC);
9
endv_glied;
10
11
architectureBehavioralofv_gliedis
12
signalint_1:std_logic;
13
begin
14
int_1<=clk_inandenable;
15
clk_out<=int_1orueberlauf;
16
endBehavioral;
17
18
architectureBehavioral2ofv_gliedis
19
componentComp
20
generic(n:integer:=127);
21
Port(RST:inSTD_LOGIC;
22
clk_out:outSTD_LOGIC;
23
Teiler_int:inSTD_LOGIC_VECTOR(nDOWNTO0)
24
);
25
endComp;
26
27
signalclk_out_2:std_logic;
28
signalclk_int_out:std_logic_vector(127DOWNTO0);
29
30
begin
31
32
v_glieder:foriin127downto0generate
33
gl1:ifi=127generate
34
u1:v_gliedPORTMAP(
35
clk_in=>clk_int,
36
ueberlauf=>'0',
37
clk_out=>clk_int_out(i),
38
enable=>Teiler_int(i)
39
);
40
endgenerate;
41
gl2:ifi<127generate
42
u2:v_gliedPORTMAP(
43
clk_in=>clk_int,
44
ueberlauf=>clk_int_out(i+1),
45
clk_out=>clk_int_out(i),
46
enable=>Teiler_int(i)
47
);
48
endgenerate;
49
endgeneratev_glieder;
50
51
clk_int<=not(RSTandclk_int_out(0));
52
clk_out<=clk_out_2;
53
clk_out_2<=notclk_int;
54
55
endBehavioral2;
Ich dank Dir schonmal ganz herzlich für Deine Hilfe und die Teile auf
Deinem Code! Würde mich freuen, wenn Du mir nochmal Nachhilfe geben
würdest. :)
Ich verstehe zwar nicht, was interessant an der Rückseite von meinem
Schmierzettel sein soll, aber sag mir Deine Anschrift und ich sende Dir
ein paar fehldrucke zu! Aktenvernichter-Spaghetti bekommste auch gratis
dazu!
@Peter.
Falls die Rückseiten Deiner Schmierzettel immer so unverfänglich sind,
dass man sie der ganzen Welt zeigen kann, dann ist ja OK. Bei uns werden
aus Vorsicht alle Ausdrucke mit selbstproduzierten Vernichtet. An
Papierstreifen habe ich also genug ;-).
Gruß DaMicha.
Hallo,
vielleicht dann doch noch mal was Konstruktives.
Ich hab die Oszillator-Schaltung mal umgesetzt (Siehe Anhang). Ziel
Architektur war ein Xilinx Spartan 2E50. Das sollte aber egal sein. Sie
funktioniert soweit, sobald man mit Timinginformationen simuliert. Also
bestenfalls eine Post-Place & Route Simulation.
Es sind jedoch ein paar Dinge zu beachten:
Auf dem internen Clock Signal (clk_int) und dem overflow Signal
(overflow) muss ein Keep gesetzt werden (Siehe Quellcode). Falls nicht,
versucht die ISE eine parallele Logic Struktur aufzubauen und die Pfade
durch die einzelnen Verzögerungsstufen werden alle annähernd gleich
lang. Wer möchte kann das ja mal ausprobieren und im RTL Schematic
nachschauen.
Falls man in meinem Design die Konstante für die Länge der Kette ändert,
muss man auch unter Modelsim in der Post-Place & Route Simulation das
Designfile nocheinmal bauen, da sonst die Konstate für die Kettenlänge
nicht aktualisiert wird und die Testbench nicht läuft.
Das Reset für Schaltung muss wenigstens die halbe Dauer der maximal
möglichen Periode (längste Kette) haben, da sonst die Schaltung Amok
läuft.
Und noch eine Anmerkung. Die Frequenz der Schaltung sollte von der
Temperatur und dem verwendeten FPGA (auch zwischen FPGAs gleichen Typs)
und eigentlich allem Möglichen abhängig sein. Ich würde so eine
Schaltung nicht verwenden wollen.
Gruß DaMicha.
Hallo DaMicha,
danke schonmal für Deine Hilfe!
habe Deinen Code mal in ISE geladen, bekomme jedoch bei der Post-Place &
Route Simulation einen Fehler bzw eine Meldung (siehe Anhang).
Wenn ich den Simulator umstelle, tuts aber auch nicht.
Ich kann mit dem Fehler recht wenig anfangen - weisst Du hier Rat?
Im Quartus habe ich den Code prima zum laufen bekommen und kann hier
auch eine Simulation starten.
Du hast natürlich recht mit den auftretenden Schwankungen! Ziel dieses
Aufbaus war ja eigentlich auch nicht eine Frequenz zu erzeugen, sondern
vielmehr eine einstellbare Verzögerung des Eingangs zu erreichen.
Male sehen, ob und wie ich das hiermit realisieren kann....
Danke und Grüße Peter
Hallo.
Wahrscheinlich hast Du den ISE Simulator eingestellt. Wenn Du im Sources
View mit der rechten Maustaste auf das Taget (FPGA Typ) klickst und
Properties auswählst kannst Du das auf Deine Modelsim Version ändern.
Warum der Fehler auftritt kann ich aber leider nicht sagen, da es bei
mir mit dem ISE Simulator funktioniert. Vielleicht sind es
Versionsunterschiede zwischen dem freien Webpack und der ISE Foundation
Kaufversion.
Gruß DaMicha.
Servus,
wollte nur mitteilen, dass ich das Ganze mit dem DCM zum Laufen bekommen
habe. Danke für eure Hilfe und eure Tipps hier!
Dimulieren lässt sich das ganze eher nicht, aber die Messungen sind
vielversprechend.
Grüße