Algorithm for calculating previous states of LFSR counters ? - Page 1
Forum section: electronics / projects

author: bsccara
author_rank: Contributor
timestamp: July 02, 2019, 04:34:47 pm
content: On a design I'm working on I use LFSR counters with 9 and 35 bit widths, using XNOR gates for the taps. The counters run from an initial set state to an all-zero one, which signals end-of-count. I need to know what initial state to set the counters to to take a specified number of clock ticks to the all-zero state. Does anyone know of an algorithm to calculate that initial state, apart from brute-force (with pre-computed sparse tables) ?P.S. I have found a blog post that dwelves into it athttps://www.embeddedrelated.com/showarticle/1114.phpbut it calculates the output bit only and I can't figure out the math to expand it to all bits.

author: ataradov
author_rank: Super Contributor
timestamp: July 02, 2019, 05:44:43 pm
content: LFSRs are fully reversible. There is only one state that would lead to 0. This state depends on the configuration of your taps. The same way, N-1 state can be reached from only one N-2 state.So all you have to do is "play back" the sequence N times and you will arrive at the requested configuration.

author: bsccara
author_rank: Contributor
timestamp: July 02, 2019, 06:59:27 pm
content: You are right but that's the brute-force approach. Worst case I'd have to cycle through the algorithm 235-2 times to compute the initial condition (or split it half way and cycle through 234-2 times either direction, depending on the specified count). What I'm looking for is an algorithm that runs at a much lower cost, preferably something like N or N2, where N would be the LFSR size in bits.

author: ataradov
author_rank: Super Contributor
timestamp: July 02, 2019, 07:01:20 pm
content: No, you will need to cycle N times, where N is your number of steps that lead to the value of 0. LFSR size is irrelevant here.

author: bsdphk
author_rank: Regular Contributor
timestamp: July 02, 2019, 08:45:07 pm
content: 2^35 isn't really much for modern hardware.Calculating LFSR's forward is much cheaper than backward, so the fastest strategy may be to start from zero, move forward, snapshot state every 2^28 steps until you get back to zero.Now you know your cycle-length, so restart from the snapshot previous to your target and find it again.As far as I know, there is no other way to ensure that the cycle which includes a particular value (in your case zero) has sufficient length to what you are trying to do.See also:https://users.ece.cmu.edu/~koopman/crc/index.htmlSpecifically:https://users.ece.cmu.edu/~koopman/crc/crc36.html

author: bsccara
author_rank: Contributor
timestamp: July 02, 2019, 09:33:53 pm
content: Alex, we're saying the same thing; being a 35 bit counter and having a maximum period of 235- 1 if a count of 235-2 is needed the algorithm would have to cycle that many times (or alternatively once, going forward). That's what I want to avoid. The blog post I mentioned (check out the 'Time shifts' section) seems much faster but calculates just the output bit and relies on finite fields math that I don't fully understand.bsdphk, as for 235not being much, the code I now use to precalculate the sparse table (currectly the table stores every 220th initial state but all states are computed, obviously) takes several minutes to run; granted that it may not be the greatest code nor particularly optimized but thats orders of magnitude slower than what I'd like it to be.

author: ataradov
author_rank: Super Contributor
timestamp: July 02, 2019, 09:37:16 pm
content: Ah, OK. I thought your look back number was relatively small. This is an interesting problem, I would need to think about it a bit more.

author: rstofer
author_rank: Super Contributor
timestamp: July 03, 2019, 01:44:07 am
content: If a LFSR is truly reversible, why not just start with an output of zero. There is only one prior state that, when mangled by the XOR gates, leads to zero for the next state and it would seem to me that starting in state zero, the next state is exactly the state that transitions to zero when counting forward.Or not... I haven't thought about LFSRs in many years.

author: ataradov
author_rank: Super Contributor
timestamp: July 03, 2019, 01:47:54 am
content: That is exactly what I'm proposing. The problem is that it may still require 2^35 iterations. I mean you can shorten it to 2^34 and iterate either backward or forward depending on what is closer.Presumably there is some magic that could take polynomial and offset N, and then quickly jump by N from any valid state. You would do precomputation on the polynomial alone before. This is what happens in the article - polynomials are expressed in the matrix form and then matrix exponentiation is used to quickly evaluate jumped value. But I have no idea how to apply this to movements back. I guess you could just move forward by 2^35-N using that stuff. But it is still not trivial.I would be interested to know what is the actual application of this. It may be solved much easier.

author: 0culus
author_rank: Super Contributor
timestamp: July 03, 2019, 01:54:30 am
content: Quote from: rstofer on July 03, 2019, 01:44:07 amAll zero is a lockup state, so that won't work.Doesn't apply to XNOR

author: ataradov
author_rank: Super Contributor
timestamp: July 03, 2019, 01:57:05 am
content: Quote from: 0culus on July 03, 2019, 01:54:30 amNot for the XNOR-based LFSR. In that case all-1s is a lock up state. LFSR can't naturally produce its lock up state, so you could never arrive at it.

author: 0culus
author_rank: Super Contributor
timestamp: July 03, 2019, 01:59:22 am
content: Quote from: ataradov on July 03, 2019, 01:57:05 amAhh, I missed the XNOR part. My bad.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: July 03, 2019, 02:20:47 am
content: It runs same forwards as backwards, no? So just do the same thing with the inverted matrix. (I'd... have to read that rather in depth to know if the matrix representation evenisinvertible, but it should be?)That gives you access to a parallel computing approach. Sample the space with a series of exponentiated shortcuts, then linear search from each of those points. You could binary search if the sequence were ordered, but it's not that kind of ring unfortunately. Actually, is that wrong? It's a linear function, so it has to work with superposition. But with XOR rather than addition-with-carry, there's still no ordering to it?You can certainly precalculate the steps nearest to zero, saving a few there; but I'm not sure that there's anything more to find beyond that? It gets to be more of a crypto question...Tim

author: cur8xgo
author_rank: Regular Contributor
timestamp: July 03, 2019, 02:53:36 am
content: Quote from: T3sl4co1l on July 03, 2019, 02:20:47 amya I bet if you read about weaknesses of LSFR based security or LSFR predictability you will get a few papers or articles that show how to break them without brute forceor at least a clear statement that brute force is the only way

author: Siwastaja
author_rank: Super Contributor
timestamp: July 03, 2019, 06:10:53 am
content: Needing no data and completely fitting CPU registers, this is a problem that should parallelize very well. Try to run it on GPU so you have hundreds of the shader CPUs executing in parallel? Give each one a different start state from your sparse precomputed table.

author: hamster_nz
author_rank: Super Contributor
timestamp: July 03, 2019, 06:36:00 am
content: So what *exactly* do you know, and what exactly do you want to find out?For example, if you precompute the LFSR in a (maybe 512GB) table you can find the distance between two states in two lookups.

author: ataradov
author_rank: Super Contributor
timestamp: July 03, 2019, 06:47:34 am
content: You know the polynomial. You also know a number N . The current state is 0 (or any other fixed state). The goal is to find out what state was N generations ago.

author: hamster_nz
author_rank: Super Contributor
timestamp: July 03, 2019, 10:25:58 am
content: As it is a linear system, it appears you can decompose the state into a set of bits, have precalced values for those bits advanced through N states, and then recombine them.So you could have precanceled values for advancing the LFSR through 2^24 bits, and through 2^12 bits, and of course, one bit. You can then take a 36-bit LFSR through to any state in at most 2 ^12 * 3 operations, rather than 2^36-1 operations,With 36 sets of precalculated values (first set to advance through 1 state, second to advance through 2 states, advance through 4 states, ... advance through 2^34 states, advance through 2^35 states), you move through any number of states in 36 decompose-lookup-merge operations.Calculating these is table values relatively simple. Calculate the first set, use them twice to calculate the second set. Use them twice to calculate next set, and so on.The code below is a maximal 5-bit XNOR LFSR, and calculates four states ahead.Code:#include <stdio.h>#include <stdint.h>uint32_t advance_lfsr(uint32_t state) {uint32_t new_bit;new_bit = 1^((state & 0x10) ? 1 : 0) ^ ((state & 0x02) ? 1 : 0);state = (state << 1 )|new_bit;state &= 0x1f;return state;}int main(int argc, char *argv[]){uint32_t initial = 0x00;uint32_t state = initial;printf("Calculated and guessed are the LFSR advanced by 4 states\n");printf("\n");printf("State Calculated Guessed Error?\n");do {uint32_t guess, calced, i;guess = 0x0c;if((state & 0x01) != 0) guess ^= 0x19 ^ 0x0C;if((state & 0x02) != 0) guess ^= 0x07 ^ 0x0C;if((state & 0x04) != 0) guess ^= 0x0e ^ 0x0C;if((state & 0x08) != 0) guess ^= 0x09 ^ 0x0C;if((state & 0x10) != 0) guess ^= 0x06 ^ 0x0C;calced = state;for(i = 0; i < 4; i++) {calced = advance_lfsr(calced);}printf("%02x %02x %02x %s\n", state, calced, guess, calced ^ guess ? "yes" : "no");state = advance_lfsr(state);} while(state != initial);return 0;}And the results:Code:Calculated and guessed are the LFSR advanced by 4 statesState Calculated Guessed Error?00 0c 0c no01 19 19 no03 12 12 no06 05 05 no0c 0b 0b no19 16 16 no12 0d 0d no05 1b 1b no0b 17 17 no16 0f 0f no0d 1e 1e no1b 1d 1d no17 1a 1a no0f 15 15 no1e 0a 0a no1d 14 14 no1a 08 08 no15 11 11 no0a 02 02 no14 04 04 no08 09 09 no11 13 13 no02 07 07 no04 0e 0e no09 1c 1c no13 18 18 no07 10 10 no0e 00 00 no1c 01 01 no18 03 03 no10 06 06 noWhy would you be needing to do this?(Oh the key point I missed is that going forward by four states is the same as going backwards by (2^n-1)-4 states).

author: bsccara
author_rank: Contributor
timestamp: July 03, 2019, 02:25:36 pm
content: Thank you all for your replies, particularly 'hamster_nz'. As to the why... I'm implementing a design that requires multiple counters working as timers. I need them to take a programmable number of clock cycles to reach all-zeros, which signals end-of-count. These counters are implemented on a FPGA along with a lot more logic, so I need the counters to be as fast as possible (the feedback network needs to be simple) to be able to achieve timing closure and as nimble as possible on the resources. Hence LFSRs.I don't care about which states the counters go through as long as the number of them match the programmable setting. So I need to calculate which value to program into the counters as a starting state in order for them to go through that number of states prior to reaching all-zeros. These values will be provided from outside the FPGA, from software running on a PC.Since each counter may run consecutively with different starting states, up to thousands of count cycles back to back, I need the calculation to be fast.Presently I'm using brute force along with a pre-computed sparse table but the original question was if a better way existed.'hamster_nz', I'm now looking into your reply to figure out if those pre-computed tables are feasable.

author: StillTrying
author_rank: Super Contributor
timestamp: July 03, 2019, 03:43:11 pm
content: I've always thought that whatever sequence a LFSR counts, you can always create another one that counts through the same sequence but in reverse, I could be wrong though.The output stream is reversible; an LFSR with mirrored taps will cycle through the output sequence in reverse order.https://en.wikipedia.org/wiki/Linear-feedback_shift_register

author: duak
author_rank: Super Contributor
timestamp: July 03, 2019, 04:02:39 pm
content: Could you break the 35 bit LFSR into smaller segments that would be easier to un-hash? eg., if I wanted to count to 100 in decimal, I could use a 7-bit binary counter and convert to decimal or I could use two 4-bit BCD counters. Here, two 18 bit LFSRs could be cascaded. The more significant LFSR would only shift when the least significant LFSR is in state 0. It might make more sense to use even smaller segments to speed up the un-hash conversion.

author: bsccara
author_rank: Contributor
timestamp: July 03, 2019, 06:24:25 pm
content: 'duak', that would reduce the maximum number of steps (and inherently maximum count) for the same bit size, as a 36 bit LFSR would have a maximum period of 236-1, while two 18 bit ones would have a (218-1)2maximum period. Also having the most significant LFSR being enabled through a multi-LUT zero detection would make for a lower Fmaxand increased propagation delays, making timing closure much harder.

author: duak
author_rank: Super Contributor
timestamp: July 03, 2019, 07:52:12 pm
content: bsccara: yes, you are correct that the segmented LFSR counter scheme is not as efficient, however if my algebra is correct the maximum period is 2^36 - 2*2^18 + 1. This is greater than 2^35 which is your minimum requirement.If I remember correctly, LFSRs can be described using Galois Fields. I know nothing more although I understand that the French cigarettes are named after Evariste Galois, the mathematician that developed the theory behind them.I don't know what device(s) you are planning to use to implement the counters - FPGAs or gate arrays or ?. I agree there will likely be another gate delay that has to be compensated for.I think the limiting speed of the entire counter chain is determined by two factors (in addition to the clock rate of the flips-flops):1.) detecting zero - depending on the resources of the device, this could be as simple as a wired-OR or something as complicated as a multilevel tree. It may be possible to pipeline the zero detect and have it spread over two clock cycles. This could be compensated for by adjusting the preload pattern by one. Alternately, you could also detect the state before all zeros. However, these schemes will limit the minimum count.2.) the second LFSR segment will need to be enabled for one clock cycle at a time - basically the 'carry' or zero detect out of the first segment. Again, I don't know what resources your device has, but what is needed is either a 'D' flip-flop with an enable input or a gateable clock.

author: hamster_nz
author_rank: Super Contributor
timestamp: July 03, 2019, 09:44:20 pm
content: Quote from: bsccara on July 03, 2019, 02:25:36 pmIf you tell me enough to know what you are doing I might end up doing most of the work for you...e.g. which polynomial - Maybe I should just assume 35,33 & 9,5.

author: ejeffrey
author_rank: Super Contributor
timestamp: July 03, 2019, 10:10:46 pm
content: IIRC LFSR can be trivially reversed. I think what you do is mirror the taps and then it will cycle through mirrored state registers in reverse order. I don't exactly remember the details but it should be easy to figure out.

author: bsccara
author_rank: Contributor
timestamp: July 03, 2019, 10:35:33 pm
content: 'duak', I've tested your idea prior to my reply using the following HDL:Code:library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.NUMERIC_STD.ALL;entity Timer2 isport(CLK: in std_logic;COUNT: out std_logic_vector(35 downto 0));end Timer2;architecture RTL of Timer2 issignal lfsr1: std_logic_vector(18 downto 1) := (others => '0');signal lfsr2: std_logic_vector(18 downto 1) := (others => '0');beginprocess(CLK)beginif rising_edge(CLK) thenlfsr1(1) <= lfsr1(18);lfsr1(11 downto 2) <= lfsr1(10 downto 1);lfsr1(12) <= lfsr1(11) xnor lfsr1(18);lfsr1(18 downto 13) <= lfsr1(17 downto 12);end if;end process;process(CLK)beginif rising_edge(CLK) thenif lfsr1 = "000000000000000000" thenlfsr2(1) <= lfsr2(18);lfsr2(11 downto 2) <= lfsr2(10 downto 1);lfsr2(12) <= lfsr2(11) xnor lfsr2(18);lfsr2(18 downto 13) <= lfsr2(17 downto 12);end if;end if;end process;COUNT <= lfsr2 & lfsr1;end RTL;and used the following for a single, larger LFSR:Code:library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.NUMERIC_STD.ALL;entity Timer isport(CLK: in std_logic;COUNT: out std_logic_vector(34 downto 0));end Timer;architecture RTL of Timer issignal lfsr: std_logic_vector(35 downto 1) := (others => '0');beginprocess(CLK)beginif rising_edge(CLK) thenlfsr(1) <= lfsr(35);lfsr(33 downto 2) <= lfsr(32 downto 1);lfsr(34) <= lfsr(33) xnor lfsr(35);lfsr(35) <= lfsr(34);end if;end process;COUNT <= lfsr;end RTL;I ran both through the Lattice Diamond toolchain, using LSE for synthesis, as top-level modules. And I got these results for Fmaxfor the CLK signal on a Mach XO2:Stage2 x 18 bit LFSR1 x 35 bit LFSRSynthesis136.799 MHz298.240 MHzMap139.762 MHz400.000 MHzPlace & Route177.305 MHz358.938 MHzGiven these results I'd rather stick with my current LFSR design; the zero detection is not a (big) issue as it is indeed pipelined and the timer as a whole can run at well over 200 MHz.

author: bsccara
author_rank: Contributor
timestamp: July 03, 2019, 10:56:39 pm
content: 'hamster_nz', indeed you are correct on the polynomials. Also I'd like to thank your interest on my question as I'm struggling with your algorithm. Your code uses several 'magic' values that I don't quite get their origins but they do seem to be (or at least they are equal to):Code:0x0c == fourth state after 000000x19 == fourth state after 000010x07 == fourth state after 000100x0e == fourth state after 001000x09 == fourth state after 010000x06 == fourth state after 10000If I'm correct your code is very efficient at computing the state at a fixed offset from any initial state, requiring only six 'magic' values. But I need to be able to compute the state at any offset from a fixed initial state (given the periodic nature of the LFSR, as you already mentioned, that initial state can be 0 and the offset can be reversed). From your code and explanation the first 'magic' value alone would require a table with one element for each possible offset, totally negating the purpose of the algorithm. So, can you clarify the origin of those 'magic' numbers ?

author: langwadt
author_rank: Super Contributor
timestamp: July 03, 2019, 11:28:43 pm
content: Quote from: bsccara on July 03, 2019, 10:35:33 pmhow does that compare to a regular counter maybe with a bit or two of prescaler?

author: hamster_nz
author_rank: Super Contributor
timestamp: July 03, 2019, 11:47:13 pm
content: Quote from: bsccara on July 03, 2019, 10:56:39 pmI did leave enough breadcrumbsI got those numbers exactly as you suggested - I put 00 as the initial state of the LFSR, and ran it forward four states, giving 0C.I then put 01 ran it forward four states, giving 19. To isolate the change that bit makes, I have to remove the change that would occur even if this bit wasn't set, hence why it is XORed with 0CI then did the same for 02, 04, 08 & 10, so I know what effect that having each bit set leads to four cycles into the future.There isn't anything magical about the number four, I just wanted something I could count lines on the screen.So what if I want to jump ahead 8 states? Easy - just run it through it twice.Code:guess = 0x0c;if((state & 0x01) != 0) guess ^= 0x19 ^ 0x0C;if((state & 0x02) != 0) guess ^= 0x07 ^ 0x0C;if((state & 0x04) != 0) guess ^= 0x0e ^ 0x0C;if((state & 0x08) != 0) guess ^= 0x09 ^ 0x0C;if((state & 0x10) != 0) guess ^= 0x06 ^ 0x0C// advance the state four cycles into the futurestate = guess;guess = 0x0c;if((state & 0x01) != 0) guess ^= 0x19 ^ 0x0C;if((state & 0x02) != 0) guess ^= 0x07 ^ 0x0C;if((state & 0x04) != 0) guess ^= 0x0e ^ 0x0C;if((state & 0x08) != 0) guess ^= 0x09 ^ 0x0C;if((state & 0x10) != 0) guess ^= 0x06 ^ 0x0Cstate = guess;// statue is now 8 cycles into the futureNow If I run 00, 01, 02, 04, 08 and 10, through this "Advance 8 cycles" I will end up with 6 new magic numbers, that can be used to jump 8 states ahead in one operation.You can probably see where this is going...If you build a table "magic" where:* magic[] is what is used to jump ahead one state* magic[] is what is used to jump ahead two states* magic[] is what is used to jump ahead four states* magic[] is what is used to jump ahead eight states* magic[] is what is used to jump ahead sixteen statesYou can calculate the value in magic[] by using the values in magic twice. You can then calculate the value in magic[] by using calculate the value in magic[] twice, and so on. (For debugging the values for magic[] should be the numbers we already have)So we now have a way to skip forward any of 1,2,4, 8 or 16 states.If we want to skip back 10 states because the LFSR has 31 states is the same as skipping forward 21 states. You can use magic[], magic[] and magic[], to jump forward 1, then 4, then 16 states, for a total of 21, but only performing three sets of calculations:Code:So the end code looks something like:for(index = 0; index < lfsr_bit_length; index++) {if((number_to_skip & (1<<index)) != 0) {guess = magic;if((state & 0x01) != 0) guess ^= magic ^ magic;if((state & 0x02) != 0) guess ^= magic ^ magic;if((state & 0x04) != 0) guess ^= magic ^ magic;if((state & 0x08) != 0) guess ^= magic ^ magic;if((state & 0x10) != 0) guess ^= magic ^ magic;state = guess;}}For a small LFSR like this it doesn't help much, but for a 36 bit FSM it is far quicker that rolling through states.In BigO notation it changes the runtime from O(2^n) to O(n^2).

author: Someone
author_rank: Super Contributor
timestamp: July 03, 2019, 11:51:23 pm
content: Quote from: bsccara on July 03, 2019, 06:24:25 pmYou're talking about a loadable counter, have you looked at the critical timing paths? Using a binary counter with "hard" carry resources and the overflow as your end of count indicator is likely to be faster than an lfsr and the comparison logic.

author: hamster_nz
author_rank: Super Contributor
timestamp: July 04, 2019, 12:27:11 am
content: Quote from: Someone on July 03, 2019, 11:51:23 pmI initially thought that too, but the LFSR with two taps soon becomes quicker that a long counter as bit length grows.For example in Spartan 3 the carry chain is ~0.05 ns per bit. so a 36 bit counter needs 1.8ns for just carry chain alone, and then you need at least one level of logic in the loop as a MUX to load the preset values.A long "LFSR with load" and two taps requires only one level of logic, making it at least 1.8ns faster than the a long counter (in Spartan 3).The logic required to detect the zero state is another thing. That would need to be pipelined to run fast...

author: langwadt
author_rank: Super Contributor
timestamp: July 04, 2019, 12:36:28 am
content: Quote from: hamster_nz on July 04, 2019, 12:27:11 ama single bit as prescaler/CE on a 35 bit counter and you have twice as much time ?

author: hamster_nz
author_rank: Super Contributor
timestamp: July 04, 2019, 05:45:03 am
content: Curiosity got the better of me. Here is the implementation for the 9-bit LFSR, that dynmically builds the tables test it works for all values. The 36-bit one will involve:- changing uint32_t to uint64_t- changing BITS to 36- changing the taps used in advance_lfsr()- a slightly longer time to test for all values.Code:#include <stdio.h>#include <stdint.h>#define BITS (9)static uint32_t magic_zero;static uint32_t magic;/****************************************** The LFSR calculation****************************************/static uint32_t advance_lfsr(uint32_t state) {uint32_t new_bit;new_bit = 1^((state & 0x100) ? 1 : 0) ^ ((state & 0x010) ? 1 : 0);state = (state << 1 )|new_bit;state &= (1<<BITS)-1;return state;}/****************************************** The LFSR speedup, that advances 2^bit_to_advance****************************************/static uint32_t advance_fast(uint32_t state, int bit_to_advance) {uint32_t guess, i;guess = magic_zero;for(i = 0; i < BITS; i++) {if((state & (1<<i)) != 0) guess ^= magic;}return guess;}/****************************************** Calculate the magic values that are the* future contributions of 'zero' and than* the contribuions of each bit.****************************************/static void calculate_magic_values(void) {int i, bit;/* Calculate the first entry, using the traditional LFSR function */magic_zero = advance_lfsr(0);for(i = 0; i < BITS; i++) {magic = advance_lfsr(1<<i) ^ magic_zero;}/* Calculate all other entries, by applying the last set of values twice */for(bit=1; bit < BITS; bit++) {uint32_t state = 0;state = advance_fast(state,bit-1);state = advance_fast(state,bit-1);magic_zero = state;for(i = 0; i < BITS; i++) {state = 1<<i;state = advance_fast(state,bit-1);state = advance_fast(state,bit-1);magic = state ^ magic_zero;}}/* Print out the table */for(i = 0; i < BITS; i++) {printf("%03x", magic_zero);for(bit = 0; bit < BITS; bit++) {printf(" %03x", magic);}printf("\n");}}int main(int argc, char *argv[]){uint32_t distance;calculate_magic_values();/* Verify that it works for all distances */for(distance = 0; distance < 1<<BITS; distance++) {uint32_t initial = 0;uint32_t state = initial;printf("\n");printf("distance = %i\n", distance);printf("State Calculated Guessed Error?\n");do {uint32_t calced, guess, i;/* Calculate it the fast way */guess = state;for(i = 0; i < BITS; i++) {if((distance & (1<<i)) != 0) {guess = advance_fast(guess,i);}}/* Now calculate it the long way */calced = state;for(i = 0; i < distance; i++) {calced = advance_lfsr(calced);}/* Show results */printf("%03x %03x %03x %s\n", state, calced, guess, calced ^ guess ? "yes" : "no");/* Move on to next state */state = advance_lfsr(state);} while(state != initial);}return 0;}

author: Someone
author_rank: Super Contributor
timestamp: July 05, 2019, 01:11:31 am
content: Quote from: hamster_nz on July 04, 2019, 12:27:11 am... so if you're able to accept pipelining the comparison, then why not pipeline a binary (and/or other types of) counter in the first place?

author: hamster_nz
author_rank: Super Contributor
timestamp: July 05, 2019, 01:55:29 am
content: Quote from: Someone on July 05, 2019, 01:11:31 amMore a question for the OP, but I assume their view is it takes a problem you can solve with simple, fast, well understood hardware design and some not-too-hard software into one that needs tricky (and maybe unfeasible) hardware design with the goal of making it simple for software.

author: Someone
author_rank: Super Contributor
timestamp: July 05, 2019, 04:25:59 am
content: Quote from: hamster_nz on July 05, 2019, 01:55:29 amPipelining a counter is possibly unfeasible? I cannot see it being any more so than pipelining a match circuit. An LFSR that self resets to a loadable length is the oddball hardware design here. Seems like the classic case of pre-emptive optimisation gone wrong, having not seen any comparisons of fleshed out examples from you or the OP.But do continue on your academic meander, its interesting if entirely missing the practicalities. Trying to suggest a binary counter as synthesised from high level code is somehow esoteric or complex in comparison has made my day.

author: hamster_nz
author_rank: Super Contributor
timestamp: July 05, 2019, 05:29:08 am
content: Quote from: Someone on July 05, 2019, 04:25:59 amTo show the complexity:if I were to race you to build either a 16-bit counter on a breadboard out of TTL Quad D-flipflops and two-input logic gates, I bet I could get my LFSR counter up and running quicker, and it would count faster, because it is less complex.A full adder would need 5 gates per bit, so an adder-based binary counter would need 24 chips (80 for logic gates and and 16 FFs), but a LFSR would only need 5 (1 or two logic gates and 16 FFs). The binary counter might only need half that many logic gates as you can use half-adders... but that is still 14 chips vs 5.If the OP is working past where a binary counter can meet timing, moving to an LFSR based timer is a workable solution.LFSRs go from boring to interesting as you learn more about them, as they seem to pop up everywhere:- Data integrity, such as CRC codes (https://en.wikipedia.org/wiki/Cyclic_redundancy_check)- Scrambling (as used in PCIe, DisplayPort, SDI, networknghttp://en.wikipedia.org/wiki/Scrambler)- Communication such as GPS (eg.https://en.wikipedia.org/wiki/Direct-sequence_spread_spectrum)- Forward Error correction (e.g.https://en.wikipedia.org/wiki/BCH_code,as used in HDMI)- Pseudo-random binary sequences for such things as built in self tests and device characterization- High speed counters- Cryptography

author: Someone
author_rank: Super Contributor
timestamp: July 05, 2019, 05:47:41 am
content: Quote from: hamster_nz on July 05, 2019, 05:29:08 amExcept the target is an FPGA, not discrete gates, and is programmed in a high level language. I'm fully aware of the wide use of LFSRs and that as a counter they can be power efficient, but that isn't looking at the specific example here of a self resetting loadable counter.

author: hamster_nz
author_rank: Super Contributor
timestamp: July 05, 2019, 08:10:25 am
content: Two designs in the same wrapper.Code:library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.NUMERIC_STD.ALL;entity binary_counter isPort ( clk : in STD_LOGIC;load : in STD_LOGIC;initial : in STD_LOGIC_VECTOR (35 downto 0);pulse : out STD_LOGIC);end binary_counter;architecture Behavioral of binary_counter issignal counter : unsigned(initial'length downto 0) := (others => '0');constant zero : unsigned(0 downto 0) := (others => '0');beginprocess(clk)beginif rising_edge(clk) thenpulse <= std_logic(counter(counter'high));if load = '1' thencounter <= zero & unsigned(initial);elsecounter <= (zero & counter(counter'high-1 downto 0)) + 1;end if;end if;end process;end Behavioral;Code:library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.NUMERIC_STD.ALL;entity lfsr_counter isPort ( clk : in STD_LOGIC;load : in STD_LOGIC;initial : in STD_LOGIC_VECTOR (35 downto 0);pulse : out STD_LOGIC);end lfsr_counter;architecture Behavioral of lfsr_counter issignal state : STD_LOGIC_VECTOR(initial'high downto 0) := (others => '0');beginprocess(clk)beginif rising_edge(clk) thenif state = x"000000000" thenpulse <= '1';elsepulse <= '0';end if;if load = '1' thenstate <= initial;elsestate <= state(state'high-1 downto 0) & (state(state'high) xor state(5) xor '1');end if;end if;end process;end Behavioral;Although subtly different, both are constrained the same, to the time where both meet the same timing:Code:TIMESPEC TS_clk = PERIOD "clk" 3.51 ns HIGH 50%;Want to guess which timing is the counter, and which the LFSR?Code:Design statistics:Minimum period: 3.509ns{1} (Maximum frequency: 284.981MHz)Code:Design statistics:Minimum period: 2.586ns{1} (Maximum frequency: 386.698MHz)

author: Someone
author_rank: Super Contributor
timestamp: July 05, 2019, 09:33:03 am
content: Quote from: hamster_nz on July 05, 2019, 08:10:25 amNo idea what optimisations you're using in implementation but that binary counter is a full width, when we have repeatedly said it could be divided up or pipelined. If you're not making any effort to improve upon an inferred single cycle counter then its not surprising it implemented slower.Just to settle this for my own knowledge I threw three versions into a few different devices and consistently had a pipelined counter slower than either an LFSR or partitioned counter. The partitioned counter was consistently the fastest, using a few extra LUTs and control sets compared to the LFSR but fewer flops. But they all surpassed the switching limits of the clock nets, so its past the point of worrying unless you want to get into clocks routed on the general fabric (at which point there are usually better ways to reframe the problem).

author: bsccara
author_rank: Contributor
timestamp: July 05, 2019, 10:51:05 am
content: 'someone', my main goal going with the LFSR is not absolute maximum Fmax. I need it to be fast enough to not impede timing closure but also as light as possible on resources as I have 16 of them on the design. As it is the FPGA is already almost maxed out, particularly on LUTs...There's also some misunderstanding going on, as the LFSR counter does not self-reset; after being enabled from other logic it steps from a loadable initial state until zero, at which time that other logic will disable it. The loading is done while the timer is reset but I wouldn't call it self-reseting, as it doesn't continue on by itself.

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 05, 2019, 05:39:08 pm
content: Quote from: hamster_nz on July 05, 2019, 05:29:08 amI don't know much about the hardware (just about zero on VHDL, Verilog, or FPGAs), but I do scientific work (computational materials physics; simulators and such), and the two PRNG families I use, Mersenne Twister and Xorshift, are both based on linear feedback shift registers. Xorshift is pure XOR LFSR with optional output twizzling through multiplication that does not affect the state at all (it just provides better distribution in the output bits), and Mersenne Twister is a twisted generalized feedback shift register.MT19937 in particular is used everywhere; it's the default PRNG in Python (randommodule), for example.It might be important to note here that OP is actually interested in two different aspects of XNOR LFSRs: One is hardware implementation for a fast counter, towards an all-zero state; and another is a generic C implementation run on a desktop-type computer, to calculate the initial state needed for the hardware implementation to reach the all-zero state in a specific number of steps.A 9-bit XNOR LFSR can have 511 distinct states (excluding the all-ones halt state). This is such a small number of states that the generic C implementation can tabulate all values according to the number of steps to the all-zero state.A 35-bit XNOR LFSR can have 235-1 = 34,359,738,367 distinct states (again excluding the all-ones halt state). It is not feasible to tabulate all of these in a desktop program; that'd take gigabytes of memory.My example program above shows that for any XNOR LFSR implementation, you can easily create (and shows how) a complementary XNOR LFSR, that produces the same sequence, but in the reverse direction. Since I wrote it for illustration only, it is also just about the slowest way to go about it, though; but to show much faster implementations, one should use a fixed characteristic polynomial (fixed taps and LFSR size).My suggestion for the desktop program is to precalculate the reverse sequence once, saving suitable states and their distances from the zero state. To find the desired start state, one picks the saved state furthest from the zero state not further than the desired distance, and continue from that point using the complementary XNOR LFSR. A few tens of thousands of saved states means every distinct state can be reached with fewer than a million iterations, which should be plenty fast enough for a desktop configuration application.My earlier post attempted to explain that if the desktop application needs to be even faster, one can find any distinct state based on their distance from the zero state, in logarithmic time. It is just much more complicated to implement, as it usually involves functions that produce the same result in fixed time as iterating the XNOR LFSR a fixed number of times would. In other words, you can implement the functionality to find a specific state for the hardware counter to reach all-zero state in a specific number of steps, even on a weak microcontroller; it just takes somewhat more mathy programming work, i.e. human programmer time and effort.xhamster_nz above showed an alternate method, using precalculated look-up tables, to implement a fast state finder for a specific distance from the all-zero state. I found them fascinating; I have never explored that approach before. (Then again, I haven't explored skipping ahead in an LFSR before, either.) Thanks!The Xilinx XAPP 052 from 1996 states that for a 9-bit XNOR LFSR, taps 9 and 5 (corresponding to characteristic polynomial of x9+x5+1) produces a maximal-length sequence; and taps 35 and 33 (corresponding to x35+x33+1) for 35-bit XNOR LFSR. Two taps is the minimum number of taps needed for a maximal-length XNOR LFSR, so these taps seem optimal to me for OP's use case.Perhaps OP could confirm these are the XNOR LFSRs they're particularly interested in? If so, we could easily whip up example programs/C functions to generate the desired states for the hardware to reach the all-zero state in the specified number of steps. Otherwise, I am afraid this thread is at serious risk of derailing...