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

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值