本文设计思想采用明德扬至简设计法。由于本人项目需要进行光纤数据传输,为了保证通信质量要对数据进行校验。在校验算法中,最简单最成熟的非CRC校验莫属了。

  得出一个数的CRC校验码还是比较简单的:

  1. 选定一个CRC生成多项式G(x);
  2. 将发送数据左移K位,右侧补零(其中K为生成多项式最高次幂);
  3. 用移位补零后的数据对G(x)进行模2除法(其实就是异或运算);
  4. 用得到的余数即为该数据的CRC校验码;

  发送端将移位补零后数据的低K位0替换成CRC校验码组成新的数据发送出去,接收端对带有校验码的数据对同样的G(x)做模2除法。由于发送端将余数加入在数据尾部,相当于已做了“去余”处理,故若数据传输正确时,接收端的模2除运算余数应为0。其中校验位数和生成多项式不是随便选定的,一般采用常用的标准形式。其中CRCK是指有K为校验位,不同位数对应不同的纠检错能力。之前本人在网上找到一篇关于CRC校验原理的文章,比较详细且浅显易懂:http://mp.weixin.qq.com/s/RNHLZGPD9Ysbxb1FNDn6EA

  当刚看完这些资料,对CRC有了大概认识之后,我和很多初学的朋友们一样充满疑惑。CRC如何用硬件实现呢?如何对包含多个数据的数据帧进行校验呢?FCS又是如何在帧尾的下一个时钟周期就得到结果的呢?

  最原始的实现方式是采用LFSR(线性反馈移位寄存器)来完成校验功能,以下是结构示意图:

  寄存器个数等于G(x)最高次幂,图中gx表示链路通断,与多项式系数相对应:系数为1时连接,0则断开。数据在每个时钟周期从右侧输入1bit,且寄存器内数据右移一位。如此移位,反馈异或的过程即为待发送数据移位后对生成多项式做模2除的过程,故当全部数据位输入完毕,寄存器内部的值即为CRC校验码。我们以较简单的CRC8为例,其G(x) = x^8 + x^2 + x^1 + 1,根据上述分析得到:

              reg2(i) = reg1(i-1)^reg7(i-1)^d(i)

              reg1(i) = reg0(i-1)^reg7(i-1)^d(i)

              reg0(i) = reg7(i-1)^d(i)

              regk(i) = regk-1(i-1)       (k!=0,1,2)

  其中,i表示当前时刻,i-1表示上一时刻。数据位宽定为4bit,经过四个节拍,寄存器内部数据变化过程见表:

  根据上述传递方程推导得出四个节拍后reg7~reg0保存的数值,试想一下:既然每个触发器内保存数值表达式已知,那么如果直接将第四行表达式赋值寄存器,下一个时钟节拍即可得到最终校验结果,而无需等待四个时钟节拍。这就是CRC校验的并行实现方式了!传统的CRC校验算法已经非常成熟,在使用过程中不需要完全自己推导公式,了解基本原理即可。至于代码,有做好的线上生成工具  http://www.easics.com/webtools/crctool  我们选定CRC8,并将数据位宽定义为4bit,验证上述推导过程是否正确。

  生成源代码:

 ////////////////////////////////////////////////////////////////////////////////
// Purpose : synthesizable CRC function
// * polynomial: x^8 + x^2 + x^1 + 1
// * data width: 4
////////////////////////////////////////////////////////////////////////////////
module CRC8_D4; // polynomial: x^8 + x^2 + x^1 + 1
// data width: 4
// convention: the first serial bit is D[3]
function [:] nextCRC8_D4; input [:] Data;
input [:] crc;
reg [:] d;
reg [:] c;
reg [:] newcrc;
begin
d = Data;
c = crc; newcrc[] = d[] ^ c[];
newcrc[] = d[] ^ d[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ c[] ^ c[];
newcrc[] = c[];
newcrc[] = c[];
nextCRC8_D4 = newcrc;
end
endfunction
endmodule

  代码中公式逻辑部分与表格中第四节拍中寄存器保存的数据一致,证明推导正确。

  一个数据的校验大家应该已经掌握了,那如何对整个数据帧进行校验呢?可以看出代码中有data和crc两个数据接口,说明上一个数据的校验结果要作为下一个数据校验过程中移位寄存器的初值,如此循环往复在数据帧的下一拍就能输出整个数据帧的校验值了。关于CRC校验原理和逻辑实现方式已经告一段落。因数据帧校验对校验算法的纠检错能力要求较高,故采用CRC32。这里仅实现检错丢弃功能,即对接收端校验正确的数据帧保留,错误帧丢弃。同样由线上生成工具得到CRC32源代码(数据位宽32bit):

////////////////////////////////////////////////////////////////////////////////

// Purpose : synthesizable CRC function
// * polynomial: x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
// * data width: 32 ////////////////////////////////////////////////////////////////////////////////
module CRC32_D32; // polynomial: x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
// data width: 32
// convention: the first serial bit is D[31]
function [:] nextCRC32_D32; input [:] Data;
input [:] crc;
reg [:] d;
reg [:] c;
reg [:] newcrc;
begin
d = Data;
c = crc; newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
newcrc[] = d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
nextCRC32_D32 = newcrc;
end
endfunction
endmodule

  这推导一遍可要了命了!还好是现成的。代码以函数形式给出,我们对此稍作修改并补充好接口逻辑。

`timescale 1ns / 1ps

module CRC32_D32(
input clk,
input rst_n,
input clr,//同步清零
input din_vld,
input [:] din, output reg dout_vld,
output reg [:] dout//crc校验结果
); // polynomial: x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
// data width: 32
// convention: the first serial bit is D[31]
// function [31:0] nextCRC32_D32; wire [:] d;
wire [:] c; assign d = din;
assign c = dout; always@(posedge clk or negedge rst_n)begin
if(!rst_n)
dout <= 'hffff_ffff;
else if(clr)
dout <= 'hffff_ffff;
else if(din_vld)begin
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <=d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <=d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <=d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <=d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <=d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <=d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <=d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <=d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <=d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
dout[] <= d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ d[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[] ^ c[];
end
end //dout_vld
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
dout_vld <= ;
else
dout_vld <= din_vld;
end endmodule

  寄存器的每一位仅与其对应的表达式有关,故可以通过时序逻辑和阻塞赋值实现并行计算。现添加测试激励仿真验证:

 `timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2017/10/17 17:39:59
// Design Name:
// Module Name: CRC32_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////// module CRC32_tb; reg clk,rst_n;
reg [:] din;
reg din_vld;
reg clr; wire [:] dout;
wire dout_vld;
wire [:] result_final; CRC32_D32 CRC32_D32(
.clk(clk),
.rst_n(rst_n),
.clr(clr),//同步清零
.din_vld(din_vld),
.din(din), .dout_vld(dout_vld),
.dout(dout)//crc校验结果
); parameter CYC = ,
RST_TIME = ; initial begin
clk = ;
forever#(CYC /2.0) clk = ~clk;
end initial begin
rst_n = ;
#;
rst_n = ;
#(CYC*RST_TIME) rst_n = ;
end initial begin
//Initialize Inputs
#;
din = ;
clr = ;
din_vld = ;
#(CYC*RST_TIME)
#(CYC*)
din_vld = ;
din = 'h12345678;
#(CYC*)
din = 'hdf8a8a2b;
#(CYC*)
din_vld = ;
#(CYC*)
$stop;
end assign result_final = ~dout; endmodule

  波形如下:

  将第一个数的校验结果作为第二个待校验数时,最终校验结果为全1.我们再多加几个数看看

  同样,得到前四个数校验结果后,将其添加到数据帧尾作为第五个待校验数值时,最终结果亦为全1.由此可知,当将前N-1个数取反前校验结果作为第N个数一起计算时,下一拍校验值取反一定为全1,这正好是数据传输正确情况下接收端的状态。

  有CRC代码生成工具,自然有校验结果计算工具:On-line CRC calculation and free library  https://www.lammertbies.nl/comm/info/crc-calculation.html 注意本文中CRC代码计算结果与计算工具不符,这是因为校验算法中会涉及到一些以字节为单位的bit颠倒,字节颠倒和取反等操作,根据不同的应用场合会有所变动。

数据帧CRC32校验算法实现的更多相关文章

  1. CRC-32 校验算法

      crc32的头文件 ===========================分割线=========================== //crc32.h #ifndef _CRC32_H #de ...

  2. 常用校验算法CRC、MD5、SHA_转

    1.算法概述 数据摘要算法是密码学算法中非常重要的一个分支,它通过对所有数据提取指纹信息以实现数据签名.数据完整性校验等功能,由于其不可逆性,有时候会被用做敏感信息的加密.数据摘要算法也被称为哈希(H ...

  3. C#校验算法列举

    以下是工作中常用的几种校验算法,后期将不断更新 和校验 /// <summary> /// CS和校验 /// </summary> /// <param name=&q ...

  4. CRC校验算法详解

    CRC(Cyclic Redundancy Check)循环冗余校验是常用的数据校验方法,讲CRC算法的文章很多,之所以还要写这篇,是想换一个方法介绍CRC算法,希望能让大家更容易理解CRC算法. 先 ...

  5. 银行卡luhm校验算法

    /** * 15位银行卡luhm校验算法 * 1.从卡号最后一位数字开始,逆向将奇数位(1.3.5等等)相加. * 2.从卡号最后一位数字开始,逆向将偶数位数字,先乘以2(如果乘积为两位数,则将其减去 ...

  6. CRC32校验的用法

    CRC32校验数据的完整性 这里的数据包括字符串.文件,还有哪些? 文件校验相当于下载大型软件,有md5加密结果.这里的用途是什么?

  7. 使用 boost 进行 CRC32 校验

    使用 boost 进行 CRC32 校验 - firebird321的专栏 - 博客频道 - CSDN.NET 使用 boost 进行 CRC32 校验 分类: 文件操作 2008-06-06 18: ...

  8. C# 异或校验算法

    C# 的异或校验算法 直接上代码 public partial class FormCRC : Form { public FormCRC() { InitializeComponent(); } p ...

  9. CRC校验算法学习

    原文:http://www.repairfaq.org/filipg/LINK/F_crc_v31.html 本文根据上述链接原文翻译而来,如有错误,忘广大网友互相帮忙纠正,谢谢! 1.前言: 1.0 ...

随机推荐

  1. Window10中利用Windbg与虚拟机(window7)中调试驱动建立方法

    想起自己的windbg配置就转载:eqera的windows内核调试配置,真的是获益良多希望他不会介意我转载他的博客,帮了我很多,记录下来给我也给大家, 其中我主要看的是VMWare的pipe建立,而 ...

  2. IDEA配置Tomcat

    如何用IDEA写Servlet在我别的博文有! 注意:如果不能成功启动Tomcat,很有可能是JDK版本和Tomcat版本不匹配,此时你可以降低JDK版本试试

  3. JQuery中关于浏览器兼容性的问题

      前  言 LIUWE JQuery是一个特别强大的javascript代码库,,它的操作DOM的能力是相当强大的,JQuery可以说是支持各大主流浏览器,但是随着时代的不断发展,浏览器是在不断的更 ...

  4. nmap扫描某段网络连通性

    nmap -v -sP 10.0.10.0/24 进行ping扫描,打印出对扫描做出响应的主机,不做进一步测试(如端口扫描或者操作系统探测): nmap -sP 192.168.1.0/24 仅列出指 ...

  5. 【黑马18期Java毕业生】黑马程序员Java全套资料+视频+工具

        Java学习路线图引言:        黑马程序员:深知广大爱好Java的人学习是多么困难,没视频没资源,上网花钱还老被骗. 为此我们历时一个月整理这套Java学习路线图,不管你是不懂电脑的小 ...

  6. 51 nod 1624 取余最长路 思路:前缀和 + STL(set)二分查找

    题目: 写这题花了我一上午时间. 下面是本人(zhangjiuding)的思考过程: 首先想到的是三行,每一行一定要走到. 大概是这样一张图 每一行长度最少为1.即第一行(i -1) >= 1, ...

  7. httpd三种MPM的原理剖析

    html { font-family: sans-serif } body { margin: 0 } article,aside,details,figcaption,figure,footer,h ...

  8. Operating system hdu 2835 OPT

    Operating system Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  9. FPGA与PCI-E

    从并行到串行: PCI Express(又称PCIe)是一种高性能.高带宽串行通讯互连标准,取代了基于总线的通信架构,如:PCI.PCI Extended (PCI-X) 以及加速图形端口(AGP). ...

  10. JavaScript链式调用

    1.什么是链式调用? 这个很容易理解,例如 $('text').setStyle('color', 'red').show(); 一般的函数调用和链式调用的区别:链式调用完方法后,return thi ...