I try to do a CRC-16/Maxim calculation in VHDL. My current implementation looks as follows

lfsr_c(0)  <= lfsr_q(15) XOR data_in;
lfsr_c(1)  <= lfsr_q(0);
lfsr_c(2)  <= lfsr_q(1) XOR lfsr_q(15) XOR data_in;
lfsr_c(3)  <= lfsr_q(2);
lfsr_c(4)  <= lfsr_q(3);
lfsr_c(5)  <= lfsr_q(4);
lfsr_c(6)  <= lfsr_q(5);
lfsr_c(7)  <= lfsr_q(6);
lfsr_c(8)  <= lfsr_q(7);
lfsr_c(9)  <= lfsr_q(8);
lfsr_c(10) <= lfsr_q(9);
lfsr_c(11) <= lfsr_q(10);
lfsr_c(12) <= lfsr_q(11);
lfsr_c(13) <= lfsr_q(12);
lfsr_c(14) <= lfsr_q(13);
lfsr_c(15) <= lfsr_q(14) XOR lfsr_q(15) XOR data_in;

With lfsr_q initiated to 0x0000. But this gives me the result for CRC-16/BUYPASS according to https://www.crccalc.com/

What do these RefIn and RefOut exactly mean and how would I change the above lfsr to output the CRC-16/MAXIM? Is my assumption correct that I don't have to manipulate my input so I still can shift in MSB first?

  • \$\begingroup\$ I found some references that mention that one need to shift in the opposite direction, so right instead of left, but that seems to give completely wrong results. \$\endgroup\$ – po.pe May 24 '19 at 8:16

From crccalc's source code (Ref stands for 'reflect'):

    /// <summary>
    /// This is a boolean parameter. If it is FALSE, input bytes are
    /// processed with bit 7 being treated as the most significant bit
    /// (MSB) and bit 0 being treated as the least significant bit.If this
    /// parameter is FALSE, each byte is reflected before being processed.
    /// </summary>
    public bool RefIn { get; private set; }

    /// <summary>
    /// This is a boolean parameter. If it is set to FALSE, the
    /// final value in the register is fed into the XOROUT stage directly,
    /// otherwise, if this parameter is TRUE, the final register value is
    /// reflected first.
    /// </summary>

So basically, for the CRC/MAXIM, since both are true:

  • You shift in LSB first because RefIn is true
  • You mirror the output bits before applying the XOR mask

Regarding that XOR mask: you seem to have forgotten it, the MAXIM implementation specified 0xFFFF, which means you should invert each of your output bits before calculating the next stage polynomial.

Handy little resouces:

|improve this answer|||||
  • \$\begingroup\$ That means this is not suitable for crc calculation in a serial protocol if I don't want to buffer the whole message first? \$\endgroup\$ – po.pe May 27 '19 at 16:47
  • \$\begingroup\$ @Humpawumpa What gives you that idea? The XOR mask? that happens at every stage, so if your message is 15 bits long and you CRC 1 bit each clock cycle, you perform an XOR each stage. \$\endgroup\$ – DonFusili May 28 '19 at 7:13
  • \$\begingroup\$ @Humpawumpa If your problem is the fact that you shift in LSB first, this is not a problem, you just have to shift in in the same order on both the send and receive side. \$\endgroup\$ – DonFusili May 28 '19 at 7:15

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.