小学霸这次做的项目需要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