Komodo Industries, Inc

                 Home     About Us     Products     Research     Contact Us     News     Tutorials     Applications     Industries


 

Salamander

Komodo IP

Starfish SOC

KRL

 

Press

Design Services

 

                                                                                                                                                           

Reed-Solomon codes

Despite revolutionary developments in capacity-approaching codes in recent years, Reed-Solomon (RS) codes remain very relevant today, especially for high rate systems with relatively small data packets. RS codes are straightforward to decode and have excellent burst correction capability. But in addition to their practical value in facilitating reliable communication over noisy channels, Reed-Solomon codes are also beautiful and elegant and almost endlessly fascinating in their own right. We will only provide a brief introduction on this page, and the reader is strongly encouraged to seek out more information, for instance here, here, here, and here.

Before we describe the codes themselves we will need to touch on some background material. A full understanding of RS codes, however, requires a certain level of mathematical maturity that is not possible to provide in a short monograph.

Linear Block Codes

Reed-Solomon codes are linear block codes. A block code is a way of mapping some number k of symbols to another number n of symbols with n > k. We will call the block of k symbols a messageword, and the block of n symbols a codeword. The process of mapping k message symbols to n code symbols is called encoding, and the reverse process is called decoding. This mapping can be systematic, wherein the block of n codeword symbols consists of the k messageword symbols plus (n-k) added redundant symbols, or non-systematic, where the messageword symbols cannot be directly recovered from the codeword without decoding. Generally, any linear block code can be represented as an "equivalent" systematic code. A block code is called "linear" if the sum of two codewords is always a valid codeword, and a scalar multiple of any codeword is also a valid codeword.

Codeword Symbols

So coding generally maps k symbols to n symbols, but what do we mean by symbols? A binary code uses two values, for example the binary numbers {0,1}, as symbols. In general, though, a code uses q-ary symbols. Q-ary symbols, as the name suggests, use symbols taken from an alphabet A of q possible values. So, for example, 3-ary symbols would be symbols chosen from a set of three elements, such as {0, 1, 2}. Practical RS codes use q = 256, which, it turns out, can be rather conveniently represented using 8-bit symbols called bytes, familiar to computer users. So a Reed-Solomon code of length n = 255 consists of 255 8-bit symbols per codeword, or 2040 binary bits.

Fields

The 8-bit symbols used in practical RS codes are manipulated in the encoding process not as ordinary binary numbers, but as elements of a mathematical structure called a Finite Field, or Galois Field, in honor of their inventor, the brilliant French mathematician Evariste Galois. Without getting too caught up in the details, a field is a set of elements that can be added, subtracted, multiplied, and divided, with the important stipulation that the result of any of those operations is always still an element of the field. Additionally, we require that additive and multiplicative inverses and identity elements exist for each (non-zero) element of the field, and that the field elements obey the familiar commutative, associative, and distributive properties. The real numbers are a familiar example of a field: we can add, subtract, multiply and divide any two (non-zero) real numbers, and the result is always another real number. Multiplicative and additive inverses can be found for any real number; the multiplicative identity element is '1', the additive identity element is '0'. The real numbers are an infinite field. We can construct a field with a finite number of elements, if we follow certain rules for constructing such fields.

Finite Fields, or Galois Fields

Let's choose, for example, the field with 5 elements, and call the elements {0, 1, 2, 3, 4}. We will denote this field GF(5), or the Galois field with 5 elements. Note that though the elements of our finite field with 5 elements look like the ordinary integers, they are not; this is simply a convenient notation. The most important rule is that adding subtracting, multiplying and dividing any two elements of the field always results in another element of the field (i.e. the operation is "closed"). So what happens when we add, say, 3 and 4? Clearly the result can't be 7, because the only elements in our field are {0, 1, 2, 3, 4}. One possible and intuitive solution is to use modular arithmetic, that is, to do operations in the finite field with 5 elements using mod 5 arithmetic. One way to illustrate this is using the division algorithm. The division algorithm is a way of representing a number (the dividend) as a multiple of another number (the divisor), plus some remainder. In our example, we divide 3 + 4 = 7 by 5, and take the remainder: 7 = 5 x 1 + 2. The remainder (or "residue") is always less than 5, and therefore is in our set {0, 1, 2, 3, 4}. So, using mod 5 arithmetic, on our finite field, 3 + 4 = 2. We won't sweat the details here, but suffice it to say that this method always works, and our set of five elements is, in fact, a field if we conduct all our operations using mod 5 arithmetic. In fact, this construction method works for all finite fields with a prime number of elements. So, for example, we could construct a finite field with 23 elements {0, 1, 2, ..., 22} using modulo 23 arithmetic. We can also construct finite fields with a power of a prime number of elements (i.e. fields with order -- that is, number of elements -- pm, for any prime p) using polynomial arithmetic modulo an irreducible polynomial. This is, in fact, the type of finite field used in practical RS codes, namely, fields with 28 = 256 elements. These fields can be constructed using an irreducible polynomial (whose coefficients are taken from GF(2), i.e. are binary numbers) of degree 8. An irreducible polynomial is to polynomial arithmetic what a prime number is to integer arithmetic, it can't be factored evenly into the product of two smaller polynomials, just as a prime number, by definition, can't be factored into the product of two integers.

Polynomials

We can construct RS codes using linear algebra alone, but for practical reasons it is customary to add an additional structural constraint to our RS codes. We will map our k message symbols to a polynomial of degree k - 1, and call the result the message polynomial m(x) = mk-1xk-1 + mk-2xk-2 + ... + m1x + m0. The n codeword symbols can be mapped to a codeword polynomial of degree n - 1. c(x) = cn-1xn-1 + cn-2xn-2 + ... + c1x + c0.

Cyclic codes

In addition to being linear block codes, RS codes are cyclic codes. In simple terms, a code is cyclic if, for every codeword of the form {c0, c1, ..., cn-1}, {cn-1, c0, c1, ..., cn-2} is also a codeword. That is, all circular shifts of any codeword in the code are also codewords in the code. In polynomial terms, if c(x) is a codeword, then x ∙ c(x) mod (xn - 1) is also a codeword. In fact, it's easy to show that multiplication of a cyclic codeword by xm results in a (right) circular shift of the codeword m places. Since RS codes are also linear, we know that the sum of two codewords is always a codeword, and multiplication of a codeword by a scalar always results in a codeword, we can write expressions like: an-1xn-1c(x) + an-2xn-2c(x) + ... + a0c(x) with the result always guaranteed to be a codeword of the code if the code is a linear cyclic code. This leads to the remarkable result that multiplying any codeword c(x) by any polynomial a(x) (reducing the result modulo xn -1) results in a valid codeword. In fact, we won't prove it here, but for any cyclic code there exists exactly one irreducible polynomial of least degree, called the generator polynomial of the code. The code then consists of all polynomial multiples of the generator polynomial (i.e. the generator polynomial can be used to "generate" the code). This fact is crucial to the efficient construction of RS codes, because polynomial multiplication is relatively easy to implement in hardware. Note that all our polynomial coefficients are Galois field elements as defined above, and hence all our arithmetic operations must be done using Galois field arithmetic. Also note that straightforward multiplication of a message m(x) by a generator polynomial to create a codeword, i.e. c(x) = m(x) g(x), results in a non-systematic codeword. Most practical RS codeword schemes use a systematic form, so it is customary to create a codeword by multiplying the message by xn-k (which is equivalent to shifting the message to the n-k highest coefficients in the codeword polynomial), dividing the result by g(x) and adding to make the systematic codeword. c(x) = xn-km(x) + Rg(x)[xn-km(x)], where Rg(x)[∙] denotes the remainder that results from dividing by g(x).

Defining Reed-Solomon codes

So, now that we've provided some rudimentary background, it's time to define Reed-Solomon codes themselves. There are two common definitions of Reed-Solomon codes: as polynomial codes over finite fields (construction 1), and as cyclic codes of length q-1 over GF(q) (construction 2). Other definitions are possible, for example those involving orthogonal arrays, or the frequency domain construction, or as a projective geometry over GF(q), but, in the interest of brevity, we will concern ourselves with the two popular constructions outlined above. We will maintain that these two definitions are not strictly equivalent, though in the case of cyclic code constructions of length n = q - 1 it is possible to show the equivalence of the two constructions.

Polynomial Codes over Certain Finite Fields (construction I)

This is the original definition used by Irving S. Reed and Gustave Solomon in their landmark 1960 paper "Polynomial codes over certain finite fields" published in the Journal of the Society for Industrial and Applied Mathematics. The idea is this: given the message m(x) in the form of a polynomial, as outlined above, whose k coefficients are taken from the finite field GF(q), simply evaluate the polynomial at n distinct elements of the finite field, to obtain the n coefficients of the codeword. In other words, if we denote n distinct elements of the field a0, a1, a2, ..., an-1, then:

(c0, c1, c2, ..., cn-1) = m(a0), m(a1), m(a2), ..., m(an-1)

Although this construction is certainly straightforward, it is generally not used in practice, due to the lack of efficient methods for encoding and decoding. Also note that this construction is not systematic, and that it yields codes of length q if used over all the elements of the field GF(q), though often the evaluation of the message at zero, m(0), is omitted, giving a code of length n = q - 1.

A generalization of the above construction leads to the definition of Generalized Reed-Solomon (GRS) codes: let a0, a1, ..., an-1 be n distinct elements of GF(q), and let v0, v1, ..., vn-1 be n non-zero (but not necessarily distinct) elements of GF(q), then the GRSk(a, v) code consists of all vectors

(c0, c1, c2, ..., cn-1) = v0m(a0), v1m(a1), v2m(a2), ..., vn-1m(an-1).

It should be clear that if the message has k symbols, and the length of the code = n = q - 1, then the code consists of n equations in k unknowns, which is overspecified when n > k. For instance, when n = 255, and k = 239, then there will be 255 equations, but only 239 unknown message coefficients, hence the correct coefficients can be recovered even if some of them are corrupted, giving the code its error correcting capability. We won't go into exactly how that is done, but the general idea is to use polynomial interpolation to derive a bivariate polynomial whose roots are the coefficients of the message polynomial.

Generator polynomial approach (construction II)

Recall, from our discussion above, that a cyclic code can be completely specified as all polynomial multiples of a generator polynomial. Then given the message m(x) in the form of a polynomial, as outlined above, whose k coefficients are taken from the finite field with q elements, we can construct RS codewords c(x) = m(x) g(x) (or the equivalent systematic construction). All we need to do is specify the generator polynomial of the code. We'll need a few additional definitions first:

Powers of a field element

We form the powers of an element of a Galois field in the usual way, namely a0 = 1, a1 = a, a2 = a∙a, a3 = a∙a∙a, etc.

Primitive element

In any Galois field there exists one or more primitive elements. A primitive element is defined as follows: Take any element of the field, and take successive powers of the element, like so: a0 = 1, a, a2, a3, ... This gives a sequence of distinct field elements. The elements have to repeat eventually, however, because there are only q distinct elements in the finite field GF(q). It can easily be proven that the first field element to repeat is, in fact, always 1. The smallest power x of a given field element α, such that αx = 1, is called the order of α. If the order of a field element is q - 1, then the field element is called a primitive element of the field. A primitive field element α can be used to "generate" all the elements of the field by taking successive powers of α.

The general form of the generator polynomial of a RS code is defined in such a way as to have as its roots 2t consecutive powers of a primitive element α. Thus we can write,

g(x) = (x - αb)(x - αb+1)(x - αb+2)...(x - αb+2t-1)

For convenience, the constant b is often chosen to be 0 or 1. Given the generator polynomial, RS codewords can now be constructed as c(x) = m(x) g(x), or as c(x) = xn-km(x) + Rg(x)[xn-km(x)]. This is the method used most often in practice.

 

How RS codes work

Now that we've covered the construction of RS codes, let's look at how they work. The idea behind error correction coding is to start with a "message" (i.e. the thing you want to encode) of length k, and convert it to a "codeword" of longer length n, in such a way that the additional information in the coded form allows one to recover the original message if parts of it are corrupted. To see how this works, we'll need some additional definitions:

Hamming weight

The Hamming weight of a codeword is simply the number of non-zero symbols in the codeword. So, for example, if you had the following binary codeword: 1001010001, its weight would be 4. This works the same way regardless of the field the symbols come from. If you had the following codeword with symbols from the field GF(5): 30104102, its weight would be 5.

Hamming distance

The Hamming distance between two codewords in a code is the number of places in which the codewords differ. So, for example, given the following two binary codewords: 100011 and 110000, the Hamming distance between them would be 3.

Minimum distance of a code

The minimum distance of a code is the minimum distance between all the codewords in the code. In other words, take the distance between each codeword in the code and every other codeword in the code, and the smallest distance obtained over all the comparisons is the minimum distance of the code. Fortunately, for linear codes, there is a much easier way to find the minimum distance. For linear codes, the minimum distance of a code is the weight of the lowest weight codeword in the code.

The minimum distance of a code is by far the most important property of the code in determining the error correcting capability of the code. To see why this is, we need to look more closely at the decoding process. Consider a simple binary repetition code of length 4. A repetition code of length n, as the name suggests, is a code where each codeword consists of n repetitions of a single symbol. So there are two codewords in the binary repetition code of length 4: (0000) and (1111). Clearly, the minimum distance of this code is 4. Now suppose we send the message (1) as the codeword (1111) across our communications channel. Clearly, if the first bit gets corrupted in transmission, then we will receive the codeword as (0111). In this case the (Hamming) distance between our received word and (1111) is 1, and the distance between our received word and (0000) is 3. So a reasonable decoding scheme would be that if the received word is not (1111) or (0000), then choose as the decoded word the word that is closest in Hamming distance to the received word. This is called nearest neighbor decoding, and in our example clearly (0111) would be corrected to (1111). Now consider the case where two bits are corrupted in transmission. We send (1111), and the word received is (1010). Now we can't recover the sent word, because the distance to both (1111) and (0000) is 2. This is known as decoder failure. The decoder knows it has received a corrupted codeword, but it isn't capable of correcting it. Now consider that we sent (1111) and three bits are corrupted in transmission and we receive (0001). In this case we will incorrectly decode this word as (0000). This situation is known as decoder error.

This type of decoding can be generalized to much larger and more sophisticated codes, but it very quickly becomes impractical to compare a received codeword to all other words in the code, and to choose the codeword that is the smallest distance away from the received word. The important thing to observe, however, is that for any code with a minimum distance d, we can always correct up to [(d - 1)/2] errors, (here we are using square brackets [] to indicate the "floor" function, i.e. take the greatest integer less than or equal to the expression in the brackets).

For an RS code with 2t redundant "check" symbols, the minimum distance cannot exceed 2t + 1 (that is, dmin n - k + 1), because a message can exist with only one non-zero symbol. This is referred to as the Singleton bound. Using construction I, we can see that m(x), being of degree at most k - 1, cannot have more than k - 1 zeros. Thus c(x) can't have more than k - 1 zero positions (for a non-zero codeword). This means that dmin n - (k - 1). Hence (since dmin n - k + 1 and dmin n - (k - 1)), for RS codes, dmin = n - k + 1 = 2t + 1. Codes that have this distance property are called Maximum Distance Separable (MDS) codes.

So an RS code with 2t check symbols can correct up to [(2t + 1 - 1)/2] = t errors.

The foregoing is true for all codes. So what makes RS codes so special? First, RS codes are MDS, which has been proven to be the best minimum distance obtainable. Recall that minimum distance is the most important property of an error correction code. Secondly, because of their structure (they are linear, cyclic, and their generator polynomial has well defined roots), RS codes are easy to encode and relatively easy to decode.

 

References

1. Wicker, Bhargava, eds., "Reed-Solomon Codes And Their Applications", IEEE Press 1994

2. Wicker, "Error Control Systems for Digital Communications and Storage", Prentice-Hall 1995

3. Lin and Costello, "Error Control Coding: Fundamentals and Applications", Prentice-Hall 1983

4. Clark and Cain, "Error Correction Coding for Digital Communications", Plenum 1988

 

 

 
Reed-Solomon, Viterbi, and Turbo Codes. Salamander Error Correction specializes in the design and marketing of Verilog IP modules for Forward Error Correction.
(c) 2007 Komodo Industries, Inc. All rights reserved.

Komodo Industries, Inc

3364 Via Alicante

La Jolla, CA 92037

(858) 373-2112

Fax: (858) 373-1224

sales@komodo-industries.com

www.komodo-industries.com