Guten Abend,
ich möchte mein Problem kurz erläutern :
Ein FPGA soll einen Datenstrom aus losen Bytes erhalten.
Darin befinden sich willkürlich irgentwann einmal Pakete die über einen
Header erkannt werden sollen und per HeaderCRC gesichert werden.
Darauf folgt eine im Header angekündigte Menge an Payload.
Die Aufgabe ist es nun : dieser Payload soll sofort zu einem
entsprechenden Empfänger geleitet werden ohne das zuerst der gesamte
Payload empfangen werden muss und auf einen CRC am Ende gewartet wird.
Der Grund : jedwede Verzögerung soll so gering wie möglich gehalten
werden.
Ohne Fehlerprüfung im Payload wäre das nun kein Thema, jedoch kommt es
bei dieser Übertragung gelegentlich(<10^-10, entspricht bei der
Datenrate jedoch nur der Größenordnung von Minuten) vor das Fehler
auftreten, insbesondere komplette Bytes verschwinden. (z.b. nur 9 statt
10 bytes Payload empfangen werden)
Das Problem : der Empfänger darf unter keinen Umständen(d.h. möglichst
unwarscheinlich) ein fehlerhaftes Byte erhalten, da diese Bytes sofort
verwendet werden und sowohl verloren gegangene Bytes als auch
fehlerhafte Bytes einen kompletten Reset nach sich ziehen können/müssen.
D.h. für den unwarscheinlichen Fall das etwas verloren geht ist eine
Pause für die Neuübertragung akzeptabel, im Regelbetrieb soll das jedoch
nicht vorkommen.
Ich habe mich nun umgesehen und finde überall nur Methoden zur
Absicherung die ein Wissen über das Gesamte Paket/Payload voraussetzen.
Deshalb frage ich hier : hat jemand eine Idee wie sich dies gut lösen
lassen könnte oder kennt sogar einen schon vorhandenen Algorithmus der
das löst ?
Bisher ist mir lediglich die Möglichkeit eingefallen für jedes Byte eine
eigene, kleine Absicherung einzufügen.
Bsp : 1 byte mit Paritätsinformationen, wobei jedes bit für eins der 8
Folgebyte gilt, d.h. mit 12,5% Bandbreitenverlust 1 bit Fehler erkannt
werden können...das klingt nicht sehr sinnvoll.
Achja, ich sollte noch anmerken : Der Sender hat alle Zeit der Welt die
Pakete vorzubereiten, also auch das komplette Wissen über die gesamte
Payload.
Irgentwie dachte ich könnte man damit einen umgekehrten CRC bauen, aber
mir fällt einfach nicht ein wie.
1. Vorschlag: Sub-Pakete bauen, z.B. auf n Bytes Nutzdaten 1 Byte
Prüfsumme übertragen. Das verzögert den Datenstrom um n+1 Bytes und
verschlechtert die Datenrate um O(1/(n+1)).
2. Vorschlag wenn Deine größte Sorge verlustig gehende Bytes sind:
Durchnummerieren. Z.B. immer Nutzdatennibbel senden, das jeweils andere
Nibbel (des übertragenen Bytes) zum zählen nehmen, ggf. auch noch gleich
ein Paritätsbit reinpacken. Damit kannst dann z.B. die Nibbel von 0..7
durchnummerieren (mit Überlauf natürlich) +1 Paritätsbit (über alles).
Alternativ 0..3 Nummerieren und 2 Paritätsbits. Oder sowas in der Art.
Das halbiert die Nutzdatenrate, dafür kannst Du bei einem
Übertragungsfehler (Bitfehler oder Verlust) sofort abbrechen. Und der
Aufwand zum Nibbelschieben +Verwaltung hält sich in Grenzen.
HTH und HF
Danke schonmal !
Variante 1 habe ich mir auch überlegt und letztendlich werde ich
vielleicht darauf zurückgreifen müssen, vielleicht mit 3+1crc byte.
Die 2te Möglichkeit klingt prinzipiell nicht schlecht, hat aber den
Nachteil das ich ein empfangenes Byte auch nicht sofort verwenden kann,
also auf ein zweites gewartet werden muss und zudem massenhaft
Bandbreite verbrauch wird.
Aber das mit dem durchzählen bringt mich auf einen Gedanken : einen
dauerhaften 2 bit Zähler im Datenbyte deckt bis zu 3 verlorene Bytes
auf. Muss nur überlegen ob mir 6 bit Dateninformation reichen.
Aber müsste es nicht theoretisch möglich sein eine Funktion so zu bauen,
das ich 1 Byte "Checksumme" übertrage und allein daraus feststellen kann
ob die nächsten Byte gültig sein könnten ?
Simples Beispiel :
ich übertrage in byte 1 (checksummenbyte) einen Filter.
nun wird byte 1 mit 2, 2 mit 3 usw ... z.b. xor kombiniert und wenn das
Ergebnisbyte > 0 ist dann ist es ein Fehler außer das Filterbyte hat für
diese Stelle vermeldet das es auf jeden Fall an dieser Bitposition einen
Fehler gibt, dann wird es ignoriert. Exemplarisch für 2 bit :
check|data|data|data
0|1|0|1 -> wechselt immer -> kann xor geprüft werden.
1|1|1|0 -> kann nicht geprüft werden da 1-1 Folge -> gefiltert
würde hier Byte 1,2 oder 3 verschwinden würde das erkannt werden und
zudem noch 1 bit Fehler in den nicht gefilterten Bitpositionen.
Trotzdem gefällt mir das so nicht besonders, etwa kann es vorkommen das
überall Filterbits stehen und die Erkennung ist gleich 0.
Blockcodes habe ich mir schon angesehen, aber ich sehe nicht wie ich
damit etwas erreiche kann.
Grob gesagt möchte ich ja durch Hinzufügen von 1 bis maximal 2 byte
Latenz alle folgenden Bytes komplett ohne Latenz erhalten.
Mit den Blockcodes habe ich aber, wenn ich das richtig verstanden habe,
zu jedem Byte Redundanz, d.h. es kommen auch weiterhin immer wieder mal
Leerunden vor.
>> Wie das?
Darauf habe ich leider keinen Einfluss. Auf der Kommunikationsstrecke
liegt ein Teilnehmer der die Daten theoretisch einfach nur
weiterschickt. Jedoch verschluckt der sich gelegentlich.
Mir ist schon klar das dies alles ein wenig mit Kanonen auf Spatzen
geschossen ist, insbesondere für ein kleines Hobbyprojekt.
Aber wenn ich mir da was in den Kopf gesetzt habe, dann spricht nichts
dagegen es auch mal umzusetzen und sei es nur wegen des Lerneffektes.
> Aber müsste es nicht theoretisch möglich sein eine Funktion so zu bauen,> das ich 1 Byte "Checksumme" übertrage und allein daraus feststellen kann> ob die nächsten Byte gültig sein könnten ?
Ohne in der entsprechenden Mathematik recht sattelfest zu sein, wage ich
zu behaupten, dass es gerade theoretisch nicht möglich sein sollte.
Angenommen, du hast eine CRC Funktion die folgendes kann:
Du hast n-1 Bytes empfangen, und die Funktion weiss genau, ob Byte n
gültig ist. Das heisst, sie hat Byte n aus Byte 1 .. n-1 berechnet.
Solltest Du so eine solche Funktion haben, dann brauchst Du Byte n gar
nicht mehr übertragen, weil Byte n ja schon bekannt ist.
Das Spiel kann man weiterführen mit Byte n+1 usw.
Daraus ergibt sich, dass die komplette Information über das Paket in der
Funktion steckt, und es soviele verschiedene CRC Funktionen geben muss,
wie Pakete und zur Übertragung der Parameter der CRC Funktion brauchts
Du gleich viel Bits wie für das Paket selbst.
Etwas anders funktioniert die Geschichte, wenn Du sagst :
"Ich nehme an, dass in meinem Byte nur 1 Bit gestört ist".
Da könntest Du z.B. im voraus alle Parity Bits der Bytes des Paketes
übertragen und diese dann laufend mit den eintreffenden Bytes
vergleichen.
Das löst aber immer noch das Problem des verlorengegangenen Bytes und
funktioniert auch nicht, wenn 2 Bits kippen.
10^-10 ist keine kleine Fehlerrate (Zumindest wenn die Daten so kritisch
sind). Bei 100Mbyte/s Datenrate wäre das ein Fehler pro 100 Sekunden.
Für mich stellt sich erstmal die Frage, wie die Daten verloren gehen
können.
Welche Art der Datenübertragung hast Du realisiert? Serielle oder
parallele Übertragung, welcher IO-Standard, etc?
Grundsätzlich ist es schon richtig, dass die Übertragung Fehlertolerant
sein muss, aber wenn es noch grundsätzliche Hardwareprobleme gibt ist es
sinnvoller an der Quelle anzusetzen.
Sofern ich richtig verstanden habe, ist die Datenverlust noch vor Latenz
dein Feind :).
Eine Erhöhung der Redundanz in den einzelnen Bytes hilft dir aber nicht
viel, wenn "komplette Bytes verloren gehen" (wonach ich als erste
fahnden würde).
Mit einem Zähler (2bit) könntest Du immerhin sofort mitbekommen, dass
ein Byte fehlt. Damit der Empfänger aber niemals ein falsches Paket
empfängt, müsstest Du im FPGA entweder komlett puffern (hohe Latenz)
oder eine laufende Übertragung als ungültig markieren können.
Allerdings ist die Latenz noch größer, wenn Du ungültige Daten
empfängst, diese verwirfst und dein ganzes System zurücksetzen musst.
Codes wie der Reed-Solomon verteilen ihre Redundanzinformation über eine
Vielzahl von Bytes. Insbesondere bei Burst-Fehlern kann hier rückwirkend
die Information wieder hergestellt werden.
Vielleicht kann man den Reed-Solomon Code mit einer einfachen Checksumme
kombinieren. Sofern die Checksumme über kleine Paketschnipsel korrekt
ist, überträgst Du zum Empfänger einfach fröhlich weiter. Falls etwas
nicht stimmt, nutzt Du die eingebettete redundante Information und
kannst das verlorene Byte wieder herstellen (mit einer kleinen Latenz).
Iulius schrieb:
> Grob gesagt möchte ich ja durch Hinzufügen von 1 bis maximal 2 byte> Latenz alle folgenden Bytes komplett ohne Latenz erhalten.>> Mit den Blockcodes habe ich aber, wenn ich das richtig verstanden habe,> zu jedem Byte Redundanz, d.h. es kommen auch weiterhin immer wieder mal> Leerunden vor.>
Ohne Arme keine Kekse!
Du schreibst
>Das Problem : der Empfänger darf unter keinen Umständen(d.h. möglichst>unwarscheinlich) ein fehlerhaftes Byte erhalten, da diese Bytes sofort>verwendet werden und sowohl verloren gegangene Bytes als auch>fehlerhafte Bytes einen kompletten Reset nach sich ziehen können/müssen.
Derzeit hast Du noch nicht einmal einen Schutz für jedes einzelne Byte
und überlegst Dir eine Lösung für ein verlorenes Byte.
Schutz gibt es nur gegen Redundanz. Die typischen Checksummen können Dir
möglicherweise nur bei Einzelbifehlern helfen - Multibitfehler sind
nicht sicher erkennbar.
Bei Blockcodes ist die Redundanzinformation über den gesamten Block
verteilt (z.B. in jedem 2 Byte nur ein Bit). Der Anwender kann
entscheiden ob er mehr oder weniger Redundanz benötigt. Klassischerweise
werden sie wie beschrieben eingesetzt, wenn Burst-Fehler erwartet werden
(Kratzer auf der CD, kurze Störung auf dem Funkkanal). Im Fehlerfall
kann die veteilte redundante Information genutzt werden, mehrere
aufeinander folgende gestörte Bits zu restaurieren.
Ich verstehe das Problem auch nicht ganz:
Dh hast die Kontrolle über den Sender, ansonsten könntest Du ja nicht
festlegen, wie dieser die Daten zu senden hat und dort hast Du jede Zeit
der Welt, wie Du schreibst.
Du hast die Kontrolle über den Empfänger, und dort ist es auf einmal
zeitkritisch, sodass jedes Byte sofort verarbeitet werden soll.
Solltest Du dir dein System nicht vielleicht nochmals überdenken? Wie
wäre es, wenn der Sender die Daten ein bischen früher schickt, und der
Empfänger die Daten kontrolliert und verzögert?
Ich habe nur alle Zeit der Welt weil die zeitkritischen Pakete schon vor
der eigentlich Laufzeit feststehen und zur Laufzeit lediglich verschickt
werden müssen.
Der Sender an sich ist hochgradig ausgelastet und möchte schnellst
möglich eine Antwort auf seine Nachfrage, weil das Ergebnis dieser
Antwort über den weiteren Programmverlauf entscheiden kann.
Das Problem der teils fehlerhaften Verbindung zu beseitigen ist eine
Sache, daran arbeite ich auch, keine Sorge, jedoch löst das die Frage
der Absicherung nicht. denn irgentwo kann immer mal was passieren,
selbst auf der besten Leitung.
Die finale Art der Übertragung ist eh nicht geklärt, jedoch sollten 1-2
Meter Kabelstrecke überwunden werden können. Und bei dieser Strecke muss
ich doch praktisch immer mit Fehlern rechnen oder etwa nicht ?
Iulius schrieb:
> Die finale Art der Übertragung ist eh nicht geklärt, jedoch sollten 1-2> Meter Kabelstrecke überwunden werden können. Und bei dieser Strecke muss> ich doch praktisch immer mit Fehlern rechnen oder etwa nicht ?
Ein Auto ist doch recht schnell, oder?
Bisher hast Du außer dem Prinzip noch keine Infos preisgegeben über
deine physikalische Übertragungsart:
- Glasfaser Kabel Antenne
- parallel / seriell
- Datenrate
- Umgebung (Störungsmöglichkeiten)
Solange Du dir noch nicht einmal im klaren bist, welche Probleme dich
erwarten, macht eine Diskussion keinen Sinn!
Weil es für meine Fragestellung völlig unerheblich ist.
Mir geht es immer noch um die Fehlererkennung ab dem 1.ten Datenbyte
ohne nachträgliche Einwirkung durch einen hinten angestellten Prüfwert.
Und für diese Überlegung ist es völlig unerheblich ob ich nun über
Kupfer oder Glas übertrage.
Ich wollte deshalb auch nie eine Diskussion über die physikalische
Übertragungsart.
Meine Frage im letzten Post war rein rhetorischer Natur.
Wenn es Dir um die Theorie geht, dann solltest Du auch darauf antworten.
Um es nochmal zusammenzufassen:
Wenn Du eine Absicherung des einzelnen Bytes (Blockgröße ist 1 Byte)
braucht, dann musst Du Redundanz auf auf Byte-Ebene einführen, das sind
1 Parity Bit oder mehr.
Das geht auf Kosten der Bandbreite.
Weniger Redundanz geht nur, wenn man die Blockgröße erhöht, was im
Normalfall sinnvoll ist, weil man nicht in jedem Byte einen Fehler
erwartet, sondern maximal 1 (oder 2) pro Block.
Eine Überprüfung der Richtigkeit kann aber nur mit dem vollständigen
Block erfolgen, weil der Trick bei CRC und ähnlichem ist es eben, dass
die Redundanz über alle Bits gleichmäßig verstreut wird (Liebe
Mathematiker, schlagt mich nicht für diese Formulierung !).
>> Wenn Du eine Absicherung des einzelnen Bytes (Blockgröße ist 1 Byte)>> braucht, dann musst Du Redundanz auf auf Byte-Ebene einführen
Dagegen ist nichts einzuwenden.
Ich möchte es zwar gerne so machen das diese Redundanz vor dem
eigentlichen Byte kommt (da sonst ein fehlendes Byte nicht erkannt
werden kann) aber die Frage bleibt letztendlich : was ist eine gute
Möglichkeit ?
Beispiel : meine Xor/Filter Idee von oben erkennt ~90% aller fehlenden
Bytes und 25% aller Bitfehler mit dem Nachteil von 25% weniger
Bandbreite und 1 Byte mehr Latenz.
Aber das ist ein völlig naiver Ansatz, da muss es doch besseres geben.
Klar könnte ich auch einen crc an jedes 3te oder Byte hängen, aber das
bringt für meine Anforderung sogar weniger.
> Ich möchte es zwar gerne so machen das diese Redundanz vor dem> eigentlichen Byte kommt
????
Um zu wissen, ob an den Daten was faul ist, muss doch sowieso das Datum
selber und die Absicherung da sein. Und das dauert gleich lang, ob über
die Leitung die Daten zuerst kommen oder die Absicherung...
BTW:
Ich frage mich noch immer, wie du ganze Bytes verlieren kannst... :-/
> Ich habe nur alle Zeit der Welt weil die zeitkritischen Pakete schon vor> der eigentlich Laufzeit feststehen und zur Laufzeit lediglich verschickt> werden müssen.
Wenn die zeitkritischen Pakete alle gleich und vorberechnet sind, dann
kann es doch nur eine bestimmte Anzahl verschiedener Pakete geben.
Nummeriere sie durch, sende zuerst die Nummer des Pakets und dann weiss
dein Empfänger welches kommt und kann es vergleichen.
Oder du schickst überhaupt nur mehr die Nummer, und der Empfänger
generiert sich daraus das Paket selber.
Das wäre natürlich auch eine Möglichkeit, allerdings habe ich im FPGA
nicht unbegrenzt Speicher/Lookup-tables.
Für die extrem zeitkritischen Dinge habe ich ohnehin vor nur 1 Byte zu
senden und der Rest muss eben aufgeschlüsselt werden.
Insbesondere was Anfragen betrifft die z.b. eine Speicheraddresse
betreffen -> das sind schonmal mindestens 3 byte.
>> Ich frage mich noch immer, wie du ganze Bytes verlieren kannst
Da musst du den CPLD fragen der auf dem Weg dazwischen liegt und
zwischen Programmierinstruktionen für die JTAG-Chain und Datenstreams
multiplexen muss.
Ich bin ja auch schon auf der Suche dort was anderes zu finden, aber
vorerst muss ich damit leben.
>> Um zu wissen, ob an den Daten was faul ist, muss doch sowieso das Datum>> selber und die Absicherung da sein. Und das dauert gleich lang, ob über>> die Leitung die Daten zuerst kommen oder die Absicherung...
Nein, siehe mein Beispiel oben :
Informationen im ersten Byte.
Datenbyte 1 kommt, wird sofort gegen das Filterbyte gecheckt -> kann
sofort weiter geschickt werden.
Bis hier hin liegst du richtig, es wäre äquivalent dazu, das ich erst
das Datum und dann den Check schicke.
Nun kommt aber Byte 2 und wird anhand der Xor-Funktion mit byte 1
verglichen. Folge : auch dieses und genauso weitere bytes können sofort
weitergeleitet werden.
Vergleich :
xor-funktion
- datenbyte 1 nach 2 Bytes
- datenbyte 2 nach 3 bytes
- datenbyte 3 nach 4 bytes
crc o. ä
- datenbyte 1 nach 4 Bytes
- datenbyte 2 nach 4 bytes
- datenbyte 3 nach 4 bytes
Leider versagt mit die xor funktion jenseits von 3 bytes völlig da eben
immer eine Bitposition vorhanden sein muss an der sich in jedem
Folgebyte das Bit ändert.
Aber das war auch nur ein Beispiel für das was ich suche und es sollte
klar zeigen das so etwas nicht völlig unmöglich ist.
Wie groß ist den dein "Byte". Kannst du nicht immer 32bit auf einmal
senden?
Irgenwie habe ich das Gefühl das irgenwas bei dir im argen liegt.
Eine Übertragung muß erstmal wenigstens einen Frame korrekt übertragen
(dabei dürfen Frames durchaus verloren gehen). Auf diesen Frames kann
man dann eine (wie auch immer geartete) Sicherungsschicht aufbauen.
Im Allgemeinen besteht sowas wenigstens aus einem fortlaufendem Zähler,
einer Checksumme oder Parität, den Daten und im Idealfall der
Möglichkeit Daten erneut anzufordern.
Wie soll dein System überhaupt reagieren wenn Daten futsch sind?
Auch kann man den Empfang + Prüfung der Daten Pipelinen sodass eine
Latenz nur einmalig Auftritt.
Wie sind den die Daten beschaffen? Oder ist das wieder eines der
Probleme der Art: Ich will halt so schnell wie Möglich weil ich noch
garnicht weiß was ich brauche und schnell ist ja gut?
Nein, das Problem ist real und setzt zwingend eine geringe Latenz
voraus. Aber das Problem hat weder etwas mit der Frage zu tun, noch will
ich es lang und breit diskutieren. So wie hier grundsätzlich erstmal
alles in Frage gestellt wird kann mir das wohl niemand übel nehmen.
Achja, OSI kenne ich durchaus, aber Standard hilft mir leider nicht
weiter.
>> Wie soll dein System überhaupt reagieren wenn Daten futsch sind?
Sequenznummer im header -> Fehler -> neue Anforderung. Dank nur wenigen
µs Latenz ziemlich problemlos, da gehen nichtmal 100byte in der
zwischenzeit verloren.
Hab mir jetzt nochmal was neues überlegt :
4 bytes, bestehend aus 1 Prüfbyte und 3 Datenbyte.
Das Prüfbyte besteht aus :
- 3 bit welche eine bitposition angeben(0-7)
- 2 bit welche angeben wie auf dieser Bitposition geprüft werden soll
(xor gleichbleibende/aufsteigende/absteigende bitposition oder gar
nicht, da nicht möglich)
- 3 bit mit parität, je 1 bit pro byte das folgt
-> jeder 1 bit Fehler wird erkannt sowie(falls ich mich nicht verrechnet
habe) ~99% aller verlorenen Bytes.
Das wird mir vorerst reichen sodass ich mich wieder auf die tatsächliche
Funktion konzentrieren kann.
Trotzdem danke an alle die zum ursprünglichen Thema beigetragen haben.
> So wie hier grundsätzlich erstmal alles in Frage gestellt wird> kann mir das wohl niemand übel nehmen.
Als Antwort zu diesem Vorwurf kann man auch behaupten, dass hier jede
Menge Anfänger Ihre oftmals viel zu komplizierten und irrigen
Vorstellungen präsentieren und dann beleidigt sind, wenn man sie auf
Fehler und Alternativen hinweist.
Wie in der Medizin ist ein ganzheitlicher Ansatz oftmals sinnvoller als
mit Krampf und Krach auf einem unnötig komplizierten Detailproblem
herumzureiten.
Im Allgemeinen verwende ich auch die üblichen Standardlösungen, denn sie
sind erwiesenermaßen funktionstüchtig und oftmals sogar schon als
Umsetzung vorhanden.
Diese Anforderung hier hat sich in dem Fall aber erst im Verlauf
ergeben, weil die bisherige Lösung (klassische Osi 2 Schicht) mir an der
Stelle zu langsam war.
Deshalb habe ich zuerst die Überprüfung der Nutzdaten für diese Art von
Paketen abgeschafft und war mit der Leistung zufrieden, bis mir eben die
Fehler auffielen.
Die einzige andere Alternative ist eine schnellere Anbindung, aber die
steht noch aus.(wie gesagt Hobbyprojekt -> keine unbegrenzten
Möglichkeiten)
>Nein, das Problem ist real und setzt zwingend eine geringe Latenz>voraus. Aber das Problem hat weder etwas mit der Frage zu tun, noch will>ich es lang und breit diskutieren. So wie hier grundsätzlich erstmal>alles in Frage gestellt wird kann mir das wohl niemand übel nehmen.
Ich habe leider die Lust verloren mich weiter an der Problemlösung zu
beteiligen. Nichts für ungut, aber ohne die Bereitschaft einige Eckdaten
seines Hobbyprojekts kundzutun, wird es nur schwer Hilfe geben können.
Hier kennt keiner den exakten Aufbau und die konkreten Anforderungen -
ohne die sind konkrete Tips auch nicht sinnvoll möglich.
Good bye,
Michael
@ Iulius
> Ich frage mich noch immer, wie du ganze Bytes verlieren kannst... :-/
Insbesondere, weil du selber den Sender und den Empfänger unter
Kontrolle hast. Kannst du dir das Fehlen ganzer Bytes erklären?
Ich hätte da so einen Verdacht:
>>> Der Sender an sich ist hochgradig ausgelastet...
... und verschluckt dann schon mal das eine oder andere Byte???
Nein, die Verluste treten auch bei geringer Last auf.
Ich tippe immer noch, wie schon oben erwähnt, auf den CPLD der
dazwischen liegt und die Konfiguration vornimmt, also die Daten muxen
muss.
>> Hier kennt keiner den exakten Aufbau und die konkreten Anforderungen
- hochgetakteter Universalprozessor + FPGA als Co-Prozessor
- rekonfiguriert FPGA zur Laufzeit je nach aktueller Anforderung
- Datenaustausch von großen Mengen zu verarbeitender Daten
(Latenzunkritisch)
- Datenautausch von kleinen Mengen Steuerinformationen (sehr
Latenzkritisch)
Eine µs mehr Latenz entspricht mehreren tausend verschwendeten
Prozessortaktzyklen, da der Prozessor ggf nicht weiterarbeiten kann
solange eine Antwort erwartet wird.
Weitere Folge : wenn der Prozessor aufgrund der Latenz blockiert wird,
dann werden auch Folgeaufgaben zum FPGA verzögert, da unklar ist welche
Folgeaufgabe überhaupt ausgewählt wird.
Ich bezweifle zwar das das Preisgeben dieser Information meiner
Problemlösung auch nur im geringsten hilft, aber wenn es einige
glücklich macht...
Warscheinlich wird ohnehin nur der Sinn meines Projektes an sich in
Frage gestellt.
Würde es sich nicht anbieten Steuerinformationen und Datetransfer zu
trennen? Oder liegt das "Kabel" schon fest?
Dann könntest du z.B. die Daten über Ethernet versenden und Steuerdaten
über RS232/484/123 mit Hardwarehandshake/ACK und einem "Zählbyte".
Derzeit ist das Kabel fix aufgrund der Konfiguration-Geschichte.
Zukünftig wäre es denkbar das zu trennen in Jtag+Steuer- und
Datenübertragung, wobei eigentlich das Ziel war nur Ethernet zu
nutzen.(bzw nur pci-e was für mich aber nicht bezahlbar ist)
Danke, genaus so etwas habe ich gesucht.
Zwar hatte ich Viterbi auch schon bei der wiki Breitensuche gesehen,
aber wegen dem ganzen Bio zeug nicht weiter betrachtet.
Das hier scheint jedoch genau das zu sein was ich suche :
http://home.netcom.com/~chip.f/viterbi/algrthms.html
Warum ?
Wenn ich die einzelnen bitpositionen der bytes per viterbi erzeuge
anstatt den bitstrom an sich, dann kann ich ein verlorenes Byte zwar
nicht erkennen, aber sogar ausgleichen was mir sogar noch lieber ist.
Ich versuche mal mein Glück damit und stelle den Code rein wenn es
klappt.
Weil alle Codes davon ausgehen das Daten fehlerhaft sind aber nicht
fehlen.
Man geht davon aus , das z.B. eine 1 fälschlich eine 0 wurde oder
umgekehrt, aber nicht das aus einem 10bit Strom ein 5bit Strom wird.
Mal eine Verständnisfrage:
Wieso werden die Bytes eigentlich einzeln verschickt ? Wäre es nicht
sinnvoller eine Anzahl Bytes in einem Fifo zu speichern und den gesamten
Fifo-Inhalt, also mehrere Bytes, paket-basiert am Stück zu versenden ?
Wo ist für diesen Ansatz das Hindernis ?
Gruß,
SuperWilly
Außerdem:
>Hab mir jetzt nochmal was neues überlegt :>4 bytes, bestehend aus 1 Prüfbyte und 3 Datenbyte.
Aber Du sagtest doch zuvor, dass du die Bytes einzeln empfängst!
Wie passt das nun zusammen ?
Gruß,
SuperWilly
@ Läubi : du hast Recht, das habe ich vorhin nicht gleich bemerkt. Damit
hat sich die Methode wohl auch erledigt :/
@ Willy:
senden tue ich bereits ein ganzes Byte-Array(6 bis 255 bytes), aber der
Empfang beim FPGA ist bitseriell(der Rückweg auch). Daraus baue ich mir
immer je 8 bit zusammen und leite sie weiter.
- zuerst eine headererkennung
- zuweisungsnummer für internes modul
- sequenznummer um im Fehlerfall neu Anfordern zu können
- Anzahl an Nutzdatenbytes die folgen
- Headercrc
- Nutzdatenbytes
Dazu durchläuft ganz simpel eine Statemachine die einzelnen Phasen und
kann praktisch direkt in dem Takt, in dem das nächste Byte empfangen
wurde, reagieren.
Also was du da machst (machen willst) ist ja immer noch ziemlich
nebuloes, und Kaffeesatzlesen ist halt echt schwierig.
Aber was so bisher kam, ich denke, das zu uebertragende Byte mit 2
weiteren Sequenz-Bits (2-Bit Counter) zu versehen sollte doch
funktionieren. Damit kannst du schon mal ein verschlucktes Byte erkennen
und du blaehst deine Uebertragung nur um 2 weitere Bits/Byte auf.
Wenn dein CPLD die Daten verschluckt: Wieso gehst du nicht erstmal an
diese Baustelle?
Ist nicht meiner, der ist halt auf dem Dev-Board drauf.
Ich kann den zwar theoretisch neu konfigurieren, aber dazu habe ich
weder das equippment noch die Lust, da ich ohnehin möglichst "bald" auf
ein anderes Board/FPGA wechseln will mit schnellerer Anbindung sowie
partiell rekonfigurierbarem FPGA.
Den 2bit Zähler kann ich ja fürs erste auch nehmen, solange die 6
Datenbit ausreichen.
>senden tue ich bereits ein ganzes Byte-Array(6 bis 255 bytes), aber der>Empfang beim FPGA ist bitseriell(der Rückweg auch). Daraus baue ich mir>immer je 8 bit zusammen und leite sie weiter.
Mir ist der Datenpfad nicht klar. Kannst due eine Skizee reinstellen,
die zeigt, woher welche Daten wie (und vor allem mit welcher Datenrate)
kommen und wohin sie wie (mit welcher Datenrate) gehen ?
SuperWilly
> mit 2 weiteren Sequenz-Bits (2-Bit Counter) zu versehen ...> Wenn dein CPLD die Daten verschluckt: Wieso gehst du nicht erstmal an> diese Baustelle?
Und was wäre, wenn zwar der Zähler die Bytes richtig durchnummeriert,
aber die Bytes schon vor dem Zähler verschütt gehen?
Ich würde auch erst mal den Sender so aufräumen, dass alles korrekt
verschickt wird. Dann kann es bestenfalls noch sein, dass durch EMV
einzelne Bits korrupt sind. Aber auf dem Labortisch würde ich eine
0-Fehler-Strategie fahren.
Und dabei bestenfalls Fehler zulassen, deren Ursache mir ganz klar ist.
Oder sogar selber Übertragungsfehler einbauen, um zu sehen, wie der
Empfänger damit klarkommt.
Am Sender(PC) liegt das wohl kaum, denn die Konfigurationsinstruktionen
gehen ja nicht verloren, nur der andere Multiplex-Pfad.
Aber die Anbindung wird ohnehin baldmöglich getauscht da USB(12Mbit
Duplex) zwar von der Latenz gerade noch akzeptabel ist, von der
Bandbreite jedoch ganz und gar nicht.
Was aber nichts daran ändert das ich gegen Fehler abgesichert sein will,
zur Not auch gegen ETWAS weniger Leistung.
@ Willy :
ne Skizze, etwas übertrieben...
PC -> Bytearray
( -> USB -> FTDI -> CPLD -> JTAG Stream) - Blackbox für mich
Jtag-Stream : takt + 2 datenleitungen (in/out) mit 8 bit, kurze Pause ,
8 bit, kurze Pause, usw direkt an Eingangspins des FPGA
8 bit schiebregister -> 1 byte + valid
statemachine zur Auswertung
kontrollmodul
verschiedene rechenmodule
kontrollmodul
... Rückweg identisch
>PC -> Bytearray>( -> USB -> FTDI -> CPLD -> JTAG Stream) - Blackbox für mich>Jtag-Stream : takt + 2 datenleitungen (in/out) mit 8 bit, kurze Pause ,>8 bit, kurze Pause, usw direkt an Eingangspins des FPGA>8 bit schiebregister -> 1 byte + valid>statemachine zur Auswertung>kontrollmodul>verschiedene rechenmodule>kontrollmodul>... Rückweg identisch
Etwas untertrieben, verstehe ich immer noch nicht. Geht anderen wohl
genauso.
SuperWilly
Da wüsste ich aber gerne mal welcher Teil nicht verständlich sein soll.
Vom 2ten Part (der Blackbox) weiß ich nunmal nichts weiter, weil er
nicht dokumentiert ist. Ich kann das derzeit nur benutzen.
Der Rest ist mMn selbsterklärend oder zumindest fällt mir nicht ein
welchen Part ich noch breiter treten soll.
Du schreibst ja auch nicht was dir nicht klar ist....
Verstehe ich das richtig?
Du bist also nur hier am Werke:
> Eingangspins des FPGA> 8 bit schiebregister -> 1 byte + valid> statemachine zur Auswertung> kontrollmodul> verschiedene rechenmodule> kontrollmodul und zurück
Das ist alles im FPGA und du hast nur auf dieses FPGA Zugriff?
Ja das ist alles was FPGA-intern passiert, ansonsten habe ich halt die
ftdi dll am Rechner laufen.
Da die Daten schon nicht an den Pins ankommen kann es also nur am Weg
dazwischen liegen.(dem ftdi treiber vertraue ich da)
Aber wie gesagt, das interessiert mich eigentlich gar nicht da ich die
Absicherung so oder so will, selbst wenn der Link nahezu fehlerfrei ist.
Im Grund genommen interessiert es mich sogar mehr einen interessanten
Lösungsansatz zur Fehlererkennung zu finden als den Fehler jetzt zu
eliminieren, denn im finalen System ist er ohnehin weg.(hoffe ich, da
komplett anderes FPGA + Board)