CRC Berechnung für Ethernet

#1573185
Lesenswert?

Hi!

Ich möchte zwei FPGA Boards über einen Switch miteinander verbinden. 
Damit die Daten im Switch nicht verworfen werden, schick ich einen 
Ethernet Frame im Format 802.3 inkl. FCS.

Blöderweise versuch ich schon seit Tagen eine korrekte CRC zu berechnen, 
aber es will einfach nicht funktionieren.

Ich hab mir mit dem Tool auf http://www.easics.com/webtools/crctool eine 
CRC als VHDL Funktion generieren lassen, aber die CRC stimmt einfach 
nicht.

Jetzt habe ich schon versucht die Bits umzudrehen, bevor ich die Daten 
der CRC Funktion übergebe. Ich habe versucht die ersten 32 Bit des 
Frames zu invertieren und ich habe versucht die Bits des Low und High 
Nibbles zu verdrehen.

Leider hat das absolut nichts gebracht.

Hat von euch schon jemand ähnliche Probleme gehabt und diese gelöst?
#1574206
Lesenswert?

Naja, das hätte ich ja eigentlich schon ausprobiert, aber ohne Erfolg.

An anderer Stelle habe ich gelesen, dass die ersten 32 Bit invertiert 
gehören... war aber auch nicht hilfreich.

Setzt ihr mit euren VHDL Designs auf einem höheren Level an? Kaum zu 
glauben, dass man im Netz nichts brauchbares findet.
#1575322
Lesenswert?

Nachdem ich jetzt haufenweise Kombination ausprobiert habe und das 
Ergebnis mit einem Packet Sniffer überprüft habe, weiß ich wie man die 
CRC richtig berechnet.

Hier eine kurze Einführung, falls jemand einmal vor selbigem Problem 
stehen sollte...


1. CRC Modul mit http://www.easics.com/webtools/crctool generieren.
2. Bevor die Daten an das CRC Modul übergeben werden (in meinem Fall 
über den Funktionsaufruf nextCRC32_D8), müssen die Bits vertauscht 
werden.
Übergeben werden Daten von Target MAC bis letztes Byte der Payload, MSB 
zuerst.
Die ersten 32Bit der Target MAC müssen invertiert werden.
1
for i in 0 to data'left loop
2
data(i) := data(data'left - i);
3
end loop;
4
crc <=nextCRC32_D8(data, crc);

3. Am Ende der Payload muss der komplette CRC Wert invertiert werden und 
die Bits anschließend wieder vertauscht werden.

4. Die CRC wird mit dem LSB Byte zuerst an das Ende des Frames gestellt.
Gast #2387268
Lesenswert?

Nachdem ich auch mehrere Tage am CRC gesessen habe, hier die Schritte, 
wie es bei mit geklappt hat.

Die CRC Funktion habe ich mir bei OutputLogic.com generieren lassen. 
Allerdings habe ich sie erweitert, so dass sie auch gleich das Inverse 
berechnet, weil das später benutzt wird.
1
library ieee;
2
use ieee.std_logic_1164.all;
3

4
entity crc is
5
  port (   
6
  Clock      : in std_logic;
7
  Reset      : in std_logic;
8
  DataIn       : in std_logic_vector (7 downto 0);
9
  CRCCalculationEnable    : in std_logic;
10
  CRCOut        : out std_logic_vector (31 downto 0);
11
  CRCOutInverted : out std_logic_vector (31 downto 0)
12
 );
13
end crc;
14

15
architecture imp_crc of crc is
16

17
signal lfsr_q: std_logic_vector (31 downto 0);
18
signal lfsr_c: std_logic_vector (31 downto 0);
19

20
begin
21
    CRCOut          <= lfsr_q;
22

23
   CRCOutInverted(31) <=  not(lfsr_q( 0)); -- bits swappen und invertieren
24
   CRCOutInverted(30) <=  not(lfsr_q( 1));
25
   CRCOutInverted(29) <=  not(lfsr_q( 2));
26
   CRCOutInverted(28) <=  not(lfsr_q( 3));
27
   CRCOutInverted(27) <=  not(lfsr_q( 4));
28
   CRCOutInverted(26) <=  not(lfsr_q( 5));
29
   CRCOutInverted(25) <=  not(lfsr_q( 6));
30
   CRCOutInverted(24) <=  not(lfsr_q( 7));
31

32
   CRCOutInverted(23) <=  not(lfsr_q( 8));
33
   CRCOutInverted(22) <=  not(lfsr_q( 9));
34
   CRCOutInverted(21) <=  not(lfsr_q(10));
35
   CRCOutInverted(20) <=  not(lfsr_q(11));
36
   CRCOutInverted(19) <=  not(lfsr_q(12));
37
   CRCOutInverted(18) <=  not(lfsr_q(13));
38
   CRCOutInverted(17) <=  not(lfsr_q(14));
39
   CRCOutInverted(16) <=  not(lfsr_q(15));
40

41
   CRCOutInverted(15) <=  not(lfsr_q(16));
42
   CRCOutInverted(14) <=  not(lfsr_q(17));
43
   CRCOutInverted(13) <=  not(lfsr_q(18));
44
   CRCOutInverted(12) <=  not(lfsr_q(19));
45
   CRCOutInverted(11) <=  not(lfsr_q(20));
46
   CRCOutInverted(10) <=  not(lfsr_q(21));
47
   CRCOutInverted( 9) <=  not(lfsr_q(22));
48
   CRCOutInverted( 8) <=  not(lfsr_q(23));
49

50
   CRCOutInverted( 7) <=  not(lfsr_q(24));
51
   CRCOutInverted( 6) <=  not(lfsr_q(25));
52
   CRCOutInverted( 5) <=  not(lfsr_q(26));
53
   CRCOutInverted( 4) <=  not(lfsr_q(27));
54
   CRCOutInverted( 3) <=  not(lfsr_q(28));
55
   CRCOutInverted( 2) <=  not(lfsr_q(29));
56
   CRCOutInverted( 1) <=  not(lfsr_q(30));
57
   CRCOutInverted( 0) <=  not(lfsr_q(31));
58
   
59
    lfsr_c(0)  <= lfsr_q(24) xor lfsr_q(30) xor DataIn(0) xor DataIn(6);
60
    lfsr_c(1)  <= lfsr_q(24) xor lfsr_q(25) xor lfsr_q(30) xor lfsr_q(31) xor DataIn(0) xor DataIn(1) xor DataIn(6) xor DataIn(7);
61
    lfsr_c(2)  <= lfsr_q(24) xor lfsr_q(25) xor lfsr_q(26) xor lfsr_q(30) xor lfsr_q(31) xor DataIn(0) xor DataIn(1) xor DataIn(2) xor DataIn(6) xor DataIn(7);
62
    lfsr_c(3)  <= lfsr_q(25) xor lfsr_q(26) xor lfsr_q(27) xor lfsr_q(31) xor DataIn(1) xor DataIn(2) xor DataIn(3) xor DataIn(7);
63
    lfsr_c(4)  <= lfsr_q(24) xor lfsr_q(26) xor lfsr_q(27) xor lfsr_q(28) xor lfsr_q(30) xor DataIn(0) xor DataIn(2) xor DataIn(3) xor DataIn(4) xor DataIn(6);
64
    lfsr_c(5)  <= lfsr_q(24) xor lfsr_q(25) xor lfsr_q(27) xor lfsr_q(28) xor lfsr_q(29) xor lfsr_q(30) xor lfsr_q(31) xor DataIn(0) xor DataIn(1) xor DataIn(3) xor DataIn(4) xor DataIn(5) xor DataIn(6) xor DataIn(7);
65
    lfsr_c(6)  <= lfsr_q(25) xor lfsr_q(26) xor lfsr_q(28) xor lfsr_q(29) xor lfsr_q(30) xor lfsr_q(31) xor DataIn(1) xor DataIn(2) xor DataIn(4) xor DataIn(5) xor DataIn(6) xor DataIn(7);
66
    lfsr_c(7)  <= lfsr_q(24) xor lfsr_q(26) xor lfsr_q(27) xor lfsr_q(29) xor lfsr_q(31) xor DataIn(0) xor DataIn(2) xor DataIn(3) xor DataIn(5) xor DataIn(7);
67
    lfsr_c(8)  <= lfsr_q(0) xor lfsr_q(24) xor lfsr_q(25) xor lfsr_q(27) xor lfsr_q(28) xor DataIn(0) xor DataIn(1) xor DataIn(3) xor DataIn(4);
68
    lfsr_c(9)  <= lfsr_q(1) xor lfsr_q(25) xor lfsr_q(26) xor lfsr_q(28) xor lfsr_q(29) xor DataIn(1) xor DataIn(2) xor DataIn(4) xor DataIn(5);
69
    lfsr_c(10) <= lfsr_q(2) xor lfsr_q(24) xor lfsr_q(26) xor lfsr_q(27) xor lfsr_q(29) xor DataIn(0) xor DataIn(2) xor DataIn(3) xor DataIn(5);
70
    lfsr_c(11) <= lfsr_q(3) xor lfsr_q(24) xor lfsr_q(25) xor lfsr_q(27) xor lfsr_q(28) xor DataIn(0) xor DataIn(1) xor DataIn(3) xor DataIn(4);
71
    lfsr_c(12) <= lfsr_q(4) xor lfsr_q(24) xor lfsr_q(25) xor lfsr_q(26) xor lfsr_q(28) xor lfsr_q(29) xor lfsr_q(30) xor DataIn(0) xor DataIn(1) xor DataIn(2) xor DataIn(4) xor DataIn(5) xor DataIn(6);
72
    lfsr_c(13) <= lfsr_q(5) xor lfsr_q(25) xor lfsr_q(26) xor lfsr_q(27) xor lfsr_q(29) xor lfsr_q(30) xor lfsr_q(31) xor DataIn(1) xor DataIn(2) xor DataIn(3) xor DataIn(5) xor DataIn(6) xor DataIn(7);
73
    lfsr_c(14) <= lfsr_q(6) xor lfsr_q(26) xor lfsr_q(27) xor lfsr_q(28) xor lfsr_q(30) xor lfsr_q(31) xor DataIn(2) xor DataIn(3) xor DataIn(4) xor DataIn(6) xor DataIn(7);
74
    lfsr_c(15) <= lfsr_q(7) xor lfsr_q(27) xor lfsr_q(28) xor lfsr_q(29) xor lfsr_q(31) xor DataIn(3) xor DataIn(4) xor DataIn(5) xor DataIn(7);
75
    lfsr_c(16) <= lfsr_q(8) xor lfsr_q(24) xor lfsr_q(28) xor lfsr_q(29) xor DataIn(0) xor DataIn(4) xor DataIn(5);
76
    lfsr_c(17) <= lfsr_q(9) xor lfsr_q(25) xor lfsr_q(29) xor lfsr_q(30) xor DataIn(1) xor DataIn(5) xor DataIn(6);
77
    lfsr_c(18) <= lfsr_q(10) xor lfsr_q(26) xor lfsr_q(30) xor lfsr_q(31) xor DataIn(2) xor DataIn(6) xor DataIn(7);
78
    lfsr_c(19) <= lfsr_q(11) xor lfsr_q(27) xor lfsr_q(31) xor DataIn(3) xor DataIn(7);
79
    lfsr_c(20) <= lfsr_q(12) xor lfsr_q(28) xor DataIn(4);
80
    lfsr_c(21) <= lfsr_q(13) xor lfsr_q(29) xor DataIn(5);
81
    lfsr_c(22) <= lfsr_q(14) xor lfsr_q(24) xor DataIn(0);
82
    lfsr_c(23) <= lfsr_q(15) xor lfsr_q(24) xor lfsr_q(25) xor lfsr_q(30) xor DataIn(0) xor DataIn(1) xor DataIn(6);
83
    lfsr_c(24) <= lfsr_q(16) xor lfsr_q(25) xor lfsr_q(26) xor lfsr_q(31) xor DataIn(1) xor DataIn(2) xor DataIn(7);
84
    lfsr_c(25) <= lfsr_q(17) xor lfsr_q(26) xor lfsr_q(27) xor DataIn(2) xor DataIn(3);
85
    lfsr_c(26) <= lfsr_q(18) xor lfsr_q(24) xor lfsr_q(27) xor lfsr_q(28) xor lfsr_q(30) xor DataIn(0) xor DataIn(3) xor DataIn(4) xor DataIn(6);
86
    lfsr_c(27) <= lfsr_q(19) xor lfsr_q(25) xor lfsr_q(28) xor lfsr_q(29) xor lfsr_q(31) xor DataIn(1) xor DataIn(4) xor DataIn(5) xor DataIn(7);
87
    lfsr_c(28) <= lfsr_q(20) xor lfsr_q(26) xor lfsr_q(29) xor lfsr_q(30) xor DataIn(2) xor DataIn(5) xor DataIn(6);
88
    lfsr_c(29) <= lfsr_q(21) xor lfsr_q(27) xor lfsr_q(30) xor lfsr_q(31) xor DataIn(3) xor DataIn(6) xor DataIn(7);
89
    lfsr_c(30) <= lfsr_q(22) xor lfsr_q(28) xor lfsr_q(31) xor DataIn(4) xor DataIn(7);
90
    lfsr_c(31) <= lfsr_q(23) xor lfsr_q(29) xor DataIn(5);
91

92
    process (Clock,Reset) begin
93
      if rising_edge(Clock) then
94
      if (Reset = '1') then
95
        lfsr_q <= (others => '1');
96
      elsif (CRCCalculationEnable = '1') then
97
        lfsr_q <= lfsr_c;
98
         end if;
99
      end if;
100
    end process;
101
   
102
end architecture imp_crc; 
103

104
Die Berechnung erfolgt nur von den Datenbytes, die vorangestellte Präambel X"55555555555555D5" wird nicht mitgenommen.
105
Mit in der Berechnung sind allerdings die Pad-Nullen, falls das Paket auf 64 Datenbytes erweitert werden muss.
106

107
Die Datenbytes müssen vertauscht an die CRC-Funktion gegeben werden. 0 <-> 7 
108
  CRC_Calculator: crc
109
  port map
110
  (
111
    Clock      =>  Clock_125MHz,
112
    Reset      => CRCReset,
113
    DataIn(0)    => FifoData(7),  -- databits swappen
114
    DataIn(1)    => FifoData(6),
115
    DataIn(2)    => FifoData(5),
116
    DataIn(3)    => FifoData(4),
117
    DataIn(4)    => FifoData(3),
118
    DataIn(5)    => FifoData(2),
119
    DataIn(6)    => FifoData(1),
120
    DataIn(7)    => FifoData(0),
121
    CRCCalculationEnable   => CRCEnable,
122
    CRCOut       => open,
123
    CRCOutInverted    => CRCResultInverted
124
  );
125

126

127
Nach dem Daten wird der CRC gesendet, allerdings auch der vertauschte 31 <-> 0 und invertierte.
128
Dabei wird LSB-First gesendet.
129

130
when SendDataLastByte => 
131
  -- begin with the first crc datafield
132
  CRCEnable       <= '0';
133
  OutByte            <= CRCResultInverted( 7 downto 0);
134
  SendBufferState     <= SendCRC0;
135
when SendCRC0 =>
136
  OutByte            <= CRCResultInverted( 15 downto 8);
137
  SendBufferState     <= SendCRC1;
138
when SendCRC1 =>
139
  OutByte            <= CRCResultInverted( 23 downto 16);
140
  SendBufferState     <= SendCRC2;
141
when SendCRC2 =>
142
  OutByte            <= CRCResultInverted( 31 downto 24);
143
  SendBufferState     <= SendCRC3;
144
when SendCRC3 =>
145
  OutByte            <= (others => '0');
146
  TXOut              <= '0';
147
  SendBufferState     <= Idle;

Es gibt noch den Hinweis, dass die ersten 32 Bit der MAC-Adresse 
invertiert werden müssen.
Das hat bei mir damit nicht geklappt. Ich habe sie normal in den CRC 
geschoben.

Vielleicht hilft das ja jemanden.
Ich kann jedenfalls damit die Pakete über RGMII und einen Marvel 88E1111 
verschicken.
Entwickelt wurde alles auf einem DE2-115 Board mit einem Cyclone 4.
Gast #5650065
Lesenswert?

PittyJ schrieb:
> Es gibt noch den Hinweis, dass die ersten 32 Bit der MAC-Adresse
> invertiert werden müssen.
> Das hat bei mir damit nicht geklappt. Ich habe sie normal in den CRC
> geschoben.

Die Erklärung warum er die MAC-Adresse nicht extra invertieren muß ist, 
sein Schieberegister in der CRC Berechnung wird vor jedem neuen 
Ethernet-Frame mit 0xFFFF initialisiert, das invertiert die ersten 32 
Bit!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren