基于FPGA的CRC固定宽度校验的实现

输入:     一个[7:0]xxx[0:x]的数组

                一个使能信号

                clk

                rst_n

输出:     输入的数组内容

                输出使能

                校验通过与否信号


如图,这是crc的输入部分,是一个10字节数组

这是校验的部分

对前8位进行校验,然后输出crc_dout_yorn为1时校验通过,为2时校验不通过

接下来是具体代码

module crc_data(
clk		          ,             
rst_n		      ,               
din		          ,             
din_en		      ,        
crc_dout          ,     
crc_dout_en       ,     
crc_dout_yorn           

);
parameter           WIDTH       =       10;
input		        clk		                                ;
input		        rst_n		                            ;
input	   [7:0]    din[0:WIDTH-1]		                        ;
input               din_en                                  ;
output reg[7:0]    crc_dout[0:WIDTH-1]                            ;
output reg          crc_dout_en                             ;
output reg[1:0]     crc_dout_yorn                           ;
reg[15:0]       crc_end               ;
reg [3:0]       bit_cnt		           ;
reg [7:0]       crc_temp		       ;
reg [15:0]      crc_reg		           ;
reg [2:0]       state_c		           ;
reg [2:0]       state_n		           ;
reg [2:0]       end_cnt                ;
reg  [4:0]      crc_cnt                ;
wire [2:0]      add_bit_cnt 	       ;
wire [2:0]      end_bit_cnt	           ;
wire            idle2crc_xor	       ;
wire            crc_xor2crc_circle	   ;
wire            crc_circle2crg_0reg	   ;
wire            crc_circle2crg_1reg	   ;
wire            crg_0reg2crc_circle	   ;
wire            crg_0reg2crg_done	   ;
wire            crg_1reg2crc_circle	   ;
wire            crg_1reg2crg_done	   ;
wire            crc_done2idle	       ;
reg             crc_en_flag            ;
reg             crc_allend             ;
parameter	IDLE		=	0          ;
parameter	CRC_XOR		=	1          ;
parameter	CRC_CIRCLE	=	2          ;
parameter	CRG_0REG	=	3          ;
parameter	CRG_1REG	=	4          ;
parameter	CRC_DONE	=	5          ;  
crc_data_ip your_instance_name (
	.clk(clk), // input wire clk


	.probe0(din[0]), // input wire [7:0]  probe0  
	.probe1(din[1]), // input wire [7:0]  probe1 
	.probe2(din[2]), // input wire [7:0]  probe2 
	.probe3(din[3]), // input wire [7:0]  probe3 
	.probe4(din[4]), // input wire [7:0]  probe4 
	.probe5(din[5]), // input wire [7:0]  probe5 
	.probe6(din[6]), // input wire [7:0]  probe6 
	.probe7(din[7]), // input wire [7:0]  probe7 
	.probe8(din[8]), // input wire [7:0]  probe8 
	.probe9(din[9]), // input wire [7:0]  probe9 
	.probe10(din_en), // input wire [0:0]  probe10 
	.probe11(crc_dout[0]), // input wire [7:0]  probe11 
	.probe12(crc_dout[1]), // input wire [7:0]  probe12 
	.probe13(crc_dout[2]), // input wire [7:0]  probe13 
	.probe14(crc_dout[3]), // input wire [7:0]  probe14 
	.probe15(crc_dout[4]), // input wire [7:0]  probe15 
	.probe16(crc_dout[5]), // input wire [7:0]  probe16 
	.probe17(crc_dout[6]), // input wire [7:0]  probe17 
	.probe18(crc_dout[7]), // input wire [7:0]  probe18 
	.probe19(crc_dout[8]), // input wire [7:0]  probe19 
	.probe20(crc_dout[9]), // input wire [7:0]  probe20 
	.probe21(crc_dout_en), // input wire [0:0]  probe21 
	.probe22(crc_dout_yorn), // input wire [1:0]  probe22 
	.probe23(crc_end), // input wire [15:0]  probe23 
	.probe24(crc_temp), // input wire [7:0]  probe24 
	.probe25(crc_reg), // input wire [15:0]  probe25 
	.probe26(state_c), // input wire [2:0]  probe26 
	.probe27(crc_cnt), // input wire [4:0]  probe27 
	.probe28(add_bit_cnt ), // input wire [2:0]  probe28 
	.probe29(bit_cnt), // input wire [2:0]  probe29 
	.probe30(idle2crc_xor), // input wire [0:0]  probe30 
	.probe31(crc_done2idle), // input wire [0:0]  probe31 
	.probe32(crc_allend) // input wire [0:0]  probe32
);
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)begin
       end_cnt<=0;
    end
    else if(crc_cnt==WIDTH-1)
    begin
        end_cnt<=end_cnt+1;
    end
    else if(crc_allend)
    begin
        end_cnt<=0;
    end
end
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)begin
	   crc_en_flag<=0;
	end
	else if(din_en)
	   crc_en_flag<=1;
	else if(crc_cnt==WIDTH-2)
	   crc_en_flag<=0;
    else
        crc_en_flag<=crc_en_flag;
end

always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		bit_cnt<=0;
	else if(add_bit_cnt)
	begin
		if(end_bit_cnt)
			bit_cnt<=0;
		else
			bit_cnt<=bit_cnt+1;
	end
end
assign add_bit_cnt = (state_c==CRG_0REG||state_c==CRG_1REG);
assign end_bit_cnt = add_bit_cnt && bit_cnt==8-1;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)begin
		crc_cnt<=1'b0;
  	end
    	else if(end_cnt==3)begin
        	crc_cnt<=0;
    	end
	else if(din_en)begin
		crc_cnt<=crc_cnt+1;
		crc_temp<=din[0];
	end
	else if(state_c==5&&crc_cnt>0&&end_cnt<3)begin
		crc_temp<=din[crc_cnt];
		crc_cnt<=crc_cnt+1;
    end
    else if(crc_allend)
        crc_temp<=0;
	else begin
		crc_cnt<=crc_cnt;
    end
end

always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		crc_reg<=16'hffff;
	else if(state_c==CRC_XOR)
		crc_reg[7:0]<=crc_temp^crc_reg[7:0];
	else if(state_c==CRC_CIRCLE)
		crc_reg<=crc_reg>>1;
	else if(state_c==CRG_1REG)
		crc_reg<=crc_reg^16'hA001;
	else if(crc_allend)
        crc_reg<=16'hffff;
end

always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		crc_dout_en<=1'b0;
	else if(end_cnt==3)
		crc_dout_en<=1'b1;
	else
		crc_dout_en<=1'b0;
end
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
        crc_allend<=0;
	else if(crc_dout_en)
	   crc_allend<=1;
	else
	   crc_allend<=0;
end
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)begin
		crc_end<=16'h0;
		crc_dout_yorn<=0;
	end
	else if(end_cnt==1)
	   crc_end<={crc_reg[7:0],crc_reg[15:8]};
	else if(end_cnt==2)begin
		if({din[8],din[9]}==crc_end)
		  crc_dout_yorn<=1;//无误
		else
		  crc_dout_yorn<=2;//有误
	end
    else if(crc_allend)begin
        crc_dout_yorn<=0;
        crc_end<=0;
    end
    else begin
        crc_dout_yorn<=crc_dout_yorn;
        crc_end<=crc_end;
    end
end

always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin	   
	   for(int i=0;i<9;i=i+1)
	   begin
	       crc_dout[i]<=0;
	   end
	end
	else if(crc_dout_yorn)
	   crc_dout<=din;
end
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		state_c<=IDLE;
	else
		state_c<=state_n;
end

always@(*)
begin
	case(state_c)
	IDLE:begin
		if(idle2crc_xor||idle2crc_xor1)
			state_n = CRC_XOR;
		else
			state_n = state_c;
	end
	CRC_XOR:begin
		if(crc_xor2crc_circle)
			state_n = CRC_CIRCLE;
		else
			state_n = state_c;
	end
	CRC_CIRCLE:begin
		if(crc_circle2crg_0reg)
			state_n=CRG_0REG;
		else if(crc_circle2crg_1reg)
			state_n=CRG_1REG;
		else
			state_n = state_c;
	end
	CRG_0REG:begin
		if(crg_0reg2crc_circle)
			state_n = CRC_CIRCLE;
		else if(crg_0reg2crg_done)
			state_n = CRC_DONE;
		else
			state_n = state_c;
	end
	CRG_1REG:begin
		if(crg_1reg2crc_circle)
			state_n = CRC_CIRCLE;
		else if(crg_1reg2crg_done)
			state_n = CRC_DONE;
		else
			state_n = state_c;
	end
	CRC_DONE:begin
		if(crc_done2idle)
			state_n = IDLE;
		else
			state_n = state_c;
	end
	endcase
end

assign idle2crc_xor	        =(state_c==IDLE&&din_en                    )  ;
assign idle2crc_xor1        =(state_c==IDLE&&crc_en_flag                )  ;
assign crc_xor2crc_circle   =(state_c==CRC_XOR                         )  ;
assign crc_circle2crg_0reg  =(state_c  ==CRC_CIRCLE  &&crc_reg[0]==1'b0)  ;
assign crc_circle2crg_1reg  =(state_c  ==CRC_CIRCLE  &&crc_reg[0]==1'b1)  ;
assign crg_0reg2crc_circle  =(state_c  ==CRG_0REG    &&!end_bit_cnt    )  ;
assign crg_0reg2crg_done    =(state_c  ==CRG_0REG    &&end_bit_cnt     )  ;
assign crg_1reg2crc_circle  =(state_c  ==CRG_1REG    &&!end_bit_cnt    )  ;
assign crg_1reg2crg_done    =(state_c  ==CRG_1REG    &&end_bit_cnt     )  ;
assign crc_done2idle= state_c==CRC_DONE;
endmodule

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
FPGA实现CRC校验是一种常见的做法,可以通过硬件电路来计算CRC校验码。通常,需要使用一个生成多项式来进行CRC计算。生成多项式是一个固定的多项式,用于生成CRC校验码。在FPGA中,可以使用Verilog或VHDL等硬件描述语言来实现CRC校验。 首先,需要定义一个CRC模块,该模块包含输入数据、生成多项式、时钟信号和复位信号等。在模块内部,可以使用寄存器和逻辑门等元件来实现CRC计算。具体的实现方式可以参考引用\[2\]中的testbench代码。 在CRC模块中,需要根据生成多项式的规则来计算CRC校验码。生成多项式通常是一个多项式的二进制表示形式,可以根据不同的CRC标准选择相应的生成多项式。例如,CRC-32标准使用的生成多项式是引用\[3\]中给出的CRC-32。 在实现过程中,需要注意时钟信号的同步和数据的移位操作。通过逐位移位和异或运算,可以逐步计算出CRC校验码。最后,可以通过比较计算得到的CRC校验码和预期的校验码来判断是否校验正确。 总结起来,要在FPGA实现CRC校验,需要定义一个CRC模块,选择适当的生成多项式,并根据生成多项式的规则进行CRC计算。具体的实现方式可以参考引用\[2\]中的testbench代码。 #### 引用[.reference_title] - *1* *2* *3* [FPGA(一)——基于FPGACRC算法实现](https://blog.csdn.net/weixin_43361652/article/details/107954852)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值