0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于Verilog语言实现CRC校验

FPGA设计论坛 来源:博客园 2025-03-24 10:36 670次阅读

1 前言

(1) 什么是CRC校验?

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

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

d3faadae-062d-11f0-9310-92fbcf53809c.png

(2) 校验原理

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

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

d41a5ad2-062d-11f0-9310-92fbcf53809c.png

模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。在在线工具中操作相关选项生成模板。

d42c6b0a-062d-11f0-9310-92fbcf53809c.png

模板v文件如下:

 1 ////////////////////////////////////////////////////////////////////////////////
 2 // Copyright (C) 1999-2008 Easics NV.
 3 // This source file may be used and distributed without restriction
 4 // provided that this copyright statement is not removed from the file
 5 // and that any derivative work contains the original copyright notice
 6 // and the associated disclaimer.
 7 //
 8 // THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
 9 // OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10 // WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 //
12 // Purpose : synthesizable CRC function
13 //   * polynomial: x^16 + x^12 + x^5 + 1
14 //   * data width: 16
15 //
16 // Info : tools@easics.be
17 //        http://www.easics.com
18 ////////////////////////////////////////////////////////////////////////////////
19 module CRC16_D16;
20 
21   // polynomial: x^16 + x^12 + x^5 + 1
22   // data width: 16
23   // convention: the first serial bit is D[15]
24   function [15:0] nextCRC16_D16;
25 
26     input [15:0] Data;
27     input [15:0] crc;
28     reg [15:0] d;
29     reg [15:0] c;
30     reg [15:0] newcrc;
31   begin
32     d = Data;
33     c = crc;
34 
35     newcrc[0] = d[12] ^ d[11] ^ d[8] ^ d[4] ^ d[0] ^ c[0] ^ c[4] ^ c[8] ^ c[11] ^ c[12];
36     newcrc[1] = d[13] ^ d[12] ^ d[9] ^ d[5] ^ d[1] ^ c[1] ^ c[5] ^ c[9] ^ c[12] ^ c[13];
37     newcrc[2] = d[14] ^ d[13] ^ d[10] ^ d[6] ^ d[2] ^ c[2] ^ c[6] ^ c[10] ^ c[13] ^ c[14];
38     newcrc[3] = d[15] ^ d[14] ^ d[11] ^ d[7] ^ d[3] ^ c[3] ^ c[7] ^ c[11] ^ c[14] ^ c[15];
39     newcrc[4] = d[15] ^ d[12] ^ d[8] ^ d[4] ^ c[4] ^ c[8] ^ c[12] ^ c[15];
40     newcrc[5] = d[13] ^ d[12] ^ d[11] ^ d[9] ^ d[8] ^ d[5] ^ d[4] ^ d[0] ^ c[0] ^ c[4] ^ c[5] ^ c[8] ^ c[9] ^ c[11] ^ c[12] ^ c[13];
41     newcrc[6] = d[14] ^ d[13] ^ d[12] ^ d[10] ^ d[9] ^ d[6] ^ d[5] ^ d[1] ^ c[1] ^ c[5] ^ c[6] ^ c[9] ^ c[10] ^ c[12] ^ c[13] ^ c[14];
42     newcrc[7] = d[15] ^ d[14] ^ d[13] ^ d[11] ^ d[10] ^ d[7] ^ d[6] ^ d[2] ^ c[2] ^ c[6] ^ c[7] ^ c[10] ^ c[11] ^ c[13] ^ c[14] ^ c[15];
43     newcrc[8] = d[15] ^ d[14] ^ d[12] ^ d[11] ^ d[8] ^ d[7] ^ d[3] ^ c[3] ^ c[7] ^ c[8] ^ c[11] ^ c[12] ^ c[14] ^ c[15];
44     newcrc[9] = d[15] ^ d[13] ^ d[12] ^ d[9] ^ d[8] ^ d[4] ^ c[4] ^ c[8] ^ c[9] ^ c[12] ^ c[13] ^ c[15];
45     newcrc[10] = d[14] ^ d[13] ^ d[10] ^ d[9] ^ d[5] ^ c[5] ^ c[9] ^ c[10] ^ c[13] ^ c[14];
46     newcrc[11] = d[15] ^ d[14] ^ d[11] ^ d[10] ^ d[6] ^ c[6] ^ c[10] ^ c[11] ^ c[14] ^ c[15];
47     newcrc[12] = d[15] ^ d[8] ^ d[7] ^ d[4] ^ d[0] ^ c[0] ^ c[4] ^ c[7] ^ c[8] ^ c[15];
48     newcrc[13] = d[9] ^ d[8] ^ d[5] ^ d[1] ^ c[1] ^ c[5] ^ c[8] ^ c[9];
49     newcrc[14] = d[10] ^ d[9] ^ d[6] ^ d[2] ^ c[2] ^ c[6] ^ c[9] ^ c[10];
50     newcrc[15] = d[11] ^ d[10] ^ d[7] ^ d[3] ^ c[3] ^ c[7] ^ c[10] ^ c[11];
51     nextCRC16_D16 = newcrc;
52   end
53   endfunction
54 endmodule

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

 1 `timescale 1ns/1ps
 2 module crc16_test (
 3     input     wire              i_clk                 , //时钟;
 4     input     wire              i_rst_n               , //同步复位;
 5     input     wire              i_din_valid           , //输入数据有效;
 6     input     wire    [15:0]    i_din                 , //输入数据;
 7     output    wire              o_dout_valid          , //输出CRC值有效;
 8     output    wire    [15:0]    o_dout                  //输出CRC;         
 9 );
10 reg [15:0] r_dout;
11 wire [15:0] d;
12 wire [15:0] c;
13 assign d = i_din;
14 assign c = r_dout;
15 always @(posedge i_clk) begin
16     if (~i_rst_n) 
17         r_dout <= 16'hffff; //初始值为ffff;
18     else if (i_din_valid) 
19     begin //计算逻辑;
20         r_dout[0]  = d[12] ^ d[11] ^ d[8] ^ d[4] ^ d[0] ^ c[0] ^ c[4] ^ c[8] ^ c[11] ^ c[12];
21         r_dout[1]  = d[13] ^ d[12] ^ d[9] ^ d[5] ^ d[1] ^ c[1] ^ c[5] ^ c[9] ^ c[12] ^ c[13];
22         r_dout[2]  = d[14] ^ d[13] ^ d[10] ^ d[6] ^ d[2] ^ c[2] ^ c[6] ^ c[10] ^ c[13] ^ c[14];
23         r_dout[3]  = d[15] ^ d[14] ^ d[11] ^ d[7] ^ d[3] ^ c[3] ^ c[7] ^ c[11] ^ c[14] ^ c[15];
24         r_dout[4]  = d[15] ^ d[12] ^ d[8] ^ d[4] ^ c[4] ^ c[8] ^ c[12] ^ c[15];
25         r_dout[5]  = d[13] ^ d[12] ^ d[11] ^ d[9] ^ d[8] ^ d[5] ^ d[4] ^ d[0] ^ c[0] ^ c[4] ^ c[5] ^ c[8] ^ c[9] ^ c[11] ^ c[12] ^ c[13];
26         r_dout[6]  = d[14] ^ d[13] ^ d[12] ^ d[10] ^ d[9] ^ d[6] ^ d[5] ^ d[1] ^ c[1] ^ c[5] ^ c[6] ^ c[9] ^ c[10] ^ c[12] ^ c[13] ^ c[14];
27         r_dout[7]  = d[15] ^ d[14] ^ d[13] ^ d[11] ^ d[10] ^ d[7] ^ d[6] ^ d[2] ^ c[2] ^ c[6] ^ c[7] ^ c[10] ^ c[11] ^ c[13] ^ c[14] ^ c[15];
28         r_dout[8]  = d[15] ^ d[14] ^ d[12] ^ d[11] ^ d[8] ^ d[7] ^ d[3] ^ c[3] ^ c[7] ^ c[8] ^ c[11] ^ c[12] ^ c[14] ^ c[15];
29         r_dout[9]  = d[15] ^ d[13] ^ d[12] ^ d[9] ^ d[8] ^ d[4] ^ c[4] ^ c[8] ^ c[9] ^ c[12] ^ c[13] ^ c[15];
30         r_dout[10] = d[14] ^ d[13] ^ d[10] ^ d[9] ^ d[5] ^ c[5] ^ c[9] ^ c[10] ^ c[13] ^ c[14];
31         r_dout[11] = d[15] ^ d[14] ^ d[11] ^ d[10] ^ d[6] ^ c[6] ^ c[10] ^ c[11] ^ c[14] ^ c[15];
32         r_dout[12] = d[15] ^ d[8] ^ d[7] ^ d[4] ^ d[0] ^ c[0] ^ c[4] ^ c[7] ^ c[8] ^ c[15];
33         r_dout[13] = d[9] ^ d[8] ^ d[5] ^ d[1] ^ c[1] ^ c[5] ^ c[8] ^ c[9];
34         r_dout[14] = d[10] ^ d[9] ^ d[6] ^ d[2] ^ c[2] ^ c[6] ^ c[9] ^ c[10];
35         r_dout[15] = d[11] ^ d[10] ^ d[7] ^ d[3] ^ c[3] ^ c[7] ^ c[10] ^ c[11];
36     end
37 end 
38 reg r_dout_valid = 0; 
39 always @(posedge i_clk) //输入数据在一个时钟内完成CRC计算,下一个时钟输出;
40 begin
41     r_dout_valid <= i_din_valid;
42 end
43 
44 assign o_dout_valid = r_dout_valid;
45 assign o_dout = r_dout ;
46 
47 endmodule // end the crc16_test model;

3 仿真

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

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

d44e47b6-062d-11f0-9310-92fbcf53809c.png

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

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

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

d46b2020-062d-11f0-9310-92fbcf53809c.png

4 综合

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

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

d48a1d36-062d-11f0-9310-92fbcf53809c.png

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

d4981ddc-062d-11f0-9310-92fbcf53809c.png

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • crc
    crc
    +关注

    关注

    0

    文章

    201

    浏览量

    29779
  • Verilog
    +关注

    关注

    28

    文章

    1360

    浏览量

    111080
  • 校验码
    +关注

    关注

    0

    文章

    11

    浏览量

    7667
  • 模型
    +关注

    关注

    1

    文章

    3435

    浏览量

    49576

原文标题:4 综合

文章出处:【微信号:gh_9d70b445f494,微信公众号:FPGA设计论坛】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    相关推荐

    CRC算法和c语言实现

    CRC算法和c语言实现
    发表于 08-20 19:21

    Verilog并行CRC校验

    Verilog并行CRC校验
    发表于 08-20 21:52

    verilog语言实现电子钟

    各位大神求救啊用verilog语言实现电子钟
    发表于 05-04 16:37

    有关基于verilogCRC校验的问题

    近期在做一个数据采集传输模块,采集6000多个数据打包,使用CRC校验。网上查找的相关verilog程序均是对单一数据处理的程序,没有对一个完整数据包的处理。c倒是有之前使用过的程序,但语言
    发表于 03-11 15:34

    怎么用verilog HDL或VHDL去实现CRC校验

    verilog HDL或VHDL去实现呢?首先了解CRC校验的原理,我们剩下的事情就是搬砖的了。人并且总是喜欢偷懒,“拿来主义”的存在,甚嚣尘上。热心农家们,一边写代码,一边维护各种开
    发表于 06-24 17:11

    CRC校验代码自动生成工具

    CRC校验代码自动生成工具根据输入条件自动产生各种CRC的VHDL或verilog源程序
    发表于 05-20 11:16 294次下载
    <b class='flag-5'>CRC</b><b class='flag-5'>校验</b>代码自动生成工具

    CRC算法原理及C语言实现

    CRC算法原理及C语言实现:本文从理论上推导出CRC 算法实现原理,给出三种分别适应不同计算机或微控制器硬件环境的C 语言程序。读者更能根据
    发表于 09-23 23:38 31次下载

    Verilog HDL语言实现时序逻辑电路

    Verilog HDL语言实现时序逻辑电路 在Verilog HDL语言中,时序逻辑电路使用always语句块来实现。例如,
    发表于 02-08 11:46 4790次阅读

    CRC校验码算法的研究与实现

    为了提高实际通信中检查信号传输错误的能力,提高和推广CRC校验技术,本论文用逻辑代数知识、按模运算、代数知识和C语言编程工具设计了几种具体实用的CRC
    发表于 05-28 15:41 0次下载

    CRC算法原理和CRC编码的实现方式与使用VerilogCRC编码进行描述

    泛的是CRC-32 标准。本文将以CRC-32 为例,说明CRC 编码的实现方式以及如何用verilog
    发表于 08-06 16:39 36次下载
    <b class='flag-5'>CRC</b>算法原理和<b class='flag-5'>CRC</b>编码的<b class='flag-5'>实现</b>方式与使用<b class='flag-5'>Verilog</b>对<b class='flag-5'>CRC</b>编码进行描述

    使用verilog语言实现数字钟的工程文件合集免费下载

    本文档的主要内容详细介绍的是使用verilog语言实现数字钟的工程文件合集免费下载。
    发表于 03-02 08:00 10次下载
    使用<b class='flag-5'>verilog</b><b class='flag-5'>语言实现</b>数字钟的工程文件合集免费下载

    CRC校验算法原理及c语言实现

    CRC校验算法原理及c语言实现
    发表于 11-30 10:04 10次下载

    累加校验和C语言实现

    累加校验和C语言实现
    发表于 11-29 18:06 10次下载
    累加<b class='flag-5'>校验</b>和C<b class='flag-5'>语言实现</b>

    CRC校验原理及实现

    作者:王超首发:电子电路开发学习目录前言CRC算法简介CRC计算CRC校验CRC计算的C语言实现
    发表于 01-26 17:37 30次下载
    <b class='flag-5'>CRC</b><b class='flag-5'>校验</b>原理及<b class='flag-5'>实现</b>

    使用C语言实现CRC计算单元的例子

    使用C语言实现CRC计算单元的例子
    的头像 发表于 05-16 16:16 1241次阅读