CRC實戰寶典:從原理到代碼,全面攻克循環冗余校驗

CRC實戰寶典:從原理到代碼,全面攻克循環冗余校驗

github開源:CRC軟硬件協同測試項目

CRC 簡介

CRC(循環冗余校驗)是一種強大的錯誤檢測技術,廣泛應用于數字網絡和存儲系統。它是確保數據完整性的重要方法,能夠檢測傳輸或存儲過程中對原始數據的意外更改。

什么是 CRC?

CRC 是一種數學算法,具有以下特點:

  • 將數據視為有限域中的多項式表示
  • 使用預定義的多項式(稱為生成多項式)進行二進制除法
  • 生成固定長度的校驗和,附加到消息末尾
  • 能夠高概率地檢測出常見的傳輸錯誤

CRC 的優勢在于其能夠檢測:

  • 所有單比特錯誤
  • 所有雙比特錯誤(在標準 CRC 中)
  • 任何奇數個比特錯誤
  • 突發錯誤(基于多項式長度的一定范圍內)

CRC 原理

多項式表示

在 CRC 中,數據和生成多項式都表示為具有二進制系數(0 或 1)的多項式。例如:

  • 二進制序列1101表示多項式 x3 + x2 + 1
  • 二進制序列10011表示多項式 x? + x + 1

CRC 參數

完整的 CRC 算法由以下參數定義:

  1. 位寬(Width):CRC 值的比特數
  2. 多項式(Polynomial):用于除法的生成多項式
  3. 初始值(Init):CRC 寄存器的初始值
  4. 輸入反轉(RefIn):輸入字節是否反轉(位序反轉)
  5. 輸出反轉(RefOut):最終 CRC 是否反轉
  6. 輸出異或值(XorOut):與最終 CRC 異或的值

這些參數定義了不同的 CRC 標準(CRC-8、CRC-16、CRC-32 等)

CRC 計算過程

CRC 計算的高級過程包括:

  1. 發送方

    • 在原始數據后附加 k-1 個零(其中 k 是 CRC 的位寬)
    • 使用模 2 除法,用生成多項式除以上述結果
    • 余數即為 CRC 值,附加到原始數據后
  2. 接收方

    • 用相同的生成多項式除以接收到的數據(包括 CRC)
    • 如果余數為零,則認為數據無錯誤
    • 如果余數非零,則檢測到錯誤

模 2 二進制除法

CRC 計算的核心是模 2 二進制除法,其特點是:

  • 使用異或(XOR)操作代替減法
  • 沒有進位或借位操作
  • 按位處理消息
  • 可以在硬件和軟件中高效實現

常見 CRC 標準

CRC 類型位寬多項式初始值輸入反轉輸出反轉輸出異或值常見用途
CRC-880x070x000x00ATM 頭部
CRC-8/CDMA200080x9B0xFF0x00移動網絡
CRC-16/CCITT160x10210xFFFF0x0000HDLC, 藍牙
CRC-16/IBM160x80050x00000x0000USB, SCSI
CRC-32320x04C11DB70xFFFFFFFF0xFFFFFFFF以太網, ZIP

Python 實現

核心代碼

讓我們看看 CRC 在 Python 模型中的實現:

def reverse_bits(x, num_bits):"""反轉指定位數的位序"""reversed_x = 0for i in range(num_bits):reversed_x |= ((x >> i) & 1) << (num_bits - 1 - i)return reversed_xdef crc_process_byte(crc, byte, poly, width, refin):"""處理單個字節的CRC計算"""# 1. 如果需要反轉輸入if refin:byte = reverse_bits(byte, 8)# 2. 直接將字節與CRC高位進行異或(避免一位一位處理)crc ^= (byte << (width - 8))# 3. 處理8個位for _ in range(8):# 判斷最高位,使用位移判斷避免額外計算if crc & (1 << (width - 1)):# 左移+異或多項式crc = ((crc << 1) ^ poly) & ((1 << width) - 1)else:# 僅左移crc = (crc << 1) & ((1 << width) - 1)return crcdef calculate_crc(data_bytes, width, poly, init, refin, refout, xorout):"""計算字節序列的CRC校驗值"""# 確保poly不包含最高位(如果已經包含)poly = poly & ((1 << width) - 1)crc = initfor byte in data_bytes:crc = crc_process_byte(crc, byte, poly, width, refin)if refout:crc = reverse_bits(crc, width)crc ^= xoroutcrc &= (1 << width) - 1  # 確保結果在低width位return crc

關鍵函數

  1. reverse_bits:反轉值的位序(用于 RefIn 和 RefOut)
  2. crc_process_byte:在 CRC 計算過程中處理單個字節:
    • 可選擇反轉輸入字節
    • 將字節與當前 CRC 值異或
    • 使用多項式除法處理每一位
  3. calculate_crc:計算字節序列 CRC 的主函數:
    • 使用 init 值初始化 CRC 寄存器
    • 處理輸入數據中的每個字節
    • 可選擇反轉最終 CRC
    • 將結果與 XorOut 值異或

測試

import crcmoddef reverse_bits(x, num_bits):"""反轉指定位數的位序"""reversed_x = 0for i in range(num_bits):reversed_x |= ((x >> i) & 1) << (num_bits - 1 - i)return reversed_xdef crc_process_byte(crc, byte, poly, width, refin):"""處理單個字節的CRC計算"""# 1. 如果需要反轉輸入if refin:byte = reverse_bits(byte, 8)# 2. 直接將字節與CRC高位進行異或(避免一位一位處理)crc ^= (byte << (width - 8))# 3. 處理8個位for _ in range(8):# 判斷最高位,使用位移判斷避免額外計算if crc & (1 << (width - 1)):# 左移+異或多項式crc = ((crc << 1) ^ poly) & ((1 << width) - 1)else:# 僅左移crc = (crc << 1) & ((1 << width) - 1)return crcdef calculate_crc(data_bytes, width, poly, init, refin, refout, xorout):"""計算字節序列的CRC校驗值"""# 確保poly不包含最高位(如果已經包含)poly = poly & ((1 << width) - 1)crc = initfor byte in data_bytes:crc = crc_process_byte(crc, byte, poly, width, refin)if refout:crc = reverse_bits(crc, width)crc ^= xoroutcrc &= (1 << width) - 1  # 確保結果在低width位return crc# 示例用法
if __name__ == "__main__":# 示例參數(以CRC-8為例)width = 16poly = 0x10c21  # 多項式 x^8 + x^2 + x + 1 (隱式最高位)init = 0xffffxorout = 0x0000# 輸入數據(假設輸入S018F0轉換為字節數組)input_data = [0x71,0xFA,0x96,0x59,0x91,0x93,0xB2,0xD1,0x35]crc_result_standard = calculate_crc(input_data, width, poly, init, False, False, xorout)print(f"CRC結果: 0x{crc_result_standard:02X}")crc_result_reflected = calculate_crc(input_data, width, poly, init, True, True, xorout)print(f"CRC結果: 0x{crc_result_reflected:02X}")crc_result_mixed1=calculate_crc(input_data,width,poly,init,True,False,xorout)print(f"CRC結果: 0x{crc_result_mixed1:02X}")crc_result_mixed2=calculate_crc(input_data,width,poly,init,False,True,xorout)print(f"CRC結果: 0x{crc_result_mixed2:02X}")crc16_func_standard = crcmod.mkCrcFun(poly, initCrc=0xffff, rev=False, xorOut=0x0000)crc16_func_reflected = crcmod.mkCrcFun(poly, initCrc=0xffff, rev=True, xorOut=0x0000)print(f"Expected standard: {crc16_func_standard(bytes(input_data)):04x}")print(f"Expected reflected: {crc16_func_reflected(bytes(input_data)):04x}")

在這里插入圖片描述

此外,也可以在CRC在線計算,驗證結果

Verilog 實現

硬件實現在 Verilog 中分為兩個模塊:

主 CRC 模塊(crc.v

module crc #(parameter bits =8,parameter poly =8'h33,parameter init =8'hff,parameter [0:0]refin =1'b0,parameter [0:0]refout =1'b0,parameter xorout =8'h00
)(input clk,input rst_n,input data_valid,input start,input [7:0] data_in,output reg crc_ready,output reg [bits-1:0] crc_out
);// 內部寄存器
reg  [bits-1:0] crc_reg;
wire [bits-1:0] crc_next;
reg data_processed;// 實例化字節處理模塊
crc_process_byte #(.bits(bits),.poly(poly)) uut (.crc_in(crc_reg),.byte_in(data_in),.refin_in(refin),.crc_out(crc_next)
);// 位翻轉函數實現
function [bits-1:0] reflect;input [bits-1:0] data;integer i;beginreflect = 0;for (i = 0; i < bits; i = i + 1)reflect = reflect|(data[i]<<(bits-1-i));end
endfunctionalways @(posedge clk or negedge rst_n) beginif(!rst_n) begincrc_reg <= init;crc_ready <= 0;crc_out <= 0;data_processed <= 0;end else if(start) begin// 開始新的計算crc_reg <= init;crc_ready <= 0;data_processed <= 0;end else if(data_valid) begin// 處理數據crc_reg <= crc_next;crc_ready <= 0;data_processed <= 1;end else if (data_processed && !data_valid && !crc_ready) begin// 數據處理完成if(refout) begincrc_out <= (reflect(crc_reg) ^ xorout) & ((1<<bits)-1);end else begincrc_out <= (crc_reg ^ xorout) & ((1<<bits)-1);endcrc_ready <= 1;end
end
endmodule

字節處理模塊(crc_process_byte.v

module crc_process_byte #(parameter bits     = 8,parameter poly     = 8'h33
)
(input  refin_in,input  [8-1:0] byte_in,input  [bits-1:0] crc_in,output  reg [bits-1:0] crc_out
);reg [7:0] byte_reg;
reg [bits-1:0] crc_reg;
integer i;always@(*)beginbyte_reg = refin_in? reflect(byte_in): byte_in;crc_reg = crc_in^(byte_reg<<(bits-8));crc_out = 0;for(i=0;i<8;i=i+1)beginif(crc_reg[bits-1])begincrc_reg=((crc_reg<<1)^poly)&((1<<bits)-1);endelse begincrc_reg=(crc_reg<<1)&((1<<bits)-1);endendcrc_out = crc_reg;
end// 位翻轉函數實現
function [7:0] reflect;input [7:0] data;integer i;beginreflect = 0;for (i = 0; i < 8; i = i + 1)reflect = reflect|(data[i]<<(7-i));end
endfunction
endmodule

測試示例(crc_tb.v

`timescale 1ns/1nsmodule crc_tb;// 參數定義parameter CRC_WIDTH = 8;parameter CRC_POLY = 9'h107;parameter CRC_INIT = 8'hff;parameter CRC_REFIN = 0;parameter CRC_REFOUT = 0;parameter CRC_XOROUT = 0;// 信號聲明reg clk;reg rst_n;reg data_valid;reg start;reg [7:0] data_in;wire crc_ready;wire [CRC_WIDTH-1:0] crc_out;// 直接實例化CRC模塊,不再使用crc_top作為中間層crc #(.bits(CRC_WIDTH),.poly(CRC_POLY),.init(CRC_INIT),.refin(CRC_REFIN),.refout(CRC_REFOUT),.xorout(CRC_XOROUT)) crc_inst (.clk(clk),.rst_n(rst_n),.data_valid(data_valid),.start(start),.data_in(data_in),.crc_ready(crc_ready),.crc_out(crc_out));// 測試流程
initial begin// 復位rst_n = 0;start = 0;data_valid = 0;data_in = 0;#10 rst_n = 1;// 開始新的CRC計算#10 start = 1;#10 start = 0;// 輸入數據字節data_in = 8'h01; data_valid = 1; #10 data_valid = 0; #10;data_in = 8'h02; data_valid = 1; #10 data_valid = 0; #10;data_in = 8'h03; data_valid = 1; #10 data_valid = 0; #10;data_in = 8'h04; data_valid = 1; #10 data_valid = 0; #10;data_in = 8'h05; data_valid = 1; #10 data_valid = 0; #20;// 等待結果wait(crc_ready);$display("CRC-8結果: 0x%h", crc_out);end// 時鐘生成initial beginclk = 0;forever #5 clk = ~clk; // 10ns周期時鐘endendmodule

在這里插入圖片描述

輸出結果為0x85, 我們用網站進行測試

在這里插入圖片描述

輸出結果一致

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/79638.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/79638.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/79638.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【大模型】DeepSeek + Coze 打造個人專屬AI智能體使用詳解

目錄 一、前言 二、AI智能體介紹 2.1 什么是AI智能體 2.2 AI智能體核心能力 2.3 AI智能應用場景 三、coze 介紹 3.1 coze是什么 3.1.1 平臺概述 3.1.2 平臺適用人群 3.2 平臺核心功能 3.3 coze可以做什么 3.4 為什么選擇coze 四、coze 搭建AI智能體操作實踐 4.1 搭…

MySQL入門:數據表的創建

?今天我們來介紹一下除HTML外的另一種語言&#xff1a;MySQL語言&#xff1b; MySQL&#xff1a;即一種用于管理和處理關系數據庫的標準語言。要用于執行查詢、更新、管理數據庫中的數據以及定義和操作數據庫結構。 接下來我會逐一介紹它的作用以及其中數據表&#xff0c;數據…

[圖論]生成樹 引言

生成樹 引言 生成樹&#xff1a;一個連通圖的生成樹是該圖的一個極小連通子圖。生成樹中含有圖中全部(設 V V V個)頂點及構成一棵樹的 V ? 1 V-1 V?1條邊&#xff0c;且生成樹中不應有環。最小生成樹(MST)&#xff1a;圖的所有生成樹中&#xff0c;邊權之和最小的生成樹。顯…

AI調試工具有哪些?

一、深度學習框架專用調試工具 TensorBoard ? 功能&#xff1a;實時監控訓練指標&#xff08;損失值、準確率&#xff09;、可視化神經網絡結構、分析參數分布和梯度信息 ? 適用框架&#xff1a;TensorFlow、PyTorch&#xff08;通過插件&#xff09; ? 特點&#xff1a;支持…

深入理解 MCP 協議:開啟 AI 交互新時代

深入理解 MCP 協議&#xff1a;開啟 AI 交互新時代&#x1f680; 在當今人工智能蓬勃發展的時代&#x1f310;&#xff0c;大型語言模型&#xff08;LLM&#xff09;已經在眾多領域展現出了強大的能力&#xff0c;令人驚嘆&#x1f44f;&#xff01;然而&#xff0c;傳統的 LLM…

微信、抖音、小紅書emoji符號大全

1、Emoji 日常符號 &#x1f463;&#x1f440;&#x1f441;?&#x1f444;&#x1f48b;&#x1f442;&#x1f9bb;&#x1f443;&#x1f445;&#x1f9e0;&#x1fac0;&#x1fac1;&#x1f9b7;&#x1f9b4;&#x1f4aa;&#x1f9be;&#x1f9bf;&#x1f9b5;&a…

【嵌入式】——Linux系統遠程操作和程序編譯

目錄 一、虛擬機配置網絡設置 二、使用PuTTY登錄新建的賬戶 1、在ubuntu下開啟ssh服務 2、使用PuTTY連接 三、樹莓派實現遠程登錄 四、樹莓派使用VNC viewer登錄 五、Linux使用talk聊天程序 1、使用linux自帶的talk命令 2、使用c語言編寫一個talk程序 一、虛擬機配置網絡…

春和景明-C語言簡單代碼

題目要求&#xff1a; 請在centOS Linux中編寫一個C語言程序實現如下功能&#xff1a; 同時創建100個用戶&#xff0c;用戶的賬戶名稱為&#xff1a;Student01 Student02 … Student100;設置每個用戶的初始密碼為&#xff1a;stud123456請用gcc編譯C的源代碼&#xff0c;生…

設計模式之工廠模式(factory pattern):在商品對象創建系統中的應用

目錄 一、設計思路 1. 簡單工廠模式 2. 工廠方法模式 3. 抽象工廠模式 二、UML類圖&#xff08;PlantUML格式&#xff09; 1.簡單工廠模式 2.工廠方法模式 3.抽象工廠模式 三、實現過程與結果 1. 簡單工廠模式 2. 工廠方法模式 3. 抽象工廠模式 四、總結 在面向對…

Trae,字節跳動推出的 AI 編程助手插件

Trae 插件是 Trae 旗下全新一代的人工智能編程助手&#xff08;前身為 MarsCode 編程助手&#xff09;&#xff0c;以插件形式集成在本地開發環境中&#xff0c;具備極高的兼容性和靈活性&#xff0c;旨在提升開發效率和代碼質量。它支持超過100種編程語言&#xff0c;兼容主流…

工作紀實_63-Mac電腦使用brew安裝軟件

最近在接觸kafka&#xff0c;想著在自己的電腦安裝一套環境&#xff0c;docker也能行&#xff0c;但是還是想裝一些原生的軟件試試看&#xff0c;因此便想著整理一下brew的命令&#xff0c;這命令確實是方便&#xff0c;不需要下載tar包亂八七糟的東西&#xff0c;一鍵安裝 bre…

Python語法系列博客 · 第8期[特殊字符] Lambda函數與高階函數:函數式編程初體驗

上一期小練習解答&#xff08;第7期回顧&#xff09; ? 練習1&#xff1a;找出1~100中能被3或5整除的數 result [x for x in range(1, 101) if x % 3 0 or x % 5 0]? 練習2&#xff1a;生成字符串長度字典 words ["apple", "banana", "grape…

Redis--主從復制

目錄 一、配置 1.1 建立復制 1.2 斷開復制 1.3 安全性 1.4 只讀 1.5 傳輸延遲 二、拓撲 2.1 一主一從結構 2.2 一主多從結構 2.3 樹形主從結構 在分布式系統中為了解決單點問題&#xff0c;通常會把數據復制多個副本部署到其他服務器&#xff0c;滿足故障恢 復和負載均衡等需求…

已注冊商標如何防止被不使用撤銷!

近年來已注冊商標被撤銷越來越多&#xff0c;不乏著名企業或機構&#xff0c;普推知產商標老楊看到前一陣看到央視和百度等申請的商標也被申請撤銷&#xff0c;連續三年不使用撤銷也是正常的商標流程。 已注冊商標被撤銷普推老楊看到案例主要是集中在一些早期申請注冊的好記的商…

解密大模型背后的秘密:訓練、優化與挑戰

解密大模型背后的秘密&#xff1a;訓練、優化與挑戰 在當今的人工智能領域&#xff0c;大模型&#xff08;Large Language Models, LLMs&#xff09;已經成為了一個不可忽視的存在。從自然語言處理到圖像生成&#xff0c;再到推薦系統&#xff0c;大模型以其強大的泛化能力和創…

App自動化測試流程方案與架構設計

App自動化測試流程方案與架構設計 一、核心流程設計 #mermaid-svg-kN4GmIvHb8MMT83M {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-kN4GmIvHb8MMT83M .error-icon{fill:#552222;}#mermaid-svg-kN4GmIvHb8MMT83M .e…

字節跳動發布視頻生成基礎大模型 Seaweed-7B

近日&#xff0c;字節跳動發布了其全新視頻生成基礎大模型 Seaweed-7B&#xff0c;該模型由字節 Seed 團隊開發&#xff0c;參數量僅為 70 億&#xff0c;在多個方面展現出卓越性能&#xff0c;為 AI 視頻生成領域帶來了新的突破。 功能特點 支持多種生成方式&#xff1a;Sea…

如何基于區塊鏈進行虛擬電廠運營平臺建設?

本項目旨在基于區塊鏈技術建設虛擬電廠運營平臺&#xff0c;以提升省內大用戶及工業企業和工業園區的需求響應能力&#xff0c;優化能源結構配置&#xff0c;并推動能源交易、需求響應和現貨交易等新型業態的發展。通過建設虛擬電廠&#xff0c;項目將實現工業企業及園區各供用…

LeetCode[459]重復的子字符串(KMP解法)

思路&#xff1a; 最近迷上了KMP算法&#xff0c;所以這道題也是來搞一下KMP算法&#xff0c;總所周知KMP是需要維護一個前綴表&#xff0c;KMP算法不是比較一個字符串包不包含另一個字符串的嗎&#xff0c;這個重復字符串的題也能用&#xff1f;貓爺&#xff1a;毋庸置疑&…

spring-batch批處理框架(2)

文章目錄 八、作業控制8.1 作業啟動8.1.1 SpringBoot 啟動8.1.2 Spring 單元測試啟動8.1.3 RESTful API 啟動 8.2 作業停止方案1&#xff1a;Step 步驟監聽器方式方案2&#xff1a;StepExecution停止標記 8.3 作業重啟8.3.1 禁止重啟8.3.2 限制重啟次數8.3.3 無限重啟 九、Item…