CRC计算原理即SV实现

发布于:2025-07-11 ⋅ 阅读:(23) ⋅ 点赞:(0)

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。


网站公告

今日签到

点亮在社区的每一天
去签到