Forum: FPGA, VHDL & Co. CRC Generator in VHDL


von Denis (Gast)


Angehängte Dateien:

Lesenswert?

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

von Honkmichi (Gast)


Lesenswert?

Mit CRC Wert ist wahrscheinlich das CRC Prüf Polynom gemeint. Wenn du 
wissen willst was das ist, schau mal bei Wiki.

von Iulius (Gast)


Lesenswert?

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.

von Oberpauker (Gast)


Lesenswert?

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.

von berndl (Gast)


Lesenswert?

> Man muss einmal den Datenwert initialisieren, i.d.R. mit Null.

nee, meistens ist der Init != Null...

von Denis (Gast)


Lesenswert?

@ 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?

von Erik W. (exor)


Lesenswert?

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.

von Denis (Gast)


Lesenswert?

@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?

von Erik W. (exor)


Lesenswert?

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.

von Denis (Gast)


Lesenswert?

@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?

von Erik W. (exor)


Lesenswert?

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)

von Denis (Gast)


Angehängte Dateien:

Lesenswert?

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?

von Iulius (Gast)


Lesenswert?

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 !

von Denis (Gast)


Lesenswert?

@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?

von Erik W. (exor)


Lesenswert?

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

von Erik W. (exor)


Lesenswert?

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?

von Denis (Gast)


Lesenswert?

@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.

von Erik W. (exor)


Lesenswert?

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.

von Iulius (Gast)


Lesenswert?

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.

von Erik W. (exor)


Lesenswert?

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

von Iulius (Gast)


Angehängte Dateien:

Lesenswert?

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

von Denis (Gast)


Lesenswert?

@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.

von Erik W. (exor)


Lesenswert?

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
Noch kein Account? Hier anmelden.