Guten Tag.
Ich arbeite auf dem Virtex 6 (XC6VLX75T) und nutze die
Beschreibungssprache VHDL. Ich bin dabei Daten von einem AD-Wandler
(AD9249) mittels des gesagten FPGAs einzulesen, und in ChipScope
darzustellen (vgl. Beitrag:
Beitrag "ChipScope limitierende Größe beim Systemtakt?" ). In dem Beitrag wurde
bereits erwähnt, dass es bei den auftretenden Takten zu Schwierigkeiten
kommen kann -> deshalb wurde im Weiteren der Dividend N eingeführt).
Folgende Spezifikationen seien genannt:
- DCO1 = 390/N MHz (65/N MSps * (12 Bit/2))
- DCO2 = 390/N MHz (65/N MSps * (12 Bit/2))
- FCO1 = 65/N MHz (65/N MSps)
- FCO2 = 65/N MHz (65/N MSps)
mit N = [1,2,...,8].
Bei der Wahl von N = 2 erwartet man einen max. Takt von 195 MHz. Dieser
sollte zu handhaben sein.
Ich speise ein Sinussignal passender Frequenz (N = 2) in Kanal A1..H1
sowie A2..H2 ein. Dieses betrachte ich in ChipScope. Im Anhang ist
dieses für zwei Kanäle exemplarisch dargestellt. Man sieht zum Teil
"Ausreißer". Diese scheinen sehr zufällig aufzutreten (ab N = 2
sichtbar).
In einer Testbench fällt mir kein solcher Fehler auf (sowohl vor der
Synthese, als auch nach dieser).
Bemerkung: Über einen externen LogicAnalyzer sehe ich die Ausreißer
ebenso. (ChipScope auskommentiert!)
Ich hänge einmal den Timing Report sowie die relevanten Timing
Constrains für N = 2 an.
Vielleicht hat ja wer Vorschläge bzw. kann aus dem Report mögliche
Probleme ableiten. Vielen Dank
ChipScopeUser schrieb:> In einer Testbench fällt mir kein solcher Fehler auf (sowohl vor der> Synthese, als auch nach dieser).
Dann ist es also mit sehr hoher Wahrscheinlichkeit das altbekannte
Problem: zwei asynchrone Taktdomänen und nicht synchronisierte
Datenpfade...
> Diese scheinen sehr zufällig aufzutreten (ab N = 2 sichtbar).
Man könnte aber auch eine Regelmäßigkeit erkennen: zumindest die kleine
"Zacke" wiederholt sich. Und die anderen Fehler treten alle im
Nulldurchgang auf und sehen gar nicht so arg zufällig aus...
> Bemerkung: Über einen externen LogicAnalyzer sehe ich die Ausreißer> ebenso. (ChipScope auskommentiert!)
An welchen Leitungen misst du da?
ChipScopeUser schrieb:> Man sieht zum Teil> "Ausreißer". Diese scheinen sehr zufällig aufzutreten (ab N = 2> sichtbar).
Ganz so zufällig sehen die mir nicht aus.
Der 'Abstand' zwischen den Ausreißern sieht 'konstant' aus.
Woher kommt der Takt für Deinen ADC?
Woher kommt der Takt für Deinen FPGA?
Duke
Danke euch erstmal.
Lothar Miller:
1)
Werde ich nochmals überprüfen.
2)
Die Zacken treten nicht nur im Nulldurchgang auf. Ich habe dazu einmal
ein Screenshot angehängt, welcher das Verhalten ohne die Einspeisung
eines Signals zeigt.
3)
Ich habe mir den Kanal A1 auf 12 externe IO Pins (P201, P202) am FPGA
gelegt. War mit der Auswahl der Pins vom EV Kit
(https://wiki.analog.com/resources/eval/ad9249-65ebz) eingeschränkt.
Duke:
1)
Betrachtet man den Zeitverlauf (im Angang ist ja nur ein Screenshot
enthalten), sieht man, dass die Abstände nicht konstant sind.
2)
Der ADC wird von einem externen Quarz mit 65 MHz getaktet. Dieser wird
intern (im ADC) um den Faktor N herabgesetzt (je nach Konfiguration).
3)
Der Datenclock (vom ADC erzeugt) wird im FPGA eingelesen (über einen Clk
Buffer).
ChipScopeUser schrieb:> welcher das Verhalten ohne die Einspeisung eines Signals zeigt.
Also wenn wegen des Rauschens ständig irgendein Nulldurchgang
auftritt... :-/
Was bekommst du, wenn du ein Gleichspannung anlegst und aus dieser
Nullzone herausgehst?
ChipScopeUser schrieb:> 2) Gleichspannung anlegen ist aufgrund der werksseitigen> Eingangsbeschaltung nicht möglich.
Aber eine niedrigere/andere Frequenz müsste doch möglich sein...
Lothar Miller:
1)
Hab ich soeben ausprobiert. Die Ausreißer werden weniger (so scheint
es). Allerdings ist die Eingangsbeschaltung für niedrige Frequenzen
nicht wirklich ausgelegt. Ich sehe "Ausreißer" auch außerhalb des
Nulldurchganges.
Würden Teile des VHDL-"Codes" hilfreich sein? Das Projekt ist leider zu
groß, um es hochzuladen.
ChipScopeUser schrieb:> Würden Teile des VHDL-"Codes" hilfreich sein?
Wie sehen Deine Timing-Constraints aus (OFFSET_IN)?
Werdesn diese eingehalten?
Was sagt der Timing-Report?
Duke
Lothar Miller:
Ich habe mir auf deiner Homepage den Artikel zur Einsynchronisierung
durchgelesen (falls du Soetwas meintest).
Die Signale DCO, FCO und Data_in sind nicht speziell als CLk Signale
ausgeführt. Es wird in den angehängten VHDL-Dateien die Flanke vom DCO
Detektiert, um die Daten bei fallender und steigender zu übernehmen.
Anschließend wird anhand des FCO Signals das Wort eingefasst.
Fallen bisher gravierende Fehler in den entsprechenden Dateien auf, die
besagtes Verhalten hervorrufen?
Vielen Dank.
ChipScopeUser schrieb:> Anbei das ucf-File.
Sieht ja erstmal gar nicht so schlecht aus.
Unsicher bin ich mir, ob die Zuordungen mit den INST richtig
funktionieren:
Ich habe bei mir die timings direkt an die input-Netze genagelt:
1
TIMEGRP "ADC_DATA" OFFSET = IN 500 ps VALID 2500 ps BEFORE "ADC_DCO" RISING;
2
3
NET ADC_OUTA_P LOC = A6 | TNM = "ADC_DATA";
4
NET ADC_OUTA_N LOC = B6 | TNM = "ADC_DATA";
Das Constraint auf FALLING wurde immer ignoriert, obwohl ich DDR
verwende.
FCO würde ich nicht als Taktsignal verwenden, sondern nur als ein
weiteres Datensignal, um die Bits richtig zu sortieren.
Wie funktioniert das eigentlich mit den Bänken?
Gibt der ADC alles doppelt aus?
Hast Du ein schnelles Scope mit aktiven Tastköpfen zur Verfügung?
Wenn ja, würde ich mir mal die Datenleitungen darauf anschauen.
Duke
P.S.: Hier nochmal der Link zum Datenblatt:
http://www.analog.com/static/imported-files/data_sheets/AD9249.pdf
ChipScopeUser schrieb:> Es wird in den angehängten VHDL-Dateien die Flanke vom DCO> Detektiert, um die Daten bei fallender und steigender zu übernehmen.> Anschließend wird anhand des FCO Signals das Wort eingefasst.
Koennte das das Problem sein? Ich dachte, mit den OFFSET contraints
schiebst du die Datenbits in der Laufzeit so hin, dass ein mit DCO
getaktetes FF (bzw. 2FFs wg. rising/falling) genau in der Mitte des
Datenbits sampled.
Die OFFSET contraints sollen ja nur dafuer sorgen, dass die Laufzeiten
DCO vs. Datenbit richtig von der Toolchain angepasst werden.
Ich wuerde mir an deiner Stelle mal die Leitungen nach post-place&route
anschauen. Die muessen alle irgendwie "Laengenbalanciert" sein.
Und mit der FCO musst du dann natuerlich den Uebergang in deine
eigentliche Clockdomain sauber hinkriegen
Duke:
1)
Hat nichts am Verhalten geändert.
2)
Genau. Verwende FCO demnach auch als "normales" Signal.
3)
Auf Seiten des ADCs sind jeweils acht Kanäle einem Takt (DCO_1 bzw
DCO_2) zugeordnet. Ich denke, dass dieses an der vom Hersteller
verwendeten Technologie liegt. D.h. beim vorliegenden ADC hat man 2 x 8
Kanäle. Jeder Kanal ist gleich ausgeführt. Im VHDL Design
dementsprechend auch.
4)
Ja habe ich zur Verfügung. Sieht alles brauchbar aus. (Anzahl der Bits,
welche in einen Frame passen, DCO-Frequenz, FCO-Frequenz etc.)
berndl schrieb:> Ich dachte, mit den OFFSET contraints> schiebst du die Datenbits in der Laufzeit so hin
Nene. Die Constraints schieben nichts. Die Timinganalyse schaut nur, ob
die Constraints nach dem P&R eingehalten wurden. Wenn man schieben will,
muß man das selber machen (z.B. mit IDELAY).
ChipScopeUser schrieb:> Ja habe ich zur Verfügung. Sieht alles brauchbar aus.
Auch das Augendiagramm auf den Daten- und Taktleitungen (Datenblatt
Seite 22)?
Per SPI kann man sich Testmuster (Checkerboard, PN sequence, diverse
Toggle) generieren lassen. Gibt es da auch Ausreißer im Chipscope? Wenn
ja, bei welchen Mustern?
Duke
Duke:
1)
Das Augendiagramm habe ich nicht ermittelt. Das würde mir - falls ich an
den Pins des AD-Wandlers direkt messe - ja auch nur zeigen, ob die Werte
korrekt ausgegeben werden.
AD liefert eine zum Kit passende Software mit (AnalogStudio). Mit dieser
gegehen alle Kanäle. Demnach liegt der Fehler noch in meinem VHDL Code.
(Das Problem, weshalb ich die original Software nicht nutze, ist die
fehlende Synchronität der Kanäle seitens des Herstellers.
2)
Habe ich noch nicht versucht.
ChipScopeUser schrieb:> Das Augendiagramm habe ich nicht ermittelt. Das würde mir - falls ich an> den Pins des AD-Wandlers direkt messe - ja auch nur zeigen, ob die Werte> korrekt ausgegeben werden.
Flasch. Man sieht auch die Reflexionen, die von der Verbindung zum FPGA
zurückkommen.
Außerdem kannst Du mal verschiedene Einstellungen für Output Termination
am ADC (bzw. Input Termination am FPGA) testen.
Im Anhang mal ein Beispiel, wie das bei mir aussieht. Ich mußte die
Timing-Constraints enger setzen, damit die Übertragung fehlerfrei
funktioniert.
Duke
Ok. Dann werde ich das Augendiagramm aufnehmen. Zusammenfassend bisher:
(1) Der gepostete VHDL-Code weisst keine groben Fehler auf, welche das
Verhalten erklären?
(2) Nach (1) ist es ein Problem, welches über Timing Constrains zu lösen
ist?
Hattest du ähnliche Probleme (Ausreißer bei deinem Design) Duke?
ChipScopeUser schrieb:> (1) Der gepostete VHDL-Code weisst keine groben Fehler auf, welche das> Verhalten erklären?
Ich hab ihn mir nicht angeschaut. Aber bei groben Fehlern würdest Du gar
keinen Sinus sehen ;-)
> (2) Nach (1) ist es ein Problem, welches über Timing Constrains zu lösen> ist?
Möglicherweise.
> Hattest du ähnliche Probleme (Ausreißer bei deinem Design) Duke?
Im Prinzip ja. Viele Geräte funktionierten und einige nicht so recht.
Wenn Du ausreichend viele Samples verwendest, kannst Du eine FFT machen
und siehst, wie gut der ADC ist (SNR). Da fallen solche (und andere)
Ausreißer sofort auf.
Duke
Ok. In wie weit kann ich das Timing "enger" setzen? Welches Constrains
meinst du? Es ist ja ersichtlich, dass es ab etwa N = 3 funktioniert. N
= 2 bzw N = 1 ist kritisch.
Vlt nochmal ein Beitrag von mir. Ich hatte einen aehnlichen ADC an einem
FPGA Design 'geerbt', das FPGA lief mit 10MHz, der ADC (4-Kanal) hat mit
60MHz zurueck gefeuert. Timing contraints gab es nicht, es hat sich nur
jeder gewundert, dass manchmal nach der Synthese nix mehr ging (Timing
violations halt, wenn halt auch nix spezifiziert ist...).
Das war auf einem Altera Cyclon III. Wir haben uns dann mal hingesetzt,
die Timings auf dem Board (worst-case) analysiert. Und dann passende
Timing Constraints im .sdf (synopsis design constraints) spezifiziert.
(Uebrigens, unter Vivado sollte ein .xdf genau das gleiche sein, unter
ISE ist's ein bisschen anders).
Und was wir damit herausgefunden haben: Vorher waren die Daten und
Clockleitungen komplett unterschiedlich in der Laenge (und damit der
Laufzeit). Danach sah das 'sehr harmonisch' aus, die Daten und
Clockleitungen hatten nach dem Place&Route ziemlich aehnliche Laengen
(bzw. Laengenverhaeltnisse). Seitdem gibt's auch keine Probleme mehr mit
Aenderungen, der Design funktioniert bzgl. ADCs einfach.
Und ich vermute, genau da liegt dein Problem...
berndl:
Vielen Dank für deinen Hinweis. In Sachen Timing Constrains ist bei mir
wohl einiges aufzuarbeiten. Wie analysiere ich soetwas denn in meinem
Fall? Ich "erhalte" ja keine Fehlermeldung im Timing Report etc.. Das
mit den unterschiedlichen Längen der Pfade hört sich nach dem Problem
an.
Es wäre super, wenn ihr mich bei der Fehlersuche anleiten könntet. Was
ein Timing Constrain macht ist mir denke ich klar. Wie ich die Zeiten
analysiere, die ich benötige, scheinbar (in der Praxis) nicht.
Also ein Schritt für Schritt Vorgehen wäre hilfreich. Sagt mir, was ich
dazu ausprobieren bzw. posten soll.
Duke:
Arbeite am Augendiagramm ;)
ChipScopeUser schrieb:> Ich "erhalte" ja keine Fehlermeldung im Timing Report etc..
Naja, was du spezifizierst und was die Toolchain 'frisst', das ist das
was du im Timing Report siehst. Wenn da auch nur irgendwas schiefgeht,
dann kriegst du halt Fahrkarten gemeldet...
Duke's Vorschlag scheint mir ziemlich praktikabel zu sein. Und vor
allem, schau dir die Pfade mal im Chipeditor an. Da muss CLK und DATA
eng begrenzt immer gleich aussehen. Wenn's dann noch nicht funzt, dann
musst du halt die Daten ggue. der Clock im Timing verschieben... Du
musst der Toolchain schon genau sagen, was du eigentlich haben willst...
ChipScopeUser schrieb:> Wie analysiere ich soetwas denn in meinem> Fall?
Klassische Worst-Case Analyse. Was halt so am Eingang deines FPGAs
besten- oder schlimmstenfalls anliegen kann. Ist aufwendig und tut weh,
aber so ist halt das Leben...
Hm, ich hab auf die Schnelle in deinem Code nirgendwo die ISEDES des
Virtex gefunden. Machst du das etwa zu Fuß? Schau die mal die XAPP1064
an, das klappt wunderbar für solche ADCs. Ich benutze das angepasst an
den Artix 7 für den LTM9011-14 ADC. Da muss man sich überhaupt keine
Verrenkungen mit den DDR usw machen. Und das FCO nimmst du als Referenz
für die BitSlip Logik, dann synchronisiert sich die Kiste selber
korrekt.
Duke:
Das habe ich natürlich schon versucht. Werde ich dort zu "klein", dann
gibt es im Timing Report "Verletzungen". Habe mich auch schon
herangetastet.
Hab nur noch folgende Constrains im ucf-file.
TIMEGRP din1_timegroup OFFSET = IN 800ps VALID 1ns BEFORE "DCO1_p"
RISING ;
TIMEGRP din2_timegroup OFFSET = IN 800ps VALID 1ns BEFORE "DCO2_p"
RISING ;
NET bank2_diff_ch_matrix<0><1> LOC = "J11" |IOSTANDARD = "LVDS_25"
|DIFF_TERM = TRUE | TNM = "din2_timegroup";
usw.
Der Offset gibt mir doch in diesem Fall den maximal zulässigen
Zeitversatz zum DCO_1 bzw DCO_2 an, korrekt?
berndl:
Mit dem "ChipEditor" habe ich bisher noch nicht gearbeitet. Meinst du
"View/Edit Routed Design (FPGA Editor)?
ChipScopeUser schrieb:> Der Offset gibt mir doch in diesem Fall den maximal zulässigen> Zeitversatz zum DCO_1 bzw DCO_2 an, korrekt?
Die 800 ps sind die Setup-Time, ja. Die 1 ns ist Setup-Time + Hold-Time.
Diese Werte sind aus dem Datenblatt von AD etwas schwierig
herauszuholen, weil dort die Samplerate (bzw. das Vielfache davon) mit
eingeht.
Bei all diesen Betrachtungen wird oft von einem idealen Takt
ausgegangen. Vielleicht kannst Du Dir den nochmal getrennt anschauen und
auf Jitter bzw. Phasenrauschen untersuchen (Scope -> Spekki -> phase
noise analysator).
Duke
Danke euch.
Duke:
Das Datenblatt gibt in der Tat nur schwer die Zeiten preis. Ich versuche
momentan Durchblick in PlanAhead zu bekommen, um zu schauen, ob die
Leitungen eng beieinander liegen.
Ist es möglich eine Datei hochzuladen, damit ihr mal drüber schauen
könnt?
Christian:
Hab es bisher "zu Fuss" gemacht, da mir die andere Option nicht bekannt
war. Dieses nun zu ändern, würde ein komplettes redesign bedeuten. Da
die Funktionalität generell gegeben ist (bei geringen Abtastraten), ist
es wohl sinnvoller den Fehler/Timingproblem zu beheben. Ich nehme den
Hinweis jedoch für ein zukünftiges Projekt gerne auf. Danke dir.
ChipScopeUser schrieb:> Ist es möglich eine Datei hochzuladen, damit ihr mal drüber schauen> könnt?
Ich werde wohl dieses Jahr kein FPGA-Design mehr anfassen :-)
ChipScopeUser schrieb:> Hab es bisher "zu Fuss" gemacht, da mir die andere Option nicht bekannt> war. Dieses nun zu ändern, würde ein komplettes redesign bedeuten. Da> die Funktionalität generell gegeben ist (bei geringen Abtastraten), ist> es wohl sinnvoller den Fehler/Timingproblem zu beheben. Ich nehme den> Hinweis jedoch für ein zukünftiges Projekt gerne auf. Danke dir.
Naja, ich denke, du wirst das nur sehr schwer in den Griff bekommen und
damit viel mehr Arbeit haben, als wenn du das austauschst. Das ist dank
der XAPP1064 und dem ISERDES Core Generator schnell gemacht. Ich würde
es dir dringend empfehlen. Das ist alles fix und fertig, ich kann dir
auch Quelltext-Schnipsel reinstellen bei Bedarf, ist aber eigentlich
nicht nötig, das erzeugt der Coregen alles für dich, sogar als VHDL.
Außerdem macht man das mit der Abtastrate anders, man lässt den ADC mit
voller Geschwindigkeit laufen und benutzt dann im FPGA nur jedes x.
Sample. Dann bekommst du weitaus weniger Stress mit den Taktdomänen,
weil du immer den gleichen Takt hast.
Freilich hat der Virtex 6 auch die ISERDES integriert. Lass dir einfach
mal einen Core generieren, zusammen mit der xapp siehste dann sehr
schnell durch. Die Dinger gehen problemlos bis über 1GBit/s pro
Leitungspaar.
Da musst du sicherlich erst mal in den Projektoptionen den passenden
FPGA einstellen, dann wirds aktiv. Bei supported families auf der
rechten Seite ist ja der V6 dabei.
Habs ;)
Werde mich morgen mal dran setzen. Vielleicht komme ich damit ja weiter,
wenn ich das Projekt von vorn aufarbeite.
Ich habe ja zwei FCOs (zwei Bänke). Da müsste ich dann quasi zwei Cores
einfügen?
Die Option eine variable Anzahl von Kanälen (z.B. 4 von 16) zu nutzen
(platz auf dem FPGA zu sparen, bleibt mir wahrscheinlich mit der Nutzung
des Cores nicht erhalten, oder? Bzw. muss ich für jeden Kanal einen
eigenen Core anlegen/ einbinden?
Hast du für meinen Fall Beispieleinstellungen (du sagtest du hattest ein
ähnliches Projekt)?
Doch, das geht. Du brauchst für jedes Leitungspaar so einen ISERDES,
außer für den DCO. Da die sowieso alle einzeln sind, kannst du die auch
nach Bedarf instanziieren. Mit dem Ausgang des FCO steuerst du die
Bitslip Logik, die die Daten gerade rückt. Bei zwei Bänken brauchst du
halt alles doppelt, hab ich ja auch am LTM9011. Code suche ich mal im
Laufe des Tages, ist aber 1:1 aus der Xapp1064.
Hm, anscheinend geht das mit den ISERDES am V6 doch nicht so mit dem
speziellen ADC zusammen. Denn die können erst mal keine 14:1
Parallelisierung (Nur 2-4-6-8-10). Da müsste man mal schauen, ob der
Trick aus der XAPP104 für höhere Serialisations-Faktoren mit dem
Master/Slave Teil beim Virtex auch klappt...das ist ja ein blöder ADC,
die mit den 2 Lanes pro Kanal sind da viel sinnvoller. Vielleicht musste
dann doch zu Fuß implementieren...
Christian R. schrieb:> Hm, anscheinend geht das mit den ISERDES am V6 doch nicht so mit dem> speziellen ADC zusammen. Denn die können erst mal keine 14:1> Parallelisierung (Nur 2-4-6-8-10). Da müsste man mal schauen, ob der> Trick aus der XAPP104 für höhere Serialisations-Faktoren mit dem> Master/Slave Teil beim Virtex auch klappt...das ist ja ein blöder ADC,> die mit den 2 Lanes pro Kanal sind da viel sinnvoller. Vielleicht musste> dann doch zu Fuß implementieren...
Allerdings nur das Framing. Es ist trotzdem sinnvoll die ISERDES im 1:4
bzw 1:6 Mode zu verwenden. 1:4 ist portabler auf FPGA's anderer
Hersteller, einen IDDR mit x2 Mode (d.h. 1:4) dürfte jeder moderne FPGA
haben.
Danke für die zahlreichen Hinweise. Ich lese aus den letzten Beiträgen
heraus, dass das Verwenden des ISERDES nicht die einfachste/idealste
Lösung für den speziellen ADC ist.
Mein Versuch wäre es jetzt, dass "Programm" noch einmal Schritt für
Schritt aufzubauen (eigentlich ist es ja nicht viel "Code").
Vielleicht wäre dieses am besten, um den Fehler zu entdecken. Also werde
ich meinen Ansatz und dessen Umsetzung zur "Kontrolle" posten, wenn es
ok ist.
Variante (a):
- Zu Fuss
Variante (b):
- 4 x 4 ISERDES (benötigt wohl mehr Fläche auf dem FPGA, deswegen von
mir nicht so bevorzugt. Sehe auch in meinem Fall mit dem speziellen ADC
nicht unbedingt den Vorteil)
Es muss doch auch für einen Anfänger wie mich möglich sein, den ADC zum
Laufen zu bekommen. ;)
ChipScopeUser schrieb:> Danke für die zahlreichen Hinweise. Ich lese aus den letzten Beiträgen> heraus, dass das Verwenden des ISERDES nicht die einfachste/idealste> Lösung für den speziellen ADC ist.
Das siehst du falsch.
> Variante (a):> - Zu Fuss
Nur mit Constraints und ohne in den IO Zellen vorhande Funktionalität,
ist das Wahnsinn.
>> Variante (b):> - 4 x 4 ISERDES (benötigt wohl mehr Fläche auf dem FPGA, deswegen von> mir nicht so bevorzugt. Sehe auch in meinem Fall mit dem speziellen ADC> nicht unbedingt den Vorteil)
Der ISERDES ist eine in IO Zellen vorhandene Funktion, d.h. die braucht
eben gar keine Fläche. Und um von 1:4 ode 1:6 auf 1:12 zu kommen braucht
es nur wenig nachgeschaltete Logik/Register.
>> Es muss doch auch für einen Anfänger wie mich möglich sein, den ADC zum> Laufen zu bekommen. ;)
1. Schritt, mal sich die Datenblätter wirklich genau anzuschauen, ein
FPGA ist mehr als nur Clocktree, LUTs und Flipflops, und nicht einfach
los schreiben.
Lattice User:
Danke dir. Ich werde mir auf Grund deines Beitrages das Datenblatt zum
ISERDES noch einmal genau durchlesen, und gegebenfalls nachfragen.
Lattice User:
Hab mir nun ein Konzept erstellt.
(1) Einbinden des IPCores ISERDES jeweils einmal pro Kanal (zu Beginn
beschränke ich mich auf einen Kanal).
(2) Figure 4 der von Euch angesprochenen Note 1064 zeigt, wie ich einen
seriellen Stream der Wortlänge 12 einlese und parallelisiere.
(Allerdings wäre dieses für 14 Bits nicht ohne Aufwand später zu ändern,
was nicht schlimm ist in diesem Fall)
(3) Testbench erstellen und testen :)
Meine aufgetretenen Fragen:
(a) Ich orientiere mich beim Einlesen des Datenstreams am DCO-Takt, so
wie ich das verstehe. Sind zwölf Werte eingelesen (DDR), dann liegt ein
Wort am Ausgang des Cores an. Da ich für eine Bank im ADC den selben DCO
nehme, müssten die Daten vollkommen synchron an acht möglichen Ausgängen
anliegen, richtig? Das Framesignal benötige ich sozusagen vom ADC her
nicht!
(b) Für die zweite Bank am ADC mache ich das Selbe, nur, dass ich DCO2
statt DCO1 verwende. Nun muss ich die Daten von Bank 1 und Bank 2 wieder
synchronisieren.
In dieser Variante fällt der ärger mit Timing Constrains weg.
Naja, Frame brauchst du schon, musst ja den Anfang finden. Der DCO Clock
ist ja ein vielfaches des Sample Taktes und wir zum Einlesen gebraucht.
Deine interne Logik sieht den durch 7 geteilten Takt und das ist ja
gerade das entspannte an der Geschichte, die 500MHz interessieren dich
gar nicht so recht.
ChipScopeUser schrieb:> Lattice User:> Hab mir nun ein Konzept erstellt.>> (1) Einbinden des IPCores ISERDES jeweils einmal pro Kanal (zu Beginn> beschränke ich mich auf einen Kanal).> (2) Figure 4 der von Euch angesprochenen Note 1064 zeigt, wie ich einen> seriellen Stream der Wortlänge 12 einlese und parallelisiere.> (Allerdings wäre dieses für 14 Bits nicht ohne Aufwand später zu ändern,> was nicht schlimm ist in diesem Fall)> (3) Testbench erstellen und testen :)>
In etwa, nur ein kleines Problem, der ISERDES kann keine 1:12 auf dem
Virtex6.
D.h. wenn du 1:6 verwendest, bekommst du die 12 Bits des ADC in 2
Takten.
FC liest du genau so ein, damit du weisst wann die Daten anfangen.
Um auf FC zu synchronisieren, kannst du entweder das Bitslip Module des
ISERDES verwenden und solange schieben lassen bis es passt, oder eine
FSM nachschalten. Letzteres ist dann mit etwas nachdenken auch auf 14
Bit erweiterbar.
Noch einen kleinen Tipp:
wenn du den ISERDES mit 1:2 verwendest, bekommst du mit jedem takt 2
Bit, und kannst eventuell das meiste von deinem bisherigen Code
weiterverwenden.
Nachteil: Teiler N=1 wird schwierig.
Eine kurze Nachfrage:
Für das Design nach Abb. 4 sollte ich schon die App-Note verwenden,
richtig? Also nicht "direkt" den IPCore einbinden und dann das
Blockschaltbild einzeln nachbilden.
Ich habe das ganze noch nicht ganz verstanden. Was der IPCore ISERDES
macht, dass ist denke ich klar. Je nach Einstellung deserialisiert
dieser eine Eingangsfolge.
Jetzt bildet so wie ich das verstanden habe das Design
"serdes_1_to_n_clk_pll_s16_diff.vhd" den oberen und das Design
"serdes_1_to_n_data_s16_diff.vhd" den unteren Teil des Blockschaltbildes
aus Fig. 4 ab.
Lattice User:
Es ist wohl (wegen N = 1) sinnvoll den Stream in 4 x 3 zu unterteilen
(12 bit).
Was genau macht der obere und der untere Block?
Ich habe es so verstanden, dass der obere Block zunächst vier Bit
jeweils zusammenfassen soll, und einen CLK bereit stellt, welcher dem
unteren Block übergeben wird. Dieser fasst dann jeweils 3 der
vier-Bit-Blöcke zu einem 12 Bit Block zusammen.
Nun weiß ich nicht, wie ich D und S einzustellen habe in der App.
Ich möchte ja 12 Bit Ausgangswortbreite erhalten. Demnach muss das
Produkt S*D = 12 sein => S = 4, D = 3?
Wo speise ich nun meinen Datastream vom ADC ein? Dieser ist ja stets 1
Bit breit? Entschuldigung, dass ich so verwirrt frage. Irgendwie wurde
ich aus der Doku nicht schlau.
1. Frage :)
Ist Abbildung 4 aus der App-Note 1064 überhaupt die korrekte Wahl (dort
steht ja etwas von dem höheren Faktor). Meint ihr das die ganze Zeit?
2. Frage:
Wenn ja, wo lege ich den seriellen Datastream an?
Also Bild 4 ist schon das richtige. Da der S6 vom Virtex 5 abgeleitet
ist, sollte das auf dem Virtex 6 ähnlich klappen. Solche Spezialfälle
werden vom Coregen aber nicht abgedeckt, das muss man nach der Appnote
machen. Wenn ich heut noch zeit hab, schau ich mal, ob der Virtex diese
Master/Slave Geschichte hat, oder ob da ein ISERDES im 1:7 Modus reicht
(falls überhaupt möglich). Auf jeden Fall muss an den oberen Block der
DCO Takt dran, an den unteren eine Datenleitung mit dem seriellen
Datenstrom vom ADC. Den unteren Block brauchst du dann halt mehrfach. D
wäre bei dir 1, S wäre 14.
Hm, ich weiß nicht. Auch da laufen die 14 Bit ADCs im 16 Bit Modus. Der
blöde 14 Bit auf 1 Leitung Modus wie ihn dein ADC hat. Ich hab aber im
Datenblatt auch nix gefunden, wie man den in einen sinnvollen modus
schalten kann.
Christian R.:
Irgendwie sehe ich das wohl falsch. Die APP-Note deckt doch genau meinen
Fall ab. (siehe zB. Tabelle 1 Seite 5: 12 Bit bei 80 MSp/s (ich wäre mit
64 MSp/s sogar drunter)
Außerdem stimmt das Datenformat des AD9249 mit dem aus Abbildung 2/Seite
2 überein (also bei mir 12 Bit Mode).
Außerdem ist das ganze Dokument auf den Virtex6 zugeschnitten.
Auch die XAPP1071 schaut etwas schlampig gemacht aus. Aus der UG361
(IOSelecr userguide für den Virtex&) geht klar hervor, dass der
ISERDES1 nur 6 bit kann. Also nicht mit 14 bit, auch nicht mit dem Trick
die beiden ISERDES an den 2 LVDS Pins im SDR Mode zu benutzen.
Ich würde einfach nur einen einzigen ISERDES1 (pro Datenleiting) im DDR
Mode nutzen, und die Erweiterung auf auf viele Bits und das Framing mit
einer kleinen FSM dahinter machen. Als Lattice ECP3/MachXO2 User habe
ich ohnehin keine Wahl, das es da nichts zu kaskadieren gibt, und auch
Bitslipper.
Achso, ich dachte du willst den 14 Bit Modus des ADC nehmen, der ist
nämlich echt blöde. Beim 12 Bit Modus sollte das relativ einfach mit der
Kaskadierung klappen....so richtig schön ist dsas aber erst mit der 7er
Serie geworden, am Artix ist der LTM9011 ein Kinderspiel.
Lattice User:
Gerade für noch nicht so Erfahrende auf dem Gebiet des FPGA Designs ist
es schwer solche App.-Notes richtig zu lesen/deuten.
Den Userguide (IOSelecr userguide für den Virtex) habe ich auch grad
auf.
Christian R.:
Ich möchte den 12 Bit Mode nutzen. Auf diesen kann ich per SPI bereits
wechseln. Tut mir leid für die Verwirrung.
Es stehen meiner Meinung nach viele Ansätze im Raum. Jetzt muss ich
einen konsequent umsetzen. Kann mir noch einmal einer von euch
zusammenfassend sagen, welche App. Note/Lösung für einen noch nicht so
erfahrenden Entwickler umzusetzen ist ? (mit eurer Unterstützung). Bin
ja mit meinem ursprünglichen Design auf dem Holzweg gewesen.
Lattice User:
Ich versteh nicht recht. "SAME_EDGE_PIPELINED" ist die ganze Zeit
gesetzt in meinem Code.
Ihr meintet doch, dass ich von "meinem" existierenden Code weg soll (auf
Grund vom Timing: das sagten ja auch die ganzen App-Notes, dass bei
meinen Taktraten ein ISERDES zu nutzen ist). Korregiere mich ruhig;)
Ich versuche die ganze Zeit schon den ISERDES1 zu verstehen.
Funktion:
- mit dem ISERDES1 kann ich die Eingangsdatenfolge D in einen parallelen
Ausgangsdatenstream Q umsetzen.
Eingänge:
D : Eingangsdaten z.B. 1 0 1 0 0 1 1 0 0 0 1 1 1 ...
DDLY
CLK : DCO_p
CLKB : DCO_n
CE1
CE2
RST : Reset
CLKDIV :
OCLK
BITSLIP : wird benötigt, falls man die Position der Daten ermitteln
möchte
SHIFTIN1
SHIFTIN2
OFB
DYNCLKDIVSEL
DYNCLKSEL
Ausgänge:
Q : paralleler Datenstream z.B für Wortbreite 4 1010 0110 0011 1
...
O
SHIFTOUT1
SHIFTOUT2
Keine Funktion in der Testbench
ChipScopeUser schrieb:> Lattice User:> Ich versteh nicht recht. "SAME_EDGE_PIPELINED" ist die ganze Zeit> gesetzt in meinem Code.
habe mich wohl verguckt.
Eigentlich sollte IDDR mit "SAME_EDGE_PIPELINED" unkritisch sein,
zumindestens bei deinen bisher genutzten 200 MHz.
Sind DC0/DC1 an einem Clock Input des FPGA's angeschlossen?
Wenn nein geht es auch mit dem ISERDES nicht.
Lattice User:
1)
Bei 32.5 MS/s (d.h. 195 MHz DCO) funktioniert es ja nach Setzen der
Timing Constrains auch. Bei 65 MS/s (d.h. 390 MHz) funktioniert es
nicht. Deshalb w
wird ja hier gerade das mit dem ISERDES angesprochen ;)
2)
DCO1, DCO2 (beim Virtex6 XC6VLX75T-2FFG784C) liegen auf
F7(IO_L9P_MRCC_36), G7(IO_L9N_MRCC_36), H11(IO_L10P_MRCC_36) und
H10(IO_L10N_MRCC_36). Also CLK Pins.
NET DCO1_p LOC = "F7" |DIFF_TERM = "TRUE" |IOSTANDARD = "LVDS_25";
NET DCO1_n LOC = "G7" |DIFF_TERM = "TRUE" |IOSTANDARD = "LVDS_25";
NET DCO2_p LOC = "H11" |DIFF_TERM = "TRUE" |IOSTANDARD = "LVDS_25";
NET DCO2_n LOC = "H10" |DIFF_TERM = "TRUE" |IOSTANDARD =
"LVDS_25";
ich selbst kann dir kein Beispiel generieren, mangels Xilinx SW.
Eventuell findet Christan etwas Zeit.
In diesem Thread findest du eines in Verilog (Kaskadiert mit Master
Slaver, max 10 bit)
http://forums.xilinx.com/t5/Virtex-Family-FPGAs/V6-iserdes1-expansion/td-p/242272
Versuche als Einsteig in deinem Code das IDDR durch ISERDES1 in 2 bit
Mode zu ersetzen. Schafft dann zwar auch nicht die 65 MS/s aber du
bekommst ein Gefühl dafür was am an einer einzelen ISERDES1 alles
angeschlossen werden muss.
Wenn das geht, auf 4 oder 6 bit Mode upgraden.
Dann dir schöne Feiertage. Wäre hilfreich ein Beispiel für das serielle
Einlesen eines Kanals zu haben, ja :)
Ich bin mit dem ISERDES1 nicht viel weiter gekommen (siehe Anhang). Ich
wollte zunächst einen 1:4 seriell zu parallel umsetzer testen. Das
Resultat in der Testbench stimmt nicht.
Wann wird beim ISERDES1 ein Datenwert übernommen?
Fall 1: SDR
Am CLK-Eingang (CLK) liegt der DCO-Takt an. Jetzt sollte doch bei jeder
steigenden Flanke des DCO-Taktes ein Datenwert des Signals an D
übernommen werden.
Am CLKDIV liegt der Frameclock. Ist z.B. die Wortbreite 4 eingestellt,
ist dieser ein vierfaches vom DCO.
Fall 2: DDR
Am CLK-Eingang (CLK) liegt der DCO-Takt an. Jetzt sollte doch bei jeder
steigenden und bei jeder fallenden Flanke des DCO-Taktes ein Datenwert
des Signals an D übernommen werden.
Am CLKDIV liegt der Frameclock. Ist z.B. die Wortbreite 4 eingestellt,
ist dieser ein zweifaches vom DCO.
Meine TestBench zeigt anderes Verhalten.
ChipScopeUser schrieb:> Wann wird beim ISERDES1 ein Datenwert übernommen?>> Fall 1: SDR>> Am CLK-Eingang (CLK) liegt der DCO-Takt an. Jetzt sollte doch bei jeder> steigenden Flanke des DCO-Taktes ein Datenwert des Signals an D> übernommen werden.> Am CLKDIV liegt der Frameclock. Ist z.B. die Wortbreite 4 eingestellt,> ist dieser ein vierfaches vom DCO.
Nicht ein vierfaches, sondern ein Viertel.
>> Fall 2: DDR>> Am CLK-Eingang (CLK) liegt der DCO-Takt an. Jetzt sollte doch bei jeder> steigenden und bei jeder fallenden Flanke des DCO-Taktes ein Datenwert> des Signals an D übernommen werden.> Am CLKDIV liegt der Frameclock. Ist z.B. die Wortbreite 4 eingestellt,> ist dieser ein zweifaches vom DCO.
Und hier die Hälfte
ChipScopeUser schrieb:> Dann dir schöne Feiertage. Wäre hilfreich ein Beispiel für das serielle> Einlesen eines Kanals zu haben, ja :)
Danke dir. Leider hab ich hier zu Hause nur die aktuellen Files mit dem
Artix 7, die Sachen für den Spartan 6 hab ich auf Arbeit, da komm ich
von hier aus nicht ran, erst am 5.1. wieder. Ich hoffe, das versaut dir
nicht Weihnachten :)
Aber da gibts schließlich auch wichtigeres als FPGA Design.
CLK=>FCO,-- for testing 3xDCO (3 x 4 bit blocks = 12 bit)
2
CLKB=>Low,
3
CLKDIV=>DCO,-- adc data clock (max. 390 MHz)
4
OCLK=>Low,
DC0 ist deine Inputclock, und gehört auf CLK
An CLKDIV gehört eine aus DC0 im richtigen Verhältnis Clock (1/2 für
4bit). Das ist dann auch die Clock mit der du deine Weiterverarbeitung
treibst.
In der Testbench kannst du sie einfach mal teilen, auf dem FPGA muss sie
mit PLL,DCM etc erzeugt werden.
1
Divided Clock Input - CLKDIV
2
The divided clock input (CLKDIV) is typically a divided version of CLK (depending on the
3
width of the implemented deserialization). It drives the output of the serial-to-parallel
4
converter, the Bitslip submodule, and the CE module.
FC0 hat hier nichts zu suchen.
FCO gehört auf einen zweiten ISERDES1 als Dateninput, lass es erstmal
aussen vor.
Noch etwas, FC0 ist eigentlich keine Clock, sondern ein Datensignal um
zu erkennen wo deine Framegrenzen sind.
Genau, den CLKDIV musst du über DCM/PLL oder solche Clock Buffer mit
Teilerfunktion erzeugen, das ist dann auch dein interner Takt, muss dann
noch über einen Bufg. An CLK und CLKB muss der schnelle Takt, also vom
ADC der DCO.
Lattice User:
Du schriebst, dass ich das IDDR durch ein ISERDES im 2 Bit Modus
zunächst zum Test ersetzen sollte. Das funktioniert nicht. Im DDR Mode
darf das N (1:N) nur 4 und größer betragen. Versuche morgen eure
Ratschläge umzusetzen
Hab es mit N = 4 und N = 6 ausprobiert. Anbei das Simulationsresultat
und der Ausschnitt aus dem VHDL-Code. Irgendwie passt das nicht. Was
mache ich hier falsch?
Da stimmt doch einiges nicht. Wieso ist der CLKB nicht angeschlossen?
Normal muss der auf den negierten schnellen Takt. Dann betreibst du den
ISERDES im Slave Modus. Wo ist der Master? Und außerdem muss doch beim
Slave so ein SHIFTIN dann genutzt werden, der vom SHIFTOUT des Masters
kommt, wenn ich mich recht erinnere...und sollten nicht beide Clock
Enables aktiv sein?
Danke. ISERDES funktioniert. Außerdem habe ich das gefunden
https://ez.analog.com/message/145116. Exakt mein Problem ;). Also mit
der Verwendung der ISERDES fahre ich gut, denke ich.
Ich habe nun meine Daten DIN 1:4 gewandelt. Nun muss ich diese 1:3
wandeln, um auf 12 Bit zu kommen, richtig? Also DOUT als neuer DIN
verwenden von einem zweiten ISERDES mit N = 3. (Master-Slave
funktioniert leider nur bis 10 Bit)
Was ich genau mit dem Frame machen soll, ist mir noch nicht klar.
Naja, die Frage ist, ob die ISERDES sich einfach so hin Reihe schalten
lassen. Die hängen ja schon direkt am IO Pin dran. Da musst du
wahrscheinlich dahinter "einfach" noch vier 3 Bit Schieberegister
machen, um die Daten noch weiter zu parallelisieren. Allerdings musst du
dich dann um BitSlip und Einsynchronisieren selber kümmern. Das Frame
Signal behandelst du wie ein 6 Bit breites Datensignal direkt mit einem
ISERDES und nimmst das Ausgangssignal für die Bitslip Logik aus der
XAPP1064, um die ISERDES auszurichten. Das Sync-Pattern muss dann halt
"000111" oder halt "111000" sein....dann richtet sich deine erste Stufe
schon mal selber aus.
Zusammenfassung bisher:
1. ISERDES_ODD liest die Daten bei steigender Flanke ein.
CLK => ADC_CLK_net,
CLKB => not ADC_CLK_net,
CLKDIV => ADC_CLK_DIV_net,
2. ISERDES_EVEN liest die Daten bei fallender Flanke ein.
CLK => not ADC_CLK_net,
CLKB => ADC_CLK_net,
CLKDIV => ADC_CLK_DIV_net,
3. DOUT <= q_even_net(5) & q_odd_net(5) & q_even_net(4) & q_odd_net(4)
...
4. ISERDES_FRAME liest die Daten (FCO) bei steigender und fallender
Flanke (DDR) ein. DOUT sieht dann in der ART aus
"11111100000011111100000011111100..."
Nun muss ich die Bits noch "schieben", bzw. den Anfang finden. Du
sagtest, dass ich es über Bitslip mache. Ganz klar ist mir die Sache
nicht.
Ich habe die "Bits" zur Zeit ja mittels eines Delays in der TestBench
passend "hingeschoben". Dieses "Hinschieben" soll nun mittels des FCO
geschehen.
Schau noch mal in die Xapp 1064 rein, da ist eine kleine FSM, die immer,
wenn das Datenwort nach dem Iserdes für das FCO nicht passt, einen
Impuls am BitSlip eingang aller ISERDES auslöst. Dann wird wieder eine
Weile gewartet, und dann wieder geschaut, ob es passt. Irgendwann hat
der FCO dann den Wert den paasenden Wert und somit alle anderen auch. Ob
das bei der Mogelschaltung mit den zwei ISERDES dann auch richtig
aligned ist, Küste man nochmal genau durchdenken, notfalls musst du die
selbe Sache für FCO machen, dass das auch völlig zueinander passt.
Meinte auch das parallelisierte ;). Habe in der APP keine
Funktionsbeschriebung entdeckt. Hier
http://www.xilinx.com/support/documentation/application_notes/xapp1071_V6_ADC_DAC_LVDS.pdf
ist eine aufgeführt (abbildung 9).
Zum Verständnis:
1. Parallelisieren des FCO (DIN) in 6 Bit Blöcken bei 12 Bit ADC
2. Der FCO ist in Phase zum DCO.
3. Nun gilt es den "Anfang" des FCOs zu ermitteln
4. Man muss nun das parallelisierte Wort aus 1. mit einem Pattern
vergleichen (in diesem Fall mit "111111000000"
5. Falls dieses nicht stimmt, wird BitSlip high gesetzt, bis der
Comperator eine Übereinstimmung feststellt
6. Stimmen FRAME und Pattern überein, dann erhält man eine "Konstante" (
z.B. 3 BitSlip-Vorgänge)
7. Demnach müssen die Datenbits um diese "Konstante geschoben werden
Sehe ich das Grundkonzept richtig?
FC0 wird genauso wie die Daten mit einem eigenen ISERDESE1
parallelisiert. Im Falle der Odd/Even Methode reicht der Odd.
Danach ist es einfach, wenn FC0ParOdd != "111000", Bitslip für alle
ISERDESE1 der Gruppe triggern sollte reichen.
Eine komplierte FSM ist nur nötig wenn die Syncpattern im Nutzdatenstrom
enthalten, und womöglich auch falsche Syncs auftreten können. Das ist
hoer nicht der Fall.
Eine Nachfrage: mit dem BitSlip sortiert man die Bits - welche vorher zu
einem Wort zusammengefasst wurden - um. Ich muss nun doch eher den
Beginn der parallelisierung verschieben am FCO ausrichten). Was hat das
mit nem BitSlip zu tun?
ChipScopeUser schrieb:> Eine Nachfrage: mit dem BitSlip sortiert man die Bits - welche vorher zu> einem Wort zusammengefasst wurden - um.
Nein
> Ich muss nun doch eher den> Beginn der parallelisierung verschieben am FCO ausrichten).
Genau das macht Bitslip, es verschiebt den Beginn in Relation deinem
CLKDIV.
Ein Puls am Bitslip => einmal verschieben.
Genau, und das BitSlip darf immer nur ein Takt des DIVCLK auf High sein,
dann eine Weile warten, dann erst bei Bedarf wieder genau einen Takt
setzen. Einfach gesetzt lassen klappt nicht. Daher die FSM in der XAPP.
Ok. Danke. In der XAPP1064 finde ich die StateMachine nicht. Hast du da
eine Seitenzahl für mich? Ich setze mich einmal dran, die selber zu
schreiben bis dahin.
So, hier mal die Files aus dem Artix 7 Design. Das ist eigentlich direkt
aus der XAPP1064 abgeleitet, nur die Xilinx Primitiven halt getauscht.
Bei mir hab ich am DCO noch ein IDELAY Element, damit kann ich den
Abtastzeitpunkt genau in die Mitte des Datenauges schieben. Hab ich mit
einem kleinen Testdesign einmalig rausgesucht, könnte man auch
automatisieren, aber die Leiterplatte ändert sich ja nicht. Wir haben
auch alle Datenleitungen gleich lang gemacht, so dass es ausreicht, den
Takt zu verschieben.
Eine Unstimmigkeit ist aufgetreten.
VHDL-Datei zum Test der Frame State Maschine (Bspw. 6 Bit Wortbreite):
a) Ohne State Maschine:
BITSLIP <= BITSLIP im VHDL-Code (gelber Kasten). BITSLIP wird in der
TestBench wie folgt belegt.
stim_proc: process
begin
wait for 75 ns;
BITSLIP <= '1';
wait for 10 ns;
BITSLIP <= '0';
wait;
end process;
Resultat: Bitslip Operation funktioniert.
b) Mit State Maschine (1 BitSlip zum Test):
BITSLIP <= BITSLIP_net im VHDL-Code (gelber Kasten). In der TestBench
sieht alles wie im Fall a) aus.
Resultat: Bitslip funktioniert nicht. Verstehe nicht wieso.
Ist die State Maschine von der Tendenz her korrekt aufgebaut?
ChipScopeUser schrieb:> Resultat: Bitslip funktioniert nicht. Verstehe nicht wieso.>> Ist die State Maschine von der Tendenz her korrekt aufgebaut?
Falsche Verwendung von VHDL Variablen.
Falscher Aufbau eines getakteten Prozesses.
@Christian
Du machst zwischen 2 Bitslip pulsen eine Pasue von 7 Frames.
Ein Frame kann ich verstehen, aber warum so lang?
Christian R. schrieb:> Wie gesagt, aus der XAPP kopiert... ;)
Ich hinterfrage so etwas immer, bei solchen Appnotes ist immer viel C&P
im Spiel.
Wenn es mit einem Frame Pause geht, sollte dieser Einzeiler reichen
Hm, müsste man noch mal in den User Guide schauen, ich glaube da war
schon etwas mehr Pause nötig um das Bit weiter zu springen....steht ja
detailliert da beschrieben. Ich glaube "ChipScopeUser" sollte das auch
mal tun, dann würden sich einige Fragen erübrigen. Aber einen blutigen
Anfänger (sieht man an seinem Code) mit sowas zu betrauen ist eh
grenzwertig, das macht man nicht mal nebenbei. Wahrscheinlich wieder so
eine völlig über-ambitionierte Diplomarbeit, oder noch wahrscheinlicher
was von einer HTL....die überschätzen sich ja generell. Scheint Teil des
Lehrplanes zu sein.
Christian R. schrieb:> Hm, müsste man noch mal in den User Guide schauen, ich glaube da war> schon etwas mehr Pause nötig um das Bit weiter zu springen....steht ja> detailliert da beschrieben.
Habe es mir angeschaut, Im SDR Mode reicht zum eigentlichen
Weiterspringen ein Frame Pause, aber der Slip wird erst wahrend dem
Pauseframe ausgeführt was zur Folge dass die Framedaten ungültig sind.
D.h. man braucht ein weiteres Frame Pause.
Im DDR Mode ist keine Pause nötig.
PS:Irrtum vorbehalten.
PSS: Geht immer noch in einem Einzeiler.
Danke. Simulation klappt soweit für den vorliegenden adc.
Eine Frage zum IDELAYE Element. Es hat die Aufgabe das Signal
"clk_in_int", um ein festes Delay zu verschieben => clk_in_int_delay.
Beim mapping tritt folgender Fehler auf:
IDELAYCTRL not found for clock region CLOCKREGION_X1Y2. The IODELAYE1
block
ADC_INTERFACE/DATA_CLOCK_1/IODELAY1_VIRTEX6_clk has an IDELAY_TYPE
attribute of FIXED, VARIABLE, or VAR_LOADABLE.
This programming requires that there be an IDELAYCTRL block
programmed within the same clock region.
Wollte nun einfach mal das IDELAYE Element ersetzen durch
clk_in_int_delay => clk_in_int;
Dann funktioniert die Simulation nicht mehr wie sie sollte. (BitSlip
etc. rastet nicht mehr auf die Bitmaske ein). Daher: Übersehe ich etwas
bei der Aufgabe des Blockes IDELAYE?
Du musst mal lernen, die User Guides zu lesen, da siehst du dass wenn du
die IDELAY Elemente verwenden willst, du noch zusätzlich pro Clock
Region ein IDELAYCTRL benötigst. Das hab ich global, deswegen im Modul
nicht drin. Als Eingangstakt braucht das aber noch 200MHz im Normalfall.
Du hast Recht. Den hatte ich auch eingefügt nach der Fehlermeldung. Dann
ist sie verschwunden. Aber ich muss die User Guides genauer lesen. Das
Design ist nun funktionsfähig in der Simulation. UCF-File ist angelegt.
Jetzt bekomme ich diese Fehlermeldung beim Routen:
"This design is unrouteable. Router will not continue. To evaluate the
problem please use fpga_editor. The nets listed below can not be
routed:"
Mehr steht da nicht. Im FPGA Editor sehe ich nur, dass alle Netze nicht
geroutet sind.
Ich vermute, du hast noch nicht die passenden Clock Buffer an den
ISERDES dran, da muss man je nach FPGA Familie verschiedene nehmen,
schau mal, was der Core Generator da benutzt. Oder diese Verschaltung
mit den zwei ISERDES klappt doch auf dem V6 nicht...User Guide...
Nachtrag zu 2):
Lasse ich beim zweiten ISERDES testweise die Ausgänge "open", dann wird
ein Bitfile generiert.
Q1=> open,--q_odd_net(0),
Q2=> open,-- q_odd_net(1),
Q3=>open,-- q_odd_net(2),
Q4=>open,-- q_odd_net(3),
Q5=>open,--q_odd_net(4),
Q6=>open,-- q_odd_net(5),
ChipScopeUser schrieb:> Kann es demnach möglich sein, dass auf Grund der äußeren Pinbelegung ein> Routen unmöglich ist?
Am Routen scheidert es sicher nicht.
Nur wenn du die Ausgänge des ISERDESE1 nicht verbindest, wird der
Synthesizer das ganze Modul wegoptimieren. Wenn das Vorraussetzung ist,
damit du eine Bitfile bekommst, könnte es sein, dass du Pins verwendest
bei denen keine ISERDESE1 zur Verfügung stehen (oder nur einer).
Da heisst es Datenblatt und Userguides konsultieren.
Wenn du falsche Pins verwendest, hilft nur ein Redesign der Platine.
Das kann bei solchen speziellen FPGA Sachen schhon mal vorkommen, gerade
die SERDES sind da zickig, vor allem was die Taktung angeht. Schau mal
im Clocking User Guide, ob deine Clocks überhaupt bis ans Ziel kommen
können. Und hat der Virtex überhaupt 2 ISERDES pro Pin, oder ist das da
wieder diese komische Einschränkung mit LVDS oder nicht LVDS? Beim
Spartan 6 war es ein Krampf...
Danke. Ich muss nocheinmal so doof fragen. In welchem Guide finde ich
heraus, wo und wieviele ISERDES vorhanden an den pins sind? Zb beim
virtex 6 in meinem fall? Bin wie gesagt neu auf dem Gebiet.
Im User Guide, aber ich hab eben mal geschaut, laut der XAPP1071 sollte
das so in etwa klappen. Hast du mal den Code direkt aus der xapp1071
versucht? Da gibts ja auch ein Zip File mit Beispielprojekt...
Was ich mir noch vorstellen kann, dass der Clock vom ADC ungünstig zu
den Daten liegt, und somit vom Bufr nicht genutzt werden kann.....
Hab mir das ISE Projekt (XAPP1071) angeschaut. Unterschied zu dem von
mir verwendeten Modul zum Einlesen der Daten:
In adcData sind lediglich Q1 - Q4 belegt (Q5,Q6 open) (hat was mit deren
"Bitauswertung" zu tun). Demnach sollte es gehen mit zwei ISERDES (even,
odd).
Die Pinbelegung für den dort verwendeten FPGA Virtex 6 XC6VLX240T (ML605
EV Board) müsste doch identisch sein mit meinem Virtex6 XC6VLX75T
(Analog EV Board). Der Unterschied besteht doch lediglich in der Anzahl
der Logicelemente etc. Das sollte nicht den Ausschalg geben.
Naja nicht ganz. Wenn du die XAPP1071 auf deinen ADC anpassen wölltest,
müsstest du jeweils 3 Bit des ISERDES nehmen, und die entstehenden 6 Bit
dann wie in der XAPP in Abhängigkeit des Frame Sync zum 12 Bit Wort
zusammen bauen.
Ja ok. Aber es ändert nichts an der Tatsache, dass die in der APP1071
sowie ich zwei ISERDES verwenden, um ein Wort zusammenzufügen. Demnach
muss das vom Prinzip her bei mir auch generierbar (bit file) sein.
Ich denke, ich habe eine Idee, wieso das Routing nicht funktioniert. In
dem Beispiel aus der APP1071 habe ich in Bezug auf den BUFR folgende
Zeile gefunden:
-- Attributes
attribute LOC : string;
attribute LOC of AdcClock_I_Bufio : label is C_BufioLoc;
-- The BUFR is generated through a generate statement and therefore the
LOC attribute
-- must be place into the generate statement.
-- See the BUFR generation down in the source code.
Außerdem sind im ucf. folgende Zeilen dazu eingefügt:
# ADC Interface.
INST "Apps_I_AdcToplevel" AREA_GROUP = "AdcToplevel";
AREA_GROUP "AdcToplevel" RANGE=SLICE_X0Y120:SLICE_X11Y159;
Das könnte deine Vermutung mit dem Clock untermauern. Wie ich dieses
korrekt verwende, muss ich mir erst anlesen.
Also, laut Report kann er die Dateneingäng der ISERDES nicht geroutet
werden. Vielleicht musst du doch diesen komischen IBUFDS mit den zwei
Ausgängen nehmen, wie in der ersten Variante da in der 1071.
Welche Variante meinst du da genau? Abb. 6? So ähnlich mach ich das
doch. Gebe dataIn_p und DataIn_n auf eine solchen buffer. Den Ausgang
reiche ich an den dateneingang des iserdes weiter. Komisch. Für einen
Anfänger echt keine angenehme aufgabe :(. Probiere es morgen nochmal
aus.
Nee, diesen komischen Buffer mit den zwei Ausgängen aus Bild 15, das ist
der Eingangsteil von der Gesamtschaltung Bild 14 in der XAPP1071.
Ja, sowas ist in der Tat nix für einen Anfänger...ich hab da auch am
Spartan 6 eine ganze Weile gebraucht und viel lesen müssen.
Hast du mal versucht, nur den Teil mit den ISERDES reinzunehmen, sonst
gar nix anderes? Also die Ausgänge nach der ISERDES Logik direkt auf I/O
Pins geben. Ansonsten hilft wohl nur noch eine Anfrage im Xilinx Forum
oder einen Webcase aufmachen.
Christian R.:
Das Design funktiniert. Bzw. ich habe nun das Bitfile. Habe beim ODD
ISERDES das selbe Signal als Eingang wie beim EVEN ISERDES verwendet. Da
pro Pad nur ein ISERDES vorhanden ist, wurde der Fehler beim generieren
des Bit Files ausgegeben. Das habe ich übersehen.
Gebe mir nun wieder (wie im ersten Beitrag) das parallelisierte
Eingangssignal in ChipScope auf. Ich könnte wieder exakt das selbe Bild
posten. Die "Ausreißer" sind wieder da :(. Dachte, dass ich dieses mit
der Verwendung des ISERDES ausschließe.
Durch die Variation des Delays (0 - 31) kann ich das Resultat verbessern
(im Bereich 3-4. Jedoch nicht vollständig beseitigen.
Stehe ich nun wieder am Anfang?
Hm, dann muss irgendwo anders ein Fehler sein, vielleicht erzeugt derADC
ja schon den Mist? Kann man den nicht auch auf ein festes Muster
einstellen? Damit könntest du ja verschiedene Pattern probieren, und
schauen ob der Fehler immer noch auftritt.
Wir verarbeitest du die Daten weiter?
Findet das mit einer vom ADC abgeleiteten Clock statt, z.B. Clockdiv?
Wenn nein wie hast du di Übergabe an die andere Clock gelöst?
Lattice User:
Meinst du die parallelisierten Daten (z.B. bei 65 Msps mit 65 MHz FCO)?
Diese gebe ich direkt in ChipScope aus. ChipScope wird mit dem Ref. Takt
von 100 MHz getaktet.
Ich versuche gerad mal die parallelisierten Daten in einen eigenen FIFO
mit unabhängigen Takten zu schreiben (wr_clk = FCO, rd_clk = sys_clk).
Dann werde ich die Daten am FIFO Ausgang mit ChipScope im Systemtakt
einlesen. Dann darf es garantiert zu keinem Bitfehler durch ChipScope
kommen. Erscheinen dann Ausreißer, muss es am Design und nicht an
ChipScope liegen.
ChipScopeUser schrieb:> Lattice User:> Meinst du die parallelisierten Daten (z.B. bei 65 Msps mit 65 MHz FCO)?> Diese gebe ich direkt in ChipScope aus. ChipScope wird mit dem Ref. Takt> von 100 MHz getaktet.
Was meinst du mit Ref Takt? Ist dieser vomADC Takt abgeleitet?
Wenn nein, dann hast hier das Problem, da es dann vorkommen kann dass
ChipScope die Daten genau dann übernimmt wenn sie sich ändern. Und da
wegen Routingvariationen sich nicht alle Bits gleichszeitig ändern wird
Schrott übernommen.
Ein asynchroner dual clock FIFO ist ein möglicher Ansatz um das zu
lösen.
Referenztakt : 100 MHz (von einem vom ADC unabhängigen Quarz auf dem
FPGA EV Board bereitgestellt)
Referenzdelaytakt: 200 MHz (leite ich vom Referenztakt über eine DCM ab)
FCO : 65 MHz (vom ADC bereitgestellt)
DCO : 390 MHz (vom ADC bereitgestellt)
Ich arbeite am FIFO :)
Achja dazu: Gibt es beim ISERDES einen Ausgang Valid( wenn daten gültig
sind) als Eingang für den FIFO (wr_clk)? Habe keinen gefunden. Wollt
ungern mich am FCO orientieren.
ChipScopeUser schrieb:> Achja dazu: Gibt es beim ISERDES einen Ausgang Valid( wenn daten gültig> sind) als Eingang für den FIFO (wr_clk)? Habe keinen gefunden. Wollt> ungern mich am FCO orientieren.
Braucht es auch keinen, der ISERDES gibt mit jedem CLKDIV gültige Daten
aus.
Wenn du ein Valid haben möchtest um Daten zu unterdrücken wenn der
ISERDES no0ch nicht im Sync mit dem FC ist, kannst du ein Valid in der
Bitslip FSM erzeugen.
Auf keinen Fall aber direkt mit dem FC eingang etwas veranstalten zu
wollen.
Im einfachsten Falle entspricht (FC SERDES Out = "111111000000").
Ohje, na dann kann das ja nix werden, du musst für die weitere
Verarbeitung, zumindest zur zu einem FIFO den geteilten Takt nehmen, den
der BUFR für den CLKDIV am ISERDES zur Verfügung stellt. Denn nur der
ist synchron zu den Daten am Ausgang des ISERDES. Valid braucht man
nicht, denn mit jedem Takt des CLKDIV kommt ein gültiger Wert.
Ok. Muss zwei clk_out_buf_div_out abwarten (Datenwort setzt sich aus
Even (6 Bit) und Odd (6 Bit) zusammen). Klar. Ich weiß gerade nur nicht,
wie ich mit der Latenz zwischen clk_buf_div_out und den Daten umgehe.
ChipScopeUser schrieb:> Ok. Muss zwei clk_out_buf_div_out abwarten (Datenwort setzt sich aus> Even (6 Bit) und Odd (6 Bit) zusammen).
Die kommen aber parallel! Sieht man auch in deiner Simulation!
> Ich weiß gerade nur nicht,> wie ich mit der Latenz zwischen clk_buf_div_out und den Daten umgehe.
Gar nicht. Die Daten sind bei der steigenden Flanke von clk_buf_div_out
gültig. Um Dinge wie Setup/Hold kümmert sich P&R, vorrausgesetzt deine
Timingonstraints (Frqeuenz bzw Periode) sind richtig.
Es ist dringend anzuraten, dass du dir nochmal die Grundlagen von
synchronen digatalen Designs anschaust.
- FIFO eingefügt: Schreibtakt (DIV CLK), Lesetakt (SYS CLK)
- Simulation passt.
- Datenausgang des FIFOs in ChipScope dargestellt
- Umstellung auf internes Testpattern (wie vorgeschlagen). Passt
momentan bei 65/8 MSps, 65/4 MSps, 65/2 MSps (ab und zu). Funktioniert
bei Testpattern "101010101010","010101010101", ... Scheint jedoch
abhängig von der Generierung des Bitfiles zu sein. Ich habe bisher nur
folgende Timing Constrains erstellt:
NET "DCO_1_N" TNM_NET = DCO_1_N;
TIMESPEC TS_DCO_1_N = PERIOD "DCO_1_N" 390 MHz LOW 50%;
NET "DCO_1_P" TNM_NET = DCO_1_P;
TIMESPEC TS_DCO_1_P = PERIOD "DCO_1_P" 390 MHz HIGH 50%; # 65 MSps, 12
Bit, DDR
NET "EVB_REF_CLK_N" TNM_NET = EVB_REF_CLK_N;
TIMESPEC TS_EVB_REF_CLK_N = PERIOD "EVB_REF_CLK_N" 100 MHz LOW 50%;
NET "EVB_REF_CLK_P" TNM_NET = EVB_REF_CLK_P;
TIMESPEC TS_EVB_REF_CLK_P = PERIOD "EVB_REF_CLK_P" 100 MHz HIGH 50%;
Steh wohl echt wieder ganz am Anfang.
ChipScopeUser schrieb:> Scheint jedoch> abhängig von der Generierung des Bitfiles zu sein.
Dann fehlen wohl noch ein paar Constraints.
Wo sind die "OFFSET IN"-Constraints hin?
Duke