I have been working on understanding CRC calculations for implementation in VHDL. Specifically I have implemented the CRC-32C (polynomial = 0x1EDC6F41) a couple of ways. First using an LFSR approach and secondly using a lookup table for speed. Everything seems to agree with the online checkers but I am having trouble understanding why, if you calculate a CRC of some data, append the CRC to the end of the data and then recalculate the CRC, I do not get a result of zero.

For example, if I calculate the CRC of the string "123456789" (hex values 313233343536373839) I get a result from the calculator of E3 06 92 83.

Now if I calculate the CRC of 313233343536373839 E3069283 the resulting calculated CRC is BA F5 57 BE; I was expecting this to be zero.

If I repeat the same procedure above with any other of the 8 & 16 bit CRCs available on the calculator I do get zero returned.

FYI, I have been using this calculator for reference.

Also, for anyone else struggling on this topic here are some useful links:

  • 2
    \$\begingroup\$ What is the question? \$\endgroup\$
    – JYelton
    Jul 26 '19 at 20:01
  • \$\begingroup\$ I've done basic CRC checking for serial comms but I never thought that the CRC of the message and CRC should result in zero. Rather, I thought that the receiver would run the CRC calculation again on the message (without the CRC) and compare the two. Why do you think the CRC of the message + CRC should result in zero? \$\endgroup\$
    – Transistor
    Jul 26 '19 at 20:05
  • \$\begingroup\$ Have you verified by any other means that the calculator is correct for CRC-32C? Have you asked the creator of the calculator? \$\endgroup\$ Jul 26 '19 at 20:05
  • \$\begingroup\$ @Transistor In theory, it should. For something in hardware, it may be easier to run a bit more data through the CRC and get an easy comparison than comparing a register value. \$\endgroup\$
    – W5VO
    Jul 26 '19 at 20:42
  • \$\begingroup\$ @Transistor because if you have a result of CRC calculation in the shift register (without post inversion) and finally feed the same bit pattern back into the algorithm, it means all one bits get bitwse XORed to 0 thus result is always zero. However if the result was post-inverted then feeding it back will produce a constant check value. I think this is the issue of OP. \$\endgroup\$
    – Justme
    Jul 26 '19 at 23:12

A result of zero is only expected for some calculation methods.

Besides the polynomial and byte ordering, there are other options for the various CRC methods.

  1. The initial pattern.
  2. If the CRC is inverted before transmission.
  3. How padding is done for unaligned sizes.

I had some good CRC references, but unfortunately, I didn't take all of them with me when I retired. Even so, I can make the CRC-32 option work as you expect if I invert the CRC.

Using the calculator, use 12345678 ASCII (multiple of 32-bits, so no issue with padding). Then, invert the CRC result before appending it to the starting data pattern. Run the calculation again, the result is FFFFFFFF. The inversion is zero, what you expect. (I only tested with big-endian)

I was disappointed that the wikipedia article barely mentions the 3 options I noted above.


If you correctly append a CRC to the message it was calculated from, then the CRC of that whole thing will always be the same constant for that particular CRC definition. However, that constant is zero only for some CRC definitions. In particular, those whose final exclusive-or is zero.

For the CRC-32C, that constant is 0x48674bc7. To correctly append the CRC, the bytes must be in little endian order -- the opposite of what you tried. That is because CRC-32C processes the least significant bits of the message first.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.