crc校验原理及Verilog实现

news2024/11/26 11:57:04

一、CRC 校验基本原理

循环冗余校验CRC,Cyclic Redundancy Check)是一种用于检测数据传输和存储时错误的校验方法,通过多项式除法生成校验码。

值得注意的是,CRC只能用于检测错误,但是不能纠错。同样的还有SHA-256。

如果因为异常工作环境导致单个数据的某些bit出错,可以通过加入纠错码(例如汉明码、BCH、LDPC等)来纠错。

接下来简单说一下CRC校验的基本原理,可以简述为以下步骤:

数据表示与生成多项式:将待校验的数据视为一个二进制多项式(即,数据中的每个比特对应多项式的一个系数)。选取一个预先定义的生成多项式,通常记为G(x),用于进行校验。

附加校验位:在数据的尾部附加若干个零比特(通常附加的零的数量等于生成多项式的阶数),形成待校验的数据帧。

二进制除法:使用生成多项式对数据帧进行二进制除法(模2除法),得到一个余数。这个余数即为CRC校验码。

附加校验码:将计算得到的CRC校验码附加到原始数据后,形成传输的数据帧。

校验过程:在接收端,使用相同的生成多项式对接收到的数据帧(包含CRC校验码)进行二进制除法。如果余数为零,说明数据在传输过程中没有发生错误;如果余数不为零,说明数据存在错误。

二、二进制除法介绍

因为在实际实现的过程中涉及到了二进制除法(模2除法)所以这里再简单介绍一下。

除法的运算规则:在二进制除法中,所有计算均使用模2运算,也就是逐位的“异或”运算。这里就不介绍异或的运算规则了。

二进制除法的基本步骤如下:

  1. 初始化:将被除数(即需要进行CRC校验的数据帧)和除数(即生成多项式)对齐,准备进行运算。通常被除数会在其末尾添加若干个零比特,以便进行完整的校验计算。

  2. 移位比对:从被除数的高位开始,与生成多项式的高位对齐。如果当前被除数的最高位为1,则执行异或操作。

  3. 异或运算:当对齐后,判断当前位:

    如果当前被除数的最高位是1,就对生成多项式和被除数进行异或操作。

    如果当前位是0,则相当于对0进行异或运算,结果保持不变。(不懂的可以自己计算一下和0异或的结果,位数和生成多项式一致)

  4. 移位并继续除法:执行完一次异或运算后,将被除数的剩余部分向左移位,(直到出现1为止,因为如果高位是0的话那就是要和0异或,结果不变)并继续与生成多项式对齐,重复上述步骤直到所有比特位都处理完。

  5. 得到余数:最终剩下的数就是余数,这个余数就是我们要附加到原始数据上的CRC校验码。

具体的例子我们放在CRC实现的时候一起讲吧。

三、CRC校验实现具体例子

  • 假设我们要发送的数据是1101

  • 生成多项式是 x 3 + x + 1 x^3+x+1 x3+x+1,那么与多项式对应的二进制数是1011(因为多项式中的三次方项和一次项和常数项有系数,所以是第0、1、3位为1)

  • 用1101对多项式对应的二进制数1011进行模2除法得到的余数就是CRC校验码(在1101后面补上3个0,因为多项式中最高次项为3次)

CRC校验码的位数和生成多项式中的最高次项对应(这里多项式的最高次项为3,那么CRC校验码就应该是3位)

  • 计算过程如下:

1101000

1011

——————

0110000

01011

——————

0011100

0010110

——————

0001010

0001011

—————

0000001

  • 这里得到的余数是001,那么CRC校验码就是001

  • 将校验码加到要传输的数据后面,得到1101001,这就是传输时发送的数据

  • 接收方对接收的数据再对多项式进行模2除法,如果此时最终得到的余数为0,那么接收的数据就是正确的。反之,就是错误的。计算步骤如下:

1101001

1011

——————

0110001

01011

——————

0011101

001011

——————

0001011

0001011

——————

0000000

所以得到最终的余数为0,说明接收的数据是正确的


四、Verilog 代码示例

方法一:

module crc_calculator(
    input clk,
    input rst,
    input [7:0] data_in,
    output reg [3:0] crc_out,
    output reg crc_valid
);

parameter POLYNOMIAL = 5'b11001; // 生成多项式 x^4 + x + 1
reg [11:0] temp_data;
reg [2:0] state;

always @(posedge clk or posedge rst) begin
    if (rst) begin
        crc_out <= 4'b0;
        crc_valid <= 0;
        state <= 0;
    end else begin
        case (state)
            3'b000: begin
                temp_data <= {data_in, 4'b0}; // 数据扩展
                state <= 3'b001;
            end
            3'b001: begin
                if (temp_data[11]) temp_data[11:7] <= temp_data[11:7] ^ POLYNOMIAL; // 高位为1,进行异或
                temp_data <= temp_data << 1; // 左移
                if (temp_data[7:4] == 4'b0) state <= 3'b010; // 完成CRC计算
            end
            3'b010: begin
                crc_out <= temp_data[3:0]; // 输出CRC校验码
                crc_valid <= 1;
                state <= 3'b000; // 重新开始
            end
        endcase
    end
end

endmodule

方法二:

module	crc_test(
	input				clk,
	input				rst,
	input		[7:0]	data_in,
	output	reg[3:0]	crc_out,
	output	reg			crc_vld
);
 
parameter				polynomial	=	5'b11001;
localparam				IDLE	=	3'b001,
						CRC		=	3'b010,
						DONE	=	3'b100;
						
reg		[11:0]			temp = 0;
reg		[2:0]			state;
wire	[11:0]			signal_temp;
 
assign	signal_temp	=	{data_in,4'b0};
 
always @ (posedge	clk	or	posedge	rst)begin
	if(rst)begin
		state		<=	IDLE;
		crc_out		<=	4'b0;
		crc_vld		<=	1'b0;
		end
	else case(state)
		IDLE:begin
			crc_out<=	4'b0;
			crc_vld<=	1'b0;
			temp	<=	signal_temp;
			state	<=	CRC;
			end
		CRC:begin
			state	<=	CRC;
			crc_vld	<=	1'b0;
			if(temp[11])	temp[11:7]	<=	temp[11:7]	^ polynomial;
			else if(temp[10])temp[10:6]	<=	temp[10:6]	^ polynomial; 
			else if(temp[9])temp[9:5]	<=	temp[9:5] 	^ polynomial; 
			else if(temp[8])temp[8:4]	<=	temp[8:4]	^ polynomial;
			else if(temp[7])temp[7:3]	<=	temp[7:3]   ^ polynomial; 
			else if(temp[6])temp[6:2]	<=	temp[6:2]   ^ polynomial;
			else if(temp[5])temp[5:1]	<=	temp[5:1]   ^ polynomial; 
			else if(temp[4])temp[4:0]	<=	temp[4:0]   ^ polynomial;
			else state<=DONE;
			end
		DONE:begin
			crc_out	<=	temp[3:0];
			crc_vld	<=	1'b1;
			state	<=	IDLE;
			end
		default : begin
			crc_out	<=	4'b0;
			crc_vld	<=	1'b1;
			state	<=	IDLE;
			end
		endcase
end 
endmodule

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2247822.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ArcGIS API for Javascript学习

一、ArcGIS API for Javascript 介绍 ArcGIS API for Javascript 是由美国 Esri 公司推出&#xff0c;跟随ArcGIS 9.3 同时发布的&#xff0c;是Esri 基于dojo 框架和 REST 风格实现的一套编程接口。通过 ArcGIS API for Javascript可以对ArcGIS for Server 进行访问&#xff…

JavaScript的let、var、const

这张图片主要介绍了JavaScript中的三种变量声明方式&#xff1a;let、var和const。 1. let 含义&#xff1a;let是现在实际开发中常用的变量声明方式。特点&#xff1a; 块级作用域&#xff1a;let声明的变量只在其所在的块级作用域内有效。例如&#xff1a;{let x 10; } co…

24.11.25 Mybatis1

1.Mybatis介绍 1.封装JDBC 减少重复性代码 2.ORM(实体关系映射框架) 通过框架 实体类 <--> 数据表 自动封装对象 3.半自动的ORM框架 还需要写sql语句 2.使用mybatis连接数据库(调通一遍 记住需要哪些文件) 1.创建全局配置文件 mybatis-config.xml <?xml ver…

【Python爬虫五十个小案例】爬取猫眼电影Top100

博客主页&#xff1a;小馒头学python 本文专栏: Python爬虫五十个小案例 专栏简介&#xff1a;分享五十个Python爬虫小案例 &#x1f40d;引言 猫眼电影是国内知名的电影票务与资讯平台&#xff0c;其中Top100榜单是影迷和电影产业观察者关注的重点。通过爬取猫眼电影Top10…

Oh-My-ZSH安装教程

1. 安装zsh sudo apt-get install zsh2.安装on-my-zsh wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | sh上面方式很大可能因为网络连接问题而失败&#xff0c;可以通过以下方式&#xff1a; git clone gitgithub.com:ohmyzsh/ohmyzsh…

三六零[601360]行情数据接口

1、三六零&#xff1a;实时行情 Restful API # 测试接口&#xff1a;可以复制到浏览器打开 https://tsanghi.com/api/fin/stock/XSHG/realtime?tokendemo&ticker601360获取股票实时行情&#xff08;开、高、低、收、量&#xff09;。 请求方式&#xff1a;GET。 Python示例…

用 OceanBase 4.3.3,搭建《黑神话:悟空》的专属游戏AI助手

本文分享了如何基于 OceanBase 4.3.3 bp1 社区版的向量检索能力&#xff0c;通过几条简单的命令&#xff0c;快速搭建一个定制化的专属游戏助手的过程。 背景 在 OceanBase 最新推出 V 4.3.3 免费试用的同时&#xff0c;也同时发布了几个基于OB Cloud 的向量能力&#xff0c;搭…

tableau练习-制作30个图表

一、导入数据 1、导入数据 -添加-添加连接-到文件-excel格式用第一个excel导入&#xff0c;csv格式用第二个文本格式导入 2、连接数据 -从旁边这里直接拖到中间 标头连接 -日期若不一致需调节日期格式 3、保存数据 点击数据提取-再保存数据&#xff0c;保存为twbx格式 二、设计…

QT QHorizontalSpacer控件 全面详解

本系列文章全面的介绍了QT中的57种控件的使用方法以及示例,包括 Button(PushButton、toolButton、radioButton、checkBox、commandLinkButton、buttonBox)、Layouts(verticalLayout、horizontalLayout、gridLayout、formLayout)、Spacers(verticalSpacer、horizontalSpacer)、…

第六届智能控制、测量与信号处理国际学术会议 (ICMSP 2024)

重要信息 2024年11月29日-12月1日 中国陕西西安石油大学雁塔校区 大会官网&#xff1a;www.icmsp.net 大会简介 第六届智能控制、测量与信号处理国际学术会议&#xff08;ICMSP 2024&#xff09;由西安石油大学、中海油田服务股份有限公司、浙江水利水电学院与中国石油装备…

Qt中2D绘制系统

目录 一、Qt绘制系统 1.1Qt绘制基本概念 1.2 绘制代码举例 1.3画家 1.3.1 QPainter的工作原理&#xff1a; 1.3.2 自定义绘制饼状图&#xff1a; 1.4画笔和画刷 1.4.1画笔 1.4.2 画刷填充样式 1.5 反走样和渐变 1.6绘制设备 1.7坐标变换 1.8QPainterPath 1.9绘制文…

Linux——Uboot命令使用

什么是Uboot&#xff1f; 1&#xff09;Uboot是一个裸机程序&#xff0c;比较复杂。类似我们PC机的BIOS程序。 2&#xff09;Uboot就是一个bootloader&#xff0c;作用就是用于启动Linux或者其他系统&#xff0c;Uboot最主要的工作是初始化DDR&#xff0c;因为Linux的运行是运行…

2024智能机器人与自动控制国际学术会议 (IRAC 2024)

主办&#xff0c;承办&#xff0c;支持单位 会议官网 www.icirac.org 大会时间&#xff1a;2024年11月29-12月1日 大会简介 2024智能机器人与自动控制国际学术会议 &#xff08;IRAC 2024&#xff09;由华南理工大学主办&#xff0c;会议将于2024年11月29日-12月1日在中国广…

Linux网络——NAT/代理服务器

一.NAT技术 1.NAT IP转换 之前我们讨论了, IPv4 协议中, IP 地址数量不充足的问题&#xff0c;NAT 技术就是当前解决 IP 地址不够用的主要手段, 是路由器的一个重要功能。 NAT 能够将私有 IP 对外通信时转为全局 IP. 也就是一种将私有 IP 和全局IP 相互转化的技术方法: 很…

【架构】主流企业架构Zachman、ToGAF、FEA、DoDAF介绍

文章目录 前言一、Zachman架构二、ToGAF架构三、FEA架构四、DoDAF 前言 企业架构&#xff08;Enterprise Architecture&#xff0c;EA&#xff09;是指企业在信息技术和业务流程方面的整体设计和规划。 最近接触到“企业架构”这个概念&#xff0c;转念一想必定和我们软件架构…

亚信安全发布《2024年第三季度网络安全威胁报告》

《亚信安全2024年第三季度网络安全威胁报告》的发布旨在从一个全面的视角解析当前的网络安全威胁环境。此报告通过详尽梳理和总结2024年第三季度的网络攻击威胁&#xff0c;目的是提供一个准确和直观的终端威胁感知。帮助用户更好地识别网络安全风险&#xff0c;并采取有效的防…

【c++】模板详解(2)

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C 目录 前言 一、非类型模板参数 二、模板的特化 1. 概念 2. 场景举例 3. 函数模板的特化 4. 类模板的特化 全特化 偏特化 1. 部分特化 2. 对参数的…

红队笔记--W1R3S、JARBAS、SickOS、Prime打靶练习记录

W1R3S(思路为主) 信息收集 首先使用nmap探测主机&#xff0c;得到192.168.190.147 接下来扫描端口&#xff0c;可以看到ports文件保存了三种格式 其中.nmap和屏幕输出的一样&#xff1b;xml这种的适合机器 nmap -sT --min-rate 10000 -p- 192.168.190.147 -oA nmapscan/ports…

Qt/C++基于重力模拟的像素点水平堆叠效果

本文将深入解析一个基于 Qt/C 的像素点模拟程序。程序通过 重力作用&#xff0c;将随机分布的像素点下落并水平堆叠&#xff0c;同时支持窗口动态拉伸后重新计算像素点分布。 程序功能概述 随机生成像素点&#xff1a;程序在初始化时随机生成一定数量的像素点&#xff0c;每个…

十一月二十五

双向循环链表 class Node:#显性定义出构造函数def __init__(self,data):self.data data #普通节点的数据域self.next None #保存下一个节点的链接域self.prior None #保存前一个节点饿链接域 class DoubleLinkLoop:def __init__(self, node Node):self.head nodeself.siz…