您的CRC不是CRC。输入的最后32位实际上不参与计算,除了被排除在结果之外。也就是说,如果用零替换最后32位数据,进行计算,然后使用生成的“crc32”排除或最后32位数据,那么您将得到相同的结果。
所以你永远不会让它与另一个CRC计算相匹配,因为它不是CRC。
C中的这段代码复制了你的函数,其中数据位来自一系列数据 n 字节在 p ,最低有效位优先,结果是32位值:
n
p
unsigned long notacrc(void const *p, unsigned n) { unsigned char const *dat = p; unsigned long reg = 0xffffffff; while (n) { for (unsigned k = 0; k < 8; k++) reg = reg & 1 ? (reg >> 1) ^ 0xedb88320 : reg >> 1; reg ^= (unsigned long)*dat++ << 24; n--; } return reg; }
您可以立即看到数据的最后一个字节只是与最终寄存器值进行异或运算。不太明显的是最后一个 四 字节只是异或。这个完全相同的版本证明了这一点:
unsigned long notacrc_xor(void const *p, unsigned n) { unsigned char const *dat = p; // initial register values unsigned long const init[] = { 0xffffffff, 0x2dfd1072, 0xbe26ed00, 0x00be26ed, 0xdebb20e3}; unsigned xor = n > 3 ? 4 : n; // number of bytes merely xor'ed unsigned long reg = init[xor]; while (n > xor) { reg ^= *dat++; for (unsigned k = 0; k < 8; k++) reg = reg & 1 ? (reg >> 1) ^ 0xedb88320 : reg >> 1; n--; } switch (n) { case 4: reg ^= *dat++; case 3: reg ^= (unsigned long)*dat++ << 8; case 2: reg ^= (unsigned long)*dat++ << 16; case 1: reg ^= (unsigned long)*dat++ << 24; } return reg; }
在那里,您可以看到消息的最后四个字节,或者如果它是三个或更少字节的所有消息,则在末尾与最终寄存器值异或。
实际的CRC必须使用所有输入数据位来确定何时与寄存器进行异或或多项式。最后一个函数的内部部分是CRC实现的样子(尽管更高效的版本使用预先计算的表来一次处理一个或多个字节)。这是一个计算实际CRC的函数:
unsigned long crc32_jam(void const *p, unsigned n) { unsigned char const *dat = p; unsigned long reg = 0xffffffff; while (n) { reg ^= *dat++; for (unsigned k = 0; k < 8; k++) reg = reg & 1 ? (reg >> 1) ^ 0xedb88320 : reg >> 1; n--; } return reg; }
那个叫 crc32_jam 因为它实现了一个名为“JAMCRC”的特定CRC。 CRC与您尝试实施的最接近。
crc32_jam
如果要使用真正的CRC,则需要更新Verilog实现。