CRCTR
CRCTR
Redundancy Checks
Eric E. Johnson
November 1995
NMSU-ECE-95-011
High-Speed Computation of Cyclic Redundancy Checks
Eric E. Johnson
Klipsch School of Electrical and Computer Engineering
New Mexico State University
November 1995
Abstract
Cyclic redundancy checks (CRCs) are widely used in error-prone
channels to detect corruption of data blocks. This report describes
implementations of both the standard bit-by-bit technique for
computing CRCs and a high-speed technique that employs precom-
puted tables to compute CRCs on a byte-by-byte basis. The tech-
nique could be further extended to compute CRCs word-by-word.
INTRODUCTION
When data are stored on or communicated through media that may introduce errors, some form of
error detection or error detection and correction coding is usually employed. When error rates are
sufficiently low that detection alone is acceptable, cyclic redundancy check (CRC) codes are often
used.
Mathematically, a CRC is computed for a block of data by treating that data block as a string of
binary coefficients of a polynomial, which is divided by a “generator polynomial,” with the
remainder of this division used as the CRC. Consider a string of N data bits, iN-1 ... i0, in which iN-1
is the first bit sent. We define the data polynomial to be1
The multiplication by xr shifts the data polynomial r bits to the left to make room for an r-bit CRC
o(x), which is the remainder when the data polynomial d(x) is divided by the generator
polynomial
That is, i(x) = h(x) g(x) + o(x) for some h(x). Note that o(x), as the remainder of a division by
g(x), is necessarily of order r–1 or less, and therefore can be represented by a string of r bits.
The CRC is appended to the string of data bits to form a string of N+r bits c(x) = i(x) + o(x)
c(x) = xr ( iN-1 xN-1 + iN-2 xN-2 + ... + i1 x + i0 ) + or-1 xr-1 + or-2 xr-2 + ... + o1 x + o0.
1
All additions are modulo-2.
When this bit string is sent through a channel (e.g., stored on a disk and subsequently retrieved, or
received from a communications channel), the presence of errors may be detected by recomputing
the CRC using the received data bits î and verifying that the newly computed CRC matches that
received at the end of the bit string (ô). If the computed CRC does not match ô, one or more errors
have been introduced by the channel. If the computed CRC matches ô, the data block is assumed
to be error free, although there is a small probability that undetected errors have occurred. For a
suitably chosen g(x), the probability of undetected errors is approximately 2-r.
It may be more convenient to instead simply divide the polynomial corresponding to the entire
received bit stream (î + ô) by the generator polynomial. This avoids the need to know a priori the
length of the data block.
Because i(x) = h(x) g(x) + o(x), we have i(x) + o(x) = h(x) g(x) modulo 2. Thus, if the bit
stream sent is divided by g(x), the remainder will be 0, because i(x) + o(x) is an even multiple of
g(x). Likewise, if the received bit stream î(x) + ô(x) is divided by g(x) and a remainder of 0
results, the received block is probably identical to the bits sent, and therefore error-free.
g0 g1 g r-2 gr-1
•••
This circuit operates in a fashion similar to manual long division. The storage elements in Figure 1
hold the coefficients of the divisor corresponding to the indicated powers of x. For each cycle of
the division algorithm, the xr-1 coefficient at the end of one cycle will become the xr coefficient for
the next cycle. If this xr coefficient is 1, the generator polynomial will be subtracted from the
divisor. Because the xr coefficient of the generator polynomial is always 1, the resulting xr
coefficient in the divisor will always be 0, and need not be stored.
Because the generator polynomial is of order r, only the r next-most-significant bits can be
affected by the subtraction, so only r storage elements are needed. After each subtraction (actually
modulo-2 addition), the resulting modified coefficients of the divisor are stored in the shift register.
The data bits are fed into the circuit in the order iN-1 ... i0. Because i(x) is scaled by xr, i0 must
be followed by r zero bits. After i(x) has been divided by g(x), the contents of the shift register are
the remainder o(x), which can then be shifted out. The most-significant bit or-1 (found in the xr-1
element of the shift register) is sent first, followed in order by the remaining bits.
2
Algorithm for Bit-by-Bit CRC Computation
Although the shift register approach to computing CRCs is usually implemented in hardware,
when bit-by-bit processing efficiency in software is adequate, the following algorithm can be used:
• Let R represent the contents of the r-bit shift register, with the most significant bit
denoted Rr-1 and so on.
• Let G represent the r least-significant coefficients of the generator polynomial, and
let Gr1 = G right-shifted one bit position.
• Let i represent the input bit for each cycle of the computation.
The computation of the CRC proceeds as follows, using C notation in which ^ represent the
exclusive-or (modulo-2 addition) operation and << n represents left shifting by n bits:
1. Initialize R to 0.
2. For each input bit i
if (Rr-1 == 1)
R = ((R ^ Gr1) << 1) + (i ^ 1)
otherwise
R = (R << 1) + i
3
/* srtst.c eej 11/25/95
*
* implements CRC-CCITT using shift register
*/
#include <stdio.h>
void
ResetCRC()
{
R = 0;
}
void
UpdateCRC(char x)
{
int i, k;
printf("\nUpdateCRC(%02x)\n", x);
for (k=0; k<8; k++) {
i = (x >> 7) & 1; /* msb */
printf(" %04x < %1x -> ", R, i);
if (R & 0x8000) /* is msb of R == 1? */
R = ((R ^ Gr1) << 1) + (i ^ 1);
else
R = (R << 1) + i;
R &= 0x0ffff;
printf("%04x\n", R);
x <<= 1;
}
}
/************************************
* CheckCRC *
* *
* Computes CRC over buffer of *
* given length. Returns 0 if *
* last 2 bytes were correct CRC *
************************************/
long
CheckCRC(FILE *fp, int length)
{
int i;
ResetCRC();
for (i = 0; i < length; i++) {
UpdateCRC(getc(fp));
}
return R;
}
4
main()
{
FILE *fp;
int c, length = 0;
long crcSent;
5
TABLE-DRIVEN CRC COMPUTATION
A more efficient approach to CRC computation in software was described by Sarwate [2]. This
technique uses a table of precomputed effects on the shift register of 8-bit bytes, which allows the
computation to run at one cycle per byte (instead of one cycle per bit).
Precomputation
The table used by this algorithm contains words of length r that represent the composite effect of
processing an entire 8-bit byte through the polynomial division algorithm described previously.
The table is indexed by the contents of the byte to be processed, and therefore contains 28 = 256
entries. The entries are computed as follows:
1. First, compute 8 basis polynomials gj(x), which represent the effects of input bits
that will enter the shift register 7 - j bit times in the future.
2. Then, compute the table entries by adding (modulo-2) the basis polynomials
corresponding to 1 bits in the index for each entry.
This process is illustrated in the following code fragments. The CRC-CCITT is again used in this
example. Note once again that only r bits need be stored for the basis polynomials and the table
entries.
CRC Computation
The precomputed table can either be generated each time the program is started, or written to an
auxiliary file that is read when the CRC computation program is compiled (ccitttab.h in the
following example program). CRC computation uses a shift register of r bits (crcsum in the
example), into which input bytes and table entries are summed and shifted in UpdateCRC():
6
/* crctst.c eej 11/26/95
*
* implements CRC-CCITT using table lookup
*/
#include <stdio.h>
#include "ccitttab.h"
void
ResetCRC()
{
crcSum = 0;
}
void
UpdateCRC(char x)
{
int tmp;
/************************************
* *
* CheckCRC *
* *
* Computes CRC over buffer of *
* given length. Returns 0 if *
* last 2 bytes were correct CRC *
* *
************************************/
long
CheckCRC(FILE *fp, int length)
{
int i;
long tmp;
ResetCRC();
for (i = 0; i < length; i++) {
UpdateCRC(getc(fp));
}
return crcSum;
}
7
main()
{
FILE *fp;
int c, length = 0;
long crcSent;
8
/* crctst.c eej 11/26/95
*
* implements CRC-CCITT using table lookup
* ADCCP version 1: initialize crcSum (C1C0) to 1's
*/
#include <stdio.h>
#include "ccitttab.h"
void
ResetCRC()
{
crcSum = 0x0ffff;
}
void
UpdateCRC(char x)
{
int tmp;
/************************************
* *
* CheckCRC *
* *
* Computes CRC over buffer of *
* given length. Returns 0 if *
* last 2 bytes were correct CRC *
* *
************************************/
long
CheckCRC(FILE *fp, int length)
{
int i;
long tmp;
ResetCRC();
for (i = 0; i < length-2; i++) {
UpdateCRC(getc(fp));
}
for (; i < length; i++) {
UpdateCRC(getc(fp) ^ 0x0ff);
}
return crcSum;
}
9
main()
{
FILE *fp;
int c, length = 0;
long crcSent;
10
/* the file ccitttab.h contains the precomputed table */
int CrcTab[256] =
{0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0};
The code on the folowing pages presents an implementation of this 32-bit CRC scheme (which
uses the ADCCP variation).
11
#include "crctable.h"
void
ResetCRC()
{
crcSum = 0xffffffff;
}
void
UpdateCRC(char x)
{
int tmp;
void
AppendByte(char x)
{
UpdateCRC(x & 0xff);
*nextByte++ = x & 0xff;
}
/************************************
* *
* CheckCRC *
* *
* Computes CRC over buffer of *
* given length. Returns 0 if *
* last 4 bytes were correct CRC *
* *
************************************/
long
CheckCRC(char *buffer, int length)
{
int i;
long tmp;
ResetCRC();
for (i = 0; i < length-4; i++) {
UpdateCRC(*buffer++);
}
for (; i < length; i++) {
UpdateCRC((*buffer++) ^ 0x0ff);
}
return crcSum;
}
12
/* crctable.h eej 2/16/95
*
* table for computation of CRC on a byte basis */
13
0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4};
REFERENCES
1. T.R.N. Rao and E. Fujiwara, Error-Control Coding for Computer Systems, Prentice-
Hall, 1989.
2. D.V. Sarwate, “Computation of Cyclic Redundancy Checks via Table Look-Up,”
Communications of the ACM 31 (8), August 1988, pp. 1008-1013.
3. American National Standard X3.66-1979, Advanced Data Communication Control
Procedures.
4. MIL-STD-188-141A, Notice 2, Interoperability and Performance Standards for
Medium and High-Frequency Radio Equipment.
5. FED-STD-1045A, Telecommunications: HF Radio Automatic Link Establishment.
6. FED-STD-1052, Appendix B, HF Data Link Protocol.
14