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


von Felix (Gast)


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
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity TXLCD is
6
    Generic ( Quarz_Taktfrequenz : integer   := 50000000;  -- Hertz 
7
              Baudrate           : integer   :=  115200      -- Bits/Sec
8
             ); 
9
    Port ( 
10
           TXD      : out  STD_LOGIC;
11
           TX_Data  : in   STD_LOGIC_VECTOR (23 downto 0);
12
           TX_Start : in   STD_LOGIC;
13
           TX_Busy  : out  STD_LOGIC;
14
        txdenable : out std_logic;
15
           CLK      : in   STD_LOGIC
16
           );
17
end TXLCD;
18
19
architecture Behavioral of TXLCD is
20
signal txstart : std_logic := '0';
21
signal txstart1 : std_logic := '0';
22
signal txsr    : std_logic_vector  (9 downto 0) := "1111111111";  -- Startbit, 8 Datenbits, Stopbit
23
signal txbitcnt : integer range 0 to 10 := 10;
24
signal txcnt    : integer range 0 to (Quarz_Taktfrequenz/Baudrate)-1;
25
signal Trigger : std_logic;
26
signal rxd_sr  : std_logic_vector (3 downto 0) := "1111";         -- Flankenerkennung und Eintakten
27
signal rxsr    : std_logic_vector (7 downto 0) := "00000000";     -- 8 Datenbits
28
signal rxbitcnt : integer range 0 to 9 := 9;
29
signal rxcnt   : integer range 0 to (Quarz_Taktfrequenz/Baudrate)-1; 
30
signal x : std_logic:='1';
31
signal m1 : integer:=0; 
32
signal txe : std_logic ;
33
   
34
begin
35
  senden : process (CLK)
36
  begin
37
  
38
      IF RISING_EDGE(CLK) THEN
39
      txstart <= Trigger;
40
      if (Trigger='0' and txstart='1') then -- steigende Flanke, los gehts
41
         txcnt    <= 0;                      -- Zähler initialisieren
42
         txbitcnt <= 0; 
43
        
44
        if (m1 =1)then
45
      
46
         txsr     <= '1' & TX_Data (7 downto 0) & '0';    -- Stopbit, 8 Datenbits TX_DATA, Startbit, rechts gehts los TX_Data (7 downto 0)
47
        elsif (m1=3)then
48
      txsr     <= '1' & TX_Data (15 downto 8) & '0';    -- Stopbit, 8 Datenbits TX_DATA, Startbit, rechts gehts los TX_Data (15 downto 8)
49
        elsif (m1=5) then
50
      txsr     <= '1' & TX_Data (23 downto 16) & '0';    -- Stopbit, 8 Datenbits TX_DATA, Startbit, rechts gehts los TX_Data (23 downto 16)
51
52
        end if;
53
      else
54
         if(txcnt<(Quarz_Taktfrequenz/Baudrate)-1) then
55
            txcnt <= txcnt+1;
56
         else  -- nächstes Bit ausgeben  
57
            if (txbitcnt<10) then
58
              txcnt    <= 0;
59
              txbitcnt <= txbitcnt+1;
60
              txsr     <= '1' & txsr(txsr'left downto 1);
61
            end if;
62
         end if;
63
      end if;
64
    end if;
65
   end process senden;
66
   TXD     <= txsr(0);  -- LSB first
67
   TX_Busy <= '1' when (TX_Start='1' or txbitcnt<10) else '0';
68
69
70
  
71
  Enabletx:PROCESS ( CLK )
72
  variable COUNTER1: integer :=0;
73
  variable i : integer:=1;
74
   variable m : integer:=0;
75
  BEGIN
76
    IF RISING_EDGE(CLK) THEN
77
      txstart1 <= TX_Start ;
78
      if (TX_Start='1'and txstart1= '0')then
79
      i:=600000;     ------Anzahl von Daten im Packet 100000(2ms)*(3*2)---2geht high dann low
80
      txe <= '1';
81
      m :=0;
82
      COUNTER1 := 0;
83
      end if;
84
      
85
      if (i>0)then
86
      i:=i-1;
87
        if (COUNTER1 < 100000) then
88
          COUNTER1 := COUNTER1 + 1 ;
89
          if (COUNTER1 = 50000)then
90
            m := m+1;
91
            
92
          end if;
93
94
          else
95
          COUNTER1 := 0;
96
          x <= not x; 
97
98
        end if;
99
        m1 <=m;
100
      Trigger <=  x;
101
      
102
      end if;
103
      if (i=0) then
104
      txe <= '0';
105
      Trigger <=  '1';
106
      end if;
107
      
108
      
109
    END IF;
110
--    
111
  END PROCESS Enabletx;
112
   txdenable <= txe;
113
114
end Behavioral;

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


Lesenswert?

Versuch mal den vhdl tag zum Code posten zu nutzen^^

Mit:
1
[vhdl]
2
...
3
[/vhdl]

Vermutlich hängt das mit

>  i:=600000;

zusammen. Wird dekrementiert und wohl nicht nochmal neu initialisiert.

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


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:
1
      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:
1
Antwort schreiben
2
Wichtige Regeln - erst lesen, dann posten!
3
    Groß- und Kleinschreibung verwenden
4
    Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
5
Formatierung (mehr Informationen...)
6
    [vhdl]VHDL-Code[/vhdl]

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


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. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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)


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)


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. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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)


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:

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:
1
IF RISING_EDGE(CLK) THEN
2
  txstart <= Trigger;
3
  if (Trigger='0' and txstart='1') then -- fallende Flanke
4
    if (m1 =1)then txsr <= '1' & TX_Data(7 downto 0) & '0';
5
    elsif (m1=3)then txsr <= '1' & TX_Data(15 downto 8) & '0';
6
    elsif (m1=5) then txsr <= '1' & TX_Data(23 downto 16) & '0';
7
    end if;
8
  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. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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)


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)


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)


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.

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.