您现在的位置是:首页 >技术教程 >FPGA verilog设计的MODBUS CRC算法网站首页技术教程

FPGA verilog设计的MODBUS CRC算法

weixin_41925897 2024-06-17 11:27:59
简介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

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。