Forum: FPGA, VHDL & Co. Funktionsblock mit einem Takt verzögert ansprechen


von Andreas B. (loopy83)


Lesenswert?

Hallo zusammen,

ich habe einen seriellen Datenstrom mit Double Data Rate (DDR).

Dieser wird in einem IDDR2 Baustein in zwei SDR Datenströme zerlegt und 
damit werden dann zwei Schieberegister gefüllt, um sie zu 
parallelisieren.

Nun habe ich das Problem, dass der IDDR2 und die Schieberegister mit dem 
gleichen Takt getaktet sind. Daraus ergibt sich das Problem, dass das 
Schieberegister schon den ersten Wert speichert, obwohl erst einen Takt 
später verlässliche Daten am Ausgang des IDDR2 anliegen.

Dadurch ergeben sich falsche Werte im Schieberegister.

Nun möchte ich erreichen, dass die Schieberegister erst mit dem zweiten 
Takt anfangen zu arbeiten, nämlich genau dann, wenn verlässliche Daten 
am Ausgang des IDDR2 anliegen.

Dabei ist es nicht nötig, dass die Schieberegister jeweils einen Takt 
länger warten, sondern nur der erste Takt stört, da nur hier falsche 
Daten ausgelesen werden können.

Wie genau kann ich eine solche Verzögerung um genau eine Periodendauer 
realisieren?

Ein Delay im DCM des Eingangstaktes bringt keinen Sinn, weil sowohl 
IDDR2 und Schiebereg. an dessen Ausgang hängen.

Ich wäre für Hinweise sehr dankbar :)

MfG Andi

von mki (Gast)


Lesenswert?

Bastle dir eine FSM. Diese setzt beim zweiten Mal ein ready Signal. 
Dieses kannst du dann Abfragen und nur auslesen, wenn es gesetzt ist.

von Johann (Gast)


Lesenswert?

Wenn ich das richitg verstehe hast Du ein DataReady Signal (DDR) und 
Daten. Jetzt willst Du mit dem Data Ready Signal mit jeweils der 
ansteigenden und fallenden Flanke die Daten einlesen. --> Dies hast Du 
mit einem IDDR gemacht.

Jetzt stellst Du fest das die Daten nicht immer richtig sind. Dies liegt 
einfach daran das die Daten während der ansteigenden und fallenden 
Flanke noch nicht stabiel anliegen.

Was Du jetzt machen must ist die DataReady Leitung ein wenig zu 
verzögern. Somit liegen die Daten bereits stabiel an.

Die Verzögerung des DataReady-Ready Signals kann man über zwei 
Möglichkeiten erreichen.

1. Du machst auf Deiner Platine die DataReady-Leitung etwas länger als 
die Datenleitung --> somit hat die DataReady Leitung eine höhere 
Laufzeit

2. Du verzögers die DataReady Leitung im FPGA mit einem IDELAY-Element. 
Hier bin ich auch gerade dabei und lese gerade das Datenblatt.

von Andreas B. (loopy83)


Lesenswert?

Hallo,

Danke für die Antworten:

- die Sache mit dem ready-Signal werde ich mal verfolgen. Es wartet 
einfach den ersten Takt ab und setzt sich dann auf High und das 
Schieberegister bekommt dann nur werte zugeschrieben, wenn dieses Signal 
1 ist...

Werde ich mir mal Gedanken machen, wie ich das realisieren kann... 
vielleicht mit einer Art Zähler? Der Zählt von 0 bis 2 und bei 
Zählerstand = 1 setze ich ein Signal auf 1 und da bleibt es dann auch.

Oder hat jemand bessere Ideen bzw. Vorschläge wie ich so etwas 
realisieren könnte?

- eine Änderung auf der Platine, sprich Leitungslängen, kann ich nicht 
mehr verändern

- IDELAY sieht interessant aus, leider gibt es nur zwei Probleme. 
Scheinbar kann es nur direkt hinter einen IOB geschaltet werden, somit 
kann ich keine internen Signale verzögern. Zweites Problem ist, dass es 
nur für Virtex PFGAs geht... ich nutze aber einen Spartan 3A DSP

DANKE :)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> IDELAY sieht interessant aus, leider gibt es nur zwei Probleme.
> Scheinbar kann es nur direkt hinter einen IOB geschaltet werden,
Ja klar, nur im IO-Block ist es physikalisch vorhanden...

von Andreas B. (loopy83)


Lesenswert?

Genau, und deswegen kommt es für mich nicht in Frage, weil ich ja den 
Eingangstakt aufsplitte und nur einen Teilzweig verzögern möchte.

Ich habe gerade mit dem IBUFDS_DLY_ADJ herumprobiert, aber auch hier 
nutzt es mir nix, weil die Daten vorm IDDR2 verzögert werden. Das 
Problem besteht aber hinter dem IDDR2.

Ideal wäre also eine Möglichkeit, ein Zwischensignal zu verzögern, ohne 
dazu einen IOB verwenden zu müssen.

DANKE!!

von Johann (Gast)


Lesenswert?

Ich glaube so macht es keinen Sinn. Du solltest vielleicht noch mal 
erzählen was Du genau machen willst. Hast Du nun einen AD-Wandler oder 
andere Geräte?

von Andreas B. (loopy83)


Angehängte Dateien:

Lesenswert?

Hallo,

ja genau, ich habe einen 16bit ADC, der seine Daten aber seriell via 
LVDS ausgibt. Deswegen muss ich diese Daten erst parallelisieren.

Hinzu kommt, dass die Daten an der steigenden und der fallenden Flanke 
des Taktes anliegen (DDR).

Also muss ich die LVDS Daten und den LVDS Takt mittels IBUFDS bzw. diff. 
DCM in binäre Signale wandeln. Danach gehen die Daten direkt an einen 
IDDR2, aus dem zwei Datenströme kommen (einmal steigende und einmal 
fallende Flanke). Diese beiden Datenströme gehen dann in zwei 
Schieberegister, um sie zu parallelisieren und zu sortieren.

Das Problem war nun, dass der Takt direkt nach dem DCM an die 
Schieberegister geht, die Daten aber den Umweg über den IDDR2 Baustein 
nehmen. Daraus ergeben sich Verzögerungen, so dass die Daten später 
anlagen als der Takt und sich daraus Widersprüche in den gespeicherten 
Daten ergeben haben.

Also habe ich nun den Takt zum Schieberegister mit einem weiteren 
DCM_DELAY (blau) verzögert und nun liegen die Daten korrekt im 
Schieberegister.

Im Anhang habe ich versucht, das noch ein wenig zu veranschaulichen. In 
der Simulation funktioniert es nun, nun muss es nur noch in der Hardware 
funktionieren.

Kann man das so machen, oder ist das eine schlechte Designpraxis?

Werden denn in der Simulation in ISim Laufzeiten schon berücksichtigt? 
Ich syntetisiere das Projekt und mache dann eine Simulation. Die Delay 
vom DCM werden 1zu1 umgesetzt. Auch waren Laufzeitunterschiede durch den 
IDDR2 messbar, nur deswegen mußte ich diesen Aufwand ja betreiben. 
Bildet die Simulation (behavioral) ungefähr die realität wieder?
Oder muss ich dazu eine post-route Simulation machen?

Vielen Dank,
MfG Andi

von Andreas B. (loopy83)


Lesenswert?

Leider lassen sich zwei DMCs in Reihe nicht implementieren... oh mann :(

Aber vielleicht ist jetzt klar, was genau ich machen will und vielleicht 
gibt es weitere Hinweise dazu?

Hat jemand ein Bsp, wie ein process die erste steigende Flanke eines 
Taktes ignoriert und dann erst ein Signal auf 1 setzt?

So etwa, nur dass eben die erste Flanke ignoriert wird:
prozess: process (PClk)
1
begin
2
  if rising_edge(Takt) then
3
      signal = '1';
4
  end if;
5
end process;

DANKE!

von Klaus F. (kfalser)


Lesenswert?

Das Prinzip ist zwar klar, aber die Methode nicht.

Der IDDR2 Baustein taktet Dir die Signale ein, diese treten am Ausgang 
natürlich verzögert zur Taktflanke auf.
Am Schieberegister kannst Du die Daten doch mit dem selben Takt 
weiterverarbeiten, diese werden dann sauber 1 Takt später eingetaktet.
Warum sollte das stören?

Ich hoffe, Dir ist schon klar, dass Clk-in ein kontinuierlicher Takt 
sein muss, der dauernd läuft, ansonsten funktioniert die DCM nicht.
Das erkennen des 1. Bit muß deshalb aus dem Datenstrom erfolgen, eine 1. 
Flanke des Takts gibt es nicht!

von Duke Scarring (Gast)


Lesenswert?

@Andreas B.:

Vielleicht suchst Du den OPPOSITE_EDGE bzw. SAME_EDGE -Mode vom 
IDDR?

Duke

von Johann (Gast)


Lesenswert?

1.Mit welcher GEschwindigkeit wird dann Dein ADC betrieben und was für 
einen FPGA verwendest Du?

2. Ich würde es etwas einfacher gestalten. Du hast Deine Daten (DDR) 
diese würde ich in einem normalen IDDR geben und den Modus (Pipeline..) 
verwenden. Somit kommen liegt beim IDDR immer mit der ansteigenden 
Clock-Flanke beide Daten (Q1 und Q2 ) an.

Wenn Du die Rohdaten nur an den PC senden willst kannst Du die 
Sortierung auch am PC vornehmen wenn Du jedoch die Daten im FPGA weiter 
verarbeiten willst, must Du diese natürlich richtig zusammensetzen.

Ich denke mal mit einem Schiebregister bist Du da auf dem falschen Weg. 
Weil Du müstet 2 Werte auf einmal mit einem Takt schieben. Dies würde 
ich nicht machen. Ich würde eher etwas anderes probieren:

Stell Dir vor Du hast eine Speicher der 16 Bits enthalten kann. Du 
nimmst einen Zähler. Zu Beginn ist der Zähler 0. Jetzt bekommst Du die 
ersten beiden Werte vom AD-Wandler. Nun ersetzt Du die 0. und 1. 
Speicherzelle von Deinem 16Bit Speicher. Anschließend zählst Du den 
Zähler um 1 hoch. Jetzt kommen die nächsten 2 AD-Wandlerwerte. Nun 
ersetzt Du die 2. und 3. Speicherzelle und so weiter.

Diese geht so

1. immer den Counter mit der ansteigen Clock Flanke um 1 erhöhen

if(CLK'event and CLK = '1') then
   if(Reset = '1')then
      S_COUNTER <= "000";
   else
      S_COUNTER <= S_COUNTER +1;
   end if;
end if;


if(Reset = '1')then
       DATA<= "0000000000000000";
    elsif(CLK'event and CLK = '1')then
       case S_REGZ is
           when "0000" =>  DATA(0)<= Q1; DATA(1)<= Q2;
           when "0001" =>  DATA(2)<= Q1; DATA(3)<= Q2;
           when "0010" =>  DATA(2)<= Q1; DATA(3)<= Q2;
           when "0011" =>  DATA(4)<= Q1; DATA(5)<= Q2;
           when "0100" =>  DATA(6)<= Q1; DATA(7)<= Q2;
           .
           .
           .
           when others => NULL;
        end case;
    end if;


Q1 und Q2 sind die beiden Ausgänge vom IDDR

Das schöne dabei ist das der Counter einen Überlauf hat und somit wieder 
bei 0 anfängt.

Dies ist sicherlich nicht die beste Lösung jedoch würde die sicherlich 
funktionieren.

von mki (Gast)


Lesenswert?

Es gibt auch schon fertige IP´s die LVDS verstehen. Ich weiß dass bei 
Altera welche dabei sind. Bei Xilinx bin ich mir nicht so sicher aber 
ich denke mal schon. Der Nachteil ist natürlich du musst dich erstmal 
mit denen auseinander setzen.

von Johann (Gast)


Lesenswert?

Um ein LVDS-Signal in ein "normales" umzuwandeln benötigt man keinen 
IP-Core sondern man nimmt muß die Eingangsbuffer nur richtig 
konfigurieren

von mki (Gast)


Lesenswert?

So wie ich es verstanden habe kann man dank der differentiellen 
Übertragung die Daten schneller übertragen und dadurch Leitungen sparen. 
Das "normale" ist z.B. 16 bit breit. Der LVDS IP Core macht daraus vier 
LVDS Leitungen. Es wird also teilweise seriell übertragen. Dafür aber 
vier mal schneller, damit das Signal rechtzeitig ankommt. Auf der 
anderen Seite wird es dann wieder parallelisiert. Das machen die LVDS 
IP-Cores. Und vielleicht könnte man den hier auch verwenden, so sparrt 
man sich den eigenen Code.

von Andreas B. (Firma: www.collion.de) (bergy) Benutzerseite


Lesenswert?

@mki
LVDS bedeutet erst einmal nix anderes als Low Voltage Differential 
Signal und hat nix mit einem auf den entsprechenden Pins betriebenen 
Protokoll zu tun...
Die Unart daraus gleich eine serialisierte Übertragung ableiten zu 
wollen findet sich allerdings immer häufiger, unter anderem auch bei 
Xilinx, ist aber falsch.
Das was Du meinst, kommt unter zahlreichen Beschreibungen daher:
FlatLink(TM) TI
Flat Panel Display Link
Flat Panel Link
FPD-Link
dann gibt es noch HDMI und DVI welche auf dem gleichen Prinzip beruhen.
Bei Xilinx auf der Homepage findet man dazu auch gute Erklärungen und 
fertigen HDL-Code zum Verstehen. (XAPP485 & XAPP486).
Eine umfassende Dokumentation findet man bei Xilinx (inkl. dem Einsatz 
der Spartan3 IO Primitives), wenn man nach:
"Spartan-3E Display Development Kit" sucht und dann das ZIP mit dem LVDS 
Reference Design runterlädt. Das auf der gleichen Seite verlinkte PDF 
direkt wird vom Server nicht gefunden...

Gruß

Andreas

von Andreas B. (loopy83)


Lesenswert?

VIELEN DANK für die ausführliche Hilfe und die vielen Hinweise.

Ich werde erst einmal bei der Methode mit den Schieberegistern bleiben. 
Dort habe ich einfach mehr Freiheiten, später noch Steuersignale 
einzuarbeiten.

Ich habe die Sache mit der Taktverzögerung im SR jetzt so gelöst.
Ich habe ganz am Anfang oder nach dem Reset einen Counterwert 4, der 
rückwärts zählt. Ist 0 erreicht, wird er aber nur auf 3 zurückgesetzt. 
Damit ist der erste Durchlauf einen Takt länger.

Ein Steuersignal, welches mir anzeigt, wann jetzt genau gültige Daten 
kommen, lasse ich mir vom ADC erzeugen und hält die SR im Reset, wenn 
keine gültigen Daten anliegen. Wenn das Signal auf 1 gesetzt wird, 
bedeutet gültige Daten, laufen die SR los und somit habe ich eine 
definierte Anfangsbedingung.

Die LVDS Daten kommen mit dem 160MHZ Takt, verwenden tue ich einen 
Spartan 3A DSP...

Ich habe noch ein paar Probleme mit meinem FiFo am Ausgang, mit dessen 
Hilfe ich auch asynchron mit dem PC lesen kann, weil Schreib- und 
Lesetakt ja nicht abhängig voneinander sind. Ich denke, ich werde der 
Übersicht halber dafür einen neuen Thread eröffnen.

DANKE!!

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.