Forward Error Correction Coding BCH encoding/decoding Dr. M.A. Belkerdid Spring 2008 TABLE OF CONTENTS Section Title Page 1.0 ABSTRACT ........................................................................................................................ 1 2.0 FECC ................................................................................................................................... 1 2.1 Linear Block Codes ................................................................................................. 2 2.2 Convolutional Codes ............................................................................................... 2 2.3 Coding Gain ............................................................................................................. 3 3.0 GALOIS FIELDS ............................................................................................................... 5 4.0 INTRODUCTION TO BCH ENCODING/DECODING .................................................. 10 5.0 BCH ENCODING ............................................................................................................. 10 5.1 Galois field elements ............................................................................................. 12 5.2 (7,4) BCH Encoder ................................................................................................ 15 5.3 BCH codes in GF(24) ............................................................................................. 17 6.0 BCH DECODER ............................................................................................................... 18 6.1 Syndrome calculator .............................................................................................. 19 6.2 Berlkamp/Peterson Algorithm ............................................................................... 21 6.3 Chien Search Algorithm ........................................................................................ 24 7.0 APPENDIX A. C CODE .................................................................................................. 26 8.0 APPENDIX B C PROGRAM OUTPUT.......................................................................... 36 i LIST OF FIGURES Figure Title Page Figure 1. Digital Communication system ................................................................................................ 1 Figure 2. K=7, R=1/2 convolutional encoder .......................................................................................... 2 Figure 3. BER for BPSK with and without FEC ..................................................................................... 3 Figure 4. Modulation efficiency improvement with FECC ..................................................................... 4 Figure 5. Primitive polynomial circuit architecture ................................................................................. 7 Figure 6. Polynomial division circuit ...................................................................................................... 7 Figure 7. 10th order primitive polynomial implementation ..................................................................... 9 Figure 8. 10th order primitive polynomial high speed implementation .................................................. 9 Figure 9. (7,4,1) BCH Encoder .............................................................................................................. 15 Figure 10. BCH Decoder Architecture .................................................................................................. 18 Figure 11. Syndrome Calculator for (7,4) BCH decoder ....................................................................... 20 ii LIST OF TABLES Table Title Page Table 1. Table of Primitive polynomial ................................................................................................... 6 Table 2. primitive polynomials .............................................................................................................. 11 Table 3. BCH Code Table ...................................................................................................................... 12 Table 4. Elements of GF(23) .................................................................................................................. 13 Table 5. (7,4) BCH encoded codewords ................................................................................................ 16 Table 6. elements of GF(24).................................................................................................................... 17 iii 1.0 ABSTRACT This document presents the theory and C code implementation of Bose-Chaudhuri-Hocquenghem (BCH) codes. Galois Field theory is used extensively to simplify the understanding, design, and code implementation of BCH codes. A C program is written to implement all the possible codes ranging from GF(23) to GF(220). The main programs contains five (5) functions, read-p(), generate_gf(), genpoly(), encode_bch(), and decod_bch(). The read-p() function is used in the encoder to read in the user define choice of BCH code. The generate_gf() function calculates the Galois Field elements of the user chosen BCH code. The gen-poly() function calculates the polynomial generator of the user chosen BCH code. The encode_bch() function calculates the redundant parity bits and appends them to the input data bits to form the systematic codewords. The decod_bch() function includes the syndrome calculator, the Berlkamp-Peterson algorithm, and a Chien search algorithm. The program generates random data bits with different seeds and also allows the user to insert errors. A brief introduction to Forward Error Correction coding (FECC), coding gain and Galois Field arithmetic is first presented. 2.0 FECC A digital communication system is depicted in Figure 1. Data is generated at a constant source symbol rate Rs source symbols per second. The source output is encoded by a source encoder such as ASCII code or Hoffman code. The output of the source encoder is fed to the channel encoder for forward error correction coding. A linear block code such as Bose-Hockengham-Chadhuri (BCH), or Reed Solomon (RS), or a convolutional encoder is normally used before the data is sent to the modulator, and out to the antenna. The receiver performs the reverse of the transmitter. Figure 1. Digital Communication system 1 The purpose of FECC is to reduce Pe for a given Eb/N0 . How: By introducing coding gain. Mechanism: Redundancy Cost: Slows down throughput and cost of Hardware/Software 2.1 Linear Block Codes In linear block codes, also referred to as algebraic coeds, data is blocked into k-bit blocks and r parity bits are appended or post-pended the k-bits to form an k-bit block (n=k+r). 2.2 Convolutional Codes The output bit stream of a convolutional encoder is generated by a digital convolution process where as the present input bit will influence a number of encoded bits. The continuous convolution integral of the bit stream with certain primitive polynomials is given by t x(t ) g ( )m(t )d L is rewritten in the discrete domain as x j g i m j i i 0 . The xj output bits depend on the current bit and on the previous L+1 bits. K = L+1 is called the constraint length. L is the number of shift registers need to implement the convolutional encoder. There are only a handful of convolutional encoders. The most popular coeds are K=7, rate=1/2, K=9, rate ½, and rate ¾. Figure 2 depicts the most widely used code K=7, rate=1/2. The Viterbi Algorithm is used as the decoder of choice. g1 ( x) x 6 + x 4 + x 3 + x + 1 + Input 6 5 4 3 1 2 0 Output + g 2 ( x) x 6 + x 5 + x 4 + x 3 + 1 Figure 2. K=7, R=1/2 convolutional encoder 2 2.3 Coding Gain The bit error rate for un-encoded BPSK, BPSK with (7,3) BCH encoder/decoder, and a BPSK with K=7, R=1/2 Convolutional encoder/Viterbi decoder is depicted in Figure 1. Figure 2 depicts the improvement in modulation efficiency in Shannon’s plane. Figure 3. BER for BPSK with and without FEC 3 Figure 4. Modulation efficiency improvement with FECC 4 3.0 GALOIS FIELDS Polynomial algebra and addition modulo 2 with no carry are used with the following basic operations: 1 +1 =0 1.1 = 1 1.0 = 0 A sequence of bits at a constant bit rate can be represented by a polynomial given by: P(x) = C0x0 + C1x1 + C2x2 + C3x3 + C4x4 + C5x5 +….+ Cnxn Where Cn is either 1 or o, and the power of x is the bit position (delay, shift register operation), C0 is the first bit in the bit stream, while Cn is the last bit in the bit stream, and + is addition modulo 2 with no carry (exclusive OR operation). Of course, x0 =1. For example, the bit stream: 1011101101 Is represented by the polynomial given by: P(x) = 1 + x2 + x3 + x4 + x6 + x7 + x9 Pseudo-Random or Pseudo-Noise (PN) sequences can be represented by polynomials. Polynomials are generated by delay elements (shift registers, Exclusive Or gates, and Tap feedback paths (Cn). If these sequences are generated by PRIMITIVE POLYNOMIALs, then these sequences are periodic and offer great properties such as very good autocorrelation properties, similar to the properties exhibited by non-periodic BARKER or WILLARD sequences. If 2 PN sequences represented by 2 polynomials of the same order, a ere modulo 2 added together may form another class of codes called GOLD codes. Gold codes are special PN sequences with extremely good cross correlation property. Gold codes are used as the spreading waveform for the GPS CDMA system. Let’s get back to the PN sequences generated by a primitive polynomial. These sequences are referred to as maximal length sequences (maximum period). A polynomial p(x) of degree m is primitive if and only if the smallest integer n for which p(x) divides xn +1 is given by: n = 2m - 1 Example, find a primitive polynomial of order 3: m=3, then n = 23 – 1= 7 We need to factor: (x7 +1) = (x+1)p(x)q(x) with p(x) being a polynomial of degree 3. Long division is performed to find the factors of ( x7 +1). 5 x 6 + x5 + x 4 + x 3 + x 2 + x + 1 x+ 1 | x7 + 1 x 7 + x6 x6 + 1 x 6 + x5 ….. ‘’’’’ x1 + 1 x1 + 1 0 (x7 +1) =(x +1)( x6 + x5 + x4 + x3 + x2 + x + 1) Now factor out (x6 + x5 + x4 + x3 + x2 + x + 1) : (x6 + x5 + x4 + x3 + x2 + x + 1) = (x3 + x + 1) (x3 + x2 + 1) (x7 +1) =(x +1) (x3 + x + 1) (x3 + x2 + 1) There are 2 primitive polynomials of order 3. Either polynomial will generate a maximum length sequence of bits that are periodic with a period of 7. These 2 polynomials will generate a sequence of 7 bits that exhibit good randomness characteristics. The period is maxed out at 7 bits. Let’s go to fourth order primitive polynomials (PN sequences that repeat every 15 bits): m=4, then n = 24 – 1= 15 4 10 (x15 +1) =(x +1) (x + x + 1) (x + … + 1) m Primitive Polynomial Period 3 P3(x) = 1 + x + x3 7 4 P4(x) = 1 + x + x4 15 5 P5(x) = 1 + x2 + x5 31 6 P6(x) = 1 + x + x6 63 7 P7(x) = 1 + x3 + x7 127 8 P8(x) = 1 + x2 + x3 + x4 + x8 255 9 P9(x) = 1 + x4 + x9 511 Table 1. Table of Primitive polynomial 6 A maximal sequence can be generated by shift registers (the number of shift registers is equal to the degree of the primitive polynomial), exclusive OR gate and feed back paths governed by Cn, the coefficients of the primitive polynomial. For example, a PN sequence with a period of 7 bits (chips), with a primitive polynomial of order 10 given by: P(x)= x3 + x + 1 is generated by Figure 5. Primitive polynomial circuit architecture The above circuit performs polynomial division of b(x) = m(x) / g(x) as shown below: Let m(x) = 1 (loading the first register with a 1 initial condition), the output b(x) is given by: b(x) = m(x) / g(x) = 1/g(x) = 1/(1 + x+ x3) Figure 6. Polynomial division circuit The output is easily obtained using long division as follows: 7 The output is 3 1 +x+ x 1 + x + x2 + x3 + x6 + x7 + x8 + x10 + x13 + x14 + x15 + x17 + x20 + x21 | 1 1 +x+ x3 x + x3 x+ x2 +x3 x2 x2 + x3 + x4 x3 + x4 x3 + x4 + x6 x6 x6 + x7 + x9 x7 + x9 x7 + x8 + x10 x8 + x9 + x10 x8 + x9 + x11 x10 + x11 x10 + x11 + x13 x13 x13 + x14 + x16 x14 + x16 x14 + x15 + x17 x15 + x16 + x17 x15 + x16 + x18 x17 + x18 x17 + x18 + x20 x20 x20 + x21 + x23 x21 + x23 + b(x) = 1 + x + x2 + x3 + x6 + x7 + x8 + x10 + x13 + x14 + x15 + x17 + x20 + x21 +….. The output is then: bk = 111 1001110 1001110 1001110 ….. After the 3 bit initial conditions, the code repeats every 7 chips. 8 .. If m(x)= 1 + x3 (101), then b(x) = m(x) / g(x) = (1 + x3 )/g(x), and after the long division operation: bk = 111 1010011 1010011 1010011 ….. Note that the PN sequence is the same after the first 3 initial condition chips. Different initial conditions just shifts the PN sequence. Another example of a PN sequence with a period of 1023 bits (chips), with a primitive polynomial of order 10 given by: P(x) = 1 + x2 + x3 + x6 + x8 + x9 + x10 is generated by the following circuit: Figure 7. 10th order primitive polynomial implementation Figure 8. 10th order primitive polynomial high speed implementation 9 4.0 INTRODUCTION TO BCH ENCODING/DECODING A BCH encoder is based on Galois Field theory and its implementation is rather simple. A BCH decoder requires a syndrome calculator, an error location polynomial coefficients finder (x) (Berlkemp/Massey algorithm), and a root finder for the error location polynomial (x) (Chien Search algorithm). 5.0 BCH ENCODING BCH codes are denoted by (n, k), where n is encoded block length and k is the input data block length. BCH codes have the following parameters: Block Length n=2m – 1 Number of correctable errors t Number of parity check bits n-k <= mt The primitive element of the Galois Field of 2m elements, denoted by GF(2m ), is defined as . A sequence of powers of , given by 2tis used to generate minimal polynomials. The minimal polynomial of i is defined as mi(x), and the polynomial generator, g(x), for a t error correcting BCH code is the least common multiple of m1(x), m2(x), … m2t(x), and is given by: g(x) = LCM{ m1(x), m2(x), … m2t(x) }. It is clear that 2t are roots of g(x), i.e. g(i ) = 0 for i= 0, 1, 2,...2t. Furthermore if i is an even integer, then i = 2l i’, where i’ is an odd integer, and l >= 1. This then implies that i and I’ , have the same minimal polynomial, m1(x)= m1’(x) and hence: g(x) = LCM{ m1(x), m3(x), … m2t -1(x) }. The minimal polynomials are not only necessary to generate the BCH polynomial generator for a given code, but are instrumental for the syndrome calculations in the BCH decoder architecture. The BCH code generator polynomials are generated in the following manner: a) Select a primitive polynomial of degree m, and generate the elements of GF(2m) b) Determine mi(x) for i= 0, 1, 2,...2t minimum polynomials 10 c) Get g(x) = LCM{ m1(x), m3(x), … m2t -1(x) } d) The degree of g(x) is n-k. The primitive polynomials for the GF ranging from 8 to 512 elements are listed in the table below. These mth order primitive polynomial will generate (7, k) to (511, k) BCH codes. m Primitive Polynomial 3 P3(x) = 1 + x + x3 4 P4(x) = 1 + x + x4 5 P5(x) = 1 + x2 + x5 6 P6(x) = 1 + x + x6 7 P7(x) = 1 + x3 + x7 8 P8(x) = 1 + x2 + x3 + x4 + x8 9 P9(x) = 1 + x4 + x9 Table 2. primitive polynomials All the possible (n,k,t) BCH codes from n=7 to n 511 are tabulated in table 2 below. 11 n k t n k t n k t 7 15 4 11 7 5 26 21 16 11 6 57 51 45 39 36 30 24 18 16 10 7 120 113 106 99 92 85 78 71 64 57 50 43 36 29 22 15 8 247 239 231 223 215 207 1 1 2 3 1 2 3 5 7 1 2 3 4 5 6 7 10 11 13 15 1 2 3 4 5 6 7 9 10 11 13 14 15 21 23 27 31 1 2 3 4 5 6 255 199 191 187 179 171 163 155 147 139 131 123 115 107 99 91 87 79 71 63 55 47 45 37 29 21 13 9 502 493 484 475 466 457 448 439 430 421 412 403 394 385 376 367 7 8 9 10 11 12 13 14 15 18 19 21 22 23 25 26 27 29 30 31 42 43 45 47 55 59 63 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 511 358 349 340 331 322 313 304 295 286 277 268 259 250 241 238 229 220 211 202 193 184 175 166 157 148 139 130 121 112 103 94 85 76 67 58 49 40 31 28 19 10 18 19 20 21 22 23 25 26 27 28 29 30 31 36 37 38 39 41 42 43 45 46 47 51 53 54 55 58 59 61 62 63 85 87 91 93 95 109 111 119 121 31 63 127 255 511 Table 3. BCH Code Table 5.1 Galois field elements Galois field arithmetic is used to derive all the Galois field elements necessary for each BCH code. Lets use GF(23) as in example to present the properties of Field theory. The primitive polynomial is then: P3(x) = 1 + x + x3 There are 8 field elements including 0. The rest of the elements are powers of . These elements along with their conjugates, 3-tuples, and minimal polynomials are tabulated in Table 3 below. 12 Elements Conjugates 3-tuples 0 0 = 1 Minimal polynomial 0 000 20 = 1 001 1 = 24 21 = 2 010 m1 ( x ) 1 + x + x 2 2 = 2 48 = 2 6 = 22 = 4 100 m1 ( x ) 1 + x + x 2 3 = 1+ 6, 12 = (001+010) 011 m3 ( x ) 1 + x 2 + x 3 4 = +2 8 = , 16 = (010+100) 110 m1 ( x ) 1 + x + x 2 5 = 1++2 10 = , 20 = (001+110) 111 m3 ( x ) 1 + x 2 + x 3 6 = 1+2 12 = , 24 = (001+100) 101 m3 ( x ) 1 + x 2 + x 3 Table 4. Elements of GF(23) Galois Field arithmetic is used to generate the entries of Table 3 above. In GF theory, multiplication of two elements of the Galois Field is achieved by adding their exponents, for example in GF(2 3) 5 2 = 7 = 1, and 6 5 =7 4 = 4. Division is done similarly, 3/6 = 10/6 = 4. To add two elements of the Galois Field, the other forms in the table are used in each case, hence 5+3=(1++2)+(1+)=1++2+1+=2; of course addition is modulo-2 with no carry (exclusive Or-Gating). Another operation needed for BCH decoding, is the root finding technique, or solving equations in the Galois Field. This is illustrated in the example below. f(x)=x2+(1+)x+1=0 In order to solve for x, the ordinary quadratic formula normally used will not work because division by 2 (which is equal to division by 0 in the GF) is not possible. The solution of the above equation, if it exists, can be obtained by substituting all the elements of the GF given in the above table. f (0) 0 f (1) 0 f ( ) 0 f(2)=(2)2+(1+)2+1=4+2+3+1=+2+2+1++1=0 f ( 3 ) 0 13 f ( 4 ) 0 f(5)=(5)2+(1+)5+1=10+5+6+1=3+1++2+1+2+1=0 f ( 6 ) 0 And hence f(x)=(x+2)(x+5), and 2 and 5 are the roots of f(x). Root finding in the GF is a must operation in BCH, and RS decoders. It is also worth noting that f2(x)=f(x2) and for any positive integer l, [f(x)]2l=f(x2l). If is an arbitrary element of the GF. The polynomial m(x) with the smallest degree in x(degree m or less), and is its root, i.e., m()=0, is called the minimum polynomial of element . The minimal polynomials of all the elements of the GF (23) are obtained as follows: 1. Let =, then the following sequence is formed: =, 2=2, (2)2=4, (2)3=8=, (2)4=16=2, …… It is seen that repetition starts at (2)3. Hence the roots of the minimal polynomial of are given by: , 2, 4 and hence the minimal polynomial is given by m1(x)=(x+)(x+2)(x+4)=(x2+2x+x+3)(x+4)=x3+[2++4]x2+[3+6+5]x+1=x3+x+1 2. Let =3 then the following sequence is formed: =3, 2=6, (2)2=12=5, (2)3=24=3…… It is also seen that repetition starts at (2)3. Hence the roots of the minimal polynomial of 3 are given by: 3, 5, 6 And hence the minimal polynomial is given by m3(x)=(x+3)(x+5)(x+6)=x3+x2+1 From the above derivations the following is noted: m1(x)=m2(x)=m4(x) m3(x)=m5(x)=m6(x) 14 5.2 (7,4) BCH Encoder In GF(23), there is only one possible BCH code, it is (7,4) with t=1, and its code polynomial generator g(x) is given by: g(x) = LCM{ m1(x), … m2t -1(x) }=LCM{ m1(x) } g(x)= x3+x+1 The circuit consists of a shift register-Exclusive OR circuit with taps governed by g(x) in order to generate the third order parity polynomial by diving the k bit polynomial by g(x), then appending the parity bits to the end of the m bits. This is shown in Figure 9 below. The k bits proceed to the output and to the input of the parity generator circuit. After 4 shifts the switch 1 is moved to position B, and Switch 2 is opened, and the computed parity bits are sent to the output. The circuit is then ready for the next input block. Figure 9. (7,4,1) BCH Encoder The 15 4-bit data blocks and their respective 15 7-bit BCH encoded blocks for the above single bit error correcting (7,4) BCH encoder are given in Tabl2 4. 15 m(x) C(x) m0 m1 m2 m3 c0 c1 c2 c3 c4 c5 c6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 1 1 0 0 0 1 1 0 0 1 1 1 0 1 0 1 0 0 0 1 0 0 1 1 1 0 1 0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 1 0 0 0 1 0 1 1 1 0 1 1 1 0 1 0 1 0 0 0 1 0 0 0 1 0 1 1 0 0 1 1 0 0 1 1 1 0 1 0 1 0 1 0 1 0 0 1 1 1 0 1 1 1 0 1 1 0 0 0 1 1 0 0 1 1 0 0 0 1 0 1 1 0 1 1 1 0 1 0 0 1 1 1 1 0 1 1 1 0 1 0 0 1 1 1 1 1 1 1 1 1 1 1 Table 5. (7,4) BCH encoded codewords 16 5.3 BCH codes in GF(24) The possible BCH codes in GF(24) are (15,11) t=1, (15,7) t=2, (15,5) t=3 For example, the elements of (GF24), generated by a primitive polynomial given by: P4(x) = 1 + x + x4 There are 16 field elements including 0. The rest of the elements are powers of . These elements along with their conjugate, 4-tuples, and minimal polynomials are tabulated in Table 4 below. Elements Conjugates 0 0 = 1 3-tuples Minimal polynomial 0 0000 20 = 1 0001 1 = 24 8 21 = 2 0010 m1 ( x ) 1 + x + x 4 2 48, 22 = 4 0100 m1 ( x ) 1 + x + x 4 3 6, 12 , 23 = 8 1000 m3 ( x ) 1 + x + x 2 + x 3 + x 4 4 = 1+ 8 , , 0011 m1 ( x ) 1 + x + x 4 5 = +2 10 0110 m5 ( x ) 1 + x + x 2 6 = 2+3 12 , 9 , 1100 m3 ( x ) 1 + x + x 2 + x 3 + x 4 7 = 1++3 14 ,, 1011 m7 ( x ) 1 + x 3 + x 4 8 = 1+2 , , 0101 m1 ( x ) 1 + x + x 4 9 = +3 3 , , 1010 m3 ( x ) 1 + x + x 2 + x 3 + x 4 10 = 1++2 0111 m5 ( x ) 1 + x + x 2 11 = +2+3 7, , 1110 m7 ( x ) 1 + x 3 + x 4 12= 1++2+3 , 6 , 1111 m3 ( x ) 1 + x + x 2 + x 3 + x 4 13 = 1++3 7, , 1101 m7 ( x ) 1 + x 3 + x 4 14 = 1+3 7 ,, 1001 m7 ( x ) 1 + x 3 + x 4 Table 6. elements of GF(24) 17 6.0 BCH DECODER There three basic operations involved in the decoding of BCH codes. Syndrome calculation Determination of the error location polynomial (x) Computation of the roots of (x) for the error location determination The syndrome calculator involves polynomial division in GF, the error location polynomial is obtained using the Berlkamp algorithm, ant the root location calculations are done using the Chien search algorithm. The decoding process is depicted below. + Buffer registers Input output Syndrome Calculator Brelkamp Algorithm Chien Search Algorithm Figure 10. BCH Decoder Architecture The decoding process will be described using (15,5,3) BCH example. This triple error correcting code is generated by: g ( x) LMC{m1 (t ), m3 (t ), m5 (t )} m1 (t )m3 (t )m5 (t ) (1 + x + x 4 )(1 + x + x 2 + x 3 + x 4 )(1 + x + x 2 ) 1 + x + x 2 + x 4 + x 5 + x 8 + x10 18 6.1 Syndrome calculator The syndrome Si is the remainder of dividing the received code word with the corresponding minimal polynomial mi. The syndromes are zero if there are no errors in the codes. So if the intent is to detect error only a syndrome calculator is all that is needed in the decoder. The transmitted codeword is obtained by appending the parity check bits to the message data bits. The parity polynomial (parity bits) is the remainder of the division of the message polynomial by the BCH code polynomial generator. The minimal polynomials are factors of the code polynomial generator. If no error occurred then the receiver codeword divided by any of the minimal polynomials will result in zero remainder. The remainder of the division of any received codeword by a minimal polynomial is called the SYNDROME. The number of minimal polynomials (number of syndromes) per code is equal to 2t. Where t is the number of error the code can correct. The syndrome calculator will generate the syndrome polynomial given by: S ( x ) S1 x + S 2 x 2 + S 3 x 3 + S 4 x 4 + S 5 x 5 + .. + S 2t x 2t For the (7,4) BCH encoder above, n=7, k=4, and t=1, hence there are 2t =2 syndromes S1 and S2. This (7,4) BCH code has 2 minimal polynomials m1(t) and m3(t). S1 is the remainder of the division of the received codeword by m1 (x). S2 is the remainder of the division of the received codeword by m2 (x). The syndrome circuit is shown below, and the register contents at the end of each code word are the syndrome coefficient and are passed to the Berlkamp algorithm to start the error correction process if they are not all zero. The Berlkamp algorithm forms the error location polynomial given below and iteratively finds its roots. ( x) 1 + S ( x) 1 + S1x + S2 x2 + S3x3 + S4 x4 + S5 x5 + .. + S2t x2t The Chien search computes the error locations from the roots of the error location polynomial. The example shown in Figure 11 is with a single error in the 3rd bit position. 19 Figure 11. Syndrome Calculator for (7,4) BCH decoder 20 6.2 Berlkamp/Peterson Algorithm The error location polynomial is defined as; ( x) 0 + 1 x + 2 x 2 + ..... + x where t . This polynomial can be rewritten as: ( x) (1 + x 1)(1 + x 2 ) ...(1 + x ) 1 1 The roots of (x) are 1 , 2 ..... 1 and are the inverse of the error location numbers. From the above equations the polynomial coefficients are related to their roots by: 1 i 1+ 2 + ... + i 1 2 i j 1 2 + 1 3 + ... + 2 + 1 i j 3 i j k i j k 1 2 3 + ... + 3 1 + 2 1 n 1 2 3... 2 1 Newton's identities relate these coefficients to the syndromes by: S1 + 1 0 S 2 + 1 S1 + 2 2 0 S 3 + 1 S 2 + 2 S1 + 3 3 0 S + 1 S 1 + 2 S 2 + S1 + S 0 BCH codes are binary codes and hence 21 n j j 0 n odd n even S2 j S j and with t errors 2 Newton’s identities then become S1 + 1 0 S 3 + 1 S 2 + 2 S1 + 3 0 S5 + 1S 4 + 2 S3 + 4 S5 + 5 0 S 2t 1 + 1 S 2t 2 + 2 S 2t 3 + ... + t S t 1 0 This set of equations can be written in matrix form as 1 S 2 S4 S6 . . S 2t 4 S 2t 2 0 0 0 0 0 ... 0 S1 1 0 0 0 ... 0 S3 S5 . S2 S4 . S1 S3 . 1 S2 . 0 S1 . ... ... ... 0 0 . . S 2 t 5 S 2 t 3 . S 2t 6 S 2t 4 . S 2t 7 S 2 t 5 . S 2 t 8 S 2t 6 . S 2 t 9 S 2t 7 ... . ... S t 2 ... S t 0 1 S1 0 2 S 3 0 3 S5 0 4 S7 . . . . . . S t 3 t 1 S 2t 3 S t 1 t S 2t 1 Matrix inversion is computation intensive. Berlkamp developed an iterative approach to solve the system of equations and it has been referred to as the Berlkamp algorithm. Peterson and later Massey further refined the algorithm. Lin, later derived a table driven iterative Berlkamp-Peterson algorithm version. This table approach is based on t steps for Binary BCH decoding. This table is shown below. ----------------------------------------------------------------------------------------- d ( x) T k -----------------------------------------------------------------------------------------0 1 1 1 … … … 2 … … … 3 … … … .. … … … (x) t … … (2k ) (2k ) (2k ) ------------------------------------------------------------------------------------------ 22 The algorithm is to fill out all the rows starting with the row with the index 1. Once the rows are all filled out, (x) corresponding to m=t is the desired error location polynomial. d(2k) is called the discrepancy. The steps for filling out the rows are as fellows: 1. Set S ( x) S1 x + S 2 x 2 + S 3 x 3 + ... + S 2t x 2t 2. Set the initial conditions: k=0, ( 0) ( x) 1 , T ( 0) 1 3. Let d ( 2 k ) be the coefficient of x ( 2 k +1) in the product ( 2 k ) ( x)1 + S ( x) 4. Compute ( 2 k + 2) ( x) ( 2 k ) ( x) + d ( 2 k ) [ x T ( 2 k ) ( x)] xT ( 2 k ) ( x) 5. Compute T ( 2 k + 2) ( x) xT ( 2 k ) ( x) d ( 2k ) 6. Set k=k+1. If k<t go to 3 if d ( 2 k ) 0 or deg[ ( 2 k ) k ] if d ( 2 k ) 0 or deg[ ( 2 k ) k ] 7. Stop. ( x) 2t ( x) Step 3 brings in more and more syndromes as the iterative algorithm progresses. Let’s run the algorithm on a (15, 5) triple error correcting BCH code. Let’s assume that an all zero message (00000) is encoded and transmitted as a 15 zero code word. Let’s assume that 3 errors occurred in the second, seventh, and thirteenth bit positions of the codeword. The received codeword (010000100000100) is represented by r ( x) x + x 6 + x12 The syndromes, S1, S2, S3, S4, S5, and S6, are computed by dividing r(x) by the minimal polynomials. These syndromes and are given by: S1=S2=S4=1, S3=6 S6=12 S5=5 . The table is then filled out according to the algorithm and the steps are shown below: 1. S ( x) x + x 2 + 6 x 3 + x 4 + 5 x 5 + 12 x 6 2. k=0 (0) ( x) 1 + S ( x) 1 + [ x + x 2 + 6 x 3 + x 4 + 5 x 5 + 12 x 6 ] 1 + x + x 2 + 6 x 3 + x 4 + 5 x 5 + 12 x 6 d ( 0) 1 ( 2) ( x) (0) ( x) + d (0) [ x T ( 0) ( x)] 1 + x T ( 2 ) ( x) xT ( 2 k ) ( x) x d (2k ) 23 3. k=1 ( 2) ( x)1 + S ( x) (1 + x)[ x + x 2 + 6 x 3 + x 4 + 5 x 5 + 12 x 6 ] 1 + 1x + x 2 + 6 x 3 + x 4 + 5 x 5 + 12 x 6 1 + (1 + 6 ) x 3 + ...... d ( 2) (1 + 6 ) 13 ( 4) ( x) ( 2) ( x) + d ( 2) [ x T ( 2) ( x)] 1 + x + 13 x 2 T ( 4 ) ( x) x ( 2) ( x) x(1 + x) 1 1 13 x + 13 x 2 2 x + 2 x 2 ( 2) 13 d 4. k=2 ( 4) ( x)1 + S ( x) (1 + x + 13 x 2 )[ x + x 2 + 6 x 3 + x 4 + 5 x 5 + 12 x 6 ] 1 + 1x + x 2 + 6 x 3 + x 4 + 5 x 5 + 12 x 6 1 + .. + (1 + 5 + 19 ) x 5 + ...... d ( 2) (1 + 5 + 19 ) 2 ( 6) ( x) ( 4) ( x) + d ( 4) [ x T ( 4) ( x)] 1 + x + 11 x 2 + 4 x 3 The results are tabulated below ----------------------------------------------------------------------------------------d (2k ) k ( 2 k ) ( x) T (2k ) -----------------------------------------------------------------------------------------0 1 1 1 1 1+x x 13 2 1+x+13x2 2x+2x2 2 3 1+x+11x2+4x3 … … -----------------------------------------------------------------------------------------The error location polynomial is hence given by: (x)=1+x+11x2+4x3 6.3 Chien Search Algorithm The Chien search algorithm is used to find the roots of the error location polynomial given by: (x)=1+x+11x2+4x3. The roots of (x) can be fond by plugging in all the elements of the GF and picking up the ones that set (x) to zero, hence: 24 ( x) ( x + 3 )( x + 9 )( x + 14 ) ( x) (1 + 1 x)(1 + 2 x)(1 + 3 x) The error locations are then given by: 1 2 3 1 3 1 9 1 14 15 12 3 15 6 9 15 1 14 The 3 errors are in bit positions 13, 7, and 2. 25 7.0 APPENDIX A. C CODE /* BCH Encoder Decoder and Simulator * m = order of the Galois field GF(2**m) * n = 2**m - 1 = size of the multiplicative group of GF(2**m) * length = length of the BCH code * t = error correcting capability (max. no. of errors the code corrects) * d = 2*t + 1 = designed min. distance = no. of consecutive roots of g(x) + 1 * k = n - deg(g(x)) = dimension (no. of information bits/codeword) of the code * p[] = coefficients of a primitive polynomial used to generate GF(2**m) * g[] = coefficients of the generator polynomial, g(x) * alpha_to [] = log table of GF(2**m) * index_of[] = antilog table of GF(2**m) * data[] = information bits = coefficients of data polynomial, i(x) * bb[] = coefficients of redundancy polynomial x^(length-k) i(x) modulo g(x) * numerr = number of errors * errpos[] = error positions * recd[] = coefficients of the received polynomial * decerror = number of decoding errors (in _message_ positions) * */ #include <math.h> #include <stdio.h> #include <stdlib.h> int int int int int int m, n, length, k, t, d; p[11]; alpha_to[512], index_of[512], g[15]; recd[511], data[510], bb[510]; seed; numerr, errpos[512], decerror = 0; void read_p() /* * Read m, the degree of a primitive polynomial p(x) used to compute the * Galois field GF(2**m). Get precomputed coefficients p[] of p(x). Read * the code length. */ { int i, ninf; printf("bch3: An encoder/decoder for binary BCH codes\n"); printf("\nFirst, enter a value of m such that the code length is\n"); printf("2**(m-1) - 1 < length <= 2**m - 1\n\n"); do { printf("Enter m (between 2 and 20): "); scanf("%d", &m); } while ( !(m>1) || !(m<21) ); for (i=1; i<m; i++) p[i] = 0; p[0] = p[m] = 1; 26 if (m == 2) else if (m == 3) else if (m == 4) else if (m == 5) else if (m == 6) else if (m == 7) else if (m == 8) else if (m == 9) else if (m == 10) else if (m == 11) else if (m == 12) else if (m == 13) else if (m == 14) else if (m == 15) else if (m == 16) else if (m == 17) else if (m == 18) else if (m == 19) else if (m == 20) printf("p(x) = "); p[1] = 1; p[1] = 1; p[1] = 1; p[2] = 1; p[1] = 1; p[1] = 1; p[4] = p[5] = p[6] = 1; p[4] = 1; p[3] = 1; p[2] = 1; p[3] = p[4] = p[7] = 1; p[1] = p[3] = p[4] = 1; p[1] = p[11] = p[12] = 1; p[1] = 1; p[2] = p[3] = p[5] = 1; p[3] = 1; p[7] = 1; p[1] = p[5] = p[6] = 1; p[3] = 1; n = 1; for (i = 0; i <= m; i++) { n *= 2; printf("%1d", p[i]); } printf("\n"); n = n / 2 - 1; ninf = (n + 1) / 2 - 1; do { printf("Enter code length (%d < length <= %d): ", ninf, n); scanf("%d", &length); } while ( !((length <= n)&&(length>ninf)) ); } void generate_gf() /* * Generate field GF(2**m) from the irreducible polynomial p(X) with * coefficients in p[0]..p[m]. * * Lookup tables: * index->polynomial form: alpha_to[] contains j=alpha^i; * polynomial form -> index form: index_of[j=alpha^i] = i * * alpha=2 is the primitive element of GF(2**m) */ { register int i, mask; mask = 1; alpha_to[m] = 0; for (i = 0; i < m; i++) { alpha_to[i] = mask; index_of[alpha_to[i]] = i; if (p[i] != 0) alpha_to[m] ^= mask; mask <<= 1; 27 } index_of[alpha_to[m]] = m; mask >>= 1; for (i = m + 1; i < n; i++) { if (alpha_to[i - 1] >= mask) alpha_to[i] = alpha_to[m] ^ ((alpha_to[i - 1] ^ mask) << 1); else alpha_to[i] = alpha_to[i - 1] << 1; index_of[alpha_to[i]] = i; } index_of[0] = -1; } void gen_poly() /* * Compute the generator polynomial of a binary BCH code. Fist generate the * cycle sets modulo 2**m - 1, cycle[][] = (i, 2*i, 4*i, ..., 2^l*i). Then * determine those cycle sets that contain integers in the set of (d-1) * consecutive integers {1..(d-1)}. The generator polynomial is calculated * as the product of linear factors of the form (x+alpha^i), for every i in * the above cycle sets. */ { register int ii, jj, ll, kaux; register int test, aux, nocycles, root, noterms, rdncy; int cycle[1024][21], size[1024], min[1024], zeros[1024]; /* Generate cycle sets modulo n, n = 2**m - 1 */ cycle[0][0] = 0; size[0] = 1; cycle[1][0] = 1; size[1] = 1; jj = 1; /* cycle set index */ if (m > 9) { printf("Computing cycle sets modulo %d\n", n); printf("(This may take some time)...\n"); } do { /* Generate the jj-th cycle set */ ii = 0; do { ii++; cycle[jj][ii] = (cycle[jj][ii - 1] * 2) % n; size[jj]++; aux = (cycle[jj][ii] * 2) % n; } while (aux != cycle[jj][0]); /* Next cycle set representative */ ll = 0; do { ll++; test = 0; for (ii = 1; ((ii <= jj) && (!test)); ii++) /* Examine previous cycle sets */ for (kaux = 0; ((kaux < size[ii]) && (!test)); kaux++) if (ll == cycle[ii][kaux]) test = 1; 28 } while ((test) && (ll < (n - 1))); if (!(test)) { jj++; /* next cycle set index */ cycle[jj][0] = ll; size[jj] = 1; } } while (ll < (n - 1)); nocycles = jj; /* number of cycle sets modulo n */ printf("Enter the error correcting capability, t: "); scanf("%d", &t); d = 2 * t + 1; /* Search for roots 1, 2, ..., d-1 in cycle sets */ kaux = 0; rdncy = 0; for (ii = 1; ii <= nocycles; ii++) { min[kaux] = 0; test = 0; for (jj = 0; ((jj < size[ii]) && (!test)); jj++) for (root = 1; ((root < d) && (!test)); root++) if (root == cycle[ii][jj]) { test = 1; min[kaux] = ii; } if (min[kaux]) { rdncy += size[min[kaux]]; kaux++; } } noterms = kaux; kaux = 1; for (ii = 0; ii < noterms; ii++) for (jj = 0; jj < size[min[ii]]; jj++) { zeros[kaux] = cycle[min[ii]][jj]; kaux++; } k = length - rdncy; if (k<0) { printf("Parameters invalid!\n"); exit(0); } printf("This is a (%d, %d, %d) binary BCH code\n", length, k, d); /* Compute the generator polynomial */ g[0] = alpha_to[zeros[1]]; g[1] = 1; /* g(x) = (X + zeros[1]) initially */ for (ii = 2; ii <= rdncy; ii++) { g[ii] = 1; for (jj = ii - 1; jj > 0; jj--) if (g[jj] != 0) g[jj] = g[jj - 1] ^ alpha_to[(index_of[g[jj]] + zeros[ii]) % n]; else 29 g[jj] = g[jj - 1]; g[0] = alpha_to[(index_of[g[0]] + zeros[ii]) % n]; } printf("Generator polynomial:\ng(x) = "); for (ii = 0; ii <= rdncy; ii++) { printf("%d", g[ii]); if (ii && ((ii % 50) == 0)) printf("\n"); } printf("\n"); } void encode_bch() /* * Compute redundacy bb[], the coefficients of b(x). The redundancy * polynomial b(x) is the remainder after dividing x^(length-k)*data(x) * by the generator polynomial g(x). */ { register int i, j; register int feedback; for (i = 0; i < length - k; i++) bb[i] = 0; for (i = k - 1; i >= 0; i--) { feedback = data[i] ^ bb[length - k - 1]; if (feedback != 0) { for (j = length - k - 1; j > 0; j--) if (g[j] != 0) bb[j] = bb[j - 1] ^ feedback; else bb[j] = bb[j - 1]; bb[0] = g[0] && feedback; } else { for (j = length - k - 1; j > 0; j--) bb[j] = bb[j - 1]; bb[0] = 0; } } } void decode_bch() /* * Assume we have received bits in recd[i], i=0..(n-1). * * Compute the 2*t syndromes by substituting alpha^i into rec(X) and * evaluating, storing the syndromes in s[i], i=1..2t (leave s[0] zero) . * Then we use the Berlekamp algorithm to find the error location polynomial * elp[i]. * * If the degree of the elp is >t, then we cannot correct all the errors, and * we have detected an uncorrectable error pattern. The received data is output uncorrected. * If the degree of elp is <=t, we substitute alpha^i , i=1..n into the elp * to get the roots, hence the inverse roots, the error location numbers. 30 * This step is usually called "Chien's search". * * If the number of errors located is not equal the degree of the elp, then * the decoder assumes that there are more than t errors and cannot correct * them, only detect them. The received data is output uncorrected. */ { register int i, j, u, q, t2, count = 0, syn_error = 0; int elp[128][128], d[512], l[512], u_lu[512], s[512]; int root[512], loc[20], err[512], reg[20]; t2 = 2 * t; /* first form the syndromes */ printf("S(x) = "); for (i = 1; i <= t2; i++) { s[i] = 0; for (j = 0; j < length; j++) if (recd[j] != 0) s[i] ^= alpha_to[(i * j) % n]; if (s[i] != 0) syn_error = 1; /* set error flag if non-zero syndrome */ /* * Note: If the code is used only for ERROR DETECTION, then * exit program here indicating the presence of errors. */ /* convert syndrome from polynomial form to index form */ s[i] = index_of[s[i]]; printf("%3d ", s[i]); } printf("\n"); if (syn_error) { /* if there are errors, try to correct them */ /* * Compute the error location polynomial via the Berlekamp * iterative algorithm. Following the terminology of Lin and * Costello's book : d[u] is the 'mu'th discrepancy, where * u='mu'+1 and 'mu' (the Greek letter!) is the step number * ranging from -1 to 2*t (see L&C), l[u] is the degree of * the elp at that step, and u_l[u] is the difference between * the step number and the degree of the elp. */ /* initialise table entries */ d[0] = 0; /* index form */ d[1] = s[1]; /* index form */ elp[0][0] = 0; /* index form */ elp[1][0] = 1; /* polynomial form */ for (i = 1; i < t2; i++) { elp[0][i] = -1; /* index form */ elp[1][i] = 0; /* polynomial form */ } l[0] = 0; l[1] = 0; u_lu[0] = -1; u_lu[1] = 0; u = 0; do { 31 u++; if (d[u] == -1) { l[u + 1] = l[u]; for (i = 0; i <= l[u]; i++) { elp[u + 1][i] = elp[u][i]; elp[u][i] = index_of[elp[u][i]]; } } else /* * search for words with greatest u_lu[q] for * which d[q]!=0 */ { q = u - 1; while ((d[q] == -1) && (q > 0)) q--; /* have found first non-zero d[q] */ if (q > 0) { j = q; do { j--; if ((d[j] != -1) && (u_lu[q] < u_lu[j])) q = j; } while (j > 0); } /* * have now found q such that d[u]!=0 and * u_lu[q] is maximum */ /* store degree of new elp polynomial */ if (l[u] > l[q] + u - q) l[u + 1] = l[u]; else l[u + 1] = l[q] + u - q; /* form new elp(x) */ for (i = 0; i < t2; i++) elp[u + 1][i] = 0; for (i = 0; i <= l[q]; i++) if (elp[q][i] != -1) elp[u + 1][i + u - q] = alpha_to[(d[u] + n - d[q] + elp[q][i]) % n]; for (i = 0; i <= l[u]; i++) { elp[u + 1][i] ^= elp[u][i]; elp[u][i] = index_of[elp[u][i]]; } } u_lu[u + 1] = u - l[u + 1]; /* form (u+1)th discrepancy */ if (u < t2) { /* no discrepancy computed on last iteration */ if (s[u + 1] != -1) d[u + 1] = alpha_to[s[u + 1]]; else d[u + 1] = 0; for (i = 1; i <= l[u + 1]; i++) 32 if ((s[u + 1 - i] != -1) && (elp[u + 1][i] != 0)) d[u + 1] ^= alpha_to[(s[u + 1 - i] + index_of[elp[u + 1][i]]) % n]; /* put d[u+1] into index form */ d[u + 1] = index_of[d[u + 1]]; } } while ((u < t2) && (l[u + 1] <= t)); u++; if (l[u] <= t) {/* Can correct errors */ /* put elp into index form */ for (i = 0; i <= l[u]; i++) elp[u][i] = index_of[elp[u][i]]; printf("sigma(x) = "); for (i = 0; i <= l[u]; i++) printf("%3d ", elp[u][i]); printf("\n"); printf("Roots: "); /* Chien search: find roots of the error location polynomial */ for (i = 1; i <= l[u]; i++) reg[i] = elp[u][i]; count = 0; for (i = 1; i <= n; i++) { q = 1; for (j = 1; j <= l[u]; j++) if (reg[j] != -1) { reg[j] = (reg[j] + j) % n; q ^= alpha_to[reg[j]]; } if (!q) { /* store root and error * location number indices */ root[count] = i; loc[count] = n - i; count++; printf("%3d ", n - i); } } printf("\n"); if (count == l[u]) /* no. roots = degree of elp hence <= t errors */ for (i = 0; i < l[u]; i++) recd[loc[i]] ^= 1; else /* elp has degree >t hence cannot solve */ printf("Incomplete decoding: errors detected\n"); } } } main() { int i; read_p(); generate_gf(); gen_poly(); /* Read m */ /* Construct the Galois Field GF(2**m) */ /* Compute the generator polynomial of BCH code */ 33 /* Randomly generate DATA */ seed = 131073; srand(seed); for (i = 0; i < k; i++) data[i] = (rand() & 65536/16) >>12; encode_bch(); /* encode data */ /* * recd[] are the coefficients of c(x) = x**(length-k)*data(x) + b(x) */ for (i = 0; i < length - k; i++) recd[i] = bb[i]; for (i = 0; i < k; i++) recd[i + length - k] = data[i]; printf("Code polynomial:\nc(x) = "); for (i = 0; i < length; i++) { printf("%1d", recd[i]); if (i && ((i % 50) == 0)) printf("\n"); } printf("\n"); printf("Enter the number of errors:\n"); scanf("%d", &numerr); /* CHANNEL errors */ printf("Enter error locations (integers between"); printf(" 0 and %d): ", length-1); /* * recd[] are the coefficients of r(x) = c(x) + e(x) */ for (i = 0; i < numerr; i++) scanf("%d", &errpos[i]); if (numerr) for (i = 0; i < numerr; i++) recd[errpos[i]] ^= 1; printf("r(x) = "); for (i = 0; i < length; i++) { printf("%1d", recd[i]); if (i && ((i % 50) == 0)) printf("\n"); } printf("\n"); decode_bch(); /* DECODE received codeword recv[] */ /* * print out original and decoded data */ printf("Results:\n"); printf("original data = "); for (i = 0; i < k; i++) { printf("%1d", data[i]); if (i && ((i % 50) == 0)) printf("\n"); } printf("\nrecovered data = "); 34 for (i = length - k; i < length; i++) { printf("%1d", recd[i]); if ((i-length+k) && (((i-length+k) % 50) == 0)) printf("\n"); } printf("\n"); /* * DECODING ERRORS? we compare only the data portion */ for (i = length - k; i < length; i++) if (data[i - length + k] != recd[i]) decerror++; if (decerror) printf("There were %d decoding errors in message positions\n", decerror); else printf("Succesful decoding\n"); } 35 8.0 APPENDIX B C PROGRAM OUTPUT 36