设为首页 加入收藏

TOP

基于Verilog的CRC-CCITT校验(一)
2019-08-24 00:06:44 】 浏览:210
Tags:基于 Verilog CRC-CCITT 校验

由于笔者在自己设计CRC模块时遇到很多问题,在网上并未找到一篇具有实际指导意义的文章,在经过多次仿真修改再仿真之后得到了正确的结果,故愿意在本文中为大家提供整个设计流程供大家快速完成设计。本文章主要针对具体的实际应用给出一套亲测可行的实现办法,给出设计代码并提供仿真结果,供各位参考。

一.CRC概述
CRC(Cyclic Redundancy Check),循环冗余校验,是一种数字通信中的常用查错校验码。其特征是信息段和校验字段的长度可以任意选定。
校验方法为发送方对信息数据执行约定好除数的二进制除法计算,并将得到的余数附在帧的后面,发送给接收方;接收方也执行类似的算法,两侧对比结果的余数,相同则说明接收信息完整且正确,以保证数据传输的正确性和完整性。
具体来讲,在K位信息码后再拼接R位的校验码,整个编码长度为N(=K+R)位,因此,这种编码也叫(N,K)码。对于一个给定的(N,K)码,可以证明存在一个最高次幂为N-K=R的多项式G(x)。根据G(x)可以生成K位信息的校验码,而G(x)叫做这个CRC码的生成多项式。
校验码的具体生成过程为:假设要发送的信息用多项式C(X)表示,将C(x)左移R位(可表示成C(x)2R),这样C(x)的右边就会空出R位,这就是校验码的位置。用 C(x)2R 除以生成多项式G(x)得到的余数就是校验码FCS(Frame Check Series)。
 任意一个由二进制位串组成的代码都可以和一个系数仅为‘0’和‘1’取值的多项式一一对应。例如:代码1010111对应的多项式为x6+x4+x2+x+1,而多项式为x5+x3+x2+x+1对应的代码101111。
CRC校验根据所采用的生成多项式不同分为很多不同的标准,常见的有:
名称 生成多项式 简记式 应用举例

CRC-4 x4+x+1 3 ITU G.704

CRC-8 x8+x5+x4+1 31 DS18B20
CRC-12 x12+x11+x3+x2+x+1 0x80F
CRC-16 x16+x15+x2+1 0x8005 IBM SDLC
CRC-ITU(CCITT) x16+x12+x5+1 0x1021 ISO HDLC, ITU
CRC-32 x32+x26+x23+...+x2+x+1 0x04C11DB7 ZIP, RAR
CRC-32c x32+x28+x27+...+x8+x6+1 0x1EDC6F41 SCTP
说明:简记式最高位应为1,此处都省略了;

二.实现方法
本文章所要讲的标准为CRC-ITU(CCITT-Xmodem),即生成多项式为0x1021
0x1021 = 0x11021 = 1,0001,0000,0010,0001

在此提供一个在线计算CRC校验网站,方便进行验证
https://www.lammertbies.nl/comm/info/crc-calculation.html

源代码根据需求在源码网站进行生成,后根据自己的需求进行修改,仿真验证;
现提供生成源码的步骤:
STEP1: http://outputlogic.com/?page_id=321
STEP2: 根据实际需求选择输入数据位宽和输出校验码位宽,CRC校验标准为自定义或者可选的几种;

STEP3: 若选择User defined,则进入第二页选择自定义的多项式,本仿真采用CCITT标准,即生成多项式为x16+x12+x5+1,此处只需要选中1,x5,x12即可,因为x16为1是默认的;

STEP4: 对生成的Verilog或者VHDL语言代码进行修改,应用到实际当中;

三.实际应用仿真
现基于笔者实际应用场景进行一个具体的CRC校验设计与仿真,其中,always 模块里的CRC校验计算过程不需要理解,若需要理解,可以下载该网站给出的文章(下载代码会附)
A Practical Parallel CRC Generation Method
常用的CRC校验方法有直接计算二进制除法,查表法,具体计算原理见下链接
https://blog.csdn.net/xing414736597/article/details/78693781
代码如下:

module CRC(
input clk,//输入时钟
input reset,//总体复位信号
input crc_en,//选择是否进行下一步CRC运算
input [63:0] data_in,//输入数据为64位
output [15:0] crc_out//输出数据即CRC校验结果为16位
);
reg [15:0] lfsr_q,lfsr_c;
wire reset;
assign crc_out = lfsr_c;

always @(*) begin
lfsr_c[0] = lfsr_q[0] ^ lfsr_q[1] ^ lfsr_q[3] ^ lfsr_q[4] ^ lfsr_q[7] ^ lfsr_q[8] ^ lfsr_q[10] ^ lfsr_q[15] ^ data_in[0] ^ data_in[4] ^ data_in[8] ^ data_in[11] ^ data_in[12] ^ data_in[19] ^ data_in[20] ^ data_in[22] ^ data_in[26] ^ data_in[27] ^ data_in[28] ^ data_in[32] ^ data_in[33] ^ data_in[35] ^ data_in[42] ^ data_in[48] ^ data_in[49] ^ data_in[51] ^ data_in[52] ^ data_in[55] ^ data_in[56] ^ data_in[58] ^ data_in[63];
lfsr_c[1] = lfsr_q[1] ^ lfsr_q[2] ^ lfsr_q[4] ^ lfsr_q[5] ^ lfsr_q[8] ^ lfsr_q[9] ^ lfsr_q[11] ^ data_in[1] ^ data_in[5] ^ data_in[9] ^ data_in[12] ^ data_in[13] ^ data_in[20] ^ data_in[21] ^ data_in[23] ^ data_in[27] ^ data_in[28] ^ data_in[29] ^ data_in[33] ^ data_in[34] ^ data_in[36] ^ data_in[43] ^ data_in[49] ^ data_in[50] ^ data_in[52] ^ data_in[53] ^ data_in[56] ^ data_in[57] ^ data_in[59];
lfsr_c[2] = lfsr_q[2] ^ lfsr_q[3] ^ lfsr_q[5] ^ lfsr_q[6] ^ lfsr_q[9] ^ lfsr_q[10] ^ lfsr_q[12] ^ data_in[2] ^ data_in[6] ^ data_in[10] ^ data_in[13] ^ data_in[14] ^ data_in[21] ^ data_in[22] ^ data_in[24] ^ data_in[28] ^ data_in[29] ^ data_in[30] ^ data_in[34] ^ data_in[35] ^ data_in[37] ^ data_in[44] ^ data_in[50] ^ data_in[51] ^ data_in[53] ^ data_in[54] ^ data_in[57] ^ data_in[58] ^ data_in[60];
lfsr_c[3] = lfsr_q[3] ^ lfsr_q[4] ^ lfsr_q[6] ^ lfsr_q[7] ^ lfsr_q[10] ^ lfsr

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇【Verilog HDL】赋值语句之阻塞赋.. 下一篇ADI高速信号采集芯片与JESD204B接..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目