Diese Programmiersprache habe ich noch nie gesehen. Ich rate mal:
Es scheint hier zwei konkurrierende Threads zu geben:
1) Der obere Thread sende Daten.
2) Der untere Thread erzeugt die Daten.
Beabsichtigt war wohl dass der untere Thread die Variable "data" immer
dann um 1 erhöht (und das Senden startet), wenn der Sender nicht aktiv
ist.
Dazu setzt der Sender wiederum seinen Status in der Variable "sending".
Der Fehler besteht in der fehlenden Synchronisation dieser Prozesse.
Wenn die Threads durch einen aktiven Task-Scheduler ausgeführt werden
(also immer ein bisschen von jedem Thread), könnte sich folgender Ablauf
ergeben:
1
Thread 2:
2
if (data < 100 && sending == 0) begin
3
data <= data+1; // Data wird von 0 nach 1 erhöht
4
send <= 1;
5
6
Thread 1:
7
if (send && !sending) begin
8
sendbuf <= {1'b1, data, 1'b0};
9
10
Thread 2:
11
// Achtung: sending ist immer noch 0!
12
if (data < 100 && sending == 0) begin
13
data <= data+1; // Data wird von 1 nach 2 erhöht
14
send <= 1;
15
16
Thread 1:
17
sending <= 1;
18
timeout <= 1406 - 1;
Ebenso kann der selbe Fehler auftreten, wenn das Programm auf mehreren
CPU's oder CPU Kernen ausgeführt wird.
Du brauchst einen zuverlässigen Mechanismus, um die Prozesse zu
synchronisieren. Zum Beispiel, indem du irgendwie verhinderst, dass die
folgenden Zeilen von Thread1 für andere Threads unterbrochen werden:
1
// Andere Threads pausieren
2
if (send && !sending) begin
3
sendbuf <= {1'b1, data, 1'b0};
4
sending <= 1;
5
// Andere Threads fortfahren
Manche CPU's haben dazu einen speziellen Befehl, der eine Variable
testet und zugleich setzte. In Pseudo-Code nach diesem Prinzip:
1
if (ändere sending von 0 nach 1 und wenn das geklappt hat, dann)
2
// sende daten
3
end
Hier findet die Änderung und der Test in einer einzigen nicht
unterbrechbaren Operation statt. Andere Threads sehen daher niemals
einen falschen Zwischenstatus.
Auf Mikrocontrollern sieht man als einfach Lösung oft, dass kurzzeitig
alle Interrupts deaktiviert werden. Dadurch wird der aktuelle Thread
garantiert nicht unterbrochen.
Auf PC stellen Linux und Windows dafür spezielle Funktionen bereit, die
in der Regel vom Framework der Anwendung gekapselt und benutzt werden.
Die richtigen Suchwörter zu dem Thema sind: Synchronisierung, Threads,
Concurreny, Mutex, Atomare Zugriffe
Stefan U. schrieb:> Diese Programmiersprache habe ich noch nie gesehen. Ich rate mal:
falsch geraten:
schau mal wo der Thread ist:
FPGA, VHDL & Co.
Das ist gar keine Programmiersprache
Nachtrag zum möglichen Ablauf:
Die Variable data wurde nun schon zweimal erhöht, bevor sie gesendet
wurde. Die Schrittweite 2, die du beobachtest hast ist mehr oder weniger
ein Zufallsprodukt. Die Schrittweite könnte auch viel größer sein oder
unregelmäßig.
> Das ist gar keine Programmiersprache
Oh mein Fehler. Mit FPGA's kenne ich mich gar nicht aus. Aber ich
glaube, die führen viele Aktionen zeitgleich aus - insofern passt meine
Überlegung trotzdem Auch wenn es gar keine CPU's sind.
hast du einen Simulator zur Hand?
Dann nutz den mal, und schau dir an, wann send aktiv wird, wann sending
aktiv wird und in welchen Taktzyklen data hochgezählt wird.
Stefan U. schrieb:> ie Schrittweite könnte auch viel größer sein oder> unregelmäßig.
Nein: die Schrittweite wird immer genau 2 sein.
FRANK schrieb:> Auch eine Hardware-Beschreibungssprache ist eine Programmiersprache.
hast du dafür einen beleg?
Unter Programmiersprachen finde ich nicht VHDL, und unter VHDL finde ich
nicht das es eine Programmiersprache ist.
Peter II schrieb:> Unter Programmiersprachen finde ich nicht VHDL, und unter VHDL finde ich> nicht das es eine Programmiersprache ist.
... seit Peter Otto heißt, nutzt er Verilog. Und wahrscheinlich tut's
deswegen nicht ;)
Markus F. schrieb:> ... seit Peter Otto heißt, nutzt er Verilog. Und wahrscheinlich tut's> deswegen nicht ;)
Wenn sich sein Benehmen so bessert wie die Wahl der Beschreibungsprache
gibts ja noch Hoffnung ;-)
Um Achim S. Hinweise etwas zu verdeutlichen:
Wenn 'sending' = 0 wird zählst du hoch.
Wenn du hochzählst setzt du im gleichen Takt 'send'.
Wenn 'send' gesetzt ist wird im nächsten Takt 'sending' gesetzt.
Wieviele Takte lang ist dann 'if (data < 100 && sending == 0)' wahr?
Du musst also in der if Bedingung noch etwas verwenden das sich schon im
nächsten Takt geändert hat. 'send' würde sich da anbieten...
Andi
FRANK schrieb:> Auch eine Hardware-Beschreibungssprache ist eine Programmiersprache.
So wie ein Traktor und ein LKW natürlich auch ein Automobil ist, weil
sie sich selbständig bewegen...
otto schrieb:> Warum ist die serielle Ausgabe bitte 1,3,5,7
Die Ursache ist Latency. Im Simulator siehst du, dass sending 2 Takte
lang 0 ist...
Schreib da unten mal sowas:
1
always@(posedgeclk)begin
2
if(data<100&&sending==0&&send==0)begin
3
data<=data+1;
4
send<=1;
5
endelsebegin
6
send<=0;
7
end
8
end
Stefan U. schrieb:> Die Schrittweite ... ein Zufallsprodukt. Die Schrittweite könnte auch> viel größer sein oder unregelmäßig.
Sie ist in dem Fall hier vollkommen deterministisch und immer '2'. Das
ist das Schöne an der Hardware... ;-)
>> Die Schrittweite ... ein Zufallsprodukt. Die Schrittweite könnte auch>> viel größer sein oder unregelmäßig.> Sie ist in dem Fall hier vollkommen deterministisch und immer
Ich war ja auch fälschlicherweise von einem Mikroprozessor mit einem
Multitaksing OS ausgegangen.
Stefan U. schrieb:> Ich war ja auch fälschlicherweise von einem Mikroprozessor mit einem> Multitaksing OS ausgegangen.
Ja, da ist das Ganze eher zufällig und nicht so einfach nachvollziehbar.
Deshalb mag ich Hardware... ;-)