CRC 的发生和校检,发生器和检验器里的移位寄存器置成为全 1型。对于每个被发送或者被收到的数据位,当前余项的最高一位和数据位进行异或( XOR ),然后,余项是左移 1 位,并且,最低一位置零。如果异或的结果是 1 ,余项和生成多项式作异或。当检查的字段最后的一位被发送的时候,对发生器里的 CRC取反,再以最高位( MSb )在前发给检验器。
crc5的生成多项式为x5+x2+1;表示为5’b00101(x5不需表示出来)
对于每一位数据D有:
R0<=R4 ^ D
R1<=R0;
R2 <= (R4 ^ D) ^ R1;
R3 <= R2;
R4 <= R3;
数据流D是从LSB开始,对于token pid则依次处理ADR[0],ADR[1],……ADR[7],ENDP[0],……最后ENDP[3]。
(1)按bit串行计算,用testbench表现为:
bit[4:0] crc_reg,crc_reg_pre;
bits[7:0] token_bits;
bits[10:0] data_bits;
bits[4:0] crc_send;
bit[23:0] bitstream_send;
initial begin
crc_reg = 5’h1f;
token_bits = 8’b0110_1001; // IN token, {~pid[3:0],pid[3:0]}=0110_1001
data_bits = 19’b0001_0001000 // (黄色为ENDP[3:0]=0001,绿色为ADDR[7:0]=0001000)
for(int i=0;i<11;i++) begin
crc_reg_pre = crc_reg;
crc_reg[0] = data_bits[i] ^ crc_reg_pre[4];
crc_reg[1] = crc_reg_pre[0];
crc_reg[2]= crc_reg_pre[1] ^ bitdata[i] ^ crc_reg_pre[4];
crc_reg[3] = crc_reg_pre[2];
crc_reg[4] = crc_reg_pre[3];
end
crc_send = ~ {crc_reg[0], crc_reg[1], crc_reg[2], crc_reg[3], crc_reg[4]}; //取反,MSB在前
end
运算结果crc_reg=10100
bitstream_send = {crc_send,data_bits,token_bits}
在DP/DM线上是先发bitstream_send[0],最后发bitstream_send[23]。
在接收端是对{crc_send,data_bits}进行同样的crc计算,计算结果为01100(接收正确的crc计算结果都应为01100)
(2)并行计算
初始值:R0=R1=R2=R3=R4=1;
对每一比特的串行计算为:R0<=R4 ^ D; R1<=R; R2 <= (R4 ^ D) ^ R1;R3 <= R2; R4 <= R3;
则有:
最终得并行计算的公式为:
R0=1D0D1D4D5^D10
R1=1D0D3D4D6^D9
R2=1D0D1D2D3D4D7D8D10
R3= D0D1D2D3D6D7D9
R4=1D0D1D2D5D6D8
(3)按byte计算
bit[7:0] crc_reg,crc_poly;
bits[7:0] token_bits;
bits[10:0] data_bits;
bits[4:0] crc_send;
bit[23:0] bitstream_send;
initial begin
crc_reg = 8’b0001_1111; //这里的[0]对应方法(1)的[4],对应R4
crc_poly = 8’b00010100; //(对多项式’h5进行msb~lsb反置后右移3,即[0]对应R4位置
token_bits = 8’b0110_1001; // IN token, {~pid[3:0],pid[3:0]}=0110_1001
data_bits = 19’b0001_0001000 // (黄色为ENDP[3:0]=0001,绿色为ADDR[7:0]=0001000)
for(int i=0;i<2;i++) begin
crc_reg = data_bits[7:0] ^ crc_reg;
for(int j=0;j<8;j++) begin
if(crc_reg[0]==1) begin
crc_reg = {1’b0,crc_reg[7:1]};
crc_reg = crc_reg ^ crc_poly;
end
else begin
crc_reg = {1’b0,crc_reg[7:1]};
end
if((i==1) && (j==2))
break;
end
end
crc_send[4:0] = crc_reg[4:0] ^ 5’h1f; //不用高低位反置,因为[0]表示的是R4了
end
参考:
https://wenku.baidu.com/view/1ae311b3aef8941ea66e0535.html###
https://wenku.baidu.com/view/1a80b6601ed9ad51f01df2b8.html