Forum: FPGA, VHDL & Co. Spartan 3E + ATmega über SPI


von Andreas W. (Firma: andreas-weschenfelder.de.vu) (rupplyn) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich möchte grad ne "SPI"-Verbindung zwischen nem Spartan 3E und nem 
ATmega realisieren.
In Anführungszeichen, weil das ganze ne Art 3-Leitung SPI mit WR/RD- und 
Mode-Signalen ist.

In der Simulation funktioniert das auch. Auf dem FPGA allerdings nicht 
immer. (Der AVR-Code funktioniert übrigens definitiv.)

Kann mir jemand vielleicht sagen warum das nicht funktioniert?!?

von Mike (Gast)


Lesenswert?

Ganz spontan würde ich sagen es liegt hier dran:

1
if falling_edge(AT_CLK) then   --fallended flanke

Du hast hier 2 verschiedene Takte in deinem FPGA. Das ist meistens keine 
sonderlich gute Idee.

Lies dir am besten das hier mal durch:

http://www.mikrocontroller.net/articles/Taktung_FPGA/CPLD

von Kest (Gast)


Lesenswert?

Schau mal her:

  ProTimeOut:process(CLK_50MHZ)
  begin
    if rx_timeout < 65535 then
      rx_timeout <= rx_timeout + 1;
    end if;
    if tx_timeout < 65535 then
      tx_timeout <= tx_timeout + 1;
    end if;
  end process ProTimeOut;

was soll das sein? Wo ist Dein Takt? Wie schnell soll denn Dein Zähler 
werden? Klar funktioniert das in der Simulation, weil da CLK_50MHZ 
Erreignisse kommen, in Hardware ist es...äh... wie soll ich sagen... 
Müll :-)

Das ist das erste, was ich gesehen habe

Grüße,

Kest

von Falk B. (falk)


Lesenswert?

@  Andreas Weschenfelder (rupplyn)

>ich möchte grad ne "SPI"-Verbindung zwischen nem Spartan 3E und nem
>ATmega realisieren.
>In Anführungszeichen, weil das ganze ne Art 3-Leitung SPI mit WR/RD- und
>Mode-Signalen ist.

Warum willst du das Rad neu erfinden? Was spricht gegen eine klassiche 
SPI?

>In der Simulation funktioniert das auch. Auf dem FPGA allerdings nicht
>immer. (Der AVR-Code funktioniert übrigens definitiv.)

>Kann mir jemand vielleicht sagen warum das nicht funktioniert?!?

Wie der Vorposter schon bemerkte ist dein Timeout Prozess Sülze. Da 
fehlt ein Takt. Ausserdem solltest du das mit den Variablen rx_data und 
tx_data          lassen, das ist Murks. Nimm Signale. Das tut auch gar 
nicht weh.

Und was soll den sowas?
1
      --Datenleitung schreiben; MSB first
2
        if tx_data(7) = '1' then
3
          AT_D_OUT <= '1';
4
        else
5
          AT_D_OUT <= '0';
6
        end if;
7
        --Schieben und mit 0 auffuellen
8
        tx_data := tx_data(6 downto 0) & '0';
9
10
        --Datenbit schieben und einfuegen (MSB)
11
        if AT_D_IN = '1' then
12
          rx_data := rx_data(6 downto 0) & '1';
13
        else
14
          rx_data := rx_data(6 downto 0) & '0';
15
        end if;

Wo hast du dennn das her? Und ausserdem wird dadurch dein tx_data(7) 
immer So macht man das. Sieht doch gleich viel besser aus, oder?
1
  AT_D_OUT <= tx_data(7); 
2
  tx_data := tx_data(6 downto 0) & 0;
3
  rx_data := rx_data(6 downto 0) & AT_D_IN;

MFG
Falk

von Andreas Weschenfelder (Gast)


Lesenswert?

@ all
Danke erst mal für die Anregungen, ist leider nur eine Hobby-Arbeit und 
kann sie erst heut Abend umsetzen.

@ Kest
Klar, jetzt wo du das sagst, seh ich das auch.

@ Falk Brunner
Ich habe mit vhdl praktisch keine Erfahrung und versuche mir das gerade 
selbst bei zu bringen. möchte daher erst mal selbst verschiedene module 
erstellen.
Dein 3-Zeiler sieht übrigens natürlich besser aus.

von Rick Dangerus (Gast)


Lesenswert?

Wenn Du Dich mit dem schematic-Editor abquälen willst, kannst Du auch 
den folgenden Link nutzen:

http://www.ibrtses.com/electronics/fpgabasic.html
-> Using serial registers to interface to the external world

Der ist auch für das grundlegende Verständnis ganz gut.

Rick

von Thomas R. (Firma: abaxor engineering) (abaxor)


Lesenswert?

Echte Hardware kennt auch keine globalen Variablen, d.h. du kannst keine 
zwei Ausgänge parallel schalten. Dies passiert in VHDL, wenn du ein 
Signal in zwei Prozessen schreibst, hier rx_timeout und tx_timeout. Da 
dies einen Fehler bei Synthese erzeugt, frage ich mich, wie du zu einen 
Bitstream gekommen bist.

Bye Tom

von Andreas W. (Firma: andreas-weschenfelder.de.vu) (rupplyn) Benutzerseite


Angehängte Dateien:

Lesenswert?

Die Antwort von Mike hat mir am meisten geholfen. Es läuft jetzt recht 
stabil.
Allerdings erhalte ich am Parallel-Ausgang (LEDs) zuerst kurz 0xFF, 
anschließend die richtigen Daten.

Ich wollte das ganze noch auf die Main-Clk (50MHz) synchronisieren. Hab 
das folgendermaßen realisiert:

if falling_edge(CLK_50MHZ) then
--Flankenerkennung, sync auf CLK50MHZ
  if AT_CLK = '1' then
    flankenbit <= '1';
  end if;
  if (flankenbit = '1') and (AT_CLK = '0') then
  flankenbit <= '0';

  --Das hier war eine fallende Flanke... -> Auswertung

  end if;
end if;

Kommt mir allerdings selbst ein bisschen umständlich vor. Gibt's da ne 
bessere Lösung?

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.