Forum: FPGA, VHDL & Co. ADC Daten einlesen und synchronisieren


von Valko Z. (hydravliska)


Angehängte Dateien:

Lesenswert?

Guten Tag

ich habe das folgende Problem und mich würde interessiren wie ihr das 
angehen würdet.

Im Anhang habe ich versucht das ganze darzustellen.

Am FPGA (Spartan6) hängt ein LTC2379 1.6MSPS ADC. Die SPI Signale werden 
über ein Isolatorbaustein durchgeschleift. Man kann annehmen dass der 
unidirektionale Delay gleich ist bzw. nicht stört.

Der ADC SPI Takt ist mit 100 MHz festgelegt was auch den Systemtakt vom 
FPGA entspricht. Der Takt wird über den Isolator zurückgeschlifen und 
wird verwendet um die SDO Daten einzutakten. Leider ist dieser Takt 
(CLK_100_OUT bzw. CLK_100_IN) nicht durchgehend weil sonst die ADC 
Wandlung gestört werden kann.

Und jetzt ensteht im FPGA das Problem dass ich nicht weiss wie ich die 
Daten wieder auf dem Systemtakt sauber rübersynchronisiere. Der 
CLK_100_IN hat nur 18 Takten pro ADC Auslesung und somit ist eigentlich 
ziemlich schwer ein FIFO anzusteuern.

Ich dachte dass ich den Schieberegister mittels den UCF Constraint 
"FROM...TO..." abfange aber weiss nicht ob das ausreichend ist um den 
Datenbus danach "einfach" mit dem Systemtakt zu übernehmen.

FPGA:Spartan6
Tool: ISE 14v7

Bin für jede Vorschlag offen :)


Gruss

: Bearbeitet durch User
von Christian R. (supachris)


Lesenswert?

Erzeuge dir aus den internen 100MHz einen verschobenen Takt mit dem DCM, 
den du für das Einsammeln der Daten nimmst. Das Delay sollte ja relativ 
konstant sein.

von Valko Z. (hydravliska)


Lesenswert?

Hallo Christian

danke für dein Antwort.

Wie meinst du das eigentlich? Das Problem ist dass durch den 
Isolatorrückführung CLK_SYS und CLK_100_IN phasen-technisch nichts 
miteinander zu tun haben. Oder meinst du was ganz anderes?


Gruss

von Christian R. (supachris)


Lesenswert?

Doch das meine ich. Klar ist das verschoben das musst du halt mit der 
Phasenverschiebung des DCM ausgleichen. Die Verschiebung ist doch 
konstant, der Takt ist immer noch der gleiche, also kein Problem, musst 
halt mit dem zusätzlichen internen Takt dann am besten auf einen Dual 
Clock Fifo. Den Rückführungstakt brauchst du nicht, vor allem da der 
nicht dauernd läuft.

von Klakx (Gast)


Lesenswert?

erstmal danke für das hilfreiche Bild.

hast du es schon mal mit einem asynchronen bzw. pseudo-asynchronen FIFO 
probiert? Die Daten werden mit CLK_IN_100 reingeschoben und mit CLK_SYS 
ausgelesen? Inwiefern siehst du die 18 Takte als Problem, landet doch 
erst mal im FIFO.

von Valko Z. (hydravliska)


Lesenswert?

Servus

@Christian
Ob die Phase konstant ist kann glaube ich nicht garantiert werden. Die 
Toleranz vom Isolator kann an dieser Stelle stören oder nicht? Ausserdem 
bedeutet nicht dass sobald ich eine Flanke ausgebe gleich mit den 
nächsten abtasten kann. Der Roundtrip Delay, nenne ich das mal, ist mehr 
als einen Takt.

@Klarkx
Ich befürchte dass wenn der Takt nicht dauerhaft anliegt dann werden die 
FIFO Flags nicht korrekt aktualisiert.

Meine Idee wäre die Daten mit der steigende Flanke von CLK_100_IN 
abzutasten und mit der letze fallende Flanke in ein dual-ported RAM 
reinzuschreiben immer an der gleiche Adresse, 0 oder so. Somit kann ich 
auch ein Flag setzen der ich dann auch abtakten kann und somit in dem 
CLK_SYS Domain erkennen kann dass was neues ist. Der Flag wird dann bei 
der nächsten Wandlung zurückgesetzt.

Ich will es halt so elegant wie möglich lösen und vor allem alle 
asynchrone Übergänge zu 100% abdecken.

Danke nochmal für die Empfehlungen und Vorschläge.


Gruss

von Achim S. (Gast)


Lesenswert?

ich sehe nicht, wieso du in diesem Fall ein FIFO brauchen solltest.

Takte wie geplant in der CLK_100_IN Domäne ein Schieberegister sowie 
einen Zähler, der die 18 Bits runterzählt und beim letzten Bit das 
Schieberegister in ein Halteregister kopiert. Das Halteregister liegt 
zwar in der CLK_100_in Domäne, aber es ändert seinen Wert nur alle 18 
Zyklen. Du kannst also in der CLK_SYS Domäne einen zweiten Zähler 
betreiben, der die Takte auf CLK_100_Out zählt. Der hat zwar keine 
definierte Phasenbeziehung zu CLK_100_in, aber wenn du z.B. das 
Halteregister im 16. Takt ausliest und in ein Register der CLK_SYS 
Domäne kopierst kannst du trotzdem sicher sein, dass der Wert im 
Halteregister stabil ist.

FIFO ginge natürlich auch - du musst beim letzten der 18 CLK_IN_100 
Pulse das WE aktiv setzen (so wie du in meinem Vorschlag beim letzten 
der 18 Pulse das Halteregister laden müsstest). Ich seh nur nicht den 
Vorteil, ein FIFO für nur einen Wert einzusetzen.

von Burkhard K. (buks)


Lesenswert?

Valko Z. schrieb:
> Der ADC SPI Takt ist mit 100 MHz festgelegt.

Mal nachgefragt:

Wenn die "time between conversions" 625 ns beträgt und davon 200 ns auf 
"acquisition time" entfallen, sollte für die Übertragung der 18 bit doch 
eine deutlich langsamere SCLK (<= 50 MHz) ausreichen? Laut Datenblatt 
sind die 100 MHz SCLK Frequenz das Maximum - aber kein Requirement.

von Christian R. (supachris)


Lesenswert?

Valko Z. schrieb:
> Ich befürchte dass wenn der Takt nicht dauerhaft anliegt dann werden die
> FIFO Flags nicht korrekt aktualisiert.

Doch das klappt, denn das Full Flag brauchst du ja nicht, das würde mit 
dem Write Clock aktualisiert. Das Empty Flag wird mit dem Read Clock 
betrieben, sollte also klappen.
Aber du musst das Enable Signal ja auch sauber in die 2. Taktdomäne 
bringen. Was sagt denn das Datenblatt des Isolators wie die Delays 
aussehen? Irgendwie sieht die Lösung bissl kompliziert aus, ist sicher 
gar nicht nötig mit dem Takt zurück führen. Ob das Delay mehr als ein 
Takt ist, ist doch egal, dann muss halt noch ein FF in das Enable Signal 
für das Schieberegister.

von Christian R. (supachris)


Lesenswert?

Burkhard K. schrieb:
> Valko Z. schrieb:
>> Der ADC SPI Takt ist mit 100 MHz festgelegt.
>
> Mal nachgefragt:
>
> Wenn die "time between conversions" 625 ns beträgt und davon 200 ns auf
> "acquisition time" entfallen, sollte für die Übertragung der 18 bit doch
> eine deutlich langsamere SCLK (<= 50 MHz) ausreichen? Laut Datenblatt
> sind die 100 MHz SCLK Frequenz das Maximum - aber kein Requirement.

Nee, denn SPI Transfer geht nur während der kurzen acquisition time. Die 
Datenblätter sind da immer ganz trügerisch, und zeichnen die acquisition 
time viel länger als die conversion time ein. Aber es ist in 
Wirklichkeit genau andersrum. Und 200ns/18Bit sind nur 11.1ns also muss 
man schon mit 100MHz ran. Das nervt uns an den PULSAR Wandlern auch 
immer.

von Domi F. (dfx_06)


Lesenswert?

Um solche asyncen Probleme mit ADC Daten eintakten zu vereinfachen wurde 
mir damals geraten "einfach" BRAMs als Shadow zu missbrauchen.
Hat auch super funktioniert, allerdings habe ich 50MHz ADC Clock mit 
100MHz FPGA Clock verwurstet.

von Valko Z. (hydravliska)


Lesenswert?

Hallo

@Achim S.
Das war die Lösung bis jetzt. Leider hatten wir Probleme wie "Stucking 
Bits" gehabt die nicht erklärbar waren. Und fürs Redesign wollte ich mir 
was anderes überlegen.

@Christian R.
Das ich den FULL Flag nicht brauche hast du vollkommen Recht. Muss 
eigentlich das ganze einmal simulieren dann sehe ich was dabei 
rauskommt.

@Burkhard K.
Wie von Christian erklärt darf NUR während die "Acquisition Phase" 
gelesen werden. Und dann wird es recht schnell knapp mit der SPI 
Frequenz.

Danke an alle für die Antworten.


Gruss

von Achim S. (Gast)


Lesenswert?

Valko Z. schrieb:
> Das war die Lösung bis jetzt. Leider hatten wir Probleme wie "Stucking
> Bits" gehabt die nicht erklärbar waren.

das Raustakten der Daten dauert 180ns, die Zeit zwischen zwei Wandlungen 
ca. 600ns. Auch wenn es durch den Turnaround-Delay ne 
Timing-Unsicherheit von einigen 10ns besteht muss es in den 
verbleibenden (600ns-180ns-x*10ns) locker möglich sein, die Daten stabil 
von der CLK_100_in Domäne in die CLK_Sys Domäne zu übernehmen - das 
Register hat rund 400ns lang einen konstanten Wert am Ausgang. 400ns 
sind lang genug, um die Daten richtig zu übernehmen.

Wenn es Probleme mit falschen Bits gibt, würde ich mir eher das 
Eintakten von SDO mit CLK_100_in anschauen. Das Datenauge am Ausgang des 
LTC2379 ist verdammt klein. Garantiert sind (bei 10ns Takt) gerade mal 
1,5ns (tDSDO und THSDO). Das wird nochmal dadurch angeknabbert, dass die 
Delays durch den Isolator zwar ganz gut matchen, aber eben doch mal ein 
paar 100ps variieren können.

Am Eingang des Spartan 6 bleibt dir also noch ein (garantiertes) 
Setup-Hold Fenster von gut 1ns. Das ist für den Spartan 6 einfach zu 
wenig. In der Praxis mag es trotzdem häufig funktionieren (weil der 
LTC2379 ein besseres Datenauge liefert als in seiner Spec garantiert).

Habt ihr das Setup-Hold Fenster für SDO bezogen auf CLK_100_in in den 
constraints? (Ich denke immer noch, dass der Spartan 6 ein solches 
Constraint gar nicht erfüllen kann). Habt ihr mal am SDO-Eingang einen 
IODelay platziert um den Abtastzeitpunkt von SDO zu optimieren?

Ihr könntet auch mal entweder SDO oder CLK_100_in am FPGA mit ein paar 
pF belasten (aktive Scope-Probe) und so das Signal etwas verzögern. Wenn 
euer Fehler auf einem Setup-Hold Problem beruht, dann müsste es mal 
schlimmer, mal besser werden (je nachdem, welches der beiden Signale Ihr 
belastet). Eine Aufnahme des Datenauges am FPGA wäre sicher auch mal 
nicht uninteressant.

von Achim S. (Gast)


Lesenswert?

Achim S. schrieb:
> Turnaround-Delay

Mist. Sollte eigentlich "Roundtrip-Delay" heißen

von Valko Z. (hydravliska)


Lesenswert?

Hi

wir haben damals ein andere ADC gehabt aber das Interface war gleich - 
CNV anlegen und mit 100 MHz auslesen. Wir haben damals zweimal den 
gleichen Wert nacheinander ausgelesen und das "gefühlt" relativ oft. Wir 
hatten keine Bitwechsel sondern der Wert blieb gleich für zwei 
Wandlungen (als würde der CNV nicht ankommen). Damals ziemlich viel 
rumgemessen aber ohne Erfolg.

IODELAY war und ist vorgesehen.

Dass der Register konstant bleibt ist richtig und ich denke das ist 
ausreichend für das was ich vorhabe. Eigentlich kann ja ein metabstalie 
Zustand auftreten wenn bei der aktive Taktflanke der FF wechselt. Und 
das wäre da nicht der Fall.

CLK_100_IN zu CLK_SYS sowie OFFSE_IN constraints sind auch im UCF 
vorgesehen.

von Achim S. (Gast)


Lesenswert?

Valko Z. schrieb:
> Wir haben damals zweimal den
> gleichen Wert nacheinander ausgelesen und das "gefühlt" relativ oft.

Also nicht der Fehler eines Bits im Datenwort, sondern mehrfach das 
identische Datenwort: das hat dann natürlich nichts mit 
setup/hold-Problemen am SDO zu tun.

Zwei mal der identsiche Analogwert muss nicht per se ein Fehler sein 
(aber man kann dem Spannungverlauf natürlich ansehen, wenn die zwei 
identischen Werte nicht richtig sein können).

Ein Synch-Problem zwischen den Clock-Domänen ist eine denkbare Ursache, 
wobei - wie schon geschrieben - die mehrere hundert ns lange Phase mit 
stabilem Registerausgang sicher ausreichend sein muss, um die Daten 
korrekt zu übernehmen.

Ein andere denkbare Ursache hast du selbst schon beschrieben: bist du 
sicher, dass der CNV-Puls lang genug ist, um vom ADC erkannt zu werden? 
20ns ist laut Datenblatt Minimum, ich würde mindestens 3 Zyklen deines 
10ns Takts vorsehen.

Je nachdem, wie ihr die bisherige Lösung implementiert habt, kämen auch 
Problem innerhalb der CLK_100_in Domäne in Frage. Nutzt Ihr hinter dem 
Schieberegister noch so was wie ein Halteregister, in das der Wert des 
Schieberegisters übernommen wird? Da wäre denkbar, dass der 
"Übernahmepuls" Probleme macht. (Bei der Nutzung eines FIFOs wäre das 
prinzipielle Problem aber das selbe: dort muss ein entsprechender 
WE-Puls erzeugt werden).

Ich würde bei deinem ADC-Timing sowohl auf ein "Halteregister" als auch 
auf ein FIFO verzichten und direkt die Werte des Schieberegisters dann 
in CLK_SYS übernehmen, wenn ich weiß, dass sie seit sehr langer Zeit 
stabil sind (je nachdem, wie die Druchlaufzeiten durch euren Isolator 
sind z.B. 200ns nach dem Absenden des 18. CLK_100_OUT Pulses). Wenn man 
den Delay zwischen CLK_100_Out und CLK_100_in wenigstens halbwegs kennt 
muss es damit klappen, Synch-Probleme zwischen den CLK-Domänen zu 
vermeiden. Und wenn man beim Delay grob daneben liegt, erhält man als 
Fehler nicht zwei mal den identischen Analogwert sondern z.B. Messwerte, 
die um eine oder mehrere Bitpositionen verschoben sind.

Valko Z. schrieb:
> Damals ziemlich viel
> rumgemessen aber ohne Erfolg.

Vielleicht habt ihr alles das eh schon gemacht, aber was mir als erstes 
in den Sinn kommen würde wäre:
- Oszi an Busy-Flag hängen und schauen, ob dessen Puls zwischendurch mal 
ausbleibt (sofern der ADC regelmäßig abgefragt wird sollte sich eine 
ausfallende Wandlung recht gut triggern lassen)
- FPGA den letzten Analogwert mit dem vorletzten vergleichen lassen und 
bei identischen Werten einen Trigger fürs Oszi erzeugen. Mit dem Oszi 
den Datentransfer anschauen (Pretrigger von einigen µs) und analysieren, 
wie der tatsächliche Datentransfer aussah wenn das FPGA meint, zwei mal 
die identischen Daten emfpangen zu haben.

von Valko Z. (hydravliska)


Lesenswert?

Hi

@Achim S.
das ganze mit Trigger ausgeben und Chipscope einbauen um zu schauen dass 
alles passt habe ich mehrmals gemacht. Am Ende konnte erstmal kein FPGA 
Fehler festgestellt werden. Das Redesign beinhaltet jetzt ein 
gleichwertiges Bauteil aber von ein anderen Hersteller. Mal schauen wie 
da sich das ganze verhält :)


Gruss

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.