1 前言

(1)    什么是CRC校验?

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

LFSR计算CRC,可以用多项式G(x)表示,G(x) = X16+X12+X5+1模型可如下图所示。

(2)    校验原理

其根本思想就是先在要发送的帧后面附加一个数(这个就是用来校验的校验码,但要注意,这里的数也是二进制序列的,下同),生成一个新帧发送给接收端。当然,这个附加的数不是随意的,它要使所生成的新帧能与发送端和接收端共同选定的某个特定数整除(注意,这里不是直接采用二进制除法,而是采用一种称之为“模2除法”)。到达接收端后,再把接收到的新帧除以(同样采用“模2除法”)这个选定的除数。因为在发送端发送数据帧之前就已通过附加一个数,做了“去余”处理(也就已经能整除了),所以结果应该是没有余数。如果有余数,则表明该帧在传输过程中出现了差错。

要校验的数据加上此数据计算出来的crc组成新的数据帧,如下图所示。

模2除法:

模2除法与算术除法类似,但每一位除的结果不影响其它位,即不向上一位借位,所以实际上就是异或。在循环冗余校验码(CRC)的计算中有应用到模2除法。

(3)    步骤

CRC校验中有两个关键点,一是预先确定一个发送送端和接收端都用来作为除数的二进制比特串(或多项式),可以随机选择,也可以使用国际标准,但是最高位和最低位必须为1;二是把原始帧与上面计算出的除数进行模2除法运算,计算出CRC码。

1. 选择合适的除数

2. 看选定除数的二进制位数,然后再要发送的数据帧上面加上这个位数-1位的0,然后用新生成的帧以模2除法的方式除上面的除数,得到的余数就是该帧的CRC校验码。注意,余数的位数一定只比除数位数少一位,也就是CRC校验码位数比除数位数少一位,如果前面位是0也不能省略。

3. 将计算出来的CRC校验码附加在原数据帧后面,构建成一个新的数据帧进行发送;最后接收端在以模2除法方式除以前面选择的除数,如果没有余数,则说明数据帧在传输的过程中没有出错。

(4)    计算实例

现假设选择的CRC生成多项式为G(X) = X4 + X3 + 1,要求出二进制序列10110011的CRC校验码。下面是具体的计算过程:

①将多项式转化为二进制序列,由G(X) = X4 + X3 + 1可知二进制一种有五位,第4位、第三位和第零位分别为1,则序列为11001

②多项式的位数位5,则在数据帧的后面加上5-1位0,数据帧变为101100110000,然后使用模2除法除以除数11001,得到余数。

③将计算出来的CRC校验码添加在原始帧的后面,真正的数据帧为101100110100,再把这个数据帧发送到接收端。

④接收端收到数据帧后,用上面选定的除数,用模2除法除去,验证余数是否为0,如果为0,则说明数据帧没有出错。

2 流程

(1)并行计算crc用verilog语言描述是复杂繁琐的,所以可以使用在线工具生成verilog或者VHDL模板:http://www.easics.com/webtools/crctool,模板生成的代码稍加修改即可使用。

(2)本次校验模型为G(x) = X16+X12+X5+1。在在线工具中操作相关选项生成模板。

模板v文件如下:

 ////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1999-2008 Easics NV.
// This source file may be used and distributed without restriction
// provided that this copyright statement is not removed from the file
// and that any derivative work contains the original copyright notice
// and the associated disclaimer.
//
// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// Purpose : synthesizable CRC function
// * polynomial: x^16 + x^12 + x^5 + 1
// * data width: 16
//
// Info : tools@easics.be
// http://www.easics.com
////////////////////////////////////////////////////////////////////////////////
module CRC16_D16; // polynomial: x^16 + x^12 + x^5 + 1
// data width: 16
// convention: the first serial bit is D[15]
function [:] nextCRC16_D16; input [:] Data;
input [:] crc;
reg [:] d;
reg [:] c;
reg [:] newcrc;
begin
d = Data;
c = crc; newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[];
nextCRC16_D16 = newcrc;
end
endfunction
endmodule

(3)修改模板最终如下:

 `timescale 1ns/1ps
module crc16_test (
input wire i_clk , //时钟;
input wire i_rst_n , //同步复位;
input wire i_din_valid , //输入数据有效;
input wire [:] i_din , //输入数据;
output wire o_dout_valid , //输出CRC值有效;
output wire [:] o_dout //输出CRC;
);
reg [:] r_dout;
wire [:] d;
wire [:] c;
assign d = i_din;
assign c = r_dout;
always @(posedge i_clk) begin
if (~i_rst_n)
r_dout <= 'hffff; //初始值为ffff;
else if (i_din_valid)
begin //计算逻辑;
r_dout[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
r_dout[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
r_dout[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
r_dout[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
r_dout[] = d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[];
r_dout[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
r_dout[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
r_dout[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
r_dout[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
r_dout[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
r_dout[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
r_dout[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
r_dout[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
r_dout[] = d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[];
r_dout[] = d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[];
r_dout[] = d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[];
end
end
reg r_dout_valid = ;
always @(posedge i_clk) //输入数据在一个时钟内完成CRC计算,下一个时钟输出;
begin
r_dout_valid <= i_din_valid;
end assign o_dout_valid = r_dout_valid;
assign o_dout = r_dout ; endmodule // end the crc16_test model;

3 仿真

仿真结果和在线工具计算结果进行比较,在线工具地址:http://www.ip33.com/crc.html

(1)编写tb文件,对代码进行测试,测试结果如下图所示:

(2)在线校验。输入需要校验的数据,选择参数模型,输入初始值(此次crc结果的前一个crc值,代码中初始化为ffff)。可以对比发现计算无误。

第一次计算0011(初始值为ffff),结果为1f1f。

第二次计算0013(初始值为1f1f),结果为d2c1。

4 综合

本次综合参考芯片为:xc7k325tffg676-2

(1)    资源使用量如下图所示。

(2)    模块时钟约束为100M,裕量如下图所示,满足时序要求。

以上。

Verilog语言实现并行(循环冗余码)CRC校验的更多相关文章

  1. FPGA基础(verilog语言)——语法篇

    verilog语言简介 verilog语言是一种语法类似于c的语言,但是与c语言也有不同之处,比如: 1.verilog语言是并行的,每个always块都是同时执行,而c语言是顺序执行的 2.veri ...

  2. CRC校验原理和verilog实现方法(一)

    1.CRC简介 CRC全称循环冗余校验(Cyclic Redundancy Check, CRC),是通信领域数据传输技术中常用的检错方法,用于保证数据传输的可靠性.网上有关这方面的博客和资料很多,本 ...

  3. CRC校验原理和verilog实现方法(二)

    1 前言 在 前面的博客  CRC校验原理和verilog实现方法(一)  中,介绍了CRC校验的原理和手动计算过程.本文说一下我在学习CRC校验FPGA实现的一点心得体会. 2 线性反馈移位寄存器 ...

  4. CRC校验原理和verilog实现方法(三)

    1 代码生成 verilog实现CRC校验,可以充分发挥FPGA的硬件特性,即并行运算的能力. 具体实现方式,可以参考我上一篇博客,关键是用线性反馈移位寄存器表示出多项式,另外注意校验数据高位在先.然 ...

  5. CRC校验的C语言实现

    文章转自 循环冗余校验(CRC)算法入门引导 - Ivan 的专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/liyuanbhu/article/details/7 ...

  6. CRC校验代码实现

    1.CRC校验简介 CRC就是块数据的计算值,它的全称是“Cyclic Redundancy Check”,中文名是“循环冗余码”.CRC校验是数据通讯中最常采用的校验方式.在嵌入式软件开发中,经常要 ...

  7. CRC校验

    小试一下CRC校验的verilog实现,采用最stupid的直接法. /* date : 2014/06/06 designer : pengxiaoen virsion : Altera-Model ...

  8. 基于MATLAB2016b图形化设计自动生成Verilog语言的积分模块及其应用

    在电力电子变流器设备中,常常需要计算发电量,由于电力电子变流器设备一般是高频变流设备,所以发电量的计算几乎时实时功率的积分,此时就会用到一个积分模块.发电量计算的公式如下:Q=∫P. FPGA由于其并 ...

  9. 字符串CRC校验

    字符串CRC校验 <pre name="code" class="python"><span style="font-family: ...

随机推荐

  1. SpringBoot系列——Spring-Data-JPA(究极进化版) 自动生成单表基础增、删、改、查接口

    前言 我们在之前的实现了springboot与data-jpa的增.删.改.查简单使用(请戳:SpringBoot系列——Spring-Data-JPA),并实现了升级版(请戳:SpringBoot系 ...

  2. 取之有道——巧用Root权限 启动其他APP中的Activity

    这次博主来分享一个很巧妙的办法来启动其他APP中Activity的方法. 首先说一下这样做的目的:最近博主在攻克一个技术难点,就是搞定某些三方系统中,对于应用权限的限制.为此给出用户指导,引导用户启动 ...

  3. 0422作业:基础(if,while)

    """ 1.题目:企业发放的奖金根据利润提成.利润(I)低于或等于10万元时,奖金可提10%: 利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10 ...

  4. XSS攻击之窃取Cookie

    10 年前的博客似乎有点老了,但是XSS 攻击的威胁依然还在,我们不得不防. 窃取Cookie是非常简单的,因此不要轻易相信客户端所声明的身份.即便这个Cookie是在数秒之前验证过,那也未必是真的, ...

  5. 判断值是否为undefined

    可以使用 Ext.isDefined( value ) 这个函数, 也可以使用下面代码来进行实现: /** 判断传入的值是否 为undefined */ function isUndefined(va ...

  6. H5与C3权威指南笔记--box-shadow

    box-shadow 用于给盒子添加阴影效果.IE9+ 举个栗子:box-shadow: inset 5px 5px 5px red; inset可选,该值会让阴影出现在盒子内部. 第一个5px是阴影 ...

  7. php 获取URL 各部分参数

    URL处理几个关键的函数parse_url.parse_str与http_build_query parse_url() 该函数可以解析 URL,返回其组成部分.它的用法如下: array parse ...

  8. Python机器学习实践:决策树判别汽车金融违约用户

    文章发布于公号[数智物语] (ID:decision_engine),关注公号不错过每一篇干货. 转自 | 法纳斯特(公众号ID:walker398) 作者 | 小F 决策树呈树形结构,是一种基本的回 ...

  9. 【书摘】一种基于Git的版本管理方案

    本篇摘录自<前端工程化体系设计与实践>一书,笔者认为是一套相对合理的方案,建议团队可以根据实际情况进行调整并增加协作命名规范. master分支--主分支 存储已发布版本的源码,不能在此分 ...

  10. 安装Docker时错误提示 "could not change group /var/run/docker.sock to docker: group docker not found"的解决方案

    安装Dock服务,主要命令是  yum install docker. 但是在启动的时候报错:warning msg="could not change group /var/run/doc ...