小學霸修煉祕籍之FPGA篇--CRC16校驗碼的計算(Verilog)

小學霸這次做的項目需要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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章