当前位置:网站首页>FPGA手撕代码——CRC校验码的多种Verilog实现方式 (2021乐鑫科技数字IC提前批代码编程)
FPGA手撕代码——CRC校验码的多种Verilog实现方式 (2021乐鑫科技数字IC提前批代码编程)
2022-08-02 10:13:00 【jk_101】
如有侵权,请告知删除,谢谢!!!
完整工程代码在【FPGA探索者】回复【CRC】获取。
用Verilog实现CRC-8的串行计算,G(D)=D8+D2+D+1,计算流程如下图所示:

一、分析
CRC循环冗余校验码(Cyclic Redundancy Check),检错码。
(1)该题目所述为CRC-8,即输出8位CRC校验值,给定一段长为N-bit的有效输入序列,输出(N+8)-bit的数据,其中前N-bit数据为输入的原始数据,添加的8-bit数据为CRC校验数据;
(2)该CRC-8的生成多项式为G(D)=D8+D2+D+1,对CRC进行简化表示时可以忽略最高位的D8,结合图示中三个异或运算的位置更容易理解生成多项式,8位CRC有8个寄存器C0~C7,根据多项式,C0、C1和C2的输入是由异或运算而来;

二、Verilog编程
1. 并行计算,串行输出
对于输入位宽为1的输入,这种方法的计算非常简单,直接根据生成多项式运算。
(注意!如果输入位宽不为1,则需要根据多项式进行化简,可以使用http://outputlogic.com/?page_id=321生成运算逻辑和代码)
1.1 自己一步一步写
完整工程代码在【FPGA探索者】回复【CRC】获取。
(1)先定义8个寄存器reg [7:0]
reg [7:0] crc_reg_q;// 寄存器 Q 输出端
reg [7:0] crc_reg_d;// 寄存器 D 输入端(对crc_reg_d,使用always赋值就定义成reg,使用assign就定义成wire)
(2)异或计算
寄存器0的输入crc_reg_d[0],来自寄存器7的输出crc_reg_q[7]和数据输入data_in异或运算,即:
crc_reg_d [0] = crc_reg_q[7] ^ data_in;同理可得:
always @ (*)
begin
crc_reg_d[0] = crc_reg_q[7] ^ data_in;
crc_reg_d[1] = crc_reg_q[7] ^ data_in ^ crc_reg_q[0];
crc_reg_d[2] = crc_reg_q[7] ^ data_in ^ crc_reg_q[1];
crc_reg_d[3] = crc_reg_q[2];
crc_reg_d[4] = crc_reg_q[3];
crc_reg_d[5] = crc_reg_q[4];
crc_reg_d[6] = crc_reg_q[5];
crc_reg_d[7] = crc_reg_q[6];
end上述使用组合逻辑实现异或运算和数据的传递,另外,对于每个寄存器的输入到输出(D端到Q端),使用时序逻辑,并且按照题目要求,设置初始值为全1,将数据有效标志作为控制逻辑:
always @ (posedge clk)
begin
if( rst)
crc_reg_q <= 8’hff;
elsebegin
if(data_valid )
crc_reg_q<= crc_reg_d;// 输入数据有效就更新值
else
crc_reg_q<= crc_reg_q;// 输入数据无效就等待
end
end(3)串行输出
上述已经实现了并行的 CRC,计算出的 CRC 结果就是直接的 8 位 CRC,按照题目要求,需要串行输出 CRC 结果。
思路:写一个计数器,当需要输出 CRC 时,串行计数输出,实现并串转换。这里,由于题目给了一个信号 crc_start,我把这个信号作为 CRC 的标志,当 data_valid 有效时表示输入的是数据,当 data_valid 无效且crc_start 有效表示数据输入完毕,该输出 CRC 了。
reg [2:0] count;
always @ (posedge clk)
begin
if(rst)begin
crc_out <= 0;
count<= 0;
end
elsebegin
if(data_valid) begin
crc_out <= data_in;
crc_valid <= 1'b0;
end
elseif(crc_start)begin
count <= count + 1'b1;
crc_out <= crc_reg_q [7-count];
crc_valid <= 1'b1;
end
elsebegin
crc_valid <= 1'b0;
end
end
end1.2 CRC Generator自动生成
在Step1中,根据要求,1处表示输入数据位宽为1,2处CRC输出8位,3处选择自定义CRC的多项式,4处点击运用设定,然后进入Step2。

根据生成多项式,勾选1、X1、X2即可(对应1+D1+D2,最高位的D8不用管)。

//-----------------------------------------------------------------------------
// Copyright (C) 2009 OutputLogic.com
// This source file may be used and distributedwithout restriction
// provided that this copyright statement is notremoved from the file
// and that any derivative work contains theoriginal copyright notice
// and the associated disclaimer.
//
// THIS SOURCE FILE IS PROVIDED "ASIS" AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUTLIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FORA PARTICULAR PURPOSE.
//-----------------------------------------------------------------------------
// CRC module for data[0:0] , crc[7:0]=1+x^1+x^2+x^8;
//-----------------------------------------------------------------------------
module crc(
input [0:0] data_in,
input crc_en,
output [7:0] crc_out,
input rst,
input clk);
reg [7:0] lfsr_q,lfsr_c;
assign crc_out = lfsr_q;
always @(*) begin
lfsr_c[0] = lfsr_q[7] ^ data_in[0];
lfsr_c[1] = lfsr_q[0] ^ lfsr_q[7]^ data_in[0];
lfsr_c[2] = lfsr_q[1] ^ lfsr_q[7]^ data_in[0];
lfsr_c[3] = lfsr_q[2];
lfsr_c[4] = lfsr_q[3];
lfsr_c[5] = lfsr_q[4];
lfsr_c[6] = lfsr_q[5];
lfsr_c[7] = lfsr_q[6];
end // always
always @(posedge clk, posedge rst) begin
if(rst) begin
lfsr_q <= {8{1'b1}};
end
else begin
lfsr_q <= crc_en ? lfsr_c: lfsr_q;
end
end // always
endmodule // crc将上述代码按照题目要求改变输入输出的名称,并进行串并转换(并->串)即可。

1.3 easics自动生成
https://www.easics.com/crctool
(1)1处选择CRC的生成多项式,这里与1.2的不同在于,要把最高位的D8选上,easics能识别的CRC协议更多;
(2)2处自动识别出这个CRC多项式其实是CRC8 ATM HEC协议使用的 CRC;
(3)3处设置输入数据位宽为1;
(4)选择生成Verilog代码;
(5)下载代码。

仔细阅读代码注释,注意!
convention: the first serial bit is D[0]
数据的最低位先输出,此代码将会把低位作为异或移出位,而上面已经提到的两种方法均是将最高位作为移出位去异或,所以,代码中需要稍作修改,将d[0]改成d[7],d[1]改成d[6],…,以此类推,c[0]- c[7]不要变。
有兴趣的可以去看看【大小端问题】,在不同处理器、不同协议中非常常见。
///
// Copyright (C) 1999-2008 Easics NV.
// This source file may be used and distributedwithout restriction
// provided that this copyright statement is notremoved from the file
// and that any derivative work contains theoriginal copyright notice
// and the associated disclaimer.
//
// THIS SOURCE FILE IS PROVIDED "AS IS"AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUTLIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR APARTICULAR PURPOSE.
//
// Purpose : synthesizable CRC function
// *polynomial: x^8 + x^2 + x^1 + 1
// * datawidth: 1
//
// Info : [email protected]
// http://www.easics.com
///
module CRC8_D1;
//polynomial: x^8 + x^2 + x^1 + 1
// datawidth: 1
//convention: the first serial bit is D[0]
function[7:0] nextCRC8_D1;
inputData;
input[7:0] crc;
reg [0:0]d;
reg [7:0]c;
reg [7:0]newcrc;
begin
d[0] =Data;
c = crc;
newcrc[0]= d[0] ^ c[7];
newcrc[1]= d[0] ^ c[0] ^ c[7];
newcrc[2]= d[0] ^ c[1] ^ c[7];
newcrc[3]= c[2];
newcrc[4]= c[3];
newcrc[5]= c[4];
newcrc[6]= c[5];
newcrc[7]= c[6];
nextCRC8_D1 = newcrc;
end
endfunction
endmodule2. 串行计算,串行输出(函数function用法)
CRC计算的重要思想是不断的消除最高位。
(1) 新建函数function
Verilog函数名为next_crc,输入信号为 data_in 和 current_crc,输出信号为8位的新 crc。
函数功能为:根据输入信号data_in,跳转CRC的状态;
函数的设计逻辑为:
(a)将CRC寄存器的数据左移1位,低位补零,得到
{current_crc[6:0],1'b0} (其中{ }为位拼接符);(b)新输入的数据data_in和移出的CRC最高位做异或得到
current_crc[7]^data_in;(c)使用位拼接符对异或结果进行位扩展,CRC-8进行8位的扩展,得到
{8{current_crc[7]^data_in}}; (d)扩展后的数据和生成多项式进行与运算,得到
{8{current_crc[7]^data_in}} & (8'h07); (e)将(a)的数据和(d)的数据进行异或运算,得到CRC结果;
next_crc = {current_crc[6:0],1'b0} ^({8{current_crc[7]^data_in}} & (8'h07));上述,(a)是对CRC低位的处理,(b)-(d)是对CRC最高位的处理。
8’h07从何而来?
因为生成多项式G(D) = D8+D2+D1+D0,前面提到了最高位的D8不用管,那么使用8位去表示为 0000_0111,即低3位为1,其余为0,即8’h07。
function [7:0] next_crc;
inputdata_in;
input[7:0] current_crc;
begin
next_crc = {current_crc[6:0],1'b0} ^ ({8{current_crc[7]^data_in}} &(8'h07));
end
endfunction(2) 调用function函数
初始化时给寄存器赋值全为1,当数据有效时,进行CRC计算。
reg [7:0] crc_reg;
always @ (posedge clk)
begin
if(rst)begin
crc_reg <= 8'hff;
end
elsebegin
if(data_valid) begin
crc_reg <= next_crc(data_in, crc_reg);
end
end
end(3) 串行输出(串并转换)
按照上面的老方法,串并转换(并->串)。
完整工程代码在【FPGA探索者】公众号回复【CRC】获取。
输入32个1,先输出输入的32个1,紧跟着输出32个1的CRC校验值8’b00001111。

三、原理图设计
使用Quartus原理图设计,调用DFF触发器和XOR异或门搭建题目所示的CRC逻辑。

这里没有做data_valid的控制,输入数据是连续的32个1,输入完成后的CRC值是8’h0f,串行输出8位二进制数据 8’b00001111。

四、扩展
1. 并行计算并行输出
(1)对于单bit输入的序列,只要将并行计算串行输出的串并转换去掉,直接输出8-bit的CRC校验值即可;
(2)对于多bit同时输入的序列,通过介绍的两个在线平台去生成运算逻辑(笔试肯定不会丧心病狂到考多bit并行);
2. 查表法
实际工程中,为了减少运算量,还经常使用一种查表法,将CRC的校验表直接存储在ROM中,进行索引查找,常见的CRC表可以自行去查找,这里只是抛砖引玉。
————————————————
版权声明:本文为CSDN博主「DengFengLai123」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/DengFengLai123/article/details/124356120
边栏推荐
- 如何安装dosbox(pycharm详细安装教程)
- Linux system uninstall, install, upgrade, migrate clickHouse database
- 神通数据库,批量插入数据的时候失败
- 带你认识40G单纤双向光模块-QSFP+ BiDi光模块
- Naive Bayesian Method of Li Hang's "Statistical Learning Methods" Notes
- 关于缓存数据的探讨
- TimerTask(addin timer语音)
- LayaBox---TypeScript---Mixins
- The R language uses the rollapply function in the zoo package to apply the specified function to the time series in a rolling manner and the window moves, and set the align parameter to specify that t
- This article takes you to understand the commonly used models and frameworks of recommender systems
猜你喜欢

ConvNeXt论文及实现

8月份的.NET Conf 活动 专注于 .NET MAUI

零代码工具推荐---HiFlow

QT专题:事件机制event基础篇

重磅大咖来袭!阿里云生命科学与智能计算峰会精彩内容剧透

MSYS2 QtCreator Clangd code analysis can not find mm_malloc.h problem remedy

一款优秀的中文识别库——ocr

只问耕耘,不问收获,其实收获却在耕耘中

MySql tens of millions of paging optimization, fast insertion method of tens of millions of data

matlab-day02
随机推荐
Do you agree with this view?Most businesses are digitizing just to ease anxiety
LayaBox---TypeScript---命名空间和模块
如何封装微信小程序的 wx.request() 请求
yolov7 innovation point
【云原生】快出数量级的性能是怎样炼成的?就提升了亿点点
Verilog's random number system task----$random
Long battery life or safer?Seal and dark blue SL03 comparison shopping guide
The k-nearest neighbor method in the notes of Li Hang's "Statistical Learning Methods"
Unknown content monitoring
带你认识40G单纤双向光模块-QSFP+ BiDi光模块
练习-17
瑞萨RZ/G2L处理器详细测评
List-based queuing and calling system
R语言ggplot2可视化:使用ggpubr包的ggbarplot函数可视化水平柱状图(条形图)、使用orientation参数设置柱状图转置为条形图
Geoffery Hinton:深度学习的下一个大事件
Hello, my new name is "Bronze Lock/Tongsuo"
QT专题:事件机制event基础篇
软件测试H模型
牛客网项目2.7开发注册功能 报错This application has no explicit mapping for /error......
MySql tens of millions of paging optimization, fast insertion method of tens of millions of data