CoaXPress 协议的CRC及其具体实现
CoaXPress CRC
在CXP协议中,CRC用在stream packet和control packet中,用于指示数据是否错误,如果是control packet, device发现CRC错误后应该给出CRC错误的回应。
下表是回应的packet格式,在高速数据链路downconnection中。
其中CXP使用的CRC定义如下:
CRC多项式: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
初始值: 0xFFFFFFFF
REFIN: true
REFOUT: true
XorOut: 0x00000000
这里补充一下,CRC的多项式通常表示为一个二进制序列,其中每一位对应多项式中的项是否存在。例如,x^3 +x +1对应的二进制是1011,因为从最高次项开始,x3的位置是1,x2的位置是0,x1是1,常数项1也是存在的,所以最后三位是011,组合起来就是1011。但要注意的是,有时候最高位是否被省略,或者是否包含最高位的那个1。例如,对于32次多项式,通常会生成一个33位的二进制数,因为包括x32的项,也就是最高位的1。
所以在问到CRC的二进制序列时,需要对应理解如何给出。
进行CRC校验时,LSB FIRST,P0 FIRST
CRC校验哪些数据呢?
以Control packet为例说明:
下表是没有tag标签的control command 包,其中明确说明了,参与CRC校验的数据是从0到N+1,不包含K27.7和0x02,且如果是read command packet,实际就只有word 0,1 参与校验;
同样,协议给出了一个示例:
下面是一个完整的read control packet,其中0x56 0x86 0x5D 0x6F 是CRC校验结果,对应的word 为0x6F5D8656
K27.7 K27.7 K27.7 K27.7 0x02 0x02 0x02 0x02 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x00 0x56 0x86 0x5D 0x6F K29.7 K29.7 K29.7 K29.7
CRC校验HDL代码
有了协议给出的示例,我们可以选择正确的CRC32 代码,CRC一般分为串行和并行2种,我们的应用选择串行计算即可。
代码参考: http://outputlogic.com/?page_id=321
//-----------------------------------------------------------------------------
// Copyright (C) 2009 OutputLogic.com
// This source file may be used and distributed without restriction
// provided that this copyright statement is not removed from the file
// and that any derivative work contains the original copyright notice
// and the associated disclaimer.
//
// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//-----------------------------------------------------------------------------
// CRC module for data[0:0] , crc[31:0]=1+x^1+x^2+x^4+x^5+x^7+x^8+x^10+x^11+x^12+x^16+x^22+x^23+x^26+x^32;
//-----------------------------------------------------------------------------
module crc(
input [0:0] data_in,
input crc_en,
output [31:0] crc_out,
input rst,
input clk);
reg [31:0] lfsr_q,lfsr_c;
assign crc_out = lfsr_q;
always @(*) begin
lfsr_c[0] = lfsr_q[31] ^ data_in[0];
lfsr_c[1] = lfsr_q[0] ^ lfsr_q[31] ^ data_in[0];
lfsr_c[2] = lfsr_q[1] ^ lfsr_q[31] ^ data_in[0];
lfsr_c[3] = lfsr_q[2];
lfsr_c[4] = lfsr_q[3] ^ lfsr_q[31] ^ data_in[0];
lfsr_c[5] = lfsr_q[4] ^ lfsr_q[31] ^ data_in[0];
lfsr_c[6] = lfsr_q[5];
lfsr_c[7] = lfsr_q[6] ^ lfsr_q[31] ^ data_in[0];
lfsr_c[8] = lfsr_q[7] ^ lfsr_q[31] ^ data_in[0];
lfsr_c[9] = lfsr_q[8];
lfsr_c[10] = lfsr_q[9] ^ lfsr_q[31] ^ data_in[0];
lfsr_c[11] = lfsr_q[10] ^ lfsr_q[31] ^ data_in[0];
lfsr_c[12] = lfsr_q[11] ^ lfsr_q[31] ^ data_in[0];
lfsr_c[13] = lfsr_q[12];
lfsr_c[14] = lfsr_q[13];
lfsr_c[15] = lfsr_q[14];
lfsr_c[16] = lfsr_q[15] ^ lfsr_q[31] ^ data_in[0];
lfsr_c[17] = lfsr_q[16];
lfsr_c[18] = lfsr_q[17];
lfsr_c[19] = lfsr_q[18];
lfsr_c[20] = lfsr_q[19];
lfsr_c[21] = lfsr_q[20];
lfsr_c[22] = lfsr_q[21] ^ lfsr_q[31] ^ data_in[0];
lfsr_c[23] = lfsr_q[22] ^ lfsr_q[31] ^ data_in[0];
lfsr_c[24] = lfsr_q[23];
lfsr_c[25] = lfsr_q[24];
lfsr_c[26] = lfsr_q[25] ^ lfsr_q[31] ^ data_in[0];
lfsr_c[27] = lfsr_q[26];
lfsr_c[28] = lfsr_q[27];
lfsr_c[29] = lfsr_q[28];
lfsr_c[30] = lfsr_q[29];
lfsr_c[31] = lfsr_q[30];
end // always
always @(posedge clk, posedge rst) begin
if(rst) begin
lfsr_q <= {32{1'b1}};
end
else begin
lfsr_q <= crc_en ? lfsr_c : lfsr_q;
end
end // always
endmodule // crc
Copyright © 2009-2013 OutputLogic.com |