1

Lets assume a 16 bit CRC polynomial x¹⁶+x¹²+x⁵+1 = 0x11021. That polynomial can:

  1. detect all single bit errors (data size independent).
  2. detect all burst errors up to 16 bit width (data size independent).
  3. detect all odd numbers of bit errors (since it has 4 polynomial terms; data size independent).
  4. detect 3 bit errors (HD4) up to 32571 bit data size.

Considering the above points are right...... What kind of errors does CRC cannot detect.?

1 Answers1

3
  1. That should be detect all single burst errors up to 16 bits.

  2. 0x11021 is the product of 2 "prime" polynomials, 0xf01f and 0x3. The 0x3 factor is why all odd bit errors are detected (it is a parity factor).

  3. Since all odd bit errors are detected, then this statement becomes detecting all 2 bit errors up to a data size size 32751 bits or a message size of 32767 bits, which includes the 16 bit CRC which is appended to the data bits. For a brute force approach, using a bit string of all zero bits except the first bit which is a one bit, then calculate the CRC over this string until the CRC only has a single one bit as the most significant bit. This can be emulated by starting with a CRC of 0x8000 and cycling it until it cycles back to 0x8000 again, which will take 32767 cycles. So if bit[0] and bit[32768] are == 1 (all other bits == 0), then the calculated CRC will be zero, a failure to detect the 2 error bits.

What kind of errors does CRC cannot detect?

Multiple burst errors where the total distance of the bursts spans more than 16 bits, essentially a single burst error more than 16 bits long.

Some patterns of 4 or more randomly distributed bit errors in a 64 bit message (48 bits data, 16 bits CRC) will fail to be detected. As seen in the table below, the probably of not detecting an error is fairly low. As the number of bit errors increases, the failure rate increases, but it's still low unless you have a lot of bit errors. A random pattern of bits will pass a CRC16 check about 1/65536 of the time, but this would be unusual in a normal message send / receive sequence.

48 bit data, 16 bit crc, => 64 bit message
2^64 - 1 possible error patterns
       84 of        635376 possible patterns of  4 error bits fail
     2430 of      74974368 possible patterns of  6 error bits fail
   133001 of    4426165368 possible patterns of  8 error bits fail
  4621021 of  151473214816 possible patterns of 10 error bits fail   
100246083 of 3284214703056 possible patterns of 12 error bits fail

Example code for 4 bit case. Set e to number of error bits to test.

static uint16_t crctbl[65536];

int main()
{
uint32_t I[16];                 /* indexes */
uint32_t e = 4;                 /* # of error bits */
uint32_t i, j;
uint64_t d;
uint32_t crc;
uint64_t ptrn = 0;              /* # of patterns */
uint32_t fail = 0;              /* # of failures */

    for(j = 0; j < 0x10000; j++){ /* generate table */
        crc = j;
        for (i = 0; i < 16; i++) {
            crc <<= 1;
            if (crc & 0x10000)
                crc ^= 0x11021;
        }
        crctbl[j] = (uint16_t)crc;
    }
    for(i = 0; i < e; i++)      /* init I */
        I[i] = i;
    while(1){
        d = 0;                  /* set up pattern */
        for(i = 0; i < e; i++)
            d |= ((uint64_t)1 << (63-I[i]));
        for(j = 0; j < 4; j++){ /* generate crc */
            crc = crctbl[       (d >> 48)&0xffff ];
            crc = crctbl[crc ^ ((d >> 32)&0xffff)];
            crc = crctbl[crc ^ ((d >> 16)&0xffff)];
            crc = crctbl[crc ^ ((d >>  0)&0xffff)];
        }
        ptrn++;
        if (crc == 0)           /* if failed */
            fail++;
        i = e - 1;              /* advance indexes */
        if (++I[i] < 64)        /*  to next permuation */
            continue;
        --I[i];
        j = 63;
        while (I[i--] >= j--) {
            if (i == 0)         /* show progress */
                printf("%u\n", I[0]);
            if (i == (uint32_t)(0-1))
                goto done0;
        }
        j = I[++i];
        while (i < e)
            I[i++] = ++j;
    }
done0:
    printf("%llu %u\n", ptrn, fail);
    return 0;
}
rcgldr
  • 27,407
  • 3
  • 36
  • 61
  • how did you calculate the number of patterns that fail? for example, how did you calculate 84 here? (84 of 635376 possible patterns of 4 error bits fail) – Arash Aug 23 '23 at 16:23
  • 1
    @Arash - brute force. Init fail count to 0. Init array of 4 indexes to 0, 1, 2, 3. Set a 64 bit unsigned integer to 0, then set 4 1 bits according to the array of indexes, generate CRC, if CRC == 0 increment fail count. Use "next permutation" to advance indexes and repeat until all permutations tested. I updated answer with example code. For larger cases, I started at different sets of indexes and ran on multiple cores. – rcgldr Aug 23 '23 at 20:28
  • 1
    @Arash - normally there is only a check to see if there are any failure patterns, versus counting them all. This would allow creating a table of 74,974,368 CRCs and bit indexes for 6 bits out of 64 bad, then sorting the table, and then scanning the table for any duplicate CRCs with no duplicate indexes, which would be a failure case. Say CRC[i] == CRC[i+j}, then CRC[i] XOR CRC{i+j] == 0, and that there are no duplicate indexes, which would be a 12 bit case that failed. – rcgldr Aug 25 '23 at 00:01
  • Thank you for your response. I've been working on a CRC-32 method similar to yours, but I've noticed the modified version of my code is not detecting the patterns accurately. I would greatly appreciate your opinion on this matter. If you have the time, could you please take a look at my code? You can find it here: https://github.com/ArashSr/Test/blob/main/CRC32FailedWPatrn2.c – Arash Aug 30 '23 at 04:53
  • @Arash - Change `crc = 0xFFFFFFFF;` to `crc = 0;`, and delete `crc = ~crc;`. This is only meant to test the polynomial, not the initial value for the final xor value. The assumption is that d = 0 represents an encoded string of zeroes, with a CRC of zeroes. Poly = 0x000000AF will fail 30 times at 6 bits. Poly = 0x04C11DB7 will fail 29 times at 10 bits. For larger messages, brute force would take too long and requires optimization, but it was enough for the simple cases in my answer. – rcgldr Aug 31 '23 at 05:44