Verilog 实现CRC_16(DNP)协议校验码已通过仿真

Verilog 小案例实现CRC_16(DNP)协议校验码已通过仿真



前言

CRC校验(循环冗余校验)小知识
CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,并将得到的结果附在帧的后面,接收设备也执行类似的算法,以保证数据传输的正确性和完整性。


CRC算法参数模型解释:
NAME:参数模型名称。
WIDTH:宽度,即CRC比特数。
POLY:生成项的简写,以16进制表示。例如:CRC-32即是0x04C11DB7,忽略了最高位的"1",即完整的生成项是0x104C11DB7。
INIT:这是算法开始时寄存器(crc)的初始化预置值,十六进制表示。
REFIN:待测数据的每个字节是否按位反转,True或False。
REFOUT:在计算后之后,异或输出之前,整个数据是否按位反转,True或False。
XOROUT:计算结果与此参数异或后得到最终的CRC值。


CRC-16 DNP 协议注意事项:
1.输入数据反转 例如:data=11001001 反转数据data1=10010011
2.结果异或值:FFFF 例如:CRC校验码:1100111100001001 这个结果需要与FFFF异或 也就是1100111100001001^FFFF 结果就是0011000011110110
3.输出数据反转: 例如CRC校验码数据为0011000011110110 则反转后数据为0110111100001100
主要是这三个注意事项,其他就是正常的校验码计算过程
在这里插入图片描述
CRC计算网站:好用免费的CRC校验码在线计算网站

一、Verilog代码

module CRC_16(
input clk       ,
input rst       ,
input [7:0] data,//信息码8位
//output reg        crc_flag,
output reg [23:0] temp,//移位数据用于除法运算
output reg [15:0] crc,//crc校验码
output wire [15:0] crc_real,//crc校验码反转后
output wire [7:0] data_temp
    );
	 
	
    wire [15:0] crc_temp;//crc校验结果寄存器
    
    parameter gx=17'b10011110101100101;//生成多项式
    parameter ff=16'b1111111111111111;//生成多项式FF
    //输入数据反转
    assign data_temp={data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7]};
    always@(posedge clk)begin
    	if(!rst)begin
    		crc<=16'd0;
    		temp<={data_temp[7:0],16'b0};
			//crc_flag<=1'b1;
    	end
    	else begin//(模2除法求余数)
				//crc_flag <= 1'b0;		
    		if(temp[23]==1'd1)begin //高位为1 进行异或
    				temp[23:7]<=temp[23:7]^gx;//从高到低依次取17位(和gx同位宽)进行异或
    		end
    		else if(temp[22]==1'd1)begin
    				temp[22:6]<=temp[22:6]^gx;
    		end
    		else if(temp[21]==1'd1)begin
    				temp[21:5]<=temp[21:5]^gx;
    		end
    		else if(temp[20]==1'd1)begin
    				temp[20:4]<=temp[20:4]^gx;
    		end
    		else if(temp[19]==1'd1)begin
    				temp[19:3]<=temp[19:3]^gx;
    		end
    		else if(temp[18]==1'd1)begin
    				temp[18:2]<=temp[18:2]^gx;
    		end
    		else if(temp[17]==1'd1)begin
    				temp[17:1]<=temp[17:1]^gx;
    		end
    		else if(temp[16]==1'd1)begin
    				temp[16:0]<=temp[16:0]^gx;
    		end
    		else begin
    			crc<=temp[15:0]^ff;//取出余数
				//crc_flag <= 1'b1;
    		end
    	end
    end
    
	 assign crc_real={crc[0],crc[1],crc[2],crc[3],crc[4],crc[5],crc[6],crc[7],crc[8],crc[9],crc[10],crc[11],crc[12],crc[13],crc[14],crc[15]};
    assign crc_temp={data[7:0],crc[15:0]};
    
endmodule

CRC校验码基本计算过程参考代码 快去给up点赞收藏

二、ModelSim仿真验证

1.测试文件

代码如下(示例):

`timescale 1 ps/ 1 ps
module CRC_16_vlg_tst();
// constants                                           
// general purpose registers
reg eachvec;
// test vector input registers
reg clk;
reg [7:0] data;
reg rst;
// wires  
wire [15:0]  crc;                                             
wire [23:0]  temp;
wire [15:0]  crc_real;
wire [7:0]  data_temp;

// assign statements (if any)                          
CRC_16 i1 (
// port map - connection between master ports and signals/registers   
	.clk(clk),
	.crc(crc),
	.data(data),
	//.crc_flag(crc_flag),
	.temp(temp),
	.data_temp(data_temp),
	.crc_real(crc_real),
	.rst(rst)
);
initial                                                
begin                                                  

	clk <=1'b0;
	rst <= 1'b0;
	data <= 8'b00111111;
#200
	rst <= 1'b1;
	//data <= 8'b11010010;
end  


                                               
always  #200 clk = ~clk;                                                   
endmodule


2.仿真波形

波形如下(示例):
在这里插入图片描述
当前数据输入是00111111 CRC校验码为0001100000101000 通过对比计算网站的数据结果一致

该处使用的url网络请求的数据。


总结

一天一个Verilog小技巧,365天365个小技巧~

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值