您现在的位置是:首页 >技术教程 >FPGA verilog设计的MODBUS CRC算法网站首页技术教程
FPGA verilog设计的MODBUS CRC算法
已经测试通过。
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 20:14:12 05/18/2023
// Design Name:
// Module Name: Modbus_CRC
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module Modbus_CRC(
input clk,
input rst,
input d_valid,
input [7:0] data_in,
output reg[15:0] crc_out,
output reg crc_vld
);
/*
(1).预置 16 位寄存器为十六进制 FFFF(即全为 1) ,称此寄存器为 CRC 寄存器;
(2).把第一个 8 位数据与 16 位 CRC 寄存器的低位相异或,把结果放于 CRC 寄存器;
(3).检测相异或后的CRC寄存器的最低位,若最低位为1:CRC寄存器先右移1位,再与多项式A001H进行异或;若为0,则CRC寄存器右移1位,无需与多项式进行异或。
(4).重复步骤 3 ,直到右移 8 次,这样整个 8 位数据全部进行了处理;
(5).重复步骤 2 到步骤4,进行下一个 8 位数据的处理;
(6).最后得到的 CRC 寄存器即为 CRC 码
*/
parameter polynomial = 16’hA001;// 8005的二进制反转后结果 X^16 + X^15 + X^2 + 0多项式。2023-5-21 09:23:02
localparam IDLE = 3’b001;
localparam CRC = 3’b010;
localparam DONE = 3’b100;
reg [2:0] state;
reg [3:0] shift_count;
//assign signal_temp = {data_in,17’b0};
/*
unsigned int CRC16(unsigned char buf,unsigned char length)//CRC16计算
{
unsigned char i;
unsigned int crc=0xFFFF;
while(length–)
for(crc^=(buf++),i=0;i<8;i++)
crc=(crc&0x0001)?(crc>>1)^0xA001:crc>>1;
return crc;
}
*/
always @ (posedge clk or posedge rst)begin
if(rst == 1’b0)
begin
state <= IDLE;
crc_out <= 16’hFFFF;
crc_vld <= 1’b0;
shift_count <= 4’d0;
end
else case(state)
IDLE:begin
crc_vld <= 1'b0;
shift_count <= 4'd0;
if(d_valid == 1'b1)
begin
state <= CRC;
crc_out <= crc_out^{8'b0,data_in};
end
else
begin
state <= state;
crc_out <= 16'hFFFF;
end
end
CRC:begin
crc_vld <= 1'b0;
if(shift_count<4'd8)
begin
state <= CRC;
shift_count <= shift_count +1'b1;
//(3).检测相异或后的CRC寄存器的最低位,若最低位为1:CRC寄存器先右移1位,再与多项式A001H进行异或;
//若为0,则CRC寄存器右移1位,无需与多项式进行异或。
if(crc_out[0] == 1'b1)
begin
crc_out <= {1'b0,crc_out[15:1]}^polynomial;
end
else
begin
crc_out <= {1'b0,crc_out[15:1]};
end
end
else
begin
shift_count <= 4'd0;
crc_out <= crc_out;
state <= DONE;
end
end
DONE:begin
crc_out <= crc_out;
crc_vld <= 1'b1;
state <= IDLE;
shift_count <= 4'd0;
end
default : begin
crc_out <= 16'hFFFF;
crc_vld <= 1'b0;
state <= IDLE;
shift_count <= 4'd0;
end
endcase
end
endmodule