Hallo liebe Gemeinde,
ich beschäftige mich erst seit einem Jahr mit VHDL&FPGA und bin dabei
nun ein größeres Projekt zu implementieren. Erstaunlicherweise läuft das
auch ganz gut, nur in einem Punkt bin ich auf dem Holzweg und hoffe,
dass ihr mir ein paar Ansätze geben könnt.
Ich empfange Blöcke von 176 Bits, die von einem unmittelbar benachbarten
Testboard (Spartan 6) synchron mit der fallenden CLK Flanke
herausgetaktet werden und mit der steigenden CLK Flanke im 2. FPGA
(SPARTAN 3) eingetaktet werden. Zu Testzwecken zähle ich die Flanken.
Nach einer gewissen Pause von Flanken auf der CLK-Leitung setze ich das
Signal "Starterkennung" und prüfe dann die Anzahl der Flanken auf 176,
bevor der nächste Datenblock ein wenig später ankommt. Ist die Anzahl
ungleich 176, setze ich den Error Pin. Und genau das kommt nach 1 bis
xxx von den Datenblöcken vor.
Die CLK Leitung ist nur ca. 15cm lang - bei 25MHz sollte das unkritisch
sein. Oszilloskop zeigt auch nen sauberes Signal an und der billig China
Logic Analyser (100MHz Abtastrate) entsprechend dem Bild ebenfalls.
Einer jemand eine Idee bzgl Code oder Ähnliches? Ist der Spartan 3
vielleicht überempfindlich und macht komische Sachen ohne einen
Schmitt-Trigger davor?
Hier Auszugsweise der relevante Code:
1
process(CLK_IN,RESET)
2
variableTEMP:bit;
3
4
begin
5
ifRESET='1'then
6
7
YINT_INT<=(others=>'0');
8
TEMP:='0';
9
10
--TEST
11
TEST_ZHLER_INT<="10110000";
12
13
elsifCLK_IN='1'andCLK_IN'eventthen--...CLK_IN = '0' and CLK_IN'event then --
14
15
TEMP:=to_bit(DATA_IN);
16
YINT_INT<=YINT_INT(BITS-2downto0)&TEMP;--MSB kommend in LSB Seite von Register schieben
Axel K. schrieb:> Die CLK Leitung ist nur ca. 15cm lang - bei 25MHz sollte das unkritisch> sein.
Das trifft es nicht ganz. Entscheiden ist nämlich nicht die Frequenz des
Takts sondern die Flankensteilheit.
Axel K. schrieb:> Oszilloskop zeigt auch nen sauberes Signal an
Hast du mit einem schnellen Oszi mal auf die Flanke gezoomt und dir
deren genause Signalform angesehen? Wenn die "sauber in einem Rutsch"
von unten nach oben läuft und nicht stark überschwingt, sollte hier
tatsächlich nicht das Problem liegen.
Das eigentliche Problem dürfte wahrscheinlich eher bei deinen Taktuen zu
suchen sein:
if START_ERKENNUNG_AKTIV_IN = '1' and START_ERKENNUNG_AKTIV_IN'event
Du benutzt Start_erkennung_aktiv_in als Clk. Ist es denn tatsächlich ein
Taktsignal, d.h. kommt es von einem Takteingang des FPGAs oder einem DCM
und nicht aus irgendwelchen Logikgattern? (Wenn du dieses Signal aus
Logikgleichungen selbst "berechnest" wird es als Taksignal nicht
zuverlässig funktionieren.)
Falls Start_erkennung_aktiv_in tatsächlich ein Taktsignal ist (also von
einem Tatkeingang oder eindem Clockmanager erzeugt wird): sind
Start_erkennung_aktiv_in und Clk_in synchron zueinander? Wie stellst du
sicher, dass Start_erkennung_aktiv_in nicht gerade dann den
Test_zhler_int auswertet, während clk_in den Zähler verändert?
Auf jeden Fall holst du dir im zweiten Prozess für das Signal ERROR_OUT
ein Latch bei der Synthese ab.
1
ifTEST_ZHLER_INT/=176then
2
ERROR_OUT<='1';
3
endif;
Für die Fälle, wo das elsif nicht wahr ist oder es wahr ist und dein
Zähler gleich 176 ist, wird auf ERROR_OUT nicht geschrieben. Das Problem
kannst du lösen, indem du zu Beginn deines Prozesses eine Null zuweist:
1
begin
2
ERROR_OUT<='0';
3
....
Ich könnte mir vorstellen, dass dies dein Problem behebt, da vom
Synthesetool ggf. implizite Annahmen für diesen Fall treffen.
Gruß Jannis
Jannis C. schrieb:> Auf jeden Fall holst du dir im zweiten Prozess für das Signal ERROR_OUT> ein Latch bei der Synthese ab.
Nein, da gibt es kein Latch. Es wird getaktet gespeichert, weil die
Zuweisung von Error_out innerhalb von
elsif START_ERKENNUNG_AKTIV_IN = '1' and START_ERKENNUNG_AKTIV_IN'event
then
....
end if;
stattfindet.
Ist also kein Latch sondern ein ganz normales Flip-Flop. Die Frage ist
aber, ob das Taktsignal für das Flip-Flop auch wirklich ein
funktionierendes Taktsignal ist und wie die ggf. unterschiedlichen
Taktdomänenen zueinander synchronisiert werden.
@Axel: hast du schon mal geschaut, ob dir dein Synthesetool Warnungen
wegen "schlechten Taktsignalen" ausspuckt?
Jannis C. schrieb:> Das Problem> kannst du lösen, indem du zu Beginn deines Prozesses eine Null zuweist:
Dann bekommt er ggf. nur einen kurzen Puls auf der Error_out Leitung und
nicht einen dauerhaften High-Pegel, den er jetzt hat.
Nabend,
danke erstmal für eure Beiträge!
Warnungen habe ich >300 :S, ich bin mit meinem Systakt vorsichtshalber
auf intern 50MHz runter und gehe dann Stück für Stück durch. Final
sollen später via CAT5E im besten Fall mit 100MHz übertragen werden via
externem LVDS Treiber, galvanisch getrennt.
@ Lothar: Danke für den Link! Ich war schon öfters auf deiner Seite und
habe speziell mit deinem RS232 Modul Erfahrungen gemacht. Da habe ich
zunächst selbst asynchron auf die fallende Flanke beim Startbit
getriggert, statt mit deinem 4 Bit SR und synchroner Abtastung. Bei mir
kamen diverse Übertragungsfehler und dann habe ich doch deine Lösung mit
dem 4 Bit SR genommen. Da später die Übertragung mit bis zu 100MHz
laufen soll und der Systemtakt in dem Fall bei 100-200MHz liegt, fällt
diese Methode ja eher flach. Bei deiner SPI Lösung Lösung taktest du ja
auch mit dem ankommenden CLK Signal die Daten ins SR, glaube ich. Bei
mir geht ausschliesslich die Datenleitung intern über 1 bis 2Gatter, bis
sie ans Schieberegister geht. CLK direkt vom EingangspinFPGA ans SR.
Das Error - Signal / Zähler ist nur zum Eingrenzen des Fehler
implementiert. Signal "Starterkennung" kommt devinitiv immer mit
ausreichend Abstand (mindestens 8*interne CLK Periode), sodass der
Zählerstand sicher abgefagt werden sollte.
@Achim S.: Oh, in der Tat :S 1/6Wellenlänge bei Rechteck 25MHz könnte
kritisch sein ohne Terminierung. Ich habe vor Jahren mal testweise
zwischen 2 Mikrocontrollern mit ca 1,3m Meter fliegende Leitungen stabil
getestet. Deswegen vermutlich meine sichere Annahme, dass es mit 15cm
gehen sollte... Im Endeffekt hast du mich dadurch zu Nachdenken gebracht
und ich habe soeben im Sende-FPGA die CLK/Daten Outputs von fast auf
slow gestellt und jetzt läuft es ohne Fehler, dh 176 Flanken werden
immer erkennt. Genauer schaue ich mir das morgen mal am Oszi an und
berichte!!
Vielen Dank bisher!
gruss Axel
Axel K. schrieb:> CLK direkt vom EingangspinFPGA ans SR.
Das kann man machen, wenn die Taktdomäne nur ein paar Flipflops,
eigentlich also nur das Schieberegister umfasst. Aber Tricksereien über
Taktdomänengrenzen hinweg gehen garantiert schief.
> Bei deiner SPI Lösung Lösung taktest du ja auch mit dem ankommenden CLK> Signal die Daten ins SR, glaube ich.
Nur bei der mit dem Slave im CPLD. Die FPGA Lösung ist synchron. Aber
irgendwo hier geistert auch noch ein asynchroner Ansatz herum.
Axel K. schrieb:> Ich habe vor Jahren mal testweise> zwischen 2 Mikrocontrollern mit ca 1,3m Meter fliegende Leitungen stabil> getestet. Deswegen vermutlich meine sichere Annahme, dass es mit 15cm> gehen sollte...
Der Mikrocontroller macht das, was dir auch hier empfohlen wird: er
nutzt den SPI-CLK nicht direkt als Takt, sondern er tastet ihn mit
seinem internen Takt ab und macht eine Flankenerkennung. Deswegen darf
der SPI-Takt nur einen bestimmten Bruchteil des µC-Takts betragen. Zum
Beispiel ein Zitat vom ATMega32A:
In SPI Slave mode, the control logic will sample the incoming signal of
the SCK pin. To ensure correct sampling of the clock signal, the minimum
low and high periods should be:
Low period: longer than 2 CPU clock cycles.
High period: longer than 2 CPU clock cycles.
Wenn es da zu unschönen Signalformen auf dem SPI-CLK kommt führt das
nicht dazu, dass bei einer Flanke gleich mehrfach eingelesen wird, falls
die Störungen bis zum nächsten CPU-Takt abgeklungen sind.
Genauso solltest du es mit dem FPGA auch machen. Stattdessen verwendest
du den SPI-CLK als FPGA-internen CLK. Wenn es dabei auch nur zu einen
kleinen CLK-reversal in der Flanke kommt, kann das FPGA ggf. schnell
genug darauf reagieren und zwei Werte eintakten, wo eigentlich nur einer
vorgesehen war.
Auch das FPGA-interne "Weiterreichen" der Daten vom Schieberegister zur
restlichen Logik lässt sich sehr viel einfacher sicher gestalten, wenn
du nur einen FPGA-Takt verwendest.
Axel K. schrieb:> Warnungen habe ich >300
300 ist nicht ganz wenig, aber auch nicht ganz schrecklich viel. Viele
davon werden wahrscheinlich ziemlich eintönige Wiederholungen sein -
wenn du z.B. die selbe Warnung 16 mal für alle 16 Bit eines Registers
bekommst. Geh die Warnungen durch und blende die aus, deren Ursache
dir klar ist und die nachgewiesen unkritisch sind. Alle Warnungen, die
sich auf die Takte beziehen, solltest du als kritisch betrachten und die
Ursache der Warnung abstellen.
Zuerst habe ich das vermutet, was Lothar meinte. Aber mit 8 Takten
"Abstand" sollte der Counter stabil sein.. Schön ist das aber dennoch
nicht und ich würde das an deiner Stelle richten.
Kannst du mal bitte den Code posten, wie du die Starterkennung
generierst und zurücksetzt?
Auf den Bildern ist das Singal superkurz, wenn der Fehlerfall eintritt.
Vielleicht liegt da irgendwo der Hase im Pfeffer.
Achim S. schrieb:> Wenn es da zu unschönen Signalformen auf dem SPI-CLK kommt führt das> nicht dazu, dass bei einer Flanke gleich mehrfach eingelesen wird, falls> die Störungen bis zum nächsten CPU-Takt abgeklungen sind.
Das ist auf jeden Fall korrekt. Bringt aber den Nachteil, dass am SPI
das Tco im Worst Case 1 Systemtakt + Signallaufzeit im FPGA lang sein
kann. Wenn man dann nicht mit dem Systemtakt unnötig hoch will, um dem
Effekt klein zu halten, bleibt einem nichts anderes übrig, als den
SPI-Takt direkt auf die SPI-Register zu legen und sich dann Gedanken
über den Übergang zum Systemtakt zu machen.
Beides hat sicher seine Daseinsbrechtigung und ich würde nicht sagen,
dass eine der beiden Methoden die "Bessere" ist. Kommt einfach darauf
an, was die Rahmenbedinungen sind.
Schlumpf schrieb:> Aber mit 8 Takten "Abstand" sollte der Counter stabil sein..
Richtig.
> Beides hat sicher seine Daseinsbrechtigung und ich würde nicht sagen,> dass eine der beiden Methoden die "Bessere" ist.
Die "einfachere" Methode ist auf jeden Fall die synchrone in dem Fall,
dass da nicht nur Daten empfangen, sondern auch gesendet werden sollen.
Denn dann kann man das Sende-SR ganz einfach beschreiben und muss sich
keine Gedanken um irgendeine Synchronisierung machen.
> Kommt einfach darauf an, was die Rahmenbedinungen sind.
Wenn die Taktfrequenz so unangenehm hoch wird, dann bleibt nur die
asynchrone Methode (und zudem muss bei 100MHz Takt das
Leiterplattendesign locker für ein halbes GHz ausgelegt werden).
Axel K. schrieb:> Oszilloskop zeigt auch nen sauberes Signal an
Zeig doch mal.
Die Masse zu dieser Messung solltest du aber in der unmittelbaren Nähe
des FPGAs abnehmen. "Unmittelbar" bedeutet: "wenige mm" bzw.
"Massefeder". Siehe dazu den
Beitrag "Re: Ungenauigkeiten bei Verwendung von 2 Oszilloskop-Kanälen"> Die CLK Leitung
Hast du auf den Takt passende Constraints gesetzt?
Verwendest du für die Takte Takteingänge oder simple IO-Pins?
Schlumpf schrieb:> Wenn man dann nicht mit dem Systemtakt unnötig hoch will, um dem> Effekt klein zu halten, bleibt einem nichts anderes übrig, als den> SPI-Takt direkt auf die SPI-Register zu legen und sich dann Gedanken> über den Übergang zum Systemtakt zu machen.
Ist mir bewusst und ich gebe dir recht. Wenn man weiß, was man tut, kann
es durchaus angemessen sein, den SPI-Takt direkt zur Taktung des
Schieberegisters zu verwenden. Aber ich glaube, dem TO ist noch nicht
bewusst, welche Konsequenzen seine Taktung hat, und deshalb versuche ich
ihn ein Stück weit zu sensibilisieren.
Axel K. schrieb:> 1/6Wellenlänge bei Rechteck 25MHz könnte> kritisch sein ohne Terminierung.
...
> ich habe soeben im Sende-FPGA die CLK/Daten Outputs von fast auf> slow gestellt und jetzt läuft es ohne Fehler
Es freut mich, dass die Fehler verschwunden sind und es (zumindest für
den Augenblick) korrekt läuft. Aber zu deiner Betrachtung der
Wellenlänge bei 25MHz nochmal der Hinweis: bei gleicher Flankensteilheit
ist es egal, ob der SPI-CLK auf 25MHz oder auf 1MHz oder auf 1kHz läuft.
Für die Signalintegrität relevant ist nicht die Grundfrequenz des
Rechtecksignals, sondern die hochfrequenten Anteile, die in der Flanke
stecken.
Guten Abend,
leider musste ich ein paar Tage Pause machen :/ Ich habe mir Alles mal
gründlich durchgelesen. Jedenfalls habe ich noch etwas experimentiert
und bin final dann doch bei der synchronen Abtastung des Daten UND
Clk-Signales gelandet:
1
elsifCLK200='1'andCLK200'eventthen--...CLK_IN = '0' and CLK_IN'event then
YINT_INT<=YINT_INT(BITS-2downto0)&to_bit(rxd_data_sr(2));--MSB kommend in LSB Seite von Register schieben
CLK200 ist in dem Bsp. = 4xCLK_IN_INT. So ganz optimal finde ich das
nicht, da ich so nicht die Bitmitte erwische. Aufjedenfall läuft so der
Testaufbau. Später bei den geplanten 100MHz Übertragungsrate wirds dann
eng mit der 4fachen Abtastrate... und da Daten und CLK jeweils 2x
kapazitiv-galvanisch getrennt werden + LVDS tx&rx wird es noch
ungünstiger :/
Ich habe auch mal versucht, die Daten mit der steigenden externen CLK_IN
Flanke zu samplen und gleichzeitig ein Flag zu setzen - welches ein
wenig später mit dem Systemtakt resettet wird als Freigabe für das
samplen das nächsten Bits. Das gab aber auch Fehler bei der Übertragung
- ggf könnte dieser Ansatz auch noch optimiert werden...
@Lothar: CLK200 geht über einen richtigen Takteingang + DCM. CLK der
Datenleitung über einen einfachen IO-Pin. Korrekt so?
Der Aufbau ist EMV technisch nicht optimal - deswegen bin ich auch mit
dem Takt runter.
Nachtrag: bzgl Flankensteilheit ändert das ja nix - der nicht EMV
optimale Aufbau ist dann wohl sicher das Übel für die Fehler beim
asynchronen samplen ..