Verilog语言实现并行(循环冗余码)CRC校验
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校验的更多相关文章
- FPGA基础(verilog语言)——语法篇
verilog语言简介 verilog语言是一种语法类似于c的语言,但是与c语言也有不同之处,比如: 1.verilog语言是并行的,每个always块都是同时执行,而c语言是顺序执行的 2.veri ...
- CRC校验原理和verilog实现方法(一)
1.CRC简介 CRC全称循环冗余校验(Cyclic Redundancy Check, CRC),是通信领域数据传输技术中常用的检错方法,用于保证数据传输的可靠性.网上有关这方面的博客和资料很多,本 ...
- CRC校验原理和verilog实现方法(二)
1 前言 在 前面的博客 CRC校验原理和verilog实现方法(一) 中,介绍了CRC校验的原理和手动计算过程.本文说一下我在学习CRC校验FPGA实现的一点心得体会. 2 线性反馈移位寄存器 ...
- CRC校验原理和verilog实现方法(三)
1 代码生成 verilog实现CRC校验,可以充分发挥FPGA的硬件特性,即并行运算的能力. 具体实现方式,可以参考我上一篇博客,关键是用线性反馈移位寄存器表示出多项式,另外注意校验数据高位在先.然 ...
- CRC校验的C语言实现
文章转自 循环冗余校验(CRC)算法入门引导 - Ivan 的专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/liyuanbhu/article/details/7 ...
- CRC校验代码实现
1.CRC校验简介 CRC就是块数据的计算值,它的全称是“Cyclic Redundancy Check”,中文名是“循环冗余码”.CRC校验是数据通讯中最常采用的校验方式.在嵌入式软件开发中,经常要 ...
- CRC校验
小试一下CRC校验的verilog实现,采用最stupid的直接法. /* date : 2014/06/06 designer : pengxiaoen virsion : Altera-Model ...
- 基于MATLAB2016b图形化设计自动生成Verilog语言的积分模块及其应用
在电力电子变流器设备中,常常需要计算发电量,由于电力电子变流器设备一般是高频变流设备,所以发电量的计算几乎时实时功率的积分,此时就会用到一个积分模块.发电量计算的公式如下:Q=∫P. FPGA由于其并 ...
- 字符串CRC校验
字符串CRC校验 <pre name="code" class="python"><span style="font-family: ...
随机推荐
- 【转】解决未能加载文件或程序集'WebGrease‘的问题
在多个视图中,如果有使用共用的样式代码,可以把它们移至CSS文件中去.今天Insus.NET就举例一个例子来说明. 比如前2篇中<ASP.NET MVC图片管理(上传,预览与显示)>htt ...
- java爬虫系列第五讲-如何使用代理防止爬虫被屏蔽?
本文内容 1.分析一下爬虫存在的问题及解决方案 2.webmagic中代理的使用 3.目前市面上一些比较好用的代理服务器 存在的问题 我们在使用爬虫过程中,大多都会遇到这样的问题:突然某一天爬虫爬不到 ...
- 【转】JavaSE面试题目收集
1.是否可以从一个static方法内部发出对非static方法的调用? 不可以.当一个static方法被调用时,可能还没有创建任何实例对象,如果从一个static方法中发出对非static方法的调用, ...
- PHPCMS V9 添加二级导航
今天看了看phpcms 写到二级导航时发现点问题,查询导航栏的信息时返回的$r[arrchildid]与自己想象的不符,文档上说是返回子栏目id但是却有些不同. 开始的思路: <ul class ...
- dbutils工具类使用
1DBUtils工具类 1.1概述 DBUtils是java编程中的数据库操作实用工具,小巧简单实用. DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码 DBUtils三个核心功 ...
- 关于HTTPS的简要内容
HTTPS是什么? 超文本传输安全协议(英语:Hypertext Transfer Protocol Secure,缩写:HTTPS,常称为HTTP over TLS,HTTP over SSL或HT ...
- MongoDB学习(操作集合中的文档)
文档概念 文档的数据结构和JSON基本一样. 所有存储在集合中的数据都是BSON格式. BSON是一种类json的一种二进制形式的存储格式,简称Binary JSON. 插入文档 insert()方法 ...
- 洛谷P2664 树上游戏(点分治)
题意 题目链接 Sol 神仙题..Orz yyb 考虑点分治,那么每次我们只需要统计以当前点为\(LCA\)的点对之间的贡献以及\(LCA\)到所有点的贡献. 一个很神仙的思路是,对于任意两个点对的路 ...
- 常见的异步方式async 和 await
之前研究过c#的async和await关键字,幕后干了什么,但是不知道为什么找不到相关资料了.现在重新研究一遍,顺便记录下来,方便以后查阅. 基础知识 async 关键字标注一个方法,该方法返回值是一 ...
- windows下vagrant的安装使用
vagrant是简便虚拟机操作的一个软件,而使用虚拟机有几个好处: 1.为了开发环境与生产环境一致(很多开发环境为windows而生产环境为linux),不至于出现在开发环境正常而移步到正式生产环境时 ...