CRC计算-Verilog实现

ops/2024/11/14 12:40:45/

一、前言

循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包和计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。(只能检验错误,而不能纠错)。

CRC校验的原理可以参考此篇文章:CRC校验详解(附代码示例)_crc校验代码-CSDN博客

在此不做过多的赘述。

二、数据宽度为8bit的CRC校验

CRC校验的verilog代码可以通过Easics CRC Tool此网站生成,在此网站可以选择常用的生成多项式,比如32位的以太网生成多项式。

也可以自己选择生成多项式,然后根据这篇博客中的表项,选择初始值以及是否要进行数据反转、取反。 

下面是根据8位输入,32位输出的CRC代码

module CRC32_D8(input           i_clk   ,input           i_rst   ,input [7:0]     i_data  ,input           i_en    ,output[31:0]    o_crc   );reg  [31:0]       crc                 ;wire [7:0]        d                   ;wire [31:0]       c                   ;wire [31:0]       newcrc              ;assign  o_crc =   ~{crc[0],crc[1],crc[2],crc[3],crc[4],crc[5],crc[6],crc[7],crc[8],crc[9],crc[10],crc[11],crc[12],crc[13],crc[14],crc[15],crc[16],crc[17],crc[18],crc[19],crc[20],crc[21],crc[22],crc[23],crc[24],crc[25],crc[26],crc[27],crc[28],crc[29],crc[30],crc[31]}                 ;//本次计算的CRC结果输出,数据反转,并进行取反assign d = {i_data[0],i_data[1],i_data[2],i_data[3],i_data[4],i_data[5],i_data[6],i_data[7]};   //需不需要反转需要查表assign c = crc;//将本次计算的赋值给下一次运算的中间变量assign newcrc[0] = d[6] ^ d[0] ^ c[24] ^ c[30];assign newcrc[1] = d[7] ^ d[6] ^ d[1] ^ d[0] ^ c[24] ^ c[25] ^ c[30] ^ c[31];assign newcrc[2] = d[7] ^ d[6] ^ d[2] ^ d[1] ^ d[0] ^ c[24] ^ c[25] ^ c[26] ^ c[30] ^ c[31];assign newcrc[3] = d[7] ^ d[3] ^ d[2] ^ d[1] ^ c[25] ^ c[26] ^ c[27] ^ c[31];assign newcrc[4] = d[6] ^ d[4] ^ d[3] ^ d[2] ^ d[0] ^ c[24] ^ c[26] ^ c[27] ^ c[28] ^ c[30];assign newcrc[5] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[1] ^ d[0] ^ c[24] ^ c[25] ^ c[27] ^ c[28] ^ c[29] ^ c[30] ^ c[31];assign newcrc[6] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[2] ^ d[1] ^ c[25] ^ c[26] ^ c[28] ^ c[29] ^ c[30] ^ c[31];assign newcrc[7] = d[7] ^ d[5] ^ d[3] ^ d[2] ^ d[0] ^ c[24] ^ c[26] ^ c[27] ^ c[29] ^ c[31];assign newcrc[8] = d[4] ^ d[3] ^ d[1] ^ d[0] ^ c[0] ^ c[24] ^ c[25] ^ c[27] ^ c[28];assign newcrc[9] = d[5] ^ d[4] ^ d[2] ^ d[1] ^ c[1] ^ c[25] ^ c[26] ^ c[28] ^ c[29];assign newcrc[10] = d[5] ^ d[3] ^ d[2] ^ d[0] ^ c[2] ^ c[24] ^ c[26] ^ c[27] ^ c[29];assign newcrc[11] = d[4] ^ d[3] ^ d[1] ^ d[0] ^ c[3] ^ c[24] ^ c[25] ^ c[27] ^ c[28];assign newcrc[12] = d[6] ^ d[5] ^ d[4] ^ d[2] ^ d[1] ^ d[0] ^ c[4] ^ c[24] ^ c[25] ^ c[26] ^ c[28] ^ c[29] ^ c[30];assign newcrc[13] = d[7] ^ d[6] ^ d[5] ^ d[3] ^ d[2] ^ d[1] ^ c[5] ^ c[25] ^ c[26] ^ c[27] ^ c[29] ^ c[30] ^ c[31];assign newcrc[14] = d[7] ^ d[6] ^ d[4] ^ d[3] ^ d[2] ^ c[6] ^ c[26] ^ c[27] ^ c[28] ^ c[30] ^ c[31];assign newcrc[15] = d[7] ^ d[5] ^ d[4] ^ d[3] ^ c[7] ^ c[27] ^ c[28] ^ c[29] ^ c[31];assign newcrc[16] = d[5] ^ d[4] ^ d[0] ^ c[8] ^ c[24] ^ c[28] ^ c[29];assign newcrc[17] = d[6] ^ d[5] ^ d[1] ^ c[9] ^ c[25] ^ c[29] ^ c[30];assign newcrc[18] = d[7] ^ d[6] ^ d[2] ^ c[10] ^ c[26] ^ c[30] ^ c[31];assign newcrc[19] = d[7] ^ d[3] ^ c[11] ^ c[27] ^ c[31];assign newcrc[20] = d[4] ^ c[12] ^ c[28];assign newcrc[21] = d[5] ^ c[13] ^ c[29];assign newcrc[22] = d[0] ^ c[14] ^ c[24];assign newcrc[23] = d[6] ^ d[1] ^ d[0] ^ c[15] ^ c[24] ^ c[25] ^ c[30];assign newcrc[24] = d[7] ^ d[2] ^ d[1] ^ c[16] ^ c[25] ^ c[26] ^ c[31];assign newcrc[25] = d[3] ^ d[2] ^ c[17] ^ c[26] ^ c[27];assign newcrc[26] = d[6] ^ d[4] ^ d[3] ^ d[0] ^ c[18] ^ c[24] ^ c[27] ^ c[28] ^ c[30];assign newcrc[27] = d[7] ^ d[5] ^ d[4] ^ d[1] ^ c[19] ^ c[25] ^ c[28] ^ c[29] ^ c[31];assign newcrc[28] = d[6] ^ d[5] ^ d[2] ^ c[20] ^ c[26] ^ c[29] ^ c[30];assign newcrc[29] = d[7] ^ d[6] ^ d[3] ^ c[21] ^ c[27] ^ c[30] ^ c[31];assign newcrc[30] = d[7] ^ d[4] ^ c[22] ^ c[28] ^ c[31];assign newcrc[31] = d[5] ^ c[23] ^ c[29];always@(posedge i_clk,posedge i_rst)beginif(i_rst)crc <= 32'hFFFFFFFF;else if(i_en)crc <= newcrc;elsecrc <= crc;
end
endmodule

三、数据宽度打入8bit的CRC校验

当输入的数据宽度大于1byte时,假设为B1B2B3B4B5B6B7,需要首先计算出B1的CRC1,然后在CRC1的基础上(CRC2的初值变为CRC1)计算B2的CRC2,之后一直持续此过程,直到所有的输入的字节全部计算完成。同时需要将每一个字节CRC计算的结果输出。以64bit位宽的输入为例,计算CRC-32.

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2024/04/28 15:49:12
// Design Name: 
// Module Name: CRC32_64bKEEP
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 多位宽的CRC运算,也是按照字节进行的,下一个字节CRC运算值,是在上一个字节的CRC运算值的基础上进行的
//module CRC32_64bKEEP(input           i_clk     ,input           i_rst     ,input [7:0]     i_data    ,input [7:0]     i_data_1  ,input [7:0]     i_data_2  ,input [7:0]     i_data_3  ,input [7:0]     i_data_4  ,input [7:0]     i_data_5  ,input [7:0]     i_data_6  ,input [7:0]     i_data_7  ,  input           i_en      ,output[31:0]    o_crc     ,   output[31:0]    o_crc_1   ,output[31:0]    o_crc_2   ,output[31:0]    o_crc_3   ,output[31:0]    o_crc_4   ,output[31:0]    o_crc_5   ,output[31:0]    o_crc_6   ,output[31:0]    o_crc_7      
);reg  [31:0]       crc                 ;wire [7:0]        d[0:7]              ;wire [31:0]       c[0:7]              ;wire [31:0]       newcrc[0:7]         ;reg  [31:0]       ro_crc[0:7]         ;assign d[0] = {i_data[0],i_data[1],i_data[2],i_data[3],i_data[4],i_data[5],i_data[6],i_data[7]};   //需不需要反转需要查表assign d[1] = {i_data_1[0],i_data_1[1],i_data_1[2],i_data_1[3],i_data_1[4],i_data_1[5],i_data_1[6],i_data_1[7]};assign d[2] = {i_data_2[0],i_data_2[1],i_data_2[2],i_data_2[3],i_data_2[4],i_data_2[5],i_data_2[6],i_data_2[7]};assign d[3] = {i_data_3[0],i_data_3[1],i_data_3[2],i_data_3[3],i_data_3[4],i_data_3[5],i_data_3[6],i_data_3[7]};assign d[4] = {i_data_4[0],i_data_4[1],i_data_4[2],i_data_4[3],i_data_4[4],i_data_4[5],i_data_4[6],i_data_4[7]};assign d[5] = {i_data_5[0],i_data_5[1],i_data_5[2],i_data_5[3],i_data_5[4],i_data_5[5],i_data_5[6],i_data_5[7]};assign d[6] = {i_data_6[0],i_data_6[1],i_data_6[2],i_data_6[3],i_data_6[4],i_data_6[5],i_data_6[6],i_data_6[7]};assign d[7] = {i_data_7[0],i_data_7[1],i_data_7[2],i_data_7[3],i_data_7[4],i_data_7[5],i_data_7[6],i_data_7[7]};assign o_crc   = ro_crc[0];assign o_crc_1 = ro_crc[1];assign o_crc_2 = ro_crc[2];assign o_crc_3 = ro_crc[3];assign o_crc_4 = ro_crc[4];assign o_crc_5 = ro_crc[5];assign o_crc_6 = ro_crc[6];assign o_crc_7 = ro_crc[7];assign c[0] = crc;//第一次运算c[0]=32'hFFFFFFFF,第二次运算c[0]=上一次运算的crc结果genvar i;generate for(i = 0; i < 8;i = i + 1)beginassign newcrc[i][0]  = d[i][6] ^ d[i][0]  ^ c[i][24] ^ c[i][30];assign newcrc[i][1]  = d[i][7] ^ d[i][6]  ^ d[i][1]  ^ d[i][0]  ^ c[i][24] ^ c[i][25] ^ c[i][30] ^ c[i][31];assign newcrc[i][2]  = d[i][7] ^ d[i][6]  ^ d[i][2]  ^ d[i][1]  ^ d[i][0]  ^ c[i][24] ^ c[i][25] ^ c[i][26] ^ c[i][30] ^ c[i][31];assign newcrc[i][3]  = d[i][7] ^ d[i][3]  ^ d[i][2]  ^ d[i][1]  ^ c[i][25] ^ c[i][26] ^ c[i][27] ^ c[i][31];assign newcrc[i][4]  = d[i][6] ^ d[i][4]  ^ d[i][3]  ^ d[i][2]  ^ d[i][0]  ^ c[i][24] ^ c[i][26] ^ c[i][27] ^ c[i][28] ^ c[i][30];assign newcrc[i][5]  = d[i][7] ^ d[i][6]  ^ d[i][5]  ^ d[i][4]  ^ d[i][3]  ^ d[i][1]  ^ d[i][0]  ^ c[i][24] ^ c[i][25] ^ c[i][27] ^ c[i][28] ^ c[i][29] ^ c[i][30] ^ c[i][31];assign newcrc[i][6]  = d[i][7] ^ d[i][6]  ^ d[i][5]  ^ d[i][4]  ^ d[i][2]  ^ d[i][1]  ^ c[i][25] ^ c[i][26] ^ c[i][28] ^ c[i][29] ^ c[i][30] ^ c[i][31];assign newcrc[i][7]  = d[i][7] ^ d[i][5]  ^ d[i][3]  ^ d[i][2]  ^ d[i][0]  ^ c[i][24] ^ c[i][26] ^ c[i][27] ^ c[i][29] ^ c[i][31];assign newcrc[i][8]  = d[i][4] ^ d[i][3]  ^ d[i][1]  ^ d[i][0]  ^ c[i][0]  ^ c[i][24] ^ c[i][25] ^ c[i][27] ^ c[i][28];assign newcrc[i][9]  = d[i][5] ^ d[i][4]  ^ d[i][2]  ^ d[i][1]  ^ c[i][1]  ^ c[i][25] ^ c[i][26] ^ c[i][28] ^ c[i][29];assign newcrc[i][10] = d[i][5] ^ d[i][3]  ^ d[i][2]  ^ d[i][0]  ^ c[i][2]  ^ c[i][24] ^ c[i][26] ^ c[i][27] ^ c[i][29];assign newcrc[i][11] = d[i][4] ^ d[i][3]  ^ d[i][1]  ^ d[i][0]  ^ c[i][3]  ^ c[i][24] ^ c[i][25] ^ c[i][27] ^ c[i][28];assign newcrc[i][12] = d[i][6] ^ d[i][5]  ^ d[i][4]  ^ d[i][2]  ^ d[i][1]  ^ d[i][0]  ^ c[i][4]  ^ c[i][24] ^ c[i][25] ^ c[i][26] ^ c[i][28] ^ c[i][29] ^ c[i][30];assign newcrc[i][13] = d[i][7] ^ d[i][6]  ^ d[i][5]  ^ d[i][3]  ^ d[i][2]  ^ d[i][1]  ^ c[i][5]  ^ c[i][25] ^ c[i][26] ^ c[i][27] ^ c[i][29] ^ c[i][30] ^ c[i][31];assign newcrc[i][14] = d[i][7] ^ d[i][6]  ^ d[i][4]  ^ d[i][3]  ^ d[i][2]  ^ c[i][6]  ^ c[i][26] ^ c[i][27] ^ c[i][28] ^ c[i][30] ^ c[i][31];assign newcrc[i][15] = d[i][7] ^ d[i][5]  ^ d[i][4]  ^ d[i][3]  ^ c[i][7]  ^ c[i][27] ^ c[i][28] ^ c[i][29] ^ c[i][31];assign newcrc[i][16] = d[i][5] ^ d[i][4]  ^ d[i][0]  ^ c[i][8]  ^ c[i][24] ^ c[i][28] ^ c[i][29];assign newcrc[i][17] = d[i][6] ^ d[i][5]  ^ d[i][1]  ^ c[i][9]  ^ c[i][25] ^ c[i][29] ^ c[i][30];assign newcrc[i][18] = d[i][7] ^ d[i][6]  ^ d[i][2]  ^ c[i][10] ^ c[i][26] ^ c[i][30] ^ c[i][31];assign newcrc[i][19] = d[i][7] ^ d[i][3]  ^ c[i][11] ^ c[i][27] ^ c[i][31];assign newcrc[i][20] = d[i][4] ^ c[i][12] ^ c[i][28];assign newcrc[i][21] = d[i][5] ^ c[i][13] ^ c[i][29];assign newcrc[i][22] = d[i][0] ^ c[i][14] ^ c[i][24];assign newcrc[i][23] = d[i][6] ^ d[i][1]  ^ d[i][0]  ^ c[i][15] ^ c[i][24] ^ c[i][25] ^ c[i][30];assign newcrc[i][24] = d[i][7] ^ d[i][2]  ^ d[i][1]  ^ c[i][16] ^ c[i][25] ^ c[i][26] ^ c[i][31];assign newcrc[i][25] = d[i][3] ^ d[i][2]  ^ c[i][17] ^ c[i][26] ^ c[i][27];assign newcrc[i][26] = d[i][6] ^ d[i][4]  ^ d[i][3]  ^ d[i][0]  ^ c[i][18] ^ c[i][24] ^ c[i][27] ^ c[i][28] ^ c[i][30];assign newcrc[i][27] = d[i][7] ^ d[i][5]  ^ d[i][4]  ^ d[i][1]  ^ c[i][19] ^ c[i][25] ^ c[i][28] ^ c[i][29] ^ c[i][31];assign newcrc[i][28] = d[i][6] ^ d[i][5]  ^ d[i][2]  ^ c[i][20] ^ c[i][26] ^ c[i][29] ^ c[i][30];assign newcrc[i][29] = d[i][7] ^ d[i][6]  ^ d[i][3]  ^ c[i][21] ^ c[i][27] ^ c[i][30] ^ c[i][31];assign newcrc[i][30] = d[i][7] ^ d[i][4]  ^ c[i][22] ^ c[i][28] ^ c[i][31];assign newcrc[i][31] = d[i][5] ^ c[i][23] ^ c[i][29]; if(i > 0)beginassign c[i] = newcrc[i - 1];endendendgenerate//8字节的数据输入,每一个字节都会产生一个CRC的运算结果,将每一次计算的数据输入都输出出来genvar j;generate for(j = 0;j < 8;j = j + 1)beginalways@(posedge i_clk,posedge i_rst)beginif(i_rst)ro_crc[j] <= 'd0;else if(!i_en)ro_crc[j] <= 'd0;elsero_crc[j] <= ~{ newcrc[j][0],newcrc[j][1],newcrc[j][2],newcrc[j][3],newcrc[j][4],newcrc[j][5],newcrc[j][6],newcrc[j][7],newcrc[j][8],newcrc[j][9],newcrc[j][10],newcrc[j][11],newcrc[j][12],newcrc[j][13],newcrc[j][14],newcrc[j][15],newcrc[j][16],newcrc[j][17],newcrc[j][18],newcrc[j][19],newcrc[j][20],newcrc[j][21],newcrc[j][22],newcrc[j][23],newcrc[j][24],newcrc[j][25],newcrc[j][26],newcrc[j][27],newcrc[j][28],newcrc[j][29],newcrc[j][30],newcrc[j][31]};end endendgeneratealways@(posedge i_clk,posedge i_rst)beginif(i_rst || !i_en)crc <= 32'hFFFFFFFF;else if(i_en)crc <= newcrc[7];elsecrc <= crc;
endendmodule


http://www.ppmy.cn/ops/27716.html

相关文章

python烟花代码

在Python中&#xff0c;可以使用多种方式来模拟烟花效果&#xff0c;其中一种常见的方法是使用turtle图形库来绘制。以下是一个简单的示例&#xff0c;展示了如何使用turtle来创建一个烟花效果的动画&#xff1a; import turtle import random# 设置屏幕和背景 screen turtle…

java:EasyExcel使用(一)读excel

java&#xff1a;EasyExcel使用&#xff08;一&#xff09;读excel 1 前言 EasyExcel相比于传统使用poi进行excel文件读写&#xff0c;编程使用操作上更加方便快捷&#xff0c;且对于内存溢出进行了优化处理。本文是EasyExcel读excel操作。 Java解析、生成Excel比较有名的框…

Windows下载MingGW

因为要配置vscode的c/c环境&#xff0c;需要下载一个编译器&#xff0c;gcc官方推荐开源的MingGW-W64&#xff0c;看了几个下载方法&#xff0c;决定用最简单的离线安装。 niXman/mingw-builds-binaries/releases 32位的操作系统&#xff1a;i686&#xff0c;64位的操作系统&a…

《Redis使用手册之Lua脚本》

《Redis使用手册之Lua脚本》 EVAL&#xff1a;执行脚本 127.0.0.1:6379> eval “return ‘hello world’” 0 “hello world” 127.0.0.1:6379> eval “return redis.call(‘set’,KEYS[1],ARGV[1])” 1 “message” “hello world” OK 127.0.0.1:6379> get message…

使用FPGA实现串-并型乘法器

介绍 其实我们知道&#xff0c;用FPGA实现乘法器并不是一件很简单的事&#xff0c;而且在FPGA中也有乘法器的IP核可以直接调用&#xff0c;我这里完全就是为了熟悉一些FPGA的语法然后写了这样一个电路。 串-并型乘法器模块 从字面上看&#xff0c;串-并乘法器就是其中一个乘数…

岚图汽车与东软睿驰签署战略合作协议

4月26日,东软睿驰与岚图汽车正式签署战略合作协议,双方将结合在各自领域拥有的产业资源、技术研发和资本运作等优势,聚焦智能化产品和应用,建立长期共赢的战略合作伙伴关系,通过不断探索未来新技术、新产业、新业态和新模式,围绕用户需求共同打造极致的智能出行体验。 图为岚图…

小旋风蜘蛛池优化版

下载地址&#xff1a;小旋风蜘蛛池.zip 配置的时候需要做伪静态 #如果用的是宝塔面板设置伪静态&#xff0c;则去掉 第一行 的 location / { 和最后一行的 } location / { rewrite ^/template/(.*)\.html$ /index.php last; rewrite ^/temp/(data|db|robotlog|tplrules|errp…

OpenHarmony实战开发-动画曲线、如何实现动画衔接

UI界面除了运行动画之外&#xff0c;还承载着与用户进行实时交互的功能。当用户行为根据意图变化发生改变时&#xff0c;UI界面应做到即时响应。例如用户在应用启动过程中&#xff0c;上滑退出&#xff0c;那么启动动画应该立即过渡到退出动画&#xff0c;而不应该等启动动画完…