LFSR和CRC串行实现移位寄存器结构,并行CRC时序实现

文章部分转自https://blog.csdn.net/yongan1006/article/details/8716456

LFSR主要用于通信加扰解扰;CRC主要用于通信传输数据校验。

一 、LFSR

线性反馈移位寄存器(LFSR)是内测试电路中最基本的标准模块结构,既用作伪随机测试码产生器,也作为压缩测试结果数据的特征分析器。

一个n阶的LFSR由n个触发器和若干个异或门组成。在实际应用当中,主要用到两种类型的LFSR,即异或门外接线性反馈移位寄存器(IE型LFSR,图1)和异或门内接线性反馈移位寄存器(EE型LFSR,图2)。其中g0 g1g2 gn为’0’或’1’,Q1 Q2Q3 Qn为LFSR的输出,M(x)是输入的码字多项式,如M(x)=x4+ x1+1,表示输入端的输入顺序为11001,同样,LFSR的结构也可以表示为多项式G(x),称为生成多项式:

G(x)=gn*xn+ …+g1*x1+g0;

 

LFSR和CRC串行实现移位寄存器结构,并行CRC时序实现_第1张图片


                                                                                  图1 IE型LFSR

LFSR和CRC串行实现移位寄存器结构,并行CRC时序实现_第2张图片

                                                                                  图2 EE型LFSR

需要注意的是一位寄存器的初始值不能为全0;

二 、CRC

循环冗余校验码(CRC)的基本原理是:在K位信息码后再拼接R位的校验码,整个编码长度为N位,因此,这种编码又叫(N,K)码。对于一个给定的(N,K)码,可以证明存在一个最高次幂为N-K=R的多项式G(x)可以使整个编码被除余数为0。根据G(x)可以生成K位信息的校验码,而G(x)叫做这个CRC码的生成多项式。校验码的具体生成过程为:假设发送信息用信息多项式C(X)表示,将C(x)左移R位,则可表示成C(x)*2的R次方,这样C(x)的右边就会空出R位,这就是校验码的位置。通过C(x)*2的R次方除以生成多项式G(x)得到的余数就是校验码。

通过CRC的生成原理知道CRC的检验码生成是通过除法得到,由此联想到可以通过LFSR来产生校验码。

假设原信息码子多项式为

LFSR和CRC串行实现移位寄存器结构,并行CRC时序实现_第3张图片

 

生成多项式为

  

LFSR和CRC串行实现移位寄存器结构,并行CRC时序实现_第4张图片

 

那么CRC的码字为LFSR和CRC串行实现移位寄存器结构,并行CRC时序实现_第5张图片 ,使用用LFSR电路来进行实现,将M(x)向左移r位在电路中的意义即为输入完信息码后再输入r个0,所以在电路上的表现就如图5所示。

LFSR和CRC串行实现移位寄存器结构,并行CRC时序实现_第6张图片

 

                                                                         图5 使用LFSR来产生CRE校验码

需要注意的是移位寄存器的初始值不同结果是不一致的。

三、并行实现CRC校验

上面介绍的CRC校验主要是用于单比特流的校验,但是很多实际应用中位宽很大的一组数据需要做CRC校验的情况时以上一位寄存器是不能实现的。例如M位宽的并行数据,我们可以根据移位前的N位寄存器值和M位并行数据的位宽数据做逻辑运算计算出(N+1)阶的CRC值。

代码生成工具网站:https://www.easics.be/webtools/crctool

此网站可以生成Verilog和VHDL的逻辑代码,如果是时序电路把逻辑电路可以修改成时序电路。

生成代码的“Data”是每次输入位宽的数据;“CRC”是初始CRC值和上次生成的CRC。

例如:生成多项式是x^16+x^15+x^2+1,初始值为全1;

生成代码为

////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1999-2008 Easics NV.
// This source file may be used and distributed without restriction
// provided that this copyright statement is not removed from the file
// and that any derivative work contains the original copyright notice
// and the associated disclaimer.
//
// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// Purpose : synthesizable CRC function
//   * polynomial: x^16 + x^15 + x^2 + 1
//   * data width: 16
//
// Info : [email protected]
//        http://www.easics.com
////////////////////////////////////////////////////////////////////////////////
module CRC16_D16;

  // polynomial: x^16 + x^15 + x^2 + 1
  // data width: 16
  // convention: the first serial bit is D[15]
  function [15:0] nextCRC16_D16;

    input [15:0] Data;
    input [15:0] crc;
    reg [15:0] d;
    reg [15:0] c;
    reg [15:0] newcrc;
  begin
    d = Data;
    c = crc;

    newcrc[0] = d[15] ^ d[13] ^ d[12] ^ d[11] ^ d[10] ^ d[9] ^ d[8] ^ d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[2] ^ c[3] ^ c[4] ^ c[5] ^ c[6] ^ c[7] ^ c[8] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[15];
    newcrc[1] = d[14] ^ d[13] ^ d[12] ^ d[11] ^ d[10] ^ d[9] ^ d[8] ^ d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ c[1] ^ c[2] ^ c[3] ^ c[4] ^ c[5] ^ c[6] ^ c[7] ^ c[8] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[14];
    newcrc[2] = d[14] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[14];
    newcrc[3] = d[15] ^ d[2] ^ d[1] ^ c[1] ^ c[2] ^ c[15];
    newcrc[4] = d[3] ^ d[2] ^ c[2] ^ c[3];
    newcrc[5] = d[4] ^ d[3] ^ c[3] ^ c[4];
    newcrc[6] = d[5] ^ d[4] ^ c[4] ^ c[5];
    newcrc[7] = d[6] ^ d[5] ^ c[5] ^ c[6];
    newcrc[8] = d[7] ^ d[6] ^ c[6] ^ c[7];
    newcrc[9] = d[8] ^ d[7] ^ c[7] ^ c[8];
    newcrc[10] = d[9] ^ d[8] ^ c[8] ^ c[9];
    newcrc[11] = d[10] ^ d[9] ^ c[9] ^ c[10];
    newcrc[12] = d[11] ^ d[10] ^ c[10] ^ c[11];
    newcrc[13] = d[12] ^ d[11] ^ c[11] ^ c[12];
    newcrc[14] = d[13] ^ d[12] ^ c[12] ^ c[13];
    newcrc[15] = d[15] ^ d[14] ^ d[12] ^ d[11] ^ d[10] ^ d[9] ^ d[8] ^ d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[2] ^ c[3] ^ c[4] ^ c[5] ^ c[6] ^ c[7] ^ c[8] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[14] ^ c[15];
    nextCRC16_D16 = newcrc;
  end
  endfunction
endmodule

仅供参考的时序电路为:

module CRC_16(
	input clk,
	input reset,
	input sync,
    input [15:0] Data,
	output [15:0] newcrc
    );

	
	
    reg [15:0] d;
   // wire [15:0] newcrc;
	reg [15:0] c;
	reg r_sync;
	always@(posedge clk)
		r_sync<=sync;
	
	always@(posedge clk or posedge reset) begin
		if(reset) begin
			d<=16'd0;
			c<=16'd0;
		end
		else if(sync) begin
			d<=16'd0;
			c<=16'd0;
		end
		else if(r_sync) begin
			d <= Data;
			c <= 16'hFFFF;
		end
		else begin
			d <= Data;
			c <= newcrc;
		end

	end

	assign newcrc[0] = d[15] ^ d[13] ^ d[12] ^ d[11] ^ d[10] ^ d[9] ^ d[8] ^ d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[2] ^ c[3] ^ c[4] ^ c[5] ^ c[6] ^ c[7] ^ c[8] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[15];
	assign newcrc[1] = d[14] ^ d[13] ^ d[12] ^ d[11] ^ d[10] ^ d[9] ^ d[8] ^ d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ c[1] ^ c[2] ^ c[3] ^ c[4] ^ c[5] ^ c[6] ^ c[7] ^ c[8] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[14];
	assign newcrc[2] = d[14] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[14];
	assign newcrc[3] = d[15] ^ d[2] ^ d[1] ^ c[1] ^ c[2] ^ c[15];
	assign newcrc[4] = d[3] ^ d[2] ^ c[2] ^ c[3];
	assign newcrc[5] = d[4] ^ d[3] ^ c[3] ^ c[4];
	assign newcrc[6] = d[5] ^ d[4] ^ c[4] ^ c[5];
	assign newcrc[7] = d[6] ^ d[5] ^ c[5] ^ c[6];
	assign newcrc[8] = d[7] ^ d[6] ^ c[6] ^ c[7];
	assign newcrc[9] = d[8] ^ d[7] ^ c[7] ^ c[8];
	assign newcrc[10] = d[9] ^ d[8] ^ c[8] ^ c[9];
	assign newcrc[11] = d[10] ^ d[9] ^ c[9] ^ c[10];
	assign newcrc[12] = d[11] ^ d[10] ^ c[10] ^ c[11];
	assign newcrc[13] = d[12] ^ d[11] ^ c[11] ^ c[12];
	assign newcrc[14] = d[13] ^ d[12] ^ c[12] ^ c[13];
	assign newcrc[15] = d[15] ^ d[14] ^ d[12] ^ d[11] ^ d[10] ^ d[9] ^ d[8] ^ d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[2] ^ c[3] ^ c[4] ^ c[5] ^ c[6] ^ c[7] ^ c[8] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[14] ^ c[15];


endmodule

testbench

module tb_crc_16;

	// Inputs
	reg clk;
	reg reset;
	reg sync;
	reg [15:0] Data;

	// Outputs
	wire [15:0] c;

	// Instantiate the Unit Under Test (UUT)
	CRC_16 uut (
		.clk(clk), 
		.reset(reset), 
		.sync(sync), 
		.Data(Data), 
		.newcrc(c)
	);

	initial begin
		clk=0;
		forever #5 clk=~clk;
	end
	initial begin
		reset=1;
		#30 reset=0;
	end
	initial begin
		sync=1;
		#50 sync=0;
	end
	initial begin
		#50 Data<=16'h3132;
		#10 Data<=16'h3334;

	end
      
endmodule

在CRC在线计算器网站http://www.ip33.com/crc.html   设置如下,验证结果:

LFSR和CRC串行实现移位寄存器结构,并行CRC时序实现_第7张图片

你可能感兴趣的:(FPGA,通信)