CRC(循环冗余校验)的verilog实现

算法简介:

一种信道编码技术,用来检测数据传输或者保存后可能出现的错误,其使用模2除法进行校验,计算速度快,检错能力强,有不同的标准参数模型,标准越高则检错能力和精度越好。

算法实现:

(以CRC-5为例(初值00)):其生成多项式为X5+X3+1 输入输出无需翻转。设数据串为100101

  1. 根据生成多项式不同幂次的系数得到其二进制为:101001(除数),由于首位和末尾必为1,所以省略首位为01001 = 0x099 (POLY)
  2. 给数据串后补上省略首位后的系数位数的0,得到新数据串100101 00000(被除数).
  3. 将新数据串和除数进行模2除法运算,得到5位余数即CRC校验码10111.
  4. 将得到的余数拼接在数据串末尾,得到新数据串,
  5. 用该数据串模2除以除数,若无余数,说明无误码。

实现电路:

根据多项式画出标准电路

列出表达式:

D0 <= data_in ^ D4 ;

D1 <= D0 ;

D2 <= D1 ;

D3 <= data_in ^ D4 ^D2 ;

D4 <= D3 ;

 Data-in

D0

D1

D2

D3

D4

0

0

0

0

0

0

1

1

0

0

1

0

0

0

1

0

0

1

0

1

0

1

1

0

1

1

1

0

0

1

0

1

1

1

1

0

1

1

1

1

0

1

当6个时钟周期结束后,D4-D0的值即是CRC校验码10111

verilog实现:(.V文件)

module crc (
			input [5:0] data_in , 				//输入待检测数据
			output [4:0] crc_data ,				//CRC校验码输出
			input rst ,					
			input clk ,
			output wire [4:0] result ,					// 最后用来检验的余数
			output wire [10:0] string_data   	//	定义输出的CRC数据串 
			) ;
			
			
reg [4:0] reminder_1 , reminder_2 ,				//两组中间变量, 用来储存电路现态和次态的值
				mod1 , mod2 ;

				
wire [5:0] data ;
integer i =0 ;
integer j = 0;


assign string_data = {crc_data[0],crc_data[1],crc_data[2],crc_data[3],crc_data[4],data_in[0],data_in[1],data_in[2],data_in[3],data_in[4],data_in[5]} ;			//将输入数据和CRC校验码拼接
assign data = {data_in[0],data_in[1],data_in[2],data_in[3],data_in[4],data_in[5]} ;  		 //储存输入数据100101
assign crc_data= {reminder_2[4],reminder_2[3],reminder_2[2],reminder_2[1],reminder_2[0]} ;	//将中间变量数据传入CRC值
assign result = {mod2[4],mod2[3],mod2[2],mod2[1],mod2[0]} ;					//余数

always @ (*) begin

reminder_1[0] <= data [i] ^ reminder_2 [4] ;							//根据电路图写出关系式
reminder_1[1] <= reminder_2 [0] ;											//D0 <= data_in ^ D4
reminder_1[2] <= reminder_2 [1] ;											//D1 <= D0 
reminder_1[3] <= data [i] ^ reminder_2 [4] ^ reminder_2 [2] ;		//D2 <= D1 
reminder_1[4] <= reminder_2 [3] ;											//D3 <= data_in ^ D4 ^D2
																						//D4 <= D3
mod1[0] <= string_data [j] ^ mod2 [4] ;
mod1[1] <= mod2 [0] ;
mod1[2] <= mod2 [1] ;
mod1[3] <= string_data [j] ^ mod2 [4] ^ mod2 [2] ;
mod1[4] <= mod2 [3] ;



end

always @ (posedge clk or posedge rst ) begin 
	if(rst) begin
	reminder_2 <= {5{1'b0}} ;						//复位使电路状态清0
		mod2 <= {5{1'b0}};
	end
	else if (i <= 5 && j<=10)begin
	mod2 <= mod1 ;
	reminder_2 <= reminder_1 ;							//	i递增,控制data_in的顺序进入		(LSB)
		i = i +1 ;											// j递增,控制string_data的顺序进入 (LSB)
		j = j + 1;
		end
		else if (i > 5 && j>10)begin
			mod2 <= mod2 ;
		reminder_2 <=reminder_2 ;
		end
		else begin
		reminder_2 <=reminder_2 ;
		mod2 <= mod1 ;
		j = j+1 ;
		end
			
end

endmodule

 (测试文件)

`timescale 1 ps/ 1 ps
module crc_vlg_tst();

reg clk;
reg [5:0] data_in;
reg rst;
                                               
wire [4:0]  crc_data;
wire [4:0] result ;
wire [10:0] string_data ;



                        
crc i1 (

	.clk(clk),
	.crc_data(crc_data),
	.data_in(data_in),
	.rst(rst) ,
	.string_data(string_data) ,
	.result(result)
	
);
always #10 clk = ~clk ;
initial                                                
begin 
clk = 0;
rst = 1 ;
data_in <= 6'b100101 ; 
#20
rst = 0 ; 
                                              

                                         
$display("Running testbench");                       
end                                                    
                                                
endmodule

波形验证:

 

可以看到对于拼接CRC校验码后的数据串,通过电路,最后留下的余数为00000,证明数据无误,且通过在线计算得到CRC校验码无误。

刚开始研究,代码较为繁琐,如有错误,欢迎大神沟通指正! 

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值