小学霸修炼秘籍之FPGA篇–CRC16校验码的计算(Verilog)

  • Post author:
  • Post category:其他


小学霸这次做的项目需要Modbue -TCP协议转化为Modbus- RTU协议并通过串口输出,RTU协议中在数据发送的最后需要发送CRC16 校验码,关于CRC16校验码的计算方式有很多种,在此小学霸用的是移位计算法,具体的步骤是:

1、预置一个值为0XFFFF的16位寄存器,即CRC寄存器;

2、将第一个八位数据与16 CRC寄存器的第八位相异或,结果仍存于CRC寄存器中;

3、将CRC寄存器的内容右移一位,最高位补0 ;

4、若移出位为0则重复3步骤再右移一次,若移出为1,则CRC寄存器与0XA001进行异或;

5、重复3   4  步骤直到八位数据处理完成。

6、重复2–5步骤将通信消息帧下一字节处理,直至处理完成;

处理完成后在发送CRC校验位时,要先发送低字节,后发送高字节;

Verilog实现程序为:

module CRC_count(clk,rst_n,CRC_out,signal_read,signal_write,arm_device_rddata,data_1,



signal_start,signal_start_status,signal_CRC_start,cnt_reg,cnt_data,



CRC,num_data);

input clk;

input rst_n;

input signal_read;

input signal_write;

input [7:0] arm_device_rddata;

output [15:0] CRC_out;

input [7:0] data_1;

input signal_start;

output signal_start_status;

output signal_CRC_start;

output cnt_reg;

output cnt_data;   //测试标志

output CRC;

input [7:0] num_data;

integer i;

reg signal_start_reg1,signal_start_reg2;

wire signal_start_status,signal_start_status1;

reg [7:0] cnt_reg ;

reg [7:0] cnt_data;

reg [15:0] CRC_out;

reg [15:0] CRC = 16’hffff;

reg [15:0] data_buffer = 16’ha001;

reg signal_CRC_start;

always@(posedge clk)

begin



signal_start_reg1 <= signal_start;



signal_start_reg2 <= signal_start_reg1;

end

assign signal_start_status = signal_start_reg1 && (~signal_start_reg2);

assign signal_start_status1 = signal_start_reg2 && (~signal_start_reg1);

always@(posedge clk)

begin



if(signal_start_status == 1)



begin



CRC = CRC ^ data_1;



signal_CRC_start <= 1;



cnt_data <= cnt_data + 1;






end



else



if(cnt_reg == 8)



begin



signal_CRC_start <= 0;



cnt_reg <= 0;



if(signal_read == 1 && cnt_data == 5)



begin



CRC_out <= CRC;



CRC <= 16’hffff;



cnt_data <= 0;



end



else



if(signal_write == 1 && cnt_data == 7 && num_data == 2)



begin



CRC_out <= CRC;



CRC <= 16’hffff;



cnt_data <= 0;



end



else



if(signal_write == 1 && cnt_data == 6 && num_data == 1)



begin



CRC_out <= CRC;



CRC <= 16’hffff;



cnt_data <= 0;



end






end



else



if(signal_CRC_start == 1)



begin



for(i=7;i>=0;i=i-1)



begin



cnt_reg = cnt_reg +1;



if(CRC[0] == 0)



begin



CRC = CRC>>1;



end



else



if(CRC[0] == 1)



begin



CRC = (CRC>>1)^ data_buffer;



end



end



end

end

endmodule

最后推荐一个计算CRC16校验码的计算器,在程序运行完可以做一下校对:http://www.3158bbs.com/tool-59.html



版权声明:本文为weixin_41576149原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。