FPGA实现CAN通信CRC校验

检验本质上是CRC检验生成多项式
理解CRC校验,首先需要了解生成多项式的概念,生成多项式也就是发送方和接受方约定的一个除数而已,发送方和接收方都使用这一个相同的除数进行模2运算,计算结果相同则说明传输数据没有问题,而如果计算结果不同可能传输的数据就出现了问题,目的就是为了保证数据传输的可靠性。
上面提到的模二计算本质上就是异或运算,相同的位为0,不同的位为1,也就是不考虑进位、错位的二进制加减法运算,例如:10011011 + 11001010 = 01010001.
常见的生成多项式:
CRC8 = X8 + X5 + X4 +1
CRC12 = X12 + X11 + X3 + X2 + 1
CRC16 = X16 + X15 + X5 +1
CRC15 =X15 + X14 + X10 + X8 + X7 + X4 + X3 + X0.
CRC32 = X32 + X26 + X23 + X22 + X16 + X12 + X11 + X10 + X8 + X7 + X5 + X4 + X2 + X1 + 1
每一个生成多项式都是与一个代码相对应的,比如CRC8对应的代码就是100110001

比如在实现网络通信时C语言校验实现如下

uint cal_crc(uchar *ptr, uchar len) { uint crc; uchar i; crc=0; while (len--!=0) { for (i=0x80; i!=0; i/=2) { if ((crc&0x8000)!=0){crc*=2; crc^=0x1021;} else crc*=2; if ((*ptr&i)!=0)crc^=0x1021; } ptr++; } return(crc);
}

用FPGA实现32位网络通信CRC检验码并行计算如下


`timescale 1ns / 1ps
module crc (Clk, Reset, Data, Enable, Crc,CrcNext);
parameter Tp = 1;
input Clk;
input Reset;
input [0:3] Data;
input Enable;
output [31:0] Crc;
reg  [31:0] Crc;
output [31:0] CrcNext;
assign CrcNext[0] = Enable & (Data[0] ^ Crc[28]);
assign CrcNext[1] = Enable & (Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29]);
assign CrcNext[2] = Enable & (Data[2] ^ Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29] ^ Crc[30]);
assign CrcNext[3] = Enable & (Data[3] ^ Data[2] ^ Data[1] ^ Crc[29] ^ Crc[30] ^ Crc[31]);
assign CrcNext[4] = (Enable & (Data[3] ^ Data[2] ^ Data[0] ^ Crc[28] ^ Crc[30] ^ Crc[31])) ^ Crc[0];
assign CrcNext[5] = (Enable & (Data[3] ^ Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29] ^ Crc[31])) ^ Crc[1];
assign CrcNext[6] = (Enable & (Data[2] ^ Data[1] ^ Crc[29] ^ Crc[30])) ^ Crc[ 2];
assign CrcNext[7] = (Enable & (Data[3] ^ Data[2] ^ Data[0] ^ Crc[28] ^ Crc[30] ^ Crc[31])) ^ Crc[3];
assign CrcNext[8] = (Enable & (Data[3] ^ Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29] ^ Crc[31])) ^ Crc[4];
assign CrcNext[9] = (Enable & (Data[2] ^ Data[1] ^ Crc[29] ^ Crc[30])) ^ Crc[5];
assign CrcNext[10] = (Enable & (Data[3] ^ Data[2] ^ Data[0] ^ Crc[28] ^ Crc[30] ^ Crc[31])) ^ Crc[6];
assign CrcNext[11] = (Enable & (Data[3] ^ Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29] ^ Crc[31])) ^ Crc[7];
assign CrcNext[12] = (Enable & (Data[2] ^ Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29] ^ Crc[30])) ^ Crc[8];
assign CrcNext[13] = (Enable & (Data[3] ^ Data[2] ^ Data[1] ^ Crc[29] ^ Crc[30] ^ Crc[31])) ^ Crc[9];
assign CrcNext[14] = (Enable & (Data[3] ^ Data[2] ^ Crc[30] ^ Crc[31])) ^ Crc[10];
assign CrcNext[15] = (Enable & (Data[3] ^ Crc[31])) ^ Crc[11];
assign CrcNext[16] = (Enable & (Data[0] ^ Crc[28])) ^ Crc[12];
assign CrcNext[17] = (Enable & (Data[1] ^ Crc[29])) ^ Crc[13];
assign CrcNext[18] = (Enable & (Data[2] ^ Crc[30])) ^ Crc[14];
assign CrcNext[19] = (Enable & (Data[3] ^ Crc[31])) ^ Crc[15];
assign CrcNext[20] = Crc[16];
assign CrcNext[21] = Crc[17];
assign CrcNext[22] = (Enable & (Data[0] ^ Crc[28])) ^ Crc[18];
assign CrcNext[23] = (Enable & (Data[1] ^ Data[0] ^ Crc[29] ^ Crc[28])) ^ Crc[19];
assign CrcNext[24] = (Enable & (Data[2] ^ Data[1] ^ Crc[30] ^ Crc[29])) ^ Crc[20];
assign CrcNext[25] = (Enable & (Data[3] ^ Data[2] ^ Crc[31] ^ Crc[30])) ^ Crc[21];
assign CrcNext[26] = (Enable & (Data[3] ^ Data[0] ^ Crc[31] ^ Crc[28])) ^ Crc[22];
assign CrcNext[27] = (Enable & (Data[1] ^ Crc[29])) ^ Crc[23];
assign CrcNext[28] = (Enable & (Data[2] ^ Crc[30])) ^ Crc[24];
assign CrcNext[29] = (Enable & (Data[3] ^ Crc[31])) ^ Crc[25];
assign CrcNext[30] = Crc[26];
assign CrcNext[31] = Crc[27]; always @ (posedge Clk or posedge Reset)
beginif (Reset)Crc <= #1 32'hffffffff;else if(Enable)Crc <= CrcNext;
endendmodule

在实现CAN通信时是采用15位校验码。由于CAN在数据的收发中存在插入一个翻转电平,这个翻转电平实际上也是参与CRC计算的,因此采用并行的计算方法存在一定的问题,根据CAN2.0协议提供的串行实现方案来用FPGA实现。
CAN协议C语言实现方案如下

U16 Can_FD_Analyzer::MakeCRC15(std::vector<BitState> &bits, U32 num_bits)
{//X15 + X14 + X10 + X8 + X7 + X4 + X3 + X0.U16 CRC[15] = { 0 };for (U32 i = 0; i < num_bits; i++) {U32 DoInvert = (bits[i] == mSettings->Recessive()) ^ CRC[14]; //XOR required?CRC[14] = (CRC[13] ^ DoInvert); //14CRC[13] = CRC[12];CRC[12] = CRC[11];CRC[11] = CRC[10];CRC[10] = (CRC[9] ^ DoInvert); //10CRC[9] = CRC[8];CRC[8] = (CRC[7] ^ DoInvert); //8CRC[7] = (CRC[6] ^ DoInvert); //7CRC[6] = CRC[5];CRC[5] = CRC[4];CRC[4] = (CRC[3] ^ DoInvert); //4CRC[3] = (CRC[2] ^ DoInvert); //3CRC[2] = CRC[1];CRC[1] = CRC[0];CRC[0] = DoInvert;}U16 result = 0; // CRC Resultfor (U32 i = 0; i < 15; i++) {result = result | (CRC[i] << i);}return (U16)result;
}

FPGA串行方案实现如下:
这个是采用标准帧格式,8个字节数据的发送。

//
CICalways @(posedge clk_100m or negedge rst_n )begin
if(rst_n==1'b0) begin
can_data_crc        <= 'b0                         ;
end else if (can_data_in_en==1'b1) begin
can_data_crc        <= {1'b0,in_can_id[11:1],1'b0,2'b0,in_can_dlc,in_can_data};
end end always @(posedge clk_100m or negedge rst_n )begin
if(rst_n==1'b0) begin
can_crc_en_flag     <= 'b0                         ;
end else if (can_data_in_en==1'b1) begin
can_crc_en_flag     <= 1'b1                            ;
end
else if (can_crc_cont>=can_crc_contdata) begin
can_crc_en_flag     <= 1'b0                            ;
end
end always @(posedge clk_100m or negedge rst_n )begin
if(rst_n==1'b0) begin
can_crc_en_flag_t       <= 'b0                         ;
end else  begin
can_crc_en_flag_t       <= can_crc_en_flag              ;
end
end always @(posedge clk_100m or negedge rst_n )begin
if(rst_n==1'b0) begin
can_crc_contdata        <= 18                           ;
end else if (can_data_in_en==1'b1) begin
can_crc_contdata        <= 18 + {in_can_dlc,3'b0};
end
else if (can_crc_cont>=can_crc_contdata) begin
can_crc_contdata        <= 18                           ;
end
end always @(posedge clk_100m or negedge rst_n )begin
if(rst_n==1'b0) begin
can_crc_cont        <= 1'b0                            ;
end else if (can_crc_en_flag==1'b1) begin
can_crc_cont        <= can_crc_cont + 1'b1            ;
end
else begin
can_crc_cont        <= 1'b0                            ;
end
end always @(posedge clk_100m or negedge rst_n )begin
if(rst_n==1'b0) begin
can_data_crc_t      <= 1'b0                            ;
end else if (can_data_in_en==1'b1) begin
can_data_crc_t      <= {1'b0,in_can_id[11:1],1'b0,2'b0,in_can_dlc,in_can_data}           ;
end
else if (can_crc_en_flag==1'b1) begin
can_data_crc_t      <= {can_data_crc_t[81:0],1'b1}         ;
end
else  begin
can_data_crc_t      <= 1'b0                            ;
end
end reg             [14:0]      crc_now_data            ;always @(posedge clk_100m or negedge rst_n )begin
if(rst_n==1'b0) begin
crc_now_data        <= 1'b0                            ;
end else if (can_crc_en_flag==1'b1) begin
crc_now_data        <= crc_now_next         ;
end
else  begin
crc_now_data        <= 1'b0                            ;
end
endalways @(posedge clk_100m or negedge rst_n )begin
if(rst_n==1'b0) begin
crc_now     <= 1'b0                            ;
end else if ((can_crc_en_flag==1'b0)&&(can_crc_en_flag_t==1'b1)) begin
crc_now     <= crc_now_data         ;
end
else if (tx_eof_flag==1'b1) begin
crc_now     <= 1'b0                            ;
end
endassign       crc_first          =can_data_crc_t[82] ^ crc_now_data[14] ;
assign      crc_now_next[14]   =  (    crc_now_data[13] ^ crc_first) ;
assign      crc_now_next[13]   =   crc_now_data[12]                 ;
assign      crc_now_next[12]   =   crc_now_data[11]                 ;
assign      crc_now_next[11]   =   crc_now_data[10]                 ;
assign      crc_now_next[10]   =  (    crc_now_data[9] ^ crc_first)     ;
assign      crc_now_next[9]    =   crc_now_data[8]              ;
assign      crc_now_next[8]    =  (    crc_now_data[7] ^ crc_first)     ;
assign      crc_now_next[7]    =  (    crc_now_data[6] ^ crc_first)     ;
assign      crc_now_next[6]    =   crc_now_data[5]              ;
assign      crc_now_next[5]    =   crc_now_data[4]              ;
assign      crc_now_next[4]    =  (    crc_now_data[3] ^ crc_first)     ;
assign      crc_now_next[3]    =  (    crc_now_data[2] ^ crc_first)     ;
assign      crc_now_next[2]    =   crc_now_data[1]              ;
assign      crc_now_next[1]    =   crc_now_data[0]              ;
assign      crc_now_next[0]    =  crc_first                     ; 

上述FPGA实现CAN串行方案和网络32位CRC检验已经过长时间验证,可以使用

FPGA实现CAN通信CRC校验相关推荐

  1. 通信 / CRC 校验

    一.全称 Cyclic Redundancy Check,循环冗余校验 二.诞生原因 在数据传输中,校验传输的数据的准确性必不可少,传统的方法包括 1 校验.0 校验.奇偶校验(详细说明请看这里),这 ...

  2. modbus通信CRC校验代码

    #region CRC校验private static readonly byte[] aucCRCHi = {0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x ...

  3. 基于verilog的CRC校验(汇总)

    目录 原理 计算 检错与纠错 纠错实现 Verilog实现 本来想整理一下关于CRC校验的内容,但是发现前辈们写的都很好,本文对内容进行整理汇总. 原理 crc为什么能够检错和纠错,这背后有着深刻的数 ...

  4. FPGA实现串口收发的八字节数据报文Modbus Crc校验

    一.项目工程背景 串口之间的数据交互,是一个在实际工作当中应用非常广泛的场景,所以笔者在这篇博客里为大家详细介绍"串口八字节报文modbus crc收发校验"的工程案例,相信耐心地 ...

  5. can协议crc计算_CAN总线通信的CRC校验方法

    数据校验是为保证数据的完整性进行的一种验证操作.CAN通信采用CRC校验作为一种重要的错误检测手段,是节点判断CAN帧信息的完整性并产生确认应答的依据. 在现场总线通信和控制的实际应用中,工业应用环境 ...

  6. 非常实用FPGA实现CRC校验介绍和代码生成工具

    目录 一.CRC原理. 二.CRC算法. 1.比特型算法. 2.字节型算法.(好理解也好用,实际中采用这种) 三.CRC参数模型 四.常用工具(重点来了) 1.CRC calculation  非常棒 ...

  7. 【FPGA】CRC校验算法从数学原理到代码实现

    老规矩,转b站 [[FPGA]CRC校验算法从数学原理到代码实现-哔哩哔哩]

  8. FPGA之CRC校验

    CRC校验原理 求解CRC-8的编码电路和CRC校验的原理 G(X) = X8+H7*X7+H6*X6+H5*X5+H4*X4+H3*X3+H2*X2+H1*X1+X0 生成多项式 G(X)=9'b1 ...

  9. 现场总线技术笔记——1、数字信号是怎么完成通信的?(匹配阻抗、CRC校验)

    文章目录 数字通信系统模型 信道 信道容量--解决传输速率的方法 如何提高传输的稳定性和准确性? ①通过编码规则提高准确性 ②同步和异步传输中的同步技术 ③阻抗匹配技术 信号的传输模式--基带.载带. ...

最新文章

  1. 让你的VB6.0支持滚轮操作
  2. 十一阅读攻略:和土豪做朋友,告别穷屌丝,迎接高富帅,成功逆袭!
  3. ui与html界面区别,ui前端和web前端的区别是什么?
  4. javascript 模板引擎基本原理
  5. angularjsl路由_AngularJS实现路由实例
  6. Nginx限制对代理HTTP资源的访问速率
  7. lambda方法引用总结——烧脑吃透
  8. VB.net数据库编程pdf
  9. NIST:制定Cybersecurity的框架进行时
  10. 永磁同步电机转子磁链_永磁同步电机转子初始位置检测、增量式光电编码器对位调零思路解析...
  11. 上海杨浦|2022年杨浦 “ 创业之星 ” 大赛
  12. linux查询打印机ip,Linux C打印IP地址信息
  13. HTML特效推荐,超级惊艳 10款HTML5动画特效推荐[转]
  14. 内卷老员工之java内存模型
  15. 魔兽世界出错排查以及解决方案
  16. JS转换为数字的方法Number()、parseInt()和 parseFloat()
  17. Postgresql垃圾回收Vacuum优化手册
  18. IDEA中的DBCP使用及问题解决
  19. JMETER之察看结果树(只显示报错请求)
  20. Android Studio 介绍

热门文章

  1. mysql存储过程出现OUT or INOUT argument 10 for routine
  2. 数据链路层——点对点信道
  3. Python遥感图像处理应用篇(十四):GDAL 读取多光谱数据为二维数组并存入csv文件
  4. Cisco ACE Web应用防火墙
  5. vray for sketchup 2017中文版|vray for sketchup 2017
  6. 浅谈工作/学习中找bug的思路_0_调试、try-catch以及打印报错信息和百度的方法、No default constructor for entity: com.gyf.bos.mod
  7. 10bit显示器测试软件,LAPAELO  32寸 4k 10bit面板 显示器 简单测试
  8. 值得珍藏一生的经典电影台词
  9. 甘肃金昌市“公交一卡通”正式启用
  10. Android系统的图标设计规范