Bitte Hilfe beim SPI-Code *verzweifel*

#1057627
Lesenswert?

Guten Tag zusammen,

so langsam verzweifle ich.
Die Aufgabenstellung ist so simpel wie (inwzischen) zeitraubend!
Ich habe 16 Bit die ich über eine SPI Schnittstelle auf meinen FPGA 
bekommen will.
Inzwischen habe ich 3 Versionen SPI-Code und keiner funktioniert 
zuverlässig, obgleich die Simulation bei allen funktioniert.

SPI1a und SPI1b unterscheiden sich nur unwesentlich, jedoch erschien mir 
Version a nicht besonders sauber, da ich einem Signal einen Wert zuweise 
und es direkt wieder zurücksetze.
Darum ist Version b entstanden, die bisher am ehesten Funktioniert, 
jedoch nicht immer...

Version 2 arbeitet mit einem "Masterclock" (50 MHz) der den SPI (500 
kHz) abtastet. Simulation ist hier OK - Realität FAILED.

Würde mich über eine kurze Code-Review sehr freuen und bedanke mich 
schonmal im Voraus!
Angehängte Dateien:
Gast #1057660
Lesenswert?

hast du dir schonmal den realen datenstrom angeschaut ? z.B. mitm logic 
analyser. dann könnte man mit hilfe der ergebnisse im fpga dann 
rausfinden woran er sich stört. vielleicht is ja der reelle datenstrom 
anders als du ihn dir vorstellt.
Gast #1057670
Lesenswert?

1. In Version 2 wird SPI_Enable nicht sauber eingetaktet.
Real geht es an die Eingänge von verschiedenen FFs. Nun überleg die mal, 
was passiert, wenn die Änderung vom SPI_Enable Eingang exakt mit dem 
abtastenen
Takteingang stattfindet.

2. Simulation ist hier OK - Realität FAILED.
was bedeutet dies konkret, was geht nicht?

3. Schau die am besten mal den RTL-View an.

Gruß Volker
Moderator (Firma: Titel) Persönliche Seite #1057758
Lesenswert?

> In Version 2 wird SPI_Enable nicht sauber eingetaktet.
Merksatz:
Ein Signal geht durch (mindestens) 2 FFs, erst dann wird es verwendet.

Bei deinen 1er-Lösungen mußt du übrigens anschliessend noch die 
Taktdomäne wechseln (also das Schieberegister einsynchronisieren), falls 
das mit einem Mastertakt weiterverarbeitet werden soll.

Lösung 1a) und 1b) ist eine recht unübliche Beschreibung eines 
Clock-Enables. Sieh dir mal die gängigen Lehrbücher an: findest du dort 
so einen Konstrukt? Falls die Antwort "Nein" lauten sollte: warum wohl 
nicht?
1
   if (Reseta = '0') then
2
      SPI_SR(15 downto 0) <= (others => '0');
3
      counter <= 0;
4
   elsif (SPI_Enable = '0') then
5
      if rising_edge(SPI_Clock) then
6
        :
Was da herauskommt ist in der Hardware wohl dem Zufall (oder eher dem 
Synthesizer) überlassen ...

Wie sieht dein SPI_Clock real aus?
Ist das ein "schönes" Signal oder hat der Überschwinger...?

Probiers doch mal so (abgeleitet von 1a):
1
signal SPI_SR : std_logic_vector(15 downto 0);
2
signal OUTPUT : std_logic_vector(15 downto 0);
3

4
begin
5
SchiebeReg : process(SPI_Clock)
6
begin
7
  if rising_edge(SPI_Clock) then -- steigende Flanke --> Bit einlesen
8
      SPI_SR <= SPI_SR(14 downto 0) & SPI_Data;
9
  end if;
10
end process;
11

12
Ausgabe : process(SPI_Enable)
13
begin
14
   if rising_edge(SPI_Enable) then -- deselektieren --> Daten übernehmen
15
      OUTPUT <= SPI_SR;
16
   end if;
17
end process;

EDIT:
Für ein CPLD ist das ok,
aber in einem FPGA wäre der 2. Takt schon ein Kündigungsgrund ;-)
Gast #1058057
Lesenswert?

>aber in einem FPGA wäre der 2. Takt schon ein Kündigungsgrund ;-)

das ganze hängt aber auch davob ab, wie das "externe Timing" seiner 
SPI-Signale zueinander ist (speziell SPI_Enable zu SPI_Clock).

>Wie sieht dein SPI_Clock real aus?
>Ist das ein "schönes" Signal oder hat der Überschwinger...?

Und die Flanke selbst muss sauber sein, also keine Treppenstufe.
Moderator (Firma: Titel) Persönliche Seite #1058157
Lesenswert?

> das ganze hängt aber auch davob ab, wie das "externe Timing" seiner
> SPI-Signale zueinander ist (speziell SPI_Enable zu SPI_Clock).
Ja, gut, dass nach den SPI_Enable (landläufig wohl eher SlaveSelect SS#) 
etwas Zeit vergangen sein sollte, bevor der Clock kommt, und vice versa 
bevor der SPI_Enable inaktiv wird, das sollte schon sichergestellt sein. 
Aber dafür gibt es ja Datenblätter von anderen SPI-Slaves. Da ist es 
hilfreich, wenn man sich sowas mal vorher anschaut.

>> Ist das ein "schönes" Signal oder hat der Überschwinger...?
> Und die Flanke selbst muss sauber sein, also keine Treppenstufe.
Und halbwegs akzeptable Anstiegszeiten haben...und nicht verrauscht 
sein...
Eben schön...  ;-)

@ daimlerfahrer
SPI sind gekoppelte Schieberegister. Damnach braucht SPI keinen Zähler 
für die Anzahl der übertragenen Bits. Das Ende der Übertragung wird über 
den SlaveSelect markiert. Die letzten davor übertragenen Bits werden 
intern weiterverarbeitet. Wenn du 56 Takte machst, dann werden also nur 
die Bits 41-56 verwendet, weil die beim Deselektieren im Schieberegister 
stehen.
#1058239
Lesenswert?

Zu aller erst bedanke ich mich mal für eure Hinweise.
Hier ein Screenshot des SPI-Signals, mit diesem Signal gehe ich davon 
aus, dass dies nicht der Fehler ist. Die Daten werden zur fallenden 
Flanke gesetzt und zur steigenden übernommen.

Den Zähler habe ich eingebaut um eine gewisse "Sicherheit" zu haben, 
dass ein kompletter Datensatz gesendet wurde.

In der Realität tauchen verschiedenen "Symptome" auf.

1. Es werden 90% der Daten richtig übernommen und bei 10% werden die 
Daten an die zuvor eingestellte Adresse gesendet.

2. Die Zähler-Sicherung greift viel zu oft und es werden kaum Daten 
übernommen

Problematischer für meine Anwendung sind eher falsch übernommene 
Datensätze als ausbleibende Daten.
Soll heissen - lieber kommt mal ein Datensatz NICHT an, als dass ein 
falscher ankommt.
Angehängte Dateien:
Gast #1058352
Lesenswert?

@Der Daimlerfahrer
könnten ggf. die SPI-CLK Flanken unsauber sein?
Die steigende Flanke erkenne ich mindestens so:
1
if SPI_Clock_old2 = '0' and SPI_Clock_old1 = '1' and SPI_Clock = '1' then
und muss natürlich SPI_Clock 2 mal mit dem Systemtakt syncronisiert 
haben.
Gast #1058414
Lesenswert?

meine ich dies nur, aber ist auf der 3. und 6. steigenden Taktflanke 
nicht eine Stufe vorhanden? Kann zwar an der Auflösung des Bildes 
liegen, aber mach mal folgendes:

Code mal in VHDL nen kleinen Counter, der einfach die SPI-Taktflanken 
zählt und schau dann mal, ob das Ergebnis mit den tatsächlich gesendeten 
übereinstimmt.
#1059703
Lesenswert?

Also nachdem ich den Zählerstand mal ausgegeben habe musste ich 
feststellen, dass mein SPI richtig detektiert wurde, obgleich eine 
fehlerhafte Ausgabe erfolgte.
Also SPI steht richtig, aber Ausgang steht falsch!

Dies brachte mich auf eine andere Fehlerursache: Meine kombinatorische 
Logik scheint teilweise zu lang zu brauchen. Demnach werden schon Werte 
an die Ausgänge übergeben, obgleich die "Weichenstellung" durch meine 
CASE Struktur noch nicht durchlaufen ist.
Nach dem heruntertakten des Clocks an dieser Stelle treten bisher keine 
Fehler mehr auf.

Ich war der Meinung im ISE gab es einer Stelle an der einem die maximal 
Mögliche Arbeitsfrequenz eines Design vorgegeben wird, finde es aber 
nicht mehr - weiss einer wo das steht?

Danke und Grüße!
Moderator (Firma: Titel) Persönliche Seite #1059725
Lesenswert?

Dein Stichwort ist: Timing-Constraints
Processes - User Constraints - Create Timing Constraints
Im Tab Global im Constraints Editor dann die Zykluszeit für den Takt 
eingeben.

Daraufhin findet sich in der UCF-Datei mit einem Eintrag wie z.B. für 
das Signal clk mit 100MHz:
NET "clk" TNM_NET = "clk";
TIMESPEC "TS_clk" = PERIOD "clk" 10 ns HIGH 50 %;

Das kann auch manuell in der UCF-Datei eingegeben werden.

Aber einen ersten Tip gibt schon die Synthese mit der Angabe der 
maximalen Taktfrequenz ab.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren