600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > FPGA实现CAN通信CRC校验

FPGA实现CAN通信CRC校验

时间:2018-09-12 15:11:54

相关推荐

FPGA实现CAN通信CRC校验

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 / 1psmodule 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 )beginif(rst_n==1'b0) begincan_data_crc<= 'b0;end else if (can_data_in_en==1'b1) begincan_data_crc<= {1'b0,in_can_id[11:1],1'b0,2'b0,in_can_dlc,in_can_data};endend always @(posedge clk_100m or negedge rst_n )beginif(rst_n==1'b0) begincan_crc_en_flag<= 'b0;end else if (can_data_in_en==1'b1) begincan_crc_en_flag<= 1'b1;endelse if (can_crc_cont>=can_crc_contdata) begin can_crc_en_flag<= 1'b0;endend always @(posedge clk_100m or negedge rst_n )beginif(rst_n==1'b0) begincan_crc_en_flag_t<= 'b0;end else begincan_crc_en_flag_t<= can_crc_en_flag;endend always @(posedge clk_100m or negedge rst_n )beginif(rst_n==1'b0) begincan_crc_contdata<= 18;end else if (can_data_in_en==1'b1) begincan_crc_contdata<= 18 + {in_can_dlc,3'b0};endelse if (can_crc_cont>=can_crc_contdata) begin can_crc_contdata<= 18;endend always @(posedge clk_100m or negedge rst_n )beginif(rst_n==1'b0) begincan_crc_cont<= 1'b0;end else if (can_crc_en_flag==1'b1) begincan_crc_cont<= can_crc_cont + 1'b1;endelse begin can_crc_cont<= 1'b0;endend always @(posedge clk_100m or negedge rst_n )beginif(rst_n==1'b0) begincan_data_crc_t<= 1'b0;end else if (can_data_in_en==1'b1) begincan_data_crc_t<= {1'b0,in_can_id[11:1],1'b0,2'b0,in_can_dlc,in_can_data};endelse if (can_crc_en_flag==1'b1) begincan_data_crc_t<= {can_data_crc_t[81:0],1'b1};endelse begin can_data_crc_t<= 1'b0;endend reg[14:0]crc_now_data;always @(posedge clk_100m or negedge rst_n )beginif(rst_n==1'b0) begincrc_now_data<= 1'b0;end else if (can_crc_en_flag==1'b1) begincrc_now_data<= crc_now_next;endelse begin crc_now_data<= 1'b0;endendalways @(posedge clk_100m or negedge rst_n )beginif(rst_n==1'b0) begincrc_now<= 1'b0;end else if ((can_crc_en_flag==1'b0)&&(can_crc_en_flag_t==1'b1)) begincrc_now<= crc_now_data;endelse if (tx_eof_flag==1'b1) begin crc_now<= 1'b0;endendassigncrc_first =can_data_crc_t[82] ^ crc_now_data[14] ; assigncrc_now_next[14] = (crc_now_data[13] ^ crc_first) ; assigncrc_now_next[13] = crc_now_data[12] ; assigncrc_now_next[12] = crc_now_data[11] ; assigncrc_now_next[11] = crc_now_data[10] ; assigncrc_now_next[10] = (crc_now_data[9] ^ crc_first) ; assigncrc_now_next[9] = crc_now_data[8] ; assigncrc_now_next[8] = (crc_now_data[7] ^ crc_first) ; assigncrc_now_next[7] = (crc_now_data[6] ^ crc_first) ; assigncrc_now_next[6] = crc_now_data[5] ; assigncrc_now_next[5] = crc_now_data[4] ; assigncrc_now_next[4] = (crc_now_data[3] ^ crc_first) ; assigncrc_now_next[3] = (crc_now_data[2] ^ crc_first) ; assigncrc_now_next[2] = crc_now_data[1] ; assigncrc_now_next[1] = crc_now_data[0] ; assigncrc_now_next[0] = crc_first ;

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。