calculate (and validate) ethernet FCS (crc32) in vhdl

12,417

Solution 1

I started working on an ethernet MAC a while back, and although I never got round to finishing it I do have a working CRC generator that you can use here:

CRC.vhd

Its based on a Xilinx App note on the IEEE 802.3 CRC, which you can find here.

The CRC is instantiated in the ethernet receieve component, if you look at the ETH_RECEIVE_SM process you can see how the FCS is loaded into the checker.

Hopefully you can spot your mistake by comparing with my code.

Edit:

I took the sample ethernet frame from fpga4fun and passed it through the CRC checker, see the simulation screenshot below (right click, copy URL and view in a new browser tab for full resolution):

enter image description here

You can see the residual C704DD7B at the end there, try doing the same with your own CRC checker and see what you get.

Solution 2

The generator you used may not be pre-processing and post-processing the data. If that generator takes a string of zeros and produces a zero crc, then that's the problem. A string of zeros should not produce zero. (What it produces depends on the number of zeros.)

The processing for the Ethernet crc is to invert the crc, then apply the crc algorithm, then invert the crc again.

Share:
12,417
Jonas Schäfer
Author by

Jonas Schäfer

By day DevOps Engineer with Chef & OpenStack at Cloud & Heat. By night XMPP Standards Foundation member "Full-Stack" enthusiast, starting from setting up CPU registers, via designing custom network protocols to Graphics and physics development or XMPP-based chat software.

Updated on July 24, 2022

Comments

  • Jonas Schäfer
    Jonas Schäfer almost 2 years

    I'm using the Spartan 3E Starter Kit and I'm trying to receive Ethernet frames on it via a 100 MBit link.

    For those who don't know, the board features a PHY chip, exposing the receiving clock with 25 MHz. I have (pretty much) verified that receiving works fine by buffering the received frames and resending them via a serial link.

    Furthermore, I'm using a CRC32 generator from outputlogic.com. I aggregate the received nybbles to bytes and forward them to the CRC. At the end of the frame, I latch the generated CRC and display it on the LCD, together with the CRC I found in the ethernet frame.

    However, (as you might have guessed) the two numbers do not match.

    527edb0d  -- FCS extracted from the frame
    43a4d833  -- calculated using the CRC32 generator
    

    The first one can also be verified by running the package through pythons crc32 function, both with the frame captured by wireshark and the frame captured and retrieved via serial port from the FPGA.

    I guess it must be something more or less trivial. I pasted the receiving process over here. I stripped off everything which was not neccessary. When capturing the output via serial, I added a fifo (readily made unit from Xilinx) which latched at the same time as the CRC generator to get exactly the same bytes.

    Does anyone have an idea what's wrong with that?

  • Jonas Schäfer
    Jonas Schäfer almost 12 years
    Thank you very much already for the code, it looks really helpful and well documented.
  • Peter Bennett
    Peter Bennett almost 12 years
    No problem, If you need anything explaining let me know.
  • Jonas Schäfer
    Jonas Schäfer almost 12 years
    I'm not sure about the state of the s_fcs_crc_calc_en signal in the ETH_RECEIVE_SM process — it is set high but never set to low afterwards. Does it get set to low automatically on the next clock? That would, as far as I can see, result in s_fcs_crc_calc_en and s_fcs_crc_d_valid never becoming high at the same time.
  • Jonas Schäfer
    Jonas Schäfer almost 12 years
    Nevermind, if I get the documentation in the PDF right, this seems like okay behaviour, as asserting both at the same time should have the same effect as if they were asserted at different times.
  • Jonas Schäfer
    Jonas Schäfer almost 12 years
    Hm. Although your answer was helpful and I thought for a moment it worked, I still don't get the correct result (i.e. after piping the whole frame through the crc, I don't end up with the residual). Do you have any further tips what I could look out for?
  • Peter Bennett
    Peter Bennett almost 12 years
    I modified my answer to include a screenshot of the checker processing a sample ethernet frame, have a go at processing the same frame with your own code and see what you get.
  • Jonas Schäfer
    Jonas Schäfer almost 12 years
    Ok, I got it to work in the sim, thanks for the screenshot, that helped a lot. On the chip, it doesn't work however. I may open another question about that later.
  • Peter Bennett
    Peter Bennett almost 12 years
    Doh, that's unfortunate. You could try a simulation where more than one packet is received, maybe something isn't getting reset properly. You could also check for uninitialised signals, these can account for a simulation/synthesis mismatch. Failing that I guess your next stop is to check your synthesis log for timing violations and check that you're appropriately deglitching your inputs
  • Jonas Schäfer
    Jonas Schäfer almost 12 years
  • sebs
    sebs over 11 years
    You might want to look here: stackoverflow.com/questions/9286631/… Its often a case of bit/byte-order mismatch