DSPRelated.com
Forums

Generating Maximum Length Sequence using Galois LFSR

Started by Nicholas Kinar July 4, 2009
I wrote,

[Wikipedia page on LFSR]

> It does not mention, for example, that one is calculating > a remainder. I do not know anyone who uses the terminology > Fibonacci LFSR, and the polynomial in the "Fibonacci" section > is reversed from any normal usage.
A little more investigation and I have found other references to the Fibonacci vs. Galois terminology distinction, including in one paper by professor David Wagner at U.C. Berkeley. So I guess it's a real bit of terminology. In Golomb, _Shift Register Sequences_, Chapter 3 Section 2.8, there is a discussion of how the polynomial P = 1 - x - x^2 generates a Fibonacci sequence (e.g., 1/P is an infinite polynomial with Fibonacci numbers as coefficients). But in a field of characteristic 2 this reduces to a sequence of length three (every third Fibonacci number is even, the others odd). So I do not immediately see how this leads to the above Fibonacci nomenclature. Steve
On Jul 6, 12:15�am, spop...@speedymail.org (Steve Pope) wrote:

> In Golomb, _Shift Register Sequences_, Chapter 3 Section 2.8, > there is a discussion of how the polynomial P = 1 - x - x^2 > generates a Fibonacci sequence (e.g., 1/P is an infinite > polynomial with Fibonacci numbers as coefficients). �But > in a field of characteristic 2 this reduces to a sequence > of length three (every third Fibonacci number is even, the > others odd). � So I do not immediately see how this leads to > the above Fibonacci nomenclature.
The Fibonacci numbers (or Fibonacci numbers) are generated by a linear recurrence: F_{n} = F_{n-1} + F_{n-2} whose characteristic polynomial is 1 - x - x^2, and so LFSRs whose m-bit *contents* are successive overlapping m-tuples from a binary sequence are called Fibonacci LFSRs even though the recurrence is of degree m instead of 2 and over GF(2) (or over GF(q) in general) instead of the integers. As Steve has noted several times in this thread (and as is also noted in the much-denigrated Wikipedia entry (to which I have not contributed anything, by the way, and so I have no axe to grind here)), Galois LFSRs generate the *same* sequences as Fibonacci LFSRS (output = contents of latch at the output end of the register). However, generally speaking, the *register contents* of the Galois LFSR are different from those of the Fibonacci LFSR at any time, even when their output bits are the same *sequence*. All the code snippets posted simulate Galois LFSRs. Simulation of a Fibonacci LFSR is not quite so easy to program in C since one needs to know if there are an even number or odd number of 1s in certain specific locations in a word. The bits are easily extracted via an AND operation with a mask but determining if an odd number of those happen to be 1 is more problematic. (The information *is* usually available as the parity bit of the masked word at the assembly or machine language level; can it be used in C?) If you really want the gory details of the relationship between Galois LFSRs and Fibonacci LFSRs, see a thread in this newsgroup in March 2002 titled Pseudo Random Binary Sequences. Google Groups finds it in sci.math for some reason (http://groups.google.com/group/sci.math/browse_thread/thread/ 28df95bf019230c7/35b22eae280a7368?lnk=gst&q=Sarwate +Yates#35b22eae280a7368) (I searched for "Sarwate Yates" in comp.dsp on Google Groups), but all the participants are the usual suspects from comp.dsp: Jerry Avins, Eric Jacobsen, Robert Bristow-Johnson, Randy Yates, Raymond Toy, Ray Andraka, etc., and not forgetting, yours truly, Hope this helps --Dilip Sarwate
dvsarwate@yahoo.com <dvsarwate@gmail.com> wrote:

>On Jul 6, 12:15&#4294967295;am, spop...@speedymail.org (Steve Pope) wrote:
>> In Golomb, _Shift Register Sequences_, Chapter 3 Section 2.8, >> there is a discussion of how the polynomial P = 1 - x - x^2 >> generates a Fibonacci sequence (e.g., 1/P is an infinite >> polynomial with Fibonacci numbers as coefficients). &#4294967295;But >> in a field of characteristic 2 this reduces to a sequence >> of length three (every third Fibonacci number is even, the >> others odd). &#4294967295; So I do not immediately see how this leads to >> the above Fibonacci nomenclature.
>The Fibonacci numbers (or Fibonacci numbers) >are generated by a linear recurrence:
>F_{n} = F_{n-1} + F_{n-2}
>whose characteristic polynomial is 1 - x - x^2, and >so LFSRs whose m-bit *contents* are successive >overlapping m-tuples from a binary sequence are >called Fibonacci LFSRs even though the recurrence >is of degree m instead of 2 and over GF(2) (or over >GF(q) in general) instead of the integers.
Thanks. (Is it not still true that each m-tuple represents a field element, in some basis?)
>As Steve >has noted several times in this thread (and as is also >noted in the much-denigrated Wikipedia entry (to which >I have not contributed anything, by the way, and so >I have no axe to grind here)), Galois LFSRs generate >the *same* sequences as Fibonacci LFSRS (output >= contents of latch at the output end of the register). >However, generally speaking, the *register contents* >of the Galois LFSR are different from those of the >Fibonacci LFSR at any time, even when their output >bits are the same *sequence*.
So I'll retract my negative rambling about the Wiki page, given that the above terminology seems semi-widespread. I just had not encountered it in texts such as Golomb, Berlekamp, McEliece, or internally on any projects. Obviously there's a subset of the community using this lingo. I still think the "Galois LFSR" discussion could be made... much more clear if the concept of dividing polynomials was covered.
>All the code snippets posted simulate Galois LFSRs. >Simulation of a Fibonacci LFSR is not quite so easy >to program in C since one needs to know if there are >an even number or odd number of 1s in certain >specific locations in a word. The bits are easily >extracted via an AND operation with a mask but >determining if an odd number of those happen to be >1 is more problematic. (The information *is* usually >available as the parity bit of the masked word at >the assembly or machine language level; can it be used >in C?)
The answer to the last question is no -- C gives no access to parity bits, overflow bits and the like, at least not natively as part of the language. Perhaps they can generate a signal or exception in some systems but one should not use exceptions just to construct logic. (IMO)
>If you really want the gory details of the relationship >between Galois LFSRs and Fibonacci LFSRs [..] >(http://groups.google.com/group/sci.math/browse_thread/thread/ >28df95bf019230c7/35b22eae280a7368?lnk=gst&q=Sarwate >+Yates#35b22eae280a7368)
Thanks Steve
On Jul 6, 8:12&#4294967295;am, spop...@speedymail.org (Steve Pope) wrote:

> > (Is it not still true that each m-tuple represents a field element, > in some basis?)
Yes, in a Galois LFSR, the m-tuple represents a field element in the standard polynomial basis. If the initial loading of the LFSR is 100....0 or 00....1 (depending on whether you are a big-endian or a little-endian) representing the field element 1 (multiplicative identity), then successive m-tuple contents of the Galois LFSR are alpha, alpha^2, alpha^3, .... or, for those who dislike the Greek alphabet, x, x^2, x^3, etc, all modulo the characteristic polynomial. The contents of the Fibonacci LFSR are also the same sequence of increasing powers of alpha, but the field elements are represented in the dual basis of the standard polynomial basis. For further details, read the thread from 7 years ago that has been cited earlier. --Dilip Sarwate
> It's good to keep track of the algebra. For a generating > polynomial G of degree m over GF(2), you are computing the remainder > > x^n mod G > > for a series of values n=0, n=1,.... > > This remainder is a polynomial over GF(2) of (at most) degree m-1. > How you represent it in a bit field is totally up to you, > and your method is as correct as any. > > Steve
In my C++ implementation, I use an std::vector<bool>v to keep track of the zeros and the ones, so I can simply generate an MLS without having to worry about bit-shifting a uint32_t or uint16_t or similar variable. To do the rotation, I simply pop a bit off the back of the vector, do the XOR with the taps, and then insert the resulting bit at the front of the vector. It works quite well, but for embedded hardware, it might be a little bit too slow for a quick implementation. Nicholas
> i forgot to mention that to get a virtually zero-mean MLS signal for > the purposes of measuring impulse response (or just for some noise > that is guaranteed to be "white" in some sense of the word), then you > take that bit, (we'll call it a[n] where n is discrete time) which is > 0 or 1 and create this signed MLS signal: > > x[n] = (-1)^a[n] > > so, it's nearly zero mean. there are L/2 ones and L/2-1 zeros in a[n] > (because the zero state in the shift register is the only state > missing and if it were included, there would be an equal L/2 ones and > zeros, but it's not). then there is one more -1 than +1 in x[n] over > L samples. the mean is -1/L > > this way, when you autocorrelate, you get > > > Rx[k] = MEAN{ x[n] * x[n+k] } > > ( "*" means simple multiplication.) > > which is > > Rx[k] = MEAN{ (-1)^a[n] * (-1)^a[n+k] } > > = MEAN{ (-1)^(a[n] + a[n+k]) } > > which happens to be the same as > > Rx[k] = MEAN{ (-1)^(a[n] XOR a[n+k]) } > > > now it turns out that if you take that periodic MLS bit sequence, copy > it, circularly rotate one of the copies by k samples, and XOR the two > MLSes together, it turns out that you can show that the same recursive > generating algorithm that produces the MLS also governs that XOR > product of two with a lag in between. except, we know for MLS, the > zero state gets mapped back to the zero state. for an MLS, those are > the two loops; zero goes straight to zero, but any non-zero state of > the shift register goes through the whole MLS, which are all the other > non-zero states, before it gets back to your original non-zero state. > so that MEAN above for k not a multiple of L (nor zero), is -1/L. but > the mean for k=0 or any other integer multiple of L is the mean of a > sequence of ones. > >
Thanks, Robert! I had read before that the binary sequence is converted to -1 and +1, but this really explains why it is beneficial to do this operation.
> it's similar to a recent experience i had where i missed that the > simplest and obvious way to display the step response of a filter (IIR > or FIR), assuming you know the coefficients, is to simple bang a step > input to a simulated filter with the same coefficients. somebody at > music-dsp had to point that out to me, where i was thinking of doing > Heaviside partial fraction expansion of the transfer function times 1/ > (z-1), inverse Z transform, and getting it from there. >
Ah - what a good idea!
> > BTW, if you Google "Maximum Length Sequence" and look at the link > right below the one you referred to, there is a Little MLS Tutorial > that explains the math behind most of this. it doesn't derive > primitive polynomials, but does prove how MLS can get your time- > aliased impulse response from where you can get your frequency > response. >
There are a lot of good links on the web, and these do a terrific job of quickly informing the reader. For more in-depth stuff concerning the mathematics, it is probably best to turn to a book such as the one by Golomb, which is infused with proofs. Nicholas
> > (http://groups.google.com/group/sci.math/browse_thread/thread/ > 28df95bf019230c7/35b22eae280a7368?lnk=gst&q=Sarwate > +Yates#35b22eae280a7368)
Great thread; thanks Dilip!
dvsarwate@yahoo.com <dvsarwate@gmail.com> wrote:

>On Jul 6, 8:12&#4294967295;am, spop...@speedymail.org (Steve Pope) wrote:
[Fibonacci LFSR]
>> (Is it not still true that each m-tuple represents a field element, >> in some basis?)
>Yes, in a Galois LFSR, the m-tuple represents a field element >in the standard polynomial basis. If the initial loading of the >LFSR is 100....0 or 00....1 (depending on whether you are a >big-endian or a little-endian) representing the field element 1 >(multiplicative identity), then successive m-tuple contents of >the Galois LFSR are alpha, alpha^2, alpha^3, .... or, for those >who dislike the Greek alphabet, x, x^2, x^3, etc, all modulo >the characteristic polynomial. The contents of the Fibonacci >LFSR are also the same sequence of increasing powers of >alpha, but the field elements are represented in the dual basis >of the standard polynomial basis. For further details, read >the thread from 7 years ago that has been cited earlier.
Thanks. I read through the cited thread. I assume this is perhaps the same dual basis that Berlekamp used to develop his bit-serial RS encoder. I am still curious about the origin and dissemination of the "Fibonacci LFSR" vs. "Galois LFSR" terminology -- there isn't anything less "Galois" about the Fibonacci version; it uses a different basis, sure, but the register contents are still Galois field elements. So I see it as a confusing choice of terms for this distinction. Unless this terminology is really and truly ingrained, I'd advocate spiking it. Just my opinion of course. Steve
Nicholas Kinar  <n.kinar@usask.ca> replies to my post,

>> It's good to keep track of the algebra. For a generating >> polynomial G of degree m over GF(2), you are computing the remainder >> >> x^n mod G >> >> for a series of values n=0, n=1,.... >> >> This remainder is a polynomial over GF(2) of (at most) degree m-1. >> How you represent it in a bit field is totally up to you, >> and your method is as correct as any. >> >> Steve
>In my C++ implementation, I use an std::vector<bool>v to keep track of >the zeros and the ones, so I can simply generate an MLS without having >to worry about bit-shifting a uint32_t or uint16_t or similar variable. > To do the rotation, I simply pop a bit off the back of the vector, do >the XOR with the taps, and then insert the resulting bit at the front of >the vector. It works quite well, but for embedded hardware, it might be >a little bit too slow for a quick implementation.
Methods on std::vector<bool> are notorious for being slow, since this object has packed the boolean bits into chars, to save memory space. Steve
Steve Pope wrote:
> Nicholas Kinar <n.kinar@usask.ca> replies to my post, > >>> It's good to keep track of the algebra. For a generating >>> polynomial G of degree m over GF(2), you are computing the remainder >>> >>> x^n mod G >>> >>> for a series of values n=0, n=1,.... >>> >>> This remainder is a polynomial over GF(2) of (at most) degree m-1. >>> How you represent it in a bit field is totally up to you, >>> and your method is as correct as any. >>> >>> Steve > >> In my C++ implementation, I use an std::vector<bool>v to keep track of >> the zeros and the ones, so I can simply generate an MLS without having >> to worry about bit-shifting a uint32_t or uint16_t or similar variable. >> To do the rotation, I simply pop a bit off the back of the vector, do >> the XOR with the taps, and then insert the resulting bit at the front of >> the vector. It works quite well, but for embedded hardware, it might be >> a little bit too slow for a quick implementation. > > Methods on std::vector<bool> are notorious for being slow, > since this object has packed the boolean bits into chars, > to save memory space. > > Steve
If only 'C' bit fields had had *DEFINED* behavior.... *Sigh*. -- Les Cargill