CRC和LFSR

先说下LFSR,中文叫线性反馈移位寄存器,英文的全称是了linear feedback shift register,这个其实是由SR—>FSR—>LFSR逐步发展出来的,SR也就是移位寄存器,这个我们都很熟悉,串并转换里经常用,网上找个图:
image
也就是数据挨个从左到右(从右到左)的移出,右边移出一位左边就空出一位,空出的这一位大部分情况下默认补0,如果这一位我们通过某个函数来计算,这个函数的输入就是寄存器组中已有的这些数,函数的输出填到左边空出的这一位,通过这种方式我们就进一步得到了反馈寄存器,也就是FSR,它可以源源不断的进行输出,贴个图:
image
再进一步,如果这个反馈函数,是一个线性的函数呢?这里略微补充下线性函数的定义,就是满足f(ax+by)=af(x)+bf(y)这样的函数,典型的就是f=ax+b,而LFSR的反馈函数定义如下:
image
其中的加法是异或(XOR),乘法是与(AND),Ifsr的反馈函数也满足:
image
所以LFSR是一个线性反馈移位寄存器,上面式子:\(s_{n+k}=c_1 s_{n+k-1} \oplus c_2 s_{n+k-2} \oplus \cdots \oplus c_k s_n\)\(c_1\) \(c_2\)...我们称为系数,值为0或者为1,为1就是表示该位置的值参与计算,参与计算的位也叫抽头,相应的为0就是不参与计算。而寄存器里最开始的的所有值我们称为初始值,也叫种子,基于抽头,我们可以得出一个叫反馈多项式的东西,它就是根据抽头所在的寄存器位置,给多项式定义幂次,举个例子:
image
上图的LFSR级数为16,抽头位置为16 14 13 11,注意图里的位置1并不表示抽头,而是说这里是一个输入,是之前那些值经过反馈函数给返回来的,因为这是反馈移位寄存器,这一位必须要有,所以必须为1,你也可以理解为X^0,也就是1,数学上表达就是:
1X^16 + 0X^15 + 1X^14 + 1X^13 + 0X^12 + 1X^11 + 0X^10 + 0X^9 + 0X^8 + 0X^7 + 0X^6 + 0X^5 + 0X^4 + 0X^3 + 0X^2 + 0X^1 + X^0
等价于:
X^16 + X^14 + X^13 + X^11 + 1
对应的2进制就是:
10110100000000001
一共17位,但是LFSR的表达式最高位都为1,默认省略不写,也就是:
0110100000000001
对应的16进制值是0x6801

LFSR的基础介绍的差不多了,我们再说LFSR常见的两种形式:

  • Fibonacci LFSRs 斐波那契型
  • Galois LFSRs 伽罗瓦型
    Fibonacci LFSRs就是多到1,就是多个抽头位置的值一起异或,生成的结果给到左边空出的那一位,而Galois LFSRs则是抽头位置前一级寄存器的值和输出寄存器的值异或后给到抽头位置的寄存器,贴张图:
    image

好,介绍到这里,我们就开始说CRC,CRC, 全称Cyclic Redundancy Check,中文循环冗余校验,它的原理其实是模2除法的运算,模2除法就是异或运算,要校验的原始数据就是被除数,除数就是一组选定的特殊数据,也就是多项式的2进制表达式,它俩除下来的余数补到原始数据的后面,而接收端收到数据后,会再去执行模2的除法,因为余数已经补上去了,所以接收方计算时,应该是正好能整除的,也就是余数为0。举个例子吧:
image
图里被除数是10000011,除数是1001,多项式就是X^3+1,0x01(最高位默认为1不写),图里我们看到它计算的时候是在原始数据10000011后面补了3个0,因为在多项式除法里,余数的最高次幂一定是小于除数最高次项,除数最高次为3,也就是4位,那余数最高次为2,也就是3位,所以是预留3位。换个角度想,补3个0,也就是把原始数据左移了3位,其实就是给后面把余数补上去时候,预先留的位置,虽然不知道余数是多少,但是余数的位数,一定数小于除数的位数。好,现在我们吧余数补上去,再算一遍:
image
余数正好是0,证明数据没有问题。我们可以找个工具验证一下:
image
结果和我们的一致,没有问题。

好了说了这么多,那CRC这种模2运算,和LFSR有啥关系?到目前为止,我们看到了LFSR是异或运算,CRC的模2除法也是异或运算,我们回看上面CRC计算步骤时,会发现,除的过程其实就是被除数左移,和除数异或的过程,具体逻辑是,判断被除数MSB(最高位)是否为1,如果是的话就进行异或操作,然后余数左移1位,再在右边补上和原始被除数相对应的位的值,形成新的被除数,如果MSB为0,则直接左移,同样补上原始被除数相对应的位的值,一直到被除数MSB为1为止,前面我们说过多项式最高位一定是1,所以每当我们进行异或操作时,余数的高位一定是0,所以不管怎么说,我们都会左移,文字描述很繁琐,还是贴个图:

被除数开始是1000_0011,

常见的地方是生成随机序列,还有一些校验的地方,比如xilinx一些通信类的IP,example design里会用到PRBS,这个叫pseudo—Random Binary Sequence,叫伪随机2进制序列,这个其实就是基于LFSR做的,这个

多项式表达式,最高次的幂为CRC位数,LFSR的寄存器个数为LFSR级数,所以LFSR生成的随机数是有周期的,它的个数为2^n - 1
LFSR初始值成为种子,是不可以为全0的,不然异或操作就总是为0,CRC位数为多项式最高次的幂,计算就是在要校验的数据后补CRC位数的0,然后对多项式进行模2除法,得到的余数就是CRC。接收方接收后,将原本的数据+CRC 对 多项式进行模2除法,余数为0就证明数据没有问题
POLY:生成项的简写,以16进制表示。例如:CRC-32即是0x04C11DB7,忽略了最高位的"1",即完整的生成项是0x104C11DB7。 多项式的首位必为1, 不然就会经过寄存器个数的周期后恒定为0
image
image
image
image
image
斐波那契的LFSR 实现一般是从左到右依次递增:
image
多项式是除数,被检测的数是被除数,
Specify the LFSR/CRC polynomial in hex format. For example, the polynomial
x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
would be represented as
32'h04c11db7,忽略了最高位的1
说白了就是根据那个多项式,画出反馈图,照着这个写代码,以下我根据10G eth里的64b66b多项式写的代码,我详细的列出了运算的步骤:
image
image
下面这个是解扰:
image
image
使用for语句,代码看着就很简单。

同理,CRC32的运算也是类似:
image
它实现了64位数据的crc32计算,其实就是把1位的运算展开迭代了64次,也可以理解为串转并的过程,代价就是当进数位宽很大时,组合逻辑过长,频率高时序就过不了

posted @ 2025-09-25 14:32  原声带1993  阅读(111)  评论(0)    收藏  举报