1. 问题描述
- 多项式:
0x29
(X⁸+X⁵+X³+1) - 初始值:
0x00
- 输入数据:
0x22, 0x49
求CRC值
2. CRC计算原理
2.1 处理第1个数据 0x22
初始CRC: 0000 0000
XOR输入: 0010 0010 → 0010 0010
8次移位和异或:
1. 左移,MSB=0 → 0100 0100
2. 左移,MSB=0 → 1000 1000
3. 左移,MSB=1 → 0001 0000 ^ 0010 1001 = 0011 1001
4. 左移,MSB=0 → 0111 0010
5. 左移,MSB=0 → 1110 0100
6. 左移,MSB=1 → 1100 1000 ^ 0010 1001 = 1110 0001
7. 左移,MSB=1 → 1100 0010 ^ 0010 1001 = 1110 1011
8. 左移,MSB=1 → 1101 0110 ^ 0010 1001 = 1111 1111
第1字节处理后CRC: 0xFF (1111 1111)
2.2 处理第2个数据 0x49
当前CRC: 1111 1111
XOR输入: 0100 1001 → 1011 0110
8次移位和异或:
1. 左移,MSB=1 → 0110 1100 ^ 0010 1001 = 0100 0101
2. 左移,MSB=0 → 1000 1010
3. 左移,MSB=1 → 0001 0100 ^ 0010 1001 = 0011 1101
4. 左移,MSB=0 → 0111 1010
5. 左移,MSB=0 → 1111 0100
6. 左移,MSB=1 → 1110 1000 ^ 0010 1001 = 1100 0001
7. 左移,MSB=1 → 1000 0010 ^ 0010 1001 = 1010 1011
8. 左移,MSB=0 → 01111111
第2字节处理后CRC: 0x7F (0111 1111)
3. SV实现
// CRC8 calculation with polynomial 0x29
function automatic [7:0] crc8(input bit [7:0] data2crc[$], input integer len);
bit [7:0] crc = 8'h00;
if(data2crc.size() != len) begin
`uvm_error("CRC8",$sformatf("data2crc.size() != len, data2crc.size(): %0d, len: %0d",data2crc.size(),len));
end
for(integer i = 0; i < len; i++) begin
crc = crc ^ data2crc[i]; // XOR with new data byte
for(integer j = 0; j < 8; j++) begin
if(crc[7]) begin // Check MSB
crc = (crc << 1) ^ 8'h29; // Polynomial 0x29 for UFCS
end
else begin
crc = (crc << 1);
end
end
end
return crc;
endfunction
//使用crc8
function [7:0] ufcs_transaction::calc_crc8();
bit [7:0] crc_temp = 8'h00;
bit [7:0] data2crc[$];
// Clear previous data array
data2crc.delete();
int len = 3; // Header(2) + Command(1)
// Add message header
data2crc = {this.message_header[15:8], this.message_header[7:0]};
// Add command
data2crc.push_back(this.command);
`uvm_info(get_full_name(),$sformatf("\ndata2crc: %p\nlen: %p",data2crc,len), UVM_DEBUG)
crc_temp = crc8(data2crc, len);
`uvm_info(get_full_name(),$sformatf("\ncrc_temp: 8'h%x",crc_temp), UVM_DEBUG)
end
注意:每次使用crc8时,crc的起始数值应该被置0,否者会出现计算错误,所以这里加上了automatic。