Daten vom Mikrocontroller zum Slave senden funktioniert und auch das
Senden vom Slave zum Mikrocontroller funktioniert in der Simulation,
nicht aber in der Hardware. Aus irgendeinem Grund wird der Wert für
`Counter` nicht erhöht. Wenn ich die Variable auf einen festen Wert
setze, dann wird der Wert vom Mikrocontroller korrekt ausgelesen. Mit
einem LA konnte ich zudem sehen, dass das `Busy´`-Signal korrekt
geschaltet wird, was bedeutet das der Zustandsautomat funktioniert.
Wo könnte das Problem liegen?
Danke und Gruß
Stimmt die Reset-Polarität in deinem FPGA? Du verwendest den Reset ja
tatsächlich nur an einer einzigen Stelle im Design, und wenn der falsch
gepolt ist, läuft die nur currentState-FSM nicht los und es wird immer
der Initialwert des Counters ausgegeben.
Btw, warum hast du für Counter eine Variable verwendet? Man sollte auf
Variablen verzichten, wenn es möglich ist, und hier ist es möglich.
Falsch ist die Variable allerdings nicht an dieser Stelle.
Vancouver schrieb:> Du verwendest den Reset ja tatsächlich
... ganz ohne ihn vorher einzusynchronisieren. Da kann es gut mal
passieren, dass das Design am Anfang seltsame Dinge macht, weil es zum
Start nicht sauber aus dem State_Reset herauskommt.
Siehe dazu das da:
http://www.lothar-miller.de/s9y/archives/41-Einsynchronisieren-von-asynchronen-Signalen.html
Zudem ist nach kurzem Nachdenken der Zustand State_Reset im Prinzip
völlig unnötig. Er fügt nach dem Deaktivieren des Reset eh' nur einen
einzigen Takt Latency ein, weil bedingungslos vom State_Reset nach
State_WaitBusy gesprungen wird.
Vancouver schrieb:> Stimmt die Reset-Polarität in deinem FPGA? Du verwendest den Reset ja> tatsächlich nur an einer einzigen Stelle im Design, und wenn der falsch> gepolt ist, läuft die nur currentState-FSM nicht los und es wird immer> der Initialwert des Counters ausgegeben.> Btw, warum hast du für Counter eine Variable verwendet? Man sollte auf> Variablen verzichten, wenn es möglich ist, und hier ist es möglich.> Falsch ist die Variable allerdings nicht an dieser Stelle.
Es war tatsächlich die Reset-Polarität... :)
Jetzt funktioniert es!
Dennoch werde ich den Reset auch ordentlich einsynchronisieren.
Btw. zum Thema Reset...
Das hier hat der Mikrocontroller nach der Konfiguration des FPGAs
empfangen:
1
0
2
1
3
1
4
1
5
1
6
1
7
2
8
3
Anscheinend hat das FPGA (obwohl der Reset aktiv war) einmal den Zähler
erhöht. Dieses Verhalten ist sogar reproduzierbar. Das
Einsynchronisieren scheint das Problem zu beheben.
Dolle Wurst... Ich gebe anderen schlaue Ratschläge und suche dann in
meinem eigenen Design stundenlang einen Fehler, der durch einen falsch
gepolten Reset verursacht wurde. An die Nase fass
Daniel K. schrieb:> Dieses Verhalten ist sogar reproduzierbar.
Dann ist es aber kein Verhalten, das auf ein nicht einsynchronisiertes
Signal hinweist, denn so ein asynchrones Signal zeichnet sich durch
völlige Zufälligkeit aus.
> (obwohl der Reset aktiv war)
Sicher? Dauernd?
Was passiert, wenn du dem Register Busy einen inaktiven Defaultwert
gibst? Und zwar dort, wo das eigentliche Busy Register sitzt:
1
entitySPI_Slaveis
2
Port(Clock:inSTD_LOGIC;
3
nReset:inSTD_LOGIC;
4
5
Busy:outSTD_LOGIC:='0';
6
:
Es bringt nämlich nichts, diesen Defaultwert im "Top"-Level zu vergeben,
wo er sofort vom Pegel des Submoduls "SPI_Slave" überschrieben wird:
1
signalBusy:STD_LOGIC:='0';-- Initwerte wirkungslos, denn .....
> Das Einsynchronisieren scheint das Problem zu beheben.
Das Einsynchronisieren sorgt nämlich auch für definierte Defaultwerte.
BTW:
1
Rx<=Rx_Data;
Wenn du das erst bei der steigenden Flanke des SSn (so heißt
eigentlich der CSn beim SPI Bus) machst, dann zappeln die Ausgänge
nicht so herum bei der Übertragung:
1
:
2
elsif(CS_ShiftReg="01")then
3
Rx<=Rx_Data;
4
Busy<='0';
5
endif;
BTW2:
Und im Grunde ist das Register Busy das selbe wie CS_ShiftReg(1) plus
ein Takt Latency. Du könntest also auch einfach so schreiben:
1
process
2
begin
3
waituntilrising_edge(Clock);
4
5
SCLK_ShiftReg<=SCLK_ShiftReg(0)&SCLK;
6
CS_ShiftReg<=CS_ShiftReg(0)&CS;
7
Busy<=CS_ShiftReg(1);-- einfach mit 1 Takt Latency durchreichen
8
:
BTW3: musst du bei inaktivem SSn/CSn nicht den MISO-Ausgang hochohmig
schalten? Übliche SPI-Slaves machen das, damit mehr als 1 Slave an den
Bus angeschlossen werden kann.
BTW4:
> ich habe einen einfachen SPI-Slave für mein FPGA entworfen
Nur aus Interesse: findet sich dieser Coding-Style schon irgendwo in der
Literatur?
BTW5:
Sieh dir auch mal den
Beitrag "Re: Erfahrung mit SPI Slave und Spartan 6 FPGA?" an... ;-)
Hallo Lothar,
danke für deine ganzen Anmerkungen. Schauen wir mal ob ich sie
beantwortet bekomme :)
Zu BTW 5: Für die Implementierung (ist bisher nur der erste Schuss, da
ich diese noch ausbauen möchte - u. a. soll da auch noch ein Master mit
rein) habe ich mich bei verschiedenen Quellen umgeschaut um zu schauen
wie man so etwas machen kann, bzw. wie der SPI im Detail funktioniert.
Die Quellen sind
-
https://www.analog.com/en/analog-dialogue/articles/introduction-to-spi-interface.html
- https://www.digikey.com/eewiki/pages/viewpage.action?pageId=7569477
- https://www.digikey.com/eewiki/pages/viewpage.action?pageId=4096096
- http://www.lothar-miller.de/s9y/categories/26-SPI-Slave
- Beitrag "Re: Erfahrung mit SPI Slave und Spartan 6 FPGA?"
Die Digikey-Beispiele fand ich irgendwie wahnsinnig komplex, ganz im
Gegensatz zu deinem Beispiel. Was mich an deinem Beispiel "gestört" hat,
war die fehlende Parametrierung des Modus und der fehlende Sendekanal
vom Slave, aber für eine erste Idee nicht schlecht, da einfach und
gepaart mit dem Thread aus dem Forum doch durchaus interessant, was so
die Funktionsweise des SPI angeht.
Das Beispiel habe ich dann als Grundlage genommen um etwas rumzuspielen,
bzw. den Standard aus dem TI-Link umzusetzen (sprich die Flanken fürs
Samplen und Senden - nicht im Code oben abgebildet, da neu).
Zu BTW 4: Was genau meinst du damit? Ist das subtile Kritik oder
subtiles Lob :D? Da stehe ich etwas auf dem Schlauch.
Zu BTW 3: Da hast du natürlich recht. Das fehlt in dem Beispiel und das
hatte ich bisher auch noch nicht auf dem Schirm.
Zu BTW 2: Auch da hast du recht. Ich habe das Signal erst einmal rein
genommen, weil ich noch nicht weiß ob noch eine Busy-Kondition dazu
kommen könnte. Aktuell ist es natürlich redundant.
Zu BTW 1: Guter Hinweis. Das übernehme ich mal so. Bzgl. der SS / CS
Konvention weiß ich leider nicht so viel. Mal lese ich CS, mal lese ich
SS, mal was komplett anderes. :(
Zum Rest: Mmh okay. Dann war es vielleicht doch nicht die Ursache oder
ich hatte da noch einen Knoten im Reset (der Reset liegt im FPGA-Board
auf einem Schalter). Auf jeden Fall funktioniert es nun wunderbar und
auch die Konfiguration von CPHA und CPOL ist nun drin.
Daniel K. schrieb:> Zu BTW 4: Was genau meinst du damit? Ist das subtile Kritik oder> subtiles Lob :D? Da stehe ich etwas auf dem Schlauch.
Nein, nur aus Interesse gefragt. Könnte ja sein, dass nach einem
Jahrzehnt mal einer vom asynchronen, nicht eingetakteten Reset
weggekommen ist... ;-)
> Zu BTW 1: Guter Hinweis. Das übernehme ich mal so. Bzgl. der SS / CS> Konvention weiß ich leider nicht so viel. Mal lese ich CS, mal lese ich> SS, mal was komplett anderes. :(
Für SPI ist Slave Select SS# richtig. Allerdings kann man mit einem
SPI-Interface (weil es ja nur ein Schieberegister ist) auch MicroWire
o.ä. Bausteine ansteuern. Dort nennt sich diese Steuerleitung dann CS
oder komplett anders.
Daniel K. schrieb:> Die Digikey-Beispiele fand ich irgendwie wahnsinnig komplex
Ich hab mir das mal angeschaut, helle Hölle, sowas Krudes hab ich schon
lange nicht mehr gesehen:
1
PROCESS(ss_n,clk,st_load_en,tx_load_en,rx_req)
2
BEGIN
3
4
--write address register ('0' for receive, '1' for status)
5
IF(bit_cnt(1)='1'ANDfalling_edge(clk))THEN
6
wr_add<=mosi;
7
ENDIF;
8
9
--read address register ('0' for transmit, '1' for status)
Da hat (leicht erkennbar an den unnötigen Klammern und der kuriosen
Schleife) ganz offensichtlich ein Softwareprogrammierer VHDL
programmiert, ohne einen Funken Verständnis davon zu haben, was daraus
synthetisiert wird... :-o
So einen kombiniert kombinatorisch synchronen Prozess mit
unvollständigen Sensitivlisten, mit eigenartigen Clock-Enables und
kombinatorischen Resets (Stichwort Glitches) bekommt in der Realität
kein Mensch niemals zuverlässig zum Laufen.
Das könnte bestenfalls als Prüfungsaufgabe durchgehen: finden Sie die 10
Fehler!
Lothar M. schrieb:> Da hat (leicht erkennbar an den unnötigen Klammern und der kuriosen> Schleife) ganz offensichtlich ein Softwareprogrammierer VHDL> programmiert, ohne einen Funken Verständnis davon zu haben, was daraus> synthetisiert wird... :-o>> So einen kombiniert kombinatorisch synchronen Prozess mit> unvollständigen Sensitivlisten, mit eigenartigen Clock-Enables und> kombinatorischen Resets (Stichwort Glitches) bekommt in der Realität> kein Mensch niemals zuverlässig zum Laufen.>> Das könnte bestenfalls als Prüfungsaufgabe durchgehen: finden Sie die 10> Fehler!
Zum Glück bin ich mit meiner Meinung nicht alleine :D.