FPGARelated.com
Forums

ethernet checksum nightmare

Started by Unknown December 27, 2006
Hi,
 I have been fighting with this for some time now and I cannot figure
it out. I have read the 802.3 information and I have read a lot of
forums and they all have some kind of general answer.

I am trying to create a very simple MAC module that will send data to a
PHY for transmission. I am currently using the aesic crc VHDL function
to perform my CRC checks.

Let's say I want to send the following packet (I know this is not a
correct ethernet packet. Bear with me):
00 00 12 33 FF FF (in bytes) The bytes will be sent with the left most
byte first.

0000 0000 0000 0000 0001 0010 0011 0011 1111 1111 (in bits)

I would first switch the bits in each byte individually and then feed
it to the CRC module which has been initialized with all 1s.

Therefore

0000 0000 0000 0000 1000 0100 1100 1100 1111 1111

is fed into the CRC module starting with the byte on the left most
side.

Hopefully this is correct so far.

After the last byte is fed through, I will grab the output of the CRC
module, Invert it and shift it's bits.

The output from the CRC is

7E 11 64 34 ( in bytes)

0111 1110 0001 0001 0110 0100 0011 0100 ( in bits)

After inverting

1000 0001 1110 1110 1001 1011 1100 1011 ( in bits)

After switching

1101 0011 1101 1001 0111 0111 1000 0001 ( in bits)

D3 D9 77 81 ( in bytes)

This means that my packet that I will send to the PHY will be start
with the left most byte

00 00 12 33 FF FF D3 D9 77 81  ( in bytes)

This value seems to agree with some CRC32 software I found on the net.

**************************************************

NOW lets say i am receiving this data from the PHY.

00 00 12 33 FF FF D3 D9 77 81  ( in bytes)

I do the same as for sending, I switch the bits in each byte (including
the FCS) and feed it to the CRC module which has been initialized to
all 1. After sending the right most byte, I should get the magic number
C7 04 DD 7B out which says that it is working but i don't. Below is the
exact sequence of CRC output:

Previous CRC Value |  Input   |   Next CRC Value   |   Next FCS Value
FFFFFF                     |  00       |   4E08BFB4            |
D202EF8D
4E08BFB4                 |  00       |   00B7647D            |
41D912FF
00B7647D                 |  12       |   A5EAE0CF            |
0CF8A85A
A5EAE0CF                 |  33       |   648CF998            |
E660CED9
648CF998                 |  FF       |   82AF68FF            |
00E90ABE
82AF68FF                 |  FF       |   7E116434            |
D3D97781
7E116434                 |  D3       |   BB9FD215            |
57B40622
BB9FD215                 |  D9       |   07F1A3E0            |
F83A701F
07F1A3E0                 |  77       |   16C33676            |
91933c97
16C33676                 |  81       |   F86C1D9B            |
2647C9E0

The VHDL code I used is below:
process(clk)
begin
if(clk'event and clk = '1') then
  crc_32_out <= nextCRC32_D8(input0(0) & input0(1) & input0(2) &
input0(3) & input0(4) & input0(5) & input0(6) & input0(7), input1);

  for i in 31 downto 0 loop
    crc_32_final(i) <= NOT crc_32_out(31-i);
  end loop;
end if;

end process;

I am at a lost here. I know this is a lot of information but i hope
somebody can help me out. I guess this will also help anybody that
researches this topic after me. Thanks a lot,
Amish

axr0284@yahoo.com wrote:

> is fed into the CRC module starting with the byte on the left most > side. > > Hopefully this is correct so far.
Did you remeber to initialize the CRC funtion to all 1 at the beginning. Rough code from my old working Ethernet CRC calculator is following (there might be some twists in the code that i don't remember anymore). The CRC function seems to be the same that easics tool give, altough it's done by other tools. Pseudocode: data_input,incoming_data,crc_tmp,final_crc : std_logic_vector(7 downto 0) for_all_bytes: for i in 0 to 7 loop data_input(i) <= incoming_data(7-i); end loop for_all_bytes: if start_of_packet crc_tmp=crc_32_8(data_input,others=>'1') else crc_tmp=crc_32_8(data_input,crc_tmp) finish_calc: final_crc=NOT(crc_tmp) --Kim
Kim Enkovaara wrote:
> axr0284@yahoo.com wrote: > > > is fed into the CRC module starting with the byte on the left most > > side. > > > > Hopefully this is correct so far. > > Did you remeber to initialize the CRC funtion to all 1 at the beginning. > > Rough code from my old working Ethernet CRC calculator is following (there > might be some twists in the code that i don't remember anymore). The CRC > function seems to be the same that easics tool give, altough it's done by > other tools. > > Pseudocode: > > data_input,incoming_data,crc_tmp,final_crc : std_logic_vector(7 downto 0) > > for_all_bytes: > for i in 0 to 7 loop > data_input(i) <= incoming_data(7-i); > end loop > > for_all_bytes: > if start_of_packet > crc_tmp=crc_32_8(data_input,others=>'1') > else > crc_tmp=crc_32_8(data_input,crc_tmp) > > finish_calc: > final_crc=NOT(crc_tmp) > > --Kim
Yes the CRC module is always initialized to all 1 for the first byte. Amish
When computing the packet for sending, it gives me the proper answer.
It's when receiving that i am having an issue since I do not see the
"magic number as the output of the CRC module. I think i might be
feeding in the original CRC at the end of the packet the wrong way or
something.
Amish

axr0284 wrote:

> When computing the packet for sending, it gives me the proper answer. > It's when receiving that i am having an issue since I do not see the > "magic number as the output of the CRC module. I think i might be > feeding in the original CRC at the end of the packet the wrong way or > something.
Then just why don't you calculate the CRC while receiving only for the data and compare the two CRC values. You just have to make sure that the sender works fine. I used commercial testers to make sure that the calculated CRC matches real world. --Kim
<axr0284@yahoo.com> wrote in message 
news:1167259663.414854.45200@73g2000cwn.googlegroups.com...
> Hi, > I have been fighting with this for some time now and I cannot figure > it out. I have read the 802.3 information and I have read a lot of > forums and they all have some kind of general answer. > > I am trying to create a very simple MAC module that will send data to a > PHY for transmission. I am currently using the aesic crc VHDL function > to perform my CRC checks. > > Let's say I want to send the following packet (I know this is not a > correct ethernet packet. Bear with me): > 00 00 12 33 FF FF (in bytes) The bytes will be sent with the left most > byte first. > > 0000 0000 0000 0000 0001 0010 0011 0011 1111 1111 (in bits) > > I would first switch the bits in each byte individually and then feed > it to the CRC module which has been initialized with all 1s. > > Therefore > > 0000 0000 0000 0000 1000 0100 1100 1100 1111 1111 > > is fed into the CRC module starting with the byte on the left most > side.
You flipped nibbles, not bytes. 0000 0000 0000 0000 0100 1000 1100 1100 1111 1111 or 00 00 48 CC FF FF hex is what you should input
> > Hopefully this is correct so far. > > After the last byte is fed through, I will grab the output of the CRC > module, Invert it and shift it's bits. > > The output from the CRC is > > 7E 11 64 34 ( in bytes) > > 0111 1110 0001 0001 0110 0100 0011 0100 ( in bits) > > After inverting > > 1000 0001 1110 1110 1001 1011 1100 1011 ( in bits) > > After switching > > 1101 0011 1101 1001 0111 0111 1000 0001 ( in bits) > > D3 D9 77 81 ( in bytes) >
The FCS of the ethernet packet is the only portion that is sent most significant bit first. Thus there is no need to "switch" it.
On 27 Dec 2006 14:47:43 -0800, axr0284@yahoo.com wrote:

>Hi, > I have been fighting with this for some time now and I cannot figure >it out. I have read the 802.3 information and I have read a lot of >forums and they all have some kind of general answer.
Go here for an exactly correct packet: http://www.fpga-faq.com/archives/91050.html#91062 =================== Philip Freidin philip.freidin@fpga-faq.org Host for WWW.FPGA-FAQ.ORG
Hi Colin,
Thanks for the answer. This is strange. I guess i am confused with the
results from software programs I used such as the one on this website
http://www.zorc.breitbandkatze.de/crc.html
and what I get in hardware. I would expect it to the same but i am not
sure that it is. I am trying to implement a MAC in an FPGA and I need
to be sure that what I am sending to the PHY and out on the wire will
be understood by the receiving MAC from a NIC card for example.

So if I send 00 00 12 33 FF FF to the PHY from the FPGA,
this is what is sent on the WIRE from the PHY

00 00 84 CC FF FF

lsb first for each byte

So I feed the original data "00 00 12 33 FF FF" as is through the
EASICS module with initialization of all 1, I get the <RESIDUE>
AA C5 98 B0

Now it clearly states in the 802.3 specs that "The bit sequence is
complemented and the result is the CRC"

So I need to complement the <RESIDUE> to get the <CRC> : 55 3A 67 4F

Then I need to send it MSB first since the 802.3 spec says

"The 32 bits of the CRC value are placed in the frame check sequence
  field so that the x31 term is the leftmost bit of the first octet,
  and the x0 term is the right most bit of the last octet.
  (The bits of the CRC are thus """transmitted""" in the order x31,
x30..., x1, x0.)"

So I need to switch the bits in each byte before appending to the
Packet
Therefore the <CRC> becomes the <FCS>
AA 5C E6 F2

So the full packet is
00 00 12 33 FF FF AA 5C E5 F2

but what is sent on the wire is
00 00 84 CC FF 55 3A 67 4F

 On receiving , I guess i need to flip the CRC back to 55 3A 67 4F
before feeding it into the EASICS module to get the magic number.

I hope I got it right this time. This took a while.
I think i will just recompute the packet and compare the incoming FCS
with that. It might be easier.
Thanks a lot, I really appreciate you taking the time to help me out,
Amish

(comp.dcom.lans.ethernet added)

axr0284 wrote:

> Thanks for the answer. This is strange. I guess i am confused with the > results from software programs I used such as the one on this website > http://www.zorc.breitbandkatze.de/crc.html > and what I get in hardware. I would expect it to the same but i am not > sure that it is. I am trying to implement a MAC in an FPGA and I need > to be sure that what I am sending to the PHY and out on the wire will > be understood by the receiving MAC from a NIC card for example.
I am pretty sure that the design allows a simple LFSR with the transmitted bits as input, and then shifted out at the appropriate time. I believe, but am slightly less sure, that it also works such that a properly received frame will generate a constant value in the same LFSR when run through the data and FCS of the incoming frame. Ethernet was designed in the days when logic was much more expensive than today. Simplifying the required logic was important. (snip)
> Now it clearly states in the 802.3 specs that "The bit sequence is > complemented and the result is the CRC"
(snip)
> "The 32 bits of the CRC value are placed in the frame check sequence > field so that the x31 term is the leftmost bit of the first octet, > and the x0 term is the right most bit of the last octet. > (The bits of the CRC are thus """transmitted""" in the order x31, > x30..., x1, x0.)"
(snip) -- glen
Colin Hankins wrote:

(snip)

> The FCS of the ethernet packet is the only portion that is sent most > significant bit first. Thus there is no need to "switch" it.
That isn't quite true, as an FCS isn't a number, it is a bit string. That is, it doesn't have place values. All bits are equally significant in the result. (Being only tested for equality.) Mathematically each bit is a coefficient of a term in a polynomial, but they are separate terms. Now, you might associate the bit with the higher power with the MSB, but if you consider it in terms of an LFSR even that doesn't matter. -- glen