Forum: FPGA, VHDL & Co. TXD bricht nach 75 min ab


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Felix (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,
ich habe folgende Programm geschreiben um Daten von FPGA an Arduino zu 
schicken. Leider schickt der FPGA nach 75 min keine Daten mehr...
anbei schicke ich euch auch das Code,ich konnte die Fehler leider nicht 
identifizieren.
könnte jemand mir helfen um den Feler zu finden. Danke
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity TXLCD is
    Generic ( Quarz_Taktfrequenz : integer   := 50000000;  -- Hertz 
              Baudrate           : integer   :=  115200      -- Bits/Sec
             ); 
    Port ( 
           TXD      : out  STD_LOGIC;
           TX_Data  : in   STD_LOGIC_VECTOR (23 downto 0);
           TX_Start : in   STD_LOGIC;
           TX_Busy  : out  STD_LOGIC;
        txdenable : out std_logic;
           CLK      : in   STD_LOGIC
           );
end TXLCD;

architecture Behavioral of TXLCD is
signal txstart : std_logic := '0';
signal txstart1 : std_logic := '0';
signal txsr    : std_logic_vector  (9 downto 0) := "1111111111";  -- Startbit, 8 Datenbits, Stopbit
signal txbitcnt : integer range 0 to 10 := 10;
signal txcnt    : integer range 0 to (Quarz_Taktfrequenz/Baudrate)-1;
signal Trigger : std_logic;
signal rxd_sr  : std_logic_vector (3 downto 0) := "1111";         -- Flankenerkennung und Eintakten
signal rxsr    : std_logic_vector (7 downto 0) := "00000000";     -- 8 Datenbits
signal rxbitcnt : integer range 0 to 9 := 9;
signal rxcnt   : integer range 0 to (Quarz_Taktfrequenz/Baudrate)-1; 
signal x : std_logic:='1';
signal m1 : integer:=0; 
signal txe : std_logic ;
   
begin
  senden : process (CLK)
  begin
  
      IF RISING_EDGE(CLK) THEN
      txstart <= Trigger;
      if (Trigger='0' and txstart='1') then -- steigende Flanke, los gehts
         txcnt    <= 0;                      -- Zähler initialisieren
         txbitcnt <= 0; 
        
        if (m1 =1)then
      
         txsr     <= '1' & TX_Data (7 downto 0) & '0';    -- Stopbit, 8 Datenbits TX_DATA, Startbit, rechts gehts los TX_Data (7 downto 0)
        elsif (m1=3)then
      txsr     <= '1' & TX_Data (15 downto 8) & '0';    -- Stopbit, 8 Datenbits TX_DATA, Startbit, rechts gehts los TX_Data (15 downto 8)
        elsif (m1=5) then
      txsr     <= '1' & TX_Data (23 downto 16) & '0';    -- Stopbit, 8 Datenbits TX_DATA, Startbit, rechts gehts los TX_Data (23 downto 16)

        end if;
      else
         if(txcnt<(Quarz_Taktfrequenz/Baudrate)-1) then
            txcnt <= txcnt+1;
         else  -- nächstes Bit ausgeben  
            if (txbitcnt<10) then
              txcnt    <= 0;
              txbitcnt <= txbitcnt+1;
              txsr     <= '1' & txsr(txsr'left downto 1);
            end if;
         end if;
      end if;
    end if;
   end process senden;
   TXD     <= txsr(0);  -- LSB first
   TX_Busy <= '1' when (TX_Start='1' or txbitcnt<10) else '0';


  
  Enabletx:PROCESS ( CLK )
  variable COUNTER1: integer :=0;
  variable i : integer:=1;
   variable m : integer:=0;
  BEGIN
    IF RISING_EDGE(CLK) THEN
      txstart1 <= TX_Start ;
      if (TX_Start='1'and txstart1= '0')then
      i:=600000;     ------Anzahl von Daten im Packet 100000(2ms)*(3*2)---2geht high dann low
      txe <= '1';
      m :=0;
      COUNTER1 := 0;
      end if;
      
      if (i>0)then
      i:=i-1;
        if (COUNTER1 < 100000) then
          COUNTER1 := COUNTER1 + 1 ;
          if (COUNTER1 = 50000)then
            m := m+1;
            
          end if;

          else
          COUNTER1 := 0;
          x <= not x; 

        end if;
        m1 <=m;
      Trigger <=  x;
      
      end if;
      if (i=0) then
      txe <= '0';
      Trigger <=  '1';
      end if;
      
      
    END IF;
--    
  END PROCESS Enabletx;
   txdenable <= txe;

end Behavioral;

: Bearbeitet durch Moderator
von Mampf F. (mampf) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Versuch mal den vhdl tag zum Code posten zu nutzen^^

Mit:
[vhdl]
...
[/vhdl]

Vermutlich hängt das mit

>  i:=600000;

zusammen. Wird dekrementiert und wohl nicht nochmal neu initialisiert.

: Bearbeitet durch User
von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Mampf F. schrieb:
> und wohl nicht nochmal neu initialisiert.
Höchstens wenn TX_Start zwischendurch mal wieder inaktiv wird.

Und auch dazu noch ein Wort:
      if (TX_Start='1'and txstart1= '0')then
Das TX_Start muss unbedingt einsynchronisiert werden, wenn es ein 
asynchrones externes Signal ist. Sonst passiert mit den ganzen Zählens 
m, i und counter das hier:
http://www.lothar-miller.de/s9y/archives/41-Einsynchronisieren-von-asynchronen-Signalen.html

In meinem Code auf http://www.lothar-miller.de/s9y/categories/42-RS232 
ist angenommen, dass dieses TX_Start ein synchrones Signal ist, das von 
einem anderen Modul des FPGAs kommt.

Und ich würde diese Verwaltung mit m1=1,m1=3,m1=5, also welches Byte zu 
senden ist, ausserhalb der TX-Geschichte machen. So, dass das 
Sendemodul tatsächlich einfach nur 1 Byte versendet, wie es eben 
zigmilliarden µC auch machen.

Mampf F. schrieb:
> Versuch mal den vhdl tag zum Code posten zu nutzen^^
So wie es über jeder Texteingabebox geschrieben steht:
Antwort schreiben
Wichtige Regeln - erst lesen, dann posten!
    Groß- und Kleinschreibung verwenden
    Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
Formatierung (mehr Informationen...)
    [vhdl]VHDL-Code[/vhdl]

: Bearbeitet durch Moderator
von Gustl B. (-gb-)


Bewertung
0 lesenswert
nicht lesenswert
Nun, also der Code

- benötigt externe Signale zu denen du nix geschrieben hast. Konkret: 
TX_Start. Nach TX_Start sendet der Code 3 Bytes. Mehr konnte ich nicht 
beobachten. Ob das also nach langer Zeit nichtmehr funktioniert muss 
nicht an dem Code liegen, sondern kann auch daran liegen, dass dann aus 
unbekannten Gründen TX_Start ausbleibt.

- verwendet sehr ähnliche Namen
signal txstart : std_logic := '0';
signal txstart1 : std_logic := '0';
TX_Start
Sowas sollte man vermeiden.

- verwendet Variablen ohne Not.

- wenig hilfreiche Kommentare:

      i:=600000;     ------Anzahl von Daten im Packet 
100000(2ms)*(3*2)---2geht high dann low

Mag sein, aber in deinem Code ist kein Signal/Variable das wie ein Paket 
aussieht.

if (COUNTER1 < 100000) then

Wie bist du auf diese Zahlen gekommen?
Woher kommt das externe TX_Start das einen Sendevorgang auslöst?

Edit:

      txstart <= Trigger;
      if (Trigger='0' and txstart='1') then -- steigende Flanke, los 
gehts

Ist leider falsch. Das ist die fallende Flanke von Trigger.

: Bearbeitet durch User
von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Gustl B. schrieb:
> txstart <= Trigger;
> if (Trigger='0' and txstart='1') then -- steigende Flanke, los gehts
> Ist leider falsch. Das ist die fallende Flanke von Trigger.
Der Kommentar ist noch von meinem Originalcode, da bin ich richtig 
erschrocken, dass da evtl. noch ein Fehler drin wäre. Ist zum Glück aber 
nicht...   ;-)

: Bearbeitet durch Moderator
von dfIas (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Lothar M. schrieb:
> Das TX_Start muss unbedingt einsynchronisiert werden, wenn es ein
> asynchrones externes Signal ist. Sonst passiert mit den ganzen Zählens
> m, i und counter das hier:
> 
http://www.lothar-miller.de/s9y/archives/41-Einsynchronisieren-von-asynchronen-Signalen.html
Synchronisieren ist nur die halbe Lösung. Die andere Hälfte besteht 
darin, eine Replication dieses Signals zu unterdrücken. Dazu gilt es - 
plattformabhängig - entsprechende Attribute zu setzen.

von Achim M. (minifloat)


Bewertung
0 lesenswert
nicht lesenswert
Felix schrieb:
> Daten von FPGA an Arduino zu schicken. Leider schickt der FPGA nach 75
> min keine Daten mehr...
Kann es sein, dass der Arduino nach 75 min keine Daten mehr empfängt 
oder dein Terminal oder der USB-Serial-Adapter hängt? Oder wurde das 
schon alles ausgeschlossen?

mfg mf

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
dfIas schrieb:
> Synchronisieren ist nur die halbe Lösung. Die andere Hälfte besteht
> darin, eine Replication dieses Signals zu unterdrücken.
Aha, hast du dir an dieser Ecke auch mal die Finger verbrannt?  ;-)

> Die andere Hälfte besteht
> darin, eine Replication dieses Signals zu unterdrücken.
Die Ursache für dieses "Problem" ist die selbe wie der Grund für das 
Einsynchronisieren: es darf nicht aus 1 Signal durch (interne) 
Laufzeiten zu nachfolgend inkonsistenten Signalen kommen.

Allerdings reicht bei den schnellen Flipflops, die heutzutage in FPGAs 
zu finden sind, 1 einziges Flipflop aus, um ein externes Signal nach 1 
Taktzyklus trotz jeglicher Metastabilität sicher auf einem definierten 
Pegel zu haben. Und ab dann (also in der 2. Ebene) darf es beliebig 
dupliziert werden.

Das heißt final, dass ich 3 FFs verwende: das 1. zum eigentlichen 
Eintakten (das auch nirgends in einer Abfrage verwendet wird), dahinter 
das 2. (ab dem Dupliziert werden darf) und das 3. (das zusammen mit dem 
vorigen für die vermutlich sowieso nötige Flankenerkennung eingesetzt 
wird).

Und wer trotzdem noch Angst hat, der setzt vor das 1. Flipflop noch 
eines, damit jede statistische Wahrscheinlichkeit für ein Fehlverhalten 
so klein wird, dass es sogar noch wahrscheinlicher ist, laufend jeden 
Samstag 6 Richtige im Lotto zu haben... ;-)

Zu dieser Thematik noch ein Link:
http://www.lothar-miller.de/s9y/archives/62-Testaufbau-Metastabilitaet.html
Und wenn man sich diesen Mechanismus zur vermeintlich allgegenwärtigen 
Metastabilität mal angeschaut und durchschaut hat, dann findet man den 
Fehler in Videos wie z.B. https://www.youtube.com/watch?v=vw3BG6StOFk 
ganz leicht. Das, was dort den Zähler so schnell hochzählen lässt, ist 
mitnichten eine Metastabilität, sondern einfach die unterschiedliche 
Laufzeit vom Pin bis zu den beiden Flipflops:
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html

von Gustl B. (gustl_b)


Bewertung
0 lesenswert
nicht lesenswert
Achim M. schrieb:
> Kann es sein, dass der Arduino nach 75 min keine Daten mehr empfängt
> oder dein Terminal oder der USB-Serial-Adapter hängt? Oder wurde das
> schon alles ausgeschlossen?

Das Problem hatte ich mal. So wirklich einen Schuldigen konnte ich nicht 
finden. Mit Windows stoppte die Übertragung früher als unter Linux. Und 
das war auch schlecht reproduzierbar. Ich habe dann aufgegeben und statt 
der cp2102 ft232rl verwendet und pyserial. Bei mir kamen die Abbrüche 
recht zufällig. Mal nach paar Stunden, mal erst nach Tagen oder gar 
Wochen. Könnte auch daran liegen dass das keine konstante Datenrate war.

von Gustl B. (-gb-)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So, Nachtrag:
Ich habe das jetzt mal simuliert und es wird noch wunderlicher:
Das TXLCD seldet die 3 Bytes nicht jedes Mal wenn TX_Start '1' ist, 
sondern nur jedes zweite Mal.

Warum ist das so? Gekürzt:
IF RISING_EDGE(CLK) THEN
  txstart <= Trigger;
  if (Trigger='0' and txstart='1') then -- fallende Flanke
    if (m1 =1)then txsr <= '1' & TX_Data(7 downto 0) & '0';
    elsif (m1=3)then txsr <= '1' & TX_Data(15 downto 8) & '0';
    elsif (m1=5) then txsr <= '1' & TX_Data(23 downto 16) & '0';
    end if;
  end if;
Es muss also dann die fallende Flanke von Trigger erscheinen, wenn m1 = 
1 oder m1 = 3 oder m1 = 5 ist. Und das ist nur jedes zweite Mal der 
Fall.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Gustl B. schrieb:
> Ich habe das jetzt mal simuliert
HGW, du bist der Erste, der das tut... ;-)

> und es wird noch wunderlicher
Da bin ich schon wieder erschrocken, weil trotz TXbusy am Ausgang TX nix 
zappelt. Aber klar, da wird das txsr-Schieberegister gar nicht 
angefasst, behält den Wert x"3ff" und schiebt laufend '1' raus. Da lag 
ich mit meinem initialen Misstrauen in diesen Multiplexer gar nicht so 
daneben.

von Gustl B. (gustl_b)


Bewertung
1 lesenswert
nicht lesenswert
Lothar M. schrieb:
> Da bin ich schon wieder erschrocken

Bin jetzt angeln gegangen, das mit dem Code anderer Leute ist nicht gut 
für den Puls.

von Horst G. (horst_g532)


Bewertung
0 lesenswert
nicht lesenswert
Gustl B. schrieb:
> das mit dem Code anderer Leute ist nicht gut für den Puls.

Da sagste was. Insbesondere, wenn der Code wild von anderen Seiten 
zusammenkopiert ("geschrieben") wurde, irgendwelche planlosen Änderungen 
daran vorgenommen wurden, ohne jedoch z. B. die Kommentare anzupassen, 
und das Ganze dann vom vollkommen unerfahrenen TO ohne eigene Simulation 
und unter Fehlen der Beschreibung der gesamten Peripherie mit der 
Fehlerbeschreibung "geht nicht – bitte heile machen" im Forum abgeladen 
wird.

von dfIas (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Lothar M. schrieb:
> Und wer trotzdem noch Angst hat, der setzt vor das 1. Flipflop noch
> eines, damit jede statistische Wahrscheinlichkeit für ein Fehlverhalten
> so klein wird, dass es sogar noch wahrscheinlicher ist, laufend jeden
> Samstag 6 Richtige im Lotto zu haben... ;-)
Nein, die Sache liegt anders. Zur Zeit, als man noch mit Schematic Entry 
seine Schaltung vorgegeben hatte, hätte man schon selbst Replizieren 
müssen. Das Replizieren haben sich aber die Synthese-Tools angeeignet, 
um Fan-outs zu verwalten. Du setzt also vermeintlich ein (einzelnes) FF 
vor das Eingangssignal, und ohne es zu merken macht die Synthese daraus 
hinterrücks zwei oder mehrere.
Zugegeben, bei derart simplen Schaltungen ist die Wahrscheinlichkeit 
einer Replizierung gering, aber theoretisch besteht sie. Ich entwickle 
Schaltungen für die Raumfahrt, die haben eine andere Komplexität und mit 
Replication muss man fest rechnen. Derlei Ausfälle können/dürfen wir uns 
nicht erlauben. Sehr häufig haben wir den Fall, dass für die Entwicklung 
auf Flash-basierten FPGAs aufgrund eines größeren Resourcenangebots 
keine Replication stattfindet, aber spätestens dann beim Übergang auf 
die (kleineren) Rad-hard-Typen. Daher: grundsätzlich auch dem 
Synthese-Tool immer mitteilen, dass ein Signal bzw. ein Register nicht 
vervielfältigt werden darf, sondern unique bleibt.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.