Hallo ich versuche gerade in meine Anwendung ein CRC Check einzusetzen und bin dabei über diess Seite gestoßen: http://www.easics.com/webtools/crctool Bei diesem Tool wird ein Package erzeugt das ich in meiner Anwendung benutzen kann.Der Funktionsaufruf benötigt zum einem die Daten (logisch) und einen CRC Wert(versteh ich nicht) Sollte es nicht eigentlich so sein das er mir aus meinen Daten ein CRC erzeugt? Würde mich freuen wenn mir jemand weiterhelfen könnte Gruß Denis
Mit CRC Wert ist wahrscheinlich das CRC Prüf Polynom gemeint. Wenn du wissen willst was das ist, schau mal bei Wiki.
Nein, das Prüfpolynom steckt bereits in den erzeugten Zuweisungen samt xor drinne. Mit dem crc wert ist lediglich die Initialisierung gemeint bzw der alte Wert aus dem der Neue erzeugt wird. Mein Tipp : benutz ruhig die Xor-Gleichungen, aber bastel den Rest vom Aufbau um. Das ganze macht mMn als Funktionsaufruf wenig Sinn. Besser ist es ein Modul daraus zu basteln: - das den aktuellen crc sowohl liefert als auch intern puffert - einen reseteingang hat(um wieder den puffer auf initial zu setzen) - einen Eingang hat um die neuen Daten mit dem alten crc zu akkumulieren (sinnvollerweise + enable) - das ganze getaktet vornimmt So hab ichs zumindest gemacht(auch mit dem Generator) und es funktioniert tadellos bei minimalem Ressourcenverbrauch.
Man muss einmal den Datenwert initialisieren, i.d.R. mit Null. Dann zyklisch in den Code (als Funktion) reingehen und den aktuellen CRC aus dem alten + dem neuen Datum ehrhalten. Man muss nur aufpassen, welches bei deren Zählweise Bit1 und Bit n ist. Bei mir ist das immer irgendwie verdreht.
> Man muss einmal den Datenwert initialisieren, i.d.R. mit Null.
nee, meistens ist der Init != Null...
@ Iulius Ok das mit der Umarbeitung habe ich auch schon gemacht, habe das ganze nur als Vorlage benutzt. Aber wenn ich immer wieder den voherigen Wert nehme um daraus den neuen zu generieren verstehe ich nicht wie der Check funktionieren soll. Ich habe gestern mal versucht die Pakete auszuwerten aber das funktioniert nicht. Meines Wissens nach muss ich doch "data <= data_in and crc_in" und "c <= crc_in" übergeben werden damit beim newcrc null rauskommt,oder nicht?
mit crc übergibst du wie schon gesagt einen startwert (meist != 0x00, ich seh relativ oft 0xAA) für dein berechnungspolynom bzw. wenn du mehr daten hast, als in den datenvektor reinpassen, dann musst du deine daten natürlich splitten. mit crc übergibst du dann den crc-wert des vorhergehenden teils. für jeden datenblock (der einen eigenen crc bekommen soll) fängst du natürlich wieder mit dem startwert an. woher weißt du eg dass dein crc mit polinomial-verfahren berechnet wird, wenn da das tabellenverfahren genutzt wird, ist das berechnen schon recht schwierig ohne den ursprungs-quellcode zu kennen.
@Erik Ah danke diese Info hat mir gefehlt.Mein Aufbau sieht nämlich gerade so aus das ich 20Pakete a 32Bit schicken möchte Plus ein Header mit CRC für diese 20 Pakete. Ok wenn ich danach wieder den Startwert nehme macht es natürlich Sinn aber das ging bisher aus dem was ich gelesen habe nicht hervor. Aber wie genau muss ich jetzt den Checker aufbauen? War mein oberer Ansatz dann richtig, bis auf das ich für c den Startwert einsetze. Und zu deiner Frage der Aufbau des XOR entspricht doch genau der Polynomendivision oder nicht?
Denis schrieb: > Aber wie genau muss ich jetzt den Checker aufbauen? > > War mein oberer Ansatz dann richtig, bis auf das ich für c den Startwert > einsetze. also dein 32 bit packet splittest du also in 4 teile à 8 bit erster funktionsaufruf: Data <- ersten 8 Bit Daten crc <- Startwert liefert crc1 zweiter funktionsaufruf Data <- zweiten 8 Bit Daten crc <- crc1 liefert crc2 usw. nach dem vierten funktionsaufruf hast du dann den crc für dein komplettes packet > Und zu deiner Frage der Aufbau des XOR entspricht doch genau der > Polynomendivision oder nicht? meine frage hat sich erledigt...hat sich so angehört, als wolltest du einen übergebenen crc prüfen, aber wenn du den erstellen willst um ihn in den header zu schreiben ist das schon okay.
@Erik : also den Code den ich angehangen habe dient nur als Grundlage für dieses Gesrpäch. Ich verwende natürlich einen 32 Bit breiten Bus damit die Durchlaufzeit verkürzt wird. Aber wie ich den Checker mache weiß ich trotzdem noch nicht meiner spuckt mir falsche Werte aus.Der Generator ist jetzt klar. d <= data_in and crc_in c <= crc_startwert dabei sollte dann doch null rauskommen oder?
so sollte es gehen d <= data_in & crc_in c <= crc_startwert du musst crc_in an data_in anhängen, bei dir war das ne logische und-verknüpfung (brauchste natürlich auch nen größeren bus)
Also der Checker gibt immer noch falsche Werte aus. Ich habe mal die relevanten Teile mit angehangen. Ich sende ein Paket mit der Info X"11111111" der CRC Generator erzeugt ein CRC von X"B313" wenn ich das versuche auszuwerten kommt raus X"7F15" Wie kann das sein?
Das ist viel zu aufwendig, vor allem : warum speicherst du Tonnen an Informationen ? Das einzige was du speichern musst ist der alte CRC Wert, der ggf auf einen Init Wert resettet wird. Diese alte Wert wird dann mit dem Eingang verknüpft. Mal ein Auszug wie das aussehen kann : dataIn : IN unsigned (7 downto 0); data_wrEn : IN std_logic; ... signal crc_buffer : unsigned(15 downto 0) := (others => '0'); ... if data_wrEn='1' then ... crc_buffer(6) <= dataIn(0) xor crc_buffer(14) xor crc_buffer(0); Keine Ahnung was z.b. "d<= DATA_IN & X"B313";" bei dir bewirken soll...das Polynom steckt komplett in dem xor-Wust !
@Iulius : wieso speichere ich Tonnen von Daten? Also ich glaub du verstehst mich gerade nicht.Das was ich dort mache war nur ein Test um zu überprüfen ob der CRC Check funktioniert Mein Generator bekommt ein Datenpaket d <= X"11111111" und den Startwert für CRC X"FFFF" daraus erzeugt er mir den neuen CRC Wert der X"B313" Im Checker sollte dann durch Verknüpfen der empfangen Datenpakete die derzeit dauerhaft X"11111111" sind beim durchlaufen des Generators einen CRC von null ergeben. So sieht doch der normale CRC Check aus,oder nicht?
versteh irgendwie nich, wie du dein CRC berechnest ich hätte da sowas erwartet wie newcrc(0) <= d(16) xor d(0) xor c(0); newcrc(1) <= d(17) xor d(1) xor c(1); newcrc(2) <= d(18) xor d(2) xor c(2); newcrc(3) <= d(19) xor d(3) xor c(3); newcrc(4) <= d(20) xor d(4) xor c(4); newcrc(5) <= d(21) xor d(5) xor c(5); newcrc(6) <= d(22) xor d(6) xor c(6); newcrc(7) <= d(23) xor d(7) xor c(7); newcrc(8) <= d(24) xor d(8) xor c(8); newcrc(9) <= d(25) xor d(9) xor c(9); newcrc(10) <= d(26) xor d(10) xor c(10); newcrc(11) <= d(27) xor d(11) xor c(11); newcrc(12) <= d(28) xor d(12) xor c(12); newcrc(13) <= d(29) xor d(13) xor c(13); newcrc(14) <= d(30) xor d(14) xor c(14); newcrc(15) <= d(31) xor d(15) xor c(15); wenn du nun den crc wert berechnen willst setzt du c auf initial wert z.B. c <= X"FFFF"; wenn du später überprüfen willst, ob der crc-wert korrekt ist machst du die berechnung einfach nochmal, wenn newcrc und übergebener_crc gleich sind ist alles in ordnung
ah ich seh grad, dass du ja nen anderes polynom nimmst...wär nich schlecht, wenn du das mal angibst dann gleich noch ne frage, wo wird deinem Checker eigentlich der zu überprüfende crc-wert übergeben?
@Erik ja das Polynom ist ja eher unwichtig nur es muss bei Sender und Empfänger gleich sein. Ich benutze diese Konfiguration: -- polynomial: (0 2 15 16) -- data width: 32 -- convention: the first serial bit is D[31] Das was du vorschlägst ist auch die Weise die ich bevorzugen würden.Diese habe ich auch schon programmiert und getestet und sie funktioniert. Nur mein Chef wollte es nach dem Standart machen und da ist es doch eigentlich so, dass der Check den CRC Wert des Senders mit in die Generierung des neuen CRC Werts einbezieht. Der neue CRC Wert muss bei korrekter Übertragung dann null ergeben. Also Frage, ist das was du vorschlägst und ich auch schon umgesetzt habe ein echter CRC Check?Sprich auf Sende und Empfangseite die Daten durch den gleichen Generator laufen lassen und die beiden CRC's vergleichen. Wenn diese identisch sind war die Übertragung ok.
ja wenn du den crc-wert einfach hinten anhängst müsste bei der berechnung 0 herauskommen. aber ich seh grad, dass du für die vollständige berechnung noch elemente nicht mit einbeziehst. dein DATA_IN sind 32 bit dein CRC 16bit wenn du nun mit d<= DATA_IN & X"B313" beide aneinander hängst hat d folglich eine länge von 48 bit deine CRC berechnung geht aber nur bis d(31). wenn du den generator von oben benutzen willst mach einfach nen haken bei 32 und einen bei 16 und schon hast du nen 48 bit datenbus. dann sollte bei der berechnung 0 rauskommen.
Ich versteh immer noch nicht was ihr mit dieser Zeile macht : >> wenn du nun mit d<= DATA_IN & X"B313" Warum zum Kuckuck hängt ihr einen Fixen Wert an das Data_in dran ? so mache ichs : - reset kommt rein -> crc_buffer wird resettet - data_in kommt rein - data_in wird mit crc_buffer xor verknüft nach Polynom und in crc_buffer gespeichert - crc_buffer enthält zu jedem zeitpunkt den aktuell berechneten crc Wert aus allen gelieferten Datenworten. Damit kann man problemlos einen Datenstream aus z.b. bytes in den crc-check reinschleusen und wenn der Stream zuende ist und am streamende auch der crc vom Empfänger enthalten war liegt am Ausgang des crc-check moduls 00...00 an auf das man prüfen kann. >> wieso speichere ich Tonnen von Daten? wozu speicherst du data_in in d ? Das kannst du direkt in den gleichungen verwendenund musst es nicht einen takt puffern wozu einen i_crc und ein newcrc ? der newCRC ergibt sich direkt aus der Xor-Verknüpfung des alten CRC mit dem data_in Am besten ich mach nachher mal schnell für nen 8er crc ein modul + testbench um zu zeigen was ich meine. Das hier sieht einfach kompliziert hoch 10 aus obwohl es doch eigentlich soooo einfach ist.
einfach wär es geblieben hätt er die funktion die der generator erzeugt benutzt. versteh sowieso nich, warum man für ne lineare crc-berechnung glei nen eigenes modul machen muss
Hmm, vielleicht weil man dann einfach die Daten durchschleusen kann und nicht den ganzen Krempel außerhalb speichern muss ? Hier mal schnell zusammengeschustert, aber funktioniert wunderbar : crc-8 (8+2+1+0) auf 8 bit datenstream, erzeugt mit easics, umgeschrieben zum modul, verifiziert mit diesem calculator : http://smbus.org/faq/crc8Applet.htm code + testbench + waveform im anhang
@Iulius Das X"B313 war nur der CRC Wert den Generator ausgibt wenn ich das Datenwort X"11111111" eingebe. Aber ich weiß jetzt worauf du hinaus willst. @Erik Ich habe es als Prozess eingebunden und geclockt damit ich synchron bleibe mein Compiler bringt sonst Fehler und sagt ich erzeuge ein Latch. Habe es jetzt hinbekommen danke für eure Hilfe! Mein Fehler war das ich das letzte Datenwort meiner Payload mit dem CRC verbunden habe anstatt den CRC am Schluss in den Generator einzugeben. Entweder habe ich das bei Wikipedia falsch verstanden oder es ist ein Fehler drin denn dort wird das Paket mit dem CRC verbunden und gecheckt. Ich benutze jetzt den CRC32 Ethernet für einen 32 Bit breiten Datenbus und überprüfe 20 Pakete und speise den erzeugten CRC Wert wieder mit ein. Am Schluss wird der CRC Wert als Datenwort in den Checker geladen und wenn das Senden der Daten erfolgreich war kommt als neuer CRC Wert null raus.
Denis schrieb: > Entweder habe ich das bei Wikipedia falsch verstanden oder es ist ein > Fehler drin denn dort wird das Paket mit dem CRC verbunden und gecheckt. ne das is schon richtig, was im wiki steht...dein check ging aber nur bis zum 32ten bit...wenn du crc und daten aneinander hängen musst hast du aber 48 bit. damit war deine überprüfung unvollständig.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.