关于如何正确编码 LFSR 的问题
Question about how to code the LFSR correctly
我在维基百科上找到了下面的线性反馈移位寄存器程序的例子,但我完全不明白:
#include <stdint.h>
#include <stdio.h>
unsigned lfsr_fib()
{
uint16_t start_state = 0xACE1u; /* Any nonzero start state will work. */
uint16_t lfsr = start_state;
uint16_t bit; /* Must be 16-bit to allow bit<<15 later in the code */
unsigned period = 0;
do
{ /* taps: 16 14 13 11; feedback polynomial: x^16 + x^14 + x^13 + x^11 + 1 */
bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5)) & 1u;
lfsr = (lfsr >> 1) | (bit << 15);
++period;
}
while (lfsr != start_state);
return period;
}
int main()
{
printf("%d\n", lfsr_fib());
return 0;
}
首先,关于 LFSR 的小知识。使用 LFSR 计算滚动反馈,最终确定单个比特值。然后在将寄存器向下移动一位后,将该值放入寄存器的 most-significant 位。您发布的 LFSR 进展中最重要的两个操作是:
/* taps: 16 14 13 11; feedback polynomial: x^16 + x^14 + x^13 + x^11 + 1 */
bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5)) & 1u;
lfsr = (lfsr >> 1) | (bit << 15);
您在 bit =
行中看到的移位对应于相应指数的多项式项 >= 1。它们的一系列拉取和 XOR 最终输入到最后一位的计算中。
((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5))
16 14 13 11
然后将寄存器下移一位后将结果放入前导位:
lfsr = (lfsr >> 1) | (bit << 15);
当与适当的原始多项式一起使用时(其生成超出了本文的范围,但如果您愿意的话,这是一项有趣的调查),这可以生成最大周期(所有值都是在序列开始重复之前已经精疲力尽,除了零,这是基本 LFSR 的死亡,希望出于显而易见的原因)。提供的代码通过确保原始素数不会再次出现 2^N-1 来对此进行测试,其中 N 是 LFSR 的位宽。您提供的示例使用 16 位 LFSR,并且当 运行 时,将按预期打印 65535。下面显示了一个八位版本:
unsigned lfsr_fib8()
{
uint8_t start_state = 0x01;
uint8_t lfsr = start_state;
uint8_t bit;
unsigned period = 0;
do
{ /* taps: 8 6 5 4 ; feedback polynomial: x^8 + x^6 + x^5 + x^4 + 1 */
bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 4)) & 1u;
lfsr = (lfsr >> 1) | (uint8_t)(bit << 7);
++period;
} while (lfsr != start_state);
return period;
}
如预期的那样,这将产生 255。最后,针对您的问题,一个 4 位版本。在这里我们必须有点创意(但不要太多),因为我们没有只有 4 位宽的固有本机类型。没关系。只需确保您只使用低半字节,并且不要使用高于 0x0F 的任何内容来启动起始状态。
unsigned lfsr_fib4()
{
uint8_t start_state = 0x01;
uint8_t lfsr = start_state;
uint8_t bit;
unsigned period = 0;
do
{ /* taps: 4 1 ; feedback polynomial: x^4 + x + 1 */
bit = ((lfsr >> 0) ^ (lfsr >> 3)) & 1u;
lfsr = ((lfsr >> 1) | (uint8_t)(bit << 3)) & 0x0F;
++period;
} while (lfsr != start_state);
return period;
}
这将 return 15,正如预期的那样。
我在维基百科上找到了下面的线性反馈移位寄存器程序的例子,但我完全不明白:
#include <stdint.h>
#include <stdio.h>
unsigned lfsr_fib()
{
uint16_t start_state = 0xACE1u; /* Any nonzero start state will work. */
uint16_t lfsr = start_state;
uint16_t bit; /* Must be 16-bit to allow bit<<15 later in the code */
unsigned period = 0;
do
{ /* taps: 16 14 13 11; feedback polynomial: x^16 + x^14 + x^13 + x^11 + 1 */
bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5)) & 1u;
lfsr = (lfsr >> 1) | (bit << 15);
++period;
}
while (lfsr != start_state);
return period;
}
int main()
{
printf("%d\n", lfsr_fib());
return 0;
}
首先,关于 LFSR 的小知识。使用 LFSR 计算滚动反馈,最终确定单个比特值。然后在将寄存器向下移动一位后,将该值放入寄存器的 most-significant 位。您发布的 LFSR 进展中最重要的两个操作是:
/* taps: 16 14 13 11; feedback polynomial: x^16 + x^14 + x^13 + x^11 + 1 */
bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5)) & 1u;
lfsr = (lfsr >> 1) | (bit << 15);
您在 bit =
行中看到的移位对应于相应指数的多项式项 >= 1。它们的一系列拉取和 XOR 最终输入到最后一位的计算中。
((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5))
16 14 13 11
然后将寄存器下移一位后将结果放入前导位:
lfsr = (lfsr >> 1) | (bit << 15);
当与适当的原始多项式一起使用时(其生成超出了本文的范围,但如果您愿意的话,这是一项有趣的调查),这可以生成最大周期(所有值都是在序列开始重复之前已经精疲力尽,除了零,这是基本 LFSR 的死亡,希望出于显而易见的原因)。提供的代码通过确保原始素数不会再次出现 2^N-1 来对此进行测试,其中 N 是 LFSR 的位宽。您提供的示例使用 16 位 LFSR,并且当 运行 时,将按预期打印 65535。下面显示了一个八位版本:
unsigned lfsr_fib8()
{
uint8_t start_state = 0x01;
uint8_t lfsr = start_state;
uint8_t bit;
unsigned period = 0;
do
{ /* taps: 8 6 5 4 ; feedback polynomial: x^8 + x^6 + x^5 + x^4 + 1 */
bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 4)) & 1u;
lfsr = (lfsr >> 1) | (uint8_t)(bit << 7);
++period;
} while (lfsr != start_state);
return period;
}
如预期的那样,这将产生 255。最后,针对您的问题,一个 4 位版本。在这里我们必须有点创意(但不要太多),因为我们没有只有 4 位宽的固有本机类型。没关系。只需确保您只使用低半字节,并且不要使用高于 0x0F 的任何内容来启动起始状态。
unsigned lfsr_fib4()
{
uint8_t start_state = 0x01;
uint8_t lfsr = start_state;
uint8_t bit;
unsigned period = 0;
do
{ /* taps: 4 1 ; feedback polynomial: x^4 + x + 1 */
bit = ((lfsr >> 0) ^ (lfsr >> 3)) & 1u;
lfsr = ((lfsr >> 1) | (uint8_t)(bit << 3)) & 0x0F;
++period;
} while (lfsr != start_state);
return period;
}
这将 return 15,正如预期的那样。