Hallo,
ich möchte gerade ein SPI Slave beschreiben und habe mir dazu einige
Beschreibungen im Internet angeschaut. Nach der ständig wiederholten
Warnung:
1
Xst:3002 - This design contains one or more registers/latches that are directly
2
incompatible with the Spartan6 architecture. The two primary causes of this is
3
either a register or latch described with both an asynchronous set and
4
asynchronous reset, or a register or latch described with an asynchronous
5
set or reset which however has an initialization value of the opposite
6
polarity (i.e. asynchronous reset with an initialization value of 1).
verzweifel ich so langsam.
Auch bei den Beispielen aus dem Internet kam bei mir immer diese
Message.
Wenn damit schon mal jemand Erfahrung gemacht hat, speziell mit dem
Spartan6 und eben eine Lösung für das Problem bereit stellt, wäre ich
sehr dankbar.
Ich habe auch ein simples parallel zu seriell Register auch schon bei
dem die Synthese und Simulation einwandfrei funktionieren:
Nur ist es da ja so das beim SPI ja die Clock erst einsetzt bei der
Übertragung und wenn das CS auf 'Low' ist. Hier ist es ja noch momentan
so das es die Clock benötigt zum einlesen der Daten und zum senden der
Daten.
Ich wäre für Tipps zur weiteren Umsetzung zum SPI Slave oder eben warum
der Spartan 6 Probleme mit den anderen Designs haben könnte, sehr
dankbar.
Gruß
Sowas macht man indem man den SCLK einsychronisiert und bei der
entsprechenden Flanke ein Clock Enable für den internen Takt erzeugt.
Geht natürlich nur, wenn die Frequenz des SCLK ein ganzes Stück
niedriger (Faktor 4) ist als die interne Taktfrequenz, was ja aber in
den allermeisten Fällen passen sollte.
Andi P. schrieb:> process(reset,sclk, CS)
Vorneweg: CS gehört hier nihct in die Sensitivliste.
> Nach der ständig wiederholten Warnung:> (i.e. asynchronous reset with an initialization value of 1).
Dann mach doch den asynchronen Reset raus. Wofür brauchst du denn
überhaupt?
> Ich wäre für Tipps zur weiteren Umsetzung zum SPI Slave oder eben warum> der Spartan 6 Probleme mit den anderen Designs haben könnte, sehr> dankbar.
Wie schnell ist dein FPGA-Quarztakt?
Wie schnell ist dein SPI?
Als Tipp: sieh dir an, wie Mikrocontroller das machen. Da geht der SCLK
nicht direkt auf den Takteingang eines Flipflops, sondern es wird eine
Flankenerkennung darauf gemacht und dann das Datenbit übernommen.
So etwa:
Christian R. schrieb:
> Sowas macht man indem man den SCLK einsychronisiert
Vielen Dank, kann ich beim einsynchronisieren der beiden Clocks vorgehen
wie im Beispiel von Lothar Miller?
www.lothar-miller.de/s9y/categories/35-Einsynchronisieren
Lothar Miller schrieb:
> Andi P. schrieb:>> process(reset,sclk, CS)> Vorneweg: CS gehört hier nihct in die Sensitivliste.
Ahja, ok. könntest du mir das eventuell kurz erklären wieso nicht? Ich
ging davon aus in der Sensitivliste die Signale stehen auf die auch
reagiert werden soll?
>> Nach der ständig wiederholten Warnung:>> (i.e. asynchronous reset with an initialization value of 1).> Dann mach doch den asynchronen Reset raus. Wofür brauchst du denn> überhaupt?
Du hast Recht nach der Übertragung ist das SR eh "leer" also mit 0
besetzt.
>> Ich wäre für Tipps zur weiteren Umsetzung zum SPI Slave oder eben warum>> der Spartan 6 Probleme mit den anderen Designs haben könnte, sehr>> dankbar.> Wie schnell ist dein FPGA-Quarztakt?> Wie schnell ist dein SPI?
Meinen Takt den ich in mein System rein geben werde sind 40 MHZ oder
auch mehr. Auf jedenfall wird dieser dann auf 400 MHZ erhöht durch eine
PLL die mit vier phasenverschobenen Takten dann vier Zähler taktet.
Bestimmte Zählerstände werden irgendwann ausgegeben und diese sollen
dann eben "gebündelt" durch diesen SPI Slave auf ein
Mikrocontroller(SPI) Interface übertragen werden.
Der Takt des SPI Interface ist 8 MHz.
>DST <= DST(n-2 downto 0) & MOSI; -- Daten ins SR einlesen
Wahrscheinlich doofe Frage :-/: Kann MOSI nicht auch mit '0' ersetzt
werden?
Andi P. schrieb:> Meinen Takt den ich in mein System rein geben werde sind 40 MHZ oder> auch mehr. Auf jedenfall wird dieser dann auf 400 MHZ> Der Takt des SPI Interface ist 8 MHz.
Dann passt das ja locker mit der Abtastung.
Andi P. schrieb:> Wahrscheinlich doofe Frage :-/: Kann MOSI nicht auch mit '0' ersetzt> werden?
Klar, aber dann liest der Slave ja keine Daten mehr ein, sondern nur 0.
Wo liegt da der Sinn? An MOSI (Master Out Slave In) kommen doch die
Daten von deinem µC.
Andi P. schrieb:> Wahrscheinlich doofe Frage :-/: Kann MOSI nicht auch mit '0' ersetzt> werden?
Wenn der Master nichts zu senden und der Slave nichts zu empfangen hat,
dann schon. Aber im Normalfall ist der eigentlich Vorteil ja der, dass
mit jedem SCLK Takt ein Bit vom Master zum Slave und gleichzeitig ein
Bit vom Slvae zum Master übertragen wird:
http://www.lothar-miller.de/s9y/archives/15-SPI.html> Ahja, ok. könntest du mir das eventuell kurz erklären wieso nicht? Ich> ging davon aus in der Sensitivliste die Signale stehen auf die auch> reagiert werden soll?
Die Sensitivliste sagt dem Simulator, wann er den Prozess neu
berechnen muss. Und er muss in deinem Fall den Prozess nur berechnen,
wenn sich der Takt ändert. Denn wenn sich CS ändert und SCLK keine
steigende Flanke hat, dann wird sich auch das Ergebnis des Prozesses
nicht ändern.
Der Synthese ist die Sensitivliste eh' komplett schnuppe!
> Meinen Takt den ich in mein System rein geben werde sind 40 MHZ oder> auch mehr. Auf jedenfall wird dieser dann auf 400 MHZ erhöht durch eine> PLL die mit vier phasenverschobenen Takten dann vier Zähler taktet.> Bestimmte Zählerstände werden irgendwann ausgegeben und diese sollen> dann eben "gebündelt" durch diesen SPI Slave auf ein> Mikrocontroller(SPI) Interface übertragen werden.
Dann nimm die 40MHz zum Abtasten der SPI Signale.
BTW: es wird sicher spannend, wie du die Zählerstände konsistent aus der
400MHz-Domäne herausbekommst. Durch die Phasenverschiebung wird der
virtuelle "Takt" sogar noch höher (oder andersrum: die Marge zur
Übergabe an die 40MHz-Flipflops wird knapper). Dort musst du dir also
auch noch irgendeinen Synchronisationsmechanismus ausdenken.
Christian R. schrieb :
> Andi P. schrieb:>> Wahrscheinlich doofe Frage :-/: Kann MOSI nicht auch mit '0' ersetzt>> werden?>> Klar, aber dann liest der Slave ja keine Daten mehr ein, sondern nur 0.> Wo liegt da der Sinn? An MOSI (Master Out Slave In) kommen doch die> Daten von deinem µC.
Wenn ich aber später über MOSI, Daten vom SPI Interface an den FPGA
übergebe dann sollen die ja anders im FPGA verwendet werden und nicht in
dieses Register eingelesen werden.
Lothar Miller schrieb:
>> Ahja, ok. könntest du mir das eventuell kurz erklären wieso nicht? Ich>> ging davon aus in der Sensitivliste die Signale stehen auf die auch>> reagiert werden soll?> Die Sensitivliste sagt dem Simulator, wann er den Prozess neu> berechnen muss. Und er muss in deinem Fall den Prozess nur berechnen,> wenn sich der Takt ändert. Denn wenn sich CS ändert und SCLK keine> steigende Flanke hat, dann wird sich auch das Ergebnis des Prozesses> nicht ändern.>> Der Synthese ist die Sensitivliste eh' komplett schnuppe!
Sehr gute Erklärung! Vielen Dank. :-)
> BTW: es wird sicher spannend, wie du die Zählerstände konsistent aus der> 400MHz-Domäne herausbekommst. Durch die Phasenverschiebung wird der> virtuelle "Takt" sogar noch höher (oder andersrum: die Marge zur> Übergabe an die 40MHz-Flipflops wird knapper). Dort musst du dir also> auch noch irgendeinen Synchronisationsmechanismus ausdenken.
Alles klar, wird ich beachten.
Andi P. schrieb:> Wenn ich aber später über MOSI, Daten vom SPI Interface an den FPGA> übergebe dann sollen die ja anders im FPGA verwendet werden und nicht in> dieses Register eingelesen werden.
Hm, das versteh ich jetzt nicht. SPI sind im einfachsten Fall 2
gekoppelte Schieberegister. Eins im Master, eins im Slave. Beim Transfer
werden die Inhalte der beiden Register ausgetauscht. Die Daten, die der
Master (Bei der der µC) an das FPGA (den Slave) senden will, muss er aus
seinem Schieberegister in das das Slave-Schieberegister schieben (über
den MOSI), anders gehts nicht. Wenn der Transfer abgeschlossen ist,
kannst du mit den parallelen Daten ja machen was du willst.
Will der Master was vom Slave lesen, muss der Slave die Daten in seinem
Schieberegister bereitstellen und beim Transfer raus schieben. Bei jedem
SPI Transfer wird vom Master sowieso das Register des Slave ausgelesen
(über MISO).
Du musst also immer über die zwei Schieberegister gehen.
Andi P. schrieb:> Wenn ich aber später über MOSI, Daten vom SPI Interface an den FPGA> übergebe dann sollen die ja anders im FPGA verwendet werden und nicht in> dieses Register eingelesen werden.
Machst du dann für jedes Register einen eigenen Slave-Select?
Christian R. schrieb:
> Hm, das versteh ich jetzt nicht. SPI sind im einfachsten Fall 2> gekoppelte Schieberegister ...
Du hast Recht, da stand ich wohl auf dem Schlauch! -.- Ich glaub ich
brauch erst mal ne Kaffeepause :-D.
Lothar Miller schrieb:
> Andi P. schrieb:>> Wenn ich aber später über MOSI, Daten vom SPI Interface an den FPGA>> übergebe dann sollen die ja anders im FPGA verwendet werden und nicht in>> dieses Register eingelesen werden.> Machst du dann für jedes Register einen eigenen Slave-Select?
Nein passt schon, ich war da durcheinander. Das Problem nagte nun schon
zu lange an meinen Nerven. ;-) Danke euch!
>waituntilrising_edge(clk100MHz);-- der einzige Mastertakt für
26
>ALLESimganzenFPGA!
27
>sclkSR<=sclkSR(0)&sclk;
28
>sclkCS<=sclkCS(0)&CS;
29
>
30
>ifCS='0'then
31
>ifsclkSR="01"then-- steigende Flanke am SCLK
32
>DST<=DST(n-2downto0)&MOSI;-- Daten ins SR einlesen
33
>endif;
34
>else
35
>ifsclkSR="01"then-- steigende Flanke am CS
36
>data_out<=DST;-- Übertragung fertig: Daten
37
>übergeben
38
>endif;
39
>DST<=data_in;-- neue Daten übernehmen
40
>endif;
41
>endprocess;
42
>
43
>-- Ausgangstreiber für MISO umschalten
44
>data_out<=DST(n-1)whenCS='0'else'Z';
45
>
46
>endBehavioral;
47
>
Ich habe 2 Fragen zu der SPI-Slave Beschreibung:
1. wofür ist den sclkCS drin, das wird ja gar nicht weiter verwendet.
2. und wie kann ich mit
sclkSR <= sclkSR(0) & sclk;
if sclkSR="01" then
...
eine steigende Flanke von SLK erkennen?
Danke
Thorsten
Thorsten F. schrieb:> 1. wofür ist den sclkCS drin, das wird ja gar nicht weiter verwendet.
ich denke mal, da hat der Lothar einfach geschlampt! sclkCS ist das
einsynchronisiert chip-select, er hat in der Abfrage aber das 'rohe'
Eingangssignal verwendet. Sollte im Normalfall wurscht sein
>> 2. und wie kann ich mit> sclkSR <= sclkSR(0) & sclk;> if sclkSR="01" then> ...> eine steigende Flanke von SLK erkennen?
Naja, wenn du die 'sclk' in deinen FPGA Takt einsynchronisierst
(Schieberegister mit FPGA Takt), dann erkennst du in dem Schieberegister
mit dem Pattern "01" eine steigende, mit dem Pattern "10" eine fallende
Flanke von 'sckl' (halt mit etwas zeitlicher Verzoegerung)
Thorsten F. schrieb:>> if CS = '0' then>> if sclkSR="01" then -- steigende Flanke am SCLK>> DST <= DST(n-2 downto 0) & MOSI; -- Daten ins SR einlesen>> end if;>> else>> if sclkSR="01" then -- steigende Flanke am CS>> data_out <= DST; -- Übertragung fertig: Daten>> übergeben>> end if;>> DST <= data_in; -- neue Daten übernehmen>> end if;
achso, das hier halte ich fuer bedenklich... Und zwar der 'else' Zweig
von CS. Wenn CS=1 ist, also im 'else', dann wartet er noch auf eine
sclkSR=01 um die Daten an den Ausgang der Komponente zu geben. Das ist
aber nicht korrekt! Wenn CS am Ende eines SPI-Transfers auf 1 geht, dann
ist der Transfer beendet, spaetestens dann muesste data_out valide sein
(evtl. schon vorher wenn man die SPI clocks mitzaehlt).
Erscheint mir ziemlich unsauber...
berndl schrieb:> Thorsten F. schrieb:>> 1. wofür ist den sclkCS drin, das wird ja gar nicht weiter verwendet.> ich denke mal, da hat der Lothar einfach geschlampt! sclkCS ist das> einsynchronisiert chip-select, er hat in der Abfrage aber das 'rohe'> Eingangssignal verwendet. Sollte im Normalfall wurscht sein
hatte ich mir schon gedacht aber nicht gewagt zu äussern. ;)
>>>> 2. und wie kann ich mit>> sclkSR <= sclkSR(0) & sclk;>> if sclkSR="01" then>> ...>> eine steigende Flanke von SLK erkennen?> Naja, wenn du die 'sclk' in deinen FPGA Takt einsynchronisierst> (Schieberegister mit FPGA Takt), dann erkennst du in dem Schieberegister> mit dem Pattern "01" eine steigende, mit dem Pattern "10" eine fallende> Flanke von 'sckl' (halt mit etwas zeitlicher Verzoegerung)
Aber wie kann denn aus
sclkSR <= sclkSR(0) & sclk;
"10" werden, sage ich nicht mit (0), dass der erste Wert eine 0 ist?
Es könnte noch "00" sein, aber dann könnte ich auch direkt sclk
abfragen.
Ich frage mich halt wie ich bei meinem schnellen Takt sauber erkennen
kann, jetzt hat sich was am sck von SPI getan und reagiere erst wieder
beim nächten High werden vom sck.
Thorsten
Thorsten F. schrieb:> Aber wie kann denn aus> sclkSR <= sclkSR(0) & sclk;> "10" werden, sage ich nicht mit (0), dass der erste Wert eine 0 ist?> Es könnte noch "00" sein, aber dann könnte ich auch direkt sclk> abfragen.
Denkfehler! sclkSR ist ein Schieberegister mit 2 Bit. Schieberegister
heisst, du hast einen Eingang am ersten FF (Bit 0), das wird in jedem
Clock-Cycle mit sclk neu gesetzt. Gleichzeitig uebertraegst du den Wert
von Bit 0 in das Bit 1 deines SR. In den beiden FFs des SR ist also der
zeitverzoegerte Wert (gesampled mit deiner Clock) des Eingangssignals.
Wenn du also in deinem SR eine Wertefolge "01" findest, dann heisst das,
dass sich dein Eingangssignal in den letzten beiden Clockzyklen von 0
auf 1 geaendert hat. Dito fuer alle anderen 2-Bit Kombinationen...
berndl schrieb:> Denkfehler! sclkSR ist ein Schieberegister mit 2 Bit. Schieberegister> heisst, du hast einen Eingang am ersten FF (Bit 0), das wird in jedem> Clock-Cycle mit sclk neu gesetzt. Gleichzeitig uebertraegst du den Wert> von Bit 0 in das Bit 1 deines SR. In den beiden FFs des SR ist also der> zeitverzoegerte Wert (gesampled mit deiner Clock) des Eingangssignals.> Wenn du also in deinem SR eine Wertefolge "01" findest, dann heisst das,> dass sich dein Eingangssignal in den letzten beiden Clockzyklen von 0> auf 1 geaendert hat. Dito fuer alle anderen 2-Bit Kombinationen...
Danke berndl für die Erklärung.
Das bedeutet also slk ist 0, dann steht "00" im Schieber, wenn sclk dann
von 0 auf 1 geht steht da "01" drin, dann bei den nächsten Systemtakten
"11" bis sclk auf 0 geht und ein mal "10" drin steht um dann beim
nächsten Systemtakt wieder "00" zu schieben.
Das ist ja einfach. ;)
Thorsten
>DST<=DST(n-2downto0)&MOSI;-- Daten ins SR einlesen
4
>endif;
5
>else
6
>ifsclkSR="01"then-- steigende Flanke am CS
7
>data_out<=DST;-- Übertragung fertig: Daten
8
>übergeben
9
>endif;
10
>DST<=data_in;-- neue Daten übernehmen
11
>endif;
12
>
dazu noch 2 Fragen.
"-- steigende Flanke am CS" müsste aber
"-- steigende Flanke am SCLK" heissen, oder?
und dann diese Zeile:
DST <= DST(n-2 downto 0) & MOSI; -- Daten ins SR einlesen
da werden die "Slave in"-Daten ja in DST Schieber geladen. aber warum
DST(n-2 downto 0), also warum n-2. Müsste es nicht auch in den ersten FF
rein um die anderen Werte weiter zu schieben, also DST(0)?
Thorsten
Irgendwie ist diese Anweisung nicht zielführend. Zunächst müsste es doch
1
ifsclkCS="01"then
heißen.
Die Zeile
1
DST<=data_in;
sollte in diesem Zusammenhang auch nicht genutzt werden. Würde ja
bedeuten, dass data_in quasi direkt in data_out geschrieben würde.
Lothar trifft bestimmt keine Schuld, dafür wird hier eindeutig zu viel
VHDL code gepostet. Aber merkt das kein Anderer?
Bis auf diese zwei Zeilen ist der Code recht gut geeignet als SPI Slave,
der wirklich nur Daten empfängt und parallel ausgibt. Allerdings habe
ich nach Lothars Kunst die Eingangssignale durch zweimaliges Schieben
einsynchronisiert. Die SPI Kommunikation ist mit 180 kHz recht langsam,
da mir eine sichere Übertragung wichtiger ist als eine schnelle
Übertragung. System-Clock ist 50Mhz.
> if CS = '0' then> if sclkSR="01" then -- steigende Flanke am SCLK> DST <= DST(n-2 downto 0) & MOSI; -- Daten ins SR einlesen> end if;> else> if sclkSR="01" then -- steigende Flanke am CS> data_out <= DST; -- Übertragung fertig: Daten> übergeben> end if;> DST <= data_in; -- neue Daten übernehmen> end if;>
Und vor allem sind die Kommentare nicht vollständig bzw sinnlos und
unnötig.
Außerdem musst du COPY und PASTE üben.
sclkSR != sclkCS
Gruß Jonas
Jonas Biensack schrieb:> sclkSR != sclkCS
Da habe ich mal wirklich saublöde Namen ausgedacht... :-/
Sinnvollerweise heißen die Signale natürlich sclkSR und csSR, weil es
jeweils Schieberegister (SR) zum Eintakten und für die Flankenerkennung
sind. Und dann nenne ich das Daten-Schieberegister auch gleich noch dSR:
Eine Frage, wenn csSR 01 entspricht, dann wird data_in zu data_out
direkt geschaltet oder nicht? Ich kann mir nicht vorstellen, dass es
funktioniert. Tut es bei mir auch nicht.
data_out <= dSR;
gegen
dSR <= data_in;
Kann nicht gehen, weil die Übergabe mit CS ungeschickt gelöst ist. Also
einen Schritt zurückgetreten und das Original nochmal angeschaut
(Achtung: jetzt wirds rekursiv!):
http://www.lothar-miller.de/s9y/archives/32-Einfacher-SPI-Slave.html
Dann ein klein wenig nachgedacht (!!) und das Nötige geändert (es ist
ja nur die Umstellung der direkten Flanken- und Pegelabhängigkeit auf
synchrone eingetaktete Signale). Und heraus kommt dann das hier:
if(ssSR="11")then-- solange deselektiert: immer Daten vom Din übernehmen
28
dsr<=Din;
29
elsif(sclkSR="01")then-- mit der steigenden SCLK-Flanke
30
dsr<=dsr(dsr'left-1downto0)&MOSI;-- wird MOSI eingetaktet
31
endif;
32
endprocess;
33
34
MISO<=dsr(dsr'left)whenSSn='0'else'Z';-- Richtungsteuerung MISO direkt über SSn
35
36
-- Parallel-Ausgänge übernehmen mit steigender SS-Flanke
37
processbegin
38
waituntilrising_edge(clk);
39
if(ssSR="01")then-- steigende Flanke am SS: Device wird deselektiert
40
Dout<=dsr;-- Ausgangssignale an Dout ausgeben
41
endif;
42
endprocess;
43
44
endBehavioral;
Das war ja einfach...
Und zusammen mit der Testbench im Anhang kommt dann die Waveform im
Anhang raus. Voila, funktioniert tadellos (etwas verwirrend ist evtl.
dass sich nach der letzten steigenden Flanke nochmal der Pegel vom MISO
ändert, aber das passt schon und ist dem Geiz zuverdanken: es wird nur 1
Schieberegister für Senden und Empfang verwendet).
Mit dem Logikanalysator gemessen zeigt sich bei meinem Aufbau ein
Fehler.
Miso ändert sich mit der steigenden Flanke statt mit der fallenden.
Hier meine Änderung:
chris schrieb:> Mit dem Logikanalysator gemessen zeigt sich bei meinem Aufbau ein> Fehler.
Tut mir leid, ich sehe nix. Wo ist denn das Signal MISO?
chris schrieb:> Miso ändert sich mit der steigenden Flanke statt mit der fallenden.
Stimmt doch gar nicht? Die (RTL-)Simulation sagt, dass alles passt.
Siehe Anhang. Es gibt ein Delay von einem Takt, was aber durchaus zur
Beschreibung passt. (Wozu hat Lothar schon eine komplette Testbench
mundgerecht angehängt, wenn sie doch nicht genommen wird?)
Vermutung: Dein Systemtakt ist nicht groß genug. Der muss mindestens(!)
2x größer sein, als SCK. Dafür sprechen die unregelmäßigen Flanken von
SCK.
VG ElKo
if(ssSR="11")then-- solange deselektiert: immer Daten vom Din übernehmen
4
dsr<=Din;
5
elsif(sclkSR="01")then-- mit der steigenden SCLK-Flanke
6
dsr<=dsr(dsr'left-1downto0)&MOSI;-- wird MOSI eingetaktet
7
endif;
8
endprocess;
9
10
MISO<=dsr(dsr'left)whenSSn='0'else'Z';-- Richtungsteuerung MISO direkt über SSn
Auf die Gefahr hin, dass ich mich verhaspelt habe ...
In diesem Codestück von Lothar ist es doch so, dass sich "dsr" mit der
steigenden Flanke ändert.
MISO hängt außerhalb des Prozesses direkt an "dsr" und ändert sich
deshalb auch mit der steigenden Flanke, oder?
Meine Messung zeigt das auch. Warum die Simulation nicht?
if(sclkSR="10")then-- mit der fallenden Flanke an MISO ausgeben
2
misoLoc<=dsr(dsr'left);
3
endif;
4
endprocess;
5
6
--MISO <= dsr(dsr'left) when SSn='0' else 'Z'; -- Richtungsteuerung MISO direkt über SSn
7
MISO<=misoLocwhenSSn='0'else'Z';-- Richtungsteuerung MISO direkt über SSn
beschreibt.
Soweit also alles im grünen Bereich...
> Meine Messung zeigt das
Dank den nicht dargestellten "Mastertaktes" könnte sein, dass die zwei
Takte Verzögerung durch das Flankenschieberegister dazu führen, dass der
Wechsel erst zusammen mit der nächsten Taktflanke stattfindet. Aber eben
nicht wegen dieser Taktflanke!
Wie schon gefragt: welche FPGA-Takt- und SCLK-Takt-Frequenzen hast du?
>ändert sich das MISO doch wie erwartet mit der steigenden Taktflanke...
Wenn ich es richtig sehe, sollten sich bei der SPI im Mode0 sollten sich
die Signal MOSI und MISO bei der fallenden Flanke ändern.
>Wie schon gefragt: welche FPGA-Takt- und SCLK-Takt-Frequenzen hast du?
50MHz/1MHz
chris schrieb:> Wenn ich es richtig sehe, sollten sich bei der SPI im Mode0 sollten sich> die Signal MOSI und MISO bei der fallenden Flanke ändern.
Anders: Die Daten werden auf die steigende SCK-Flanke eingelatcht. Das
heißt, auf die Flanke muss das Signal stehen. Bis zur nächsten
steigenden SCK-Flanke muss das neue Bit auf der Leitung liegen. Zu
welchem Zeitpunkt das auf die Leitung gelegt wird, ist egal. Eine
Variante ist es, auf die fallende Flanke zu schreiben. Eine andere
(Lothars) Variante ist, das neue Bit direkt nach der steigenden Flanke
zu schreiben.
In jedem Fall musst du sicherstellen, dass zur steigenden Taktflanke
(bei Mode 0) die Daten auf der Leitung sicher anliegen und gelesen
werden.
VG ElKo
ElKo schrieb:> Eine Variante ist es, auf die fallende Flanke zu schreiben.
Das ist die "reine Lehre", die aber nur von sehr wenigen SPI-Devices
tatsächlich eingehalten wird. Denn dadurch "verschenkt" man quasi die
halbe Taktfrequenz, weil ja für die Setup-Zeit nur die halbe Bitzeit
übrig bleibt.
> Eine andere (Lothars) Variante ist, das neue Bit direkt nach> der steigenden Flanke zu schreiben.
Das ist quasi die "Schieberegister" Variante.
Und auf solchen "verketteten" Schieberegistern basiert ja der SPI(*):
Daten liegen an und werden mit der nächsten aktiven (= entweder steigend
oder fallend) Taktflanke weitergeschoben. Sie müssen (wie üblich)
rechtzeitig vor der nächsten aktiven Taktflanke stabil am nächsten
Flipflop sein.
(*) siehe http://www.lothar-miller.de/s9y/archives/15-SPI.html
Ohne es jemals genauer zu reflektieren bin ich jetzt jahrelang davon
ausgegangen, dass man den maximalen Störabstand genau dann erhält, wenn
man genau auf der Hälfte zwischen den Abtastpunkten das Datensignal
umschaltet.
Aber vielleicht stimmt das gar nicht und man hat zwei getrennte
Bedingungen für einen SPI-Slave:
1. Für MOSI könnte gelten, dass man den besten Störabstand erhält, wenn
der Master genau zwischen den Abtastzeitpunkten umschaltet.
2. Für MISO könnte gelten, dass man den maximalen Störabstand erhält,
wenn der Slave genau nach der Abtastflanke umschaltet.
ElKo schrieb:> Vermutung: Dein Systemtakt ist nicht groß genug. Der muss mindestens(!)> 2x größer sein, als SCK. Dafür sprechen die unregelmäßigen Flanken von> SCK.
Guter Punkt: Das SCLK-Signal sieht auf den Screenshots schon sehr
komisch aus.
Meine Vermutung ist eher, dass der Logic-Analyzer, mit dem der
Screenshot aufgenommen wurde von der Abtastfrequenz nicht ganz hinkommt.
Man sollte das Timing-Verhalten von MISO zu SCLK mal mit einem
schnelleren Logic Analyzer oder Oszi aufnehmen.
chris schrieb:> Ohne es jemals genauer zu reflektieren bin ich jetzt jahrelang davon> ausgegangen, dass man den maximalen Störabstand genau dann erhält, wenn> man genau auf der Hälfte zwischen den Abtastpunkten das Datensignal> umschaltet.
Das kann man so pauschal leider nicht sagen. Es hängt auch von der
Setup- und Holdzeit des Empfängers ab. Es gibt auch Devices mit
negativer Holdzeit.
Wenn man die Signale über einen Optokoppler schickt, muß man deren
Latenzen auch noch berücksichtigen (vor allem für das MISO-Signal).
Duke
Beispiel aus der Praxis: Spartan 3A Starter Kit (UG330), Ansteuerung DAC
über SPI, Seite 75
https://www.xilinx.com/support/documentation/boards_and_kits/ug330.pdf> After driving the DAC_CS slave select signal Low,> the FPGA transmits data on the SPI_MOSI signal,> MSB first. The LTC2624 captures input data (SPI_MOSI)> on the rising edge of SPI_SCK; the data must be> valid for at least 4 ns relative to the rising clock> edge.
Es wird gefordert, dass das MISO und MOSI mindestens 4 ns um die
SCK-Flanke herum stabil bleiben müssen. Hier kann es also zu Problemen
kommen, direkt auf die Flanke auch die neuen Daten zu schreiben.
(unwahrscheinlich, aber möglich - auf jeden Fall nicht in der
Spezifikation)
Lothar M. schrieb:> Vorneweg: CS gehört hier nihct in die Sensitivliste.
Ich glaube, der möchte das CS aynchron beschreiben, was je nach
Anwendung sinnvoll sein kann, falsch sein kann oder auch Pflicht ist und
dann gehört es durchaus da rein, wobei der Code dann anders zu
beschreiben wäre.
Das hat man jetzt vom Herauskramen alter Threads... :-/
Der aktuelle beginnt erst beim
Beitrag "Re: Erfahrung mit SPI Slave und Spartan 6 FPGA?"
Weltbester FPGA-Pongo schrieb im Beitrag #5196420:
> dann gehört es durchaus da rein
In diese (drei Jahre alte) Sensitivliste aber eben nicht.
Wenn mich bei reinstem Sonnenschein einer fragt: "wie ist das Wetter?"
dann sage ich ja auch "die Sonne scheint!" und nicht "die Sonne scheint,
es hätte aber genausogut regnen können, wenn die Wetterlage entsprechend
wäre"... ;-)