Forum: FPGA, VHDL & Co. Fehler beim Eintakten von Daten ins Schieberegister synchron mit externem CLK @ 25MHz


von Axel K. (axel)


Angehängte Dateien:

Lesenswert?

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
variable TEMP: bit;
3
4
    begin
5
      if RESET='1' then
6
      
7
        YINT_INT <= (others => '0');
8
        TEMP := '0';
9
10
        --TEST
11
        TEST_ZHLER_INT <= "10110000";
12
13
      elsif CLK_IN = '1' and CLK_IN'event then --...CLK_IN = '0' and CLK_IN'event then --
14
          
15
        TEMP := to_bit(DATA_IN);
16
        YINT_INT <= YINT_INT(BITS-2 downto 0)& TEMP; --MSB kommend in LSB Seite von Register schieben
17
        
18
        --TEST
19
        if TEST_ZHLER_INT = "10110000" then --176
20
          TEST_ZHLER_INT <= "00000001";
21
        else 
22
          TEST_ZHLER_INT <= TEST_ZHLER_INT + 1;
23
        end if;        
24
          
25
      end if;
26
          
27
  end process;
28
29
-----------------------------------------------------------------------------------
30
31
PR_START_ERKENNUNG_AKTIV:  process(START_ERKENNUNG_AKTIV_IN, RESET)
32
33
    begin
34
  
35
      if RESET='1' then
36
        
37
        DOUT_INT <= (others => '0');
38
        
39
        ERROR_OUT <= '0';
40
      
41
      elsif START_ERKENNUNG_AKTIV_IN = '1' and START_ERKENNUNG_AKTIV_IN'event then --bei fallender DATA_IN Flanke Puls Resetten
42
      
43
        DOUT_INT <= to_stdlogicvector(YINT_INT);
44
        
45
        --TEST
46
        if TEST_ZHLER_INT /= 176 then
47
          ERROR_OUT <= '1';
48
        end if;
49
50
      end if;
51
    end process PR_START_ERKENNUNG_AKTIV;

von Achim S. (Gast)


Lesenswert?

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?

von Jannis C. (kabelwurm)


Lesenswert?

Auf jeden Fall holst du dir im zweiten Prozess für das Signal ERROR_OUT 
ein Latch bei der Synthese ab.
1
if TEST_ZHLER_INT /= 176 then
2
     ERROR_OUT <= '1';
3
end if;
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

von Achim S. (Gast)


Lesenswert?

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.

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


Lesenswert?

Axel K. schrieb:
> Hier Auszugsweise der relevante Code:
Viel zu viele Takte...

Meine Empfehlung: nimm 1 Takt mit 100MHz und mache ein ganz normales 
synchrones Design.

Denn dieser Vergleich auf 176 ist asynchron zum Zähler und deshalb hast 
du damit garantiert sporadisch seltsame Probleme.
Siehe dazu 
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html

von Axel K. (axel)


Lesenswert?

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

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


Lesenswert?

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.

von Achim S. (Gast)


Lesenswert?

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.

von Schlumpf (Gast)


Lesenswert?

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.

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


Lesenswert?

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?

von Achim S. (Gast)


Lesenswert?

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.

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


Lesenswert?

Axel K. schrieb:
> ich habe soeben im Sende-FPGA die CLK/Daten Outputs von fast auf slow
> gestellt und jetzt läuft es ohne Fehler
Dann war das signal doch nicht so sauber und du hattest Klingeln auf der 
Leitung. "Serienterminierung" ist das Stichwort.
Siehe z.B. den Beitrag "Re: Signalproblem bei langem Kabel" und 
den Beitrag "Serienwiderstand bei Hochfrequenz"

von Axel K. (axel)


Lesenswert?

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
      elsif CLK200 = '1' and CLK200'event then --...CLK_IN = '0' and CLK_IN'event then
2
      
3
        rxd_clk_sr <= rxd_clk_sr(rxd_clk_sr'left-1 downto 0) & CLK_IN_INT;  
4
        rxd_data_sr <= rxd_data_sr(rxd_data_sr'left-1 downto 0) & DATA_IN;  
5
        
6
        if (rxd_clk_sr(3 downto 2) = "01") then  --pos flanke clk
7
          YINT_INT <= YINT_INT(BITS-2 downto 0) & 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 ..

: Bearbeitet durch User
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.