累加和校驗原理與FPGA實現
- 寫在前面
- 一、基礎原理
- 二、舉個例子
- 2.1 進位累加
- 2.2 回卷累加
- 三、FPGA實現
- 3.1 發送端(產生校驗和)
- 3.2 接收端(累加和校驗)
- 3.3 仿真結果
- 寫在后面
寫在前面
??在上文《奇偶校驗原理與FPGA實現》中,講解了奇偶校驗的基礎原理,奇偶校驗僅增加1比特的信息冗余,所增加額外開銷小,但不可避免存在檢錯能力有限的問題。本文將講解另外一種校驗碼型——累加和校驗。累加和校驗的使用場景較為廣泛,在網絡通信協議(IP/TCP/UDP協議)、高速接口(AXI)、存儲器數據保護等很多場景均有使用。
一、基礎原理
??累加和校驗原理是將要發送或存儲的數據分割成固定長度的多個數據段(通常為字節或字),然后將這些數據段累加起來(通常采用二進制加法,忽略進位),得到一個累加和。最后,將累加和取反(或取補碼)作為校驗值附加到原始數據后面。
??在發送端,累加和的計算可以分為以下幾個步驟:
- 數據分割:將數據按固定長度(如8位、16位)分割成多個數據塊;
- 累加求和:將所有數據塊進行二進制加法累加。在累加過程中,如果有進位,則回卷(即進位加到最低位上)。但實際實現中,通常采用足夠寬的寄存器(如16位累加和用32位寄存器)來避免溢出,最后取低16位;
- 取反:將累加和按位取反(即1的補碼),得到校驗和(Checksum)。取反的目的是為了在接收端驗證時,包括校驗和在內的所有數據累加的結果應該為全1(即0xFFFF,對于16位校驗和),再取反則為0。這樣接收端可以通過判斷累加結果是否為0來檢查數據正確性;
- 附加校驗和:將計算得到的校驗和附加在原始數據的末尾;
??而在接收端,將接收到的所有數據(包括原始數據和附加的校驗和)進行同樣的累加操作(同樣忽略進位或使用足夠寬的寄存器),如果傳輸沒有錯誤,則累加的結果應該為0xFFFF。
??以上描述的校驗和傳輸方式為反碼傳輸,實際上常用的校驗和傳輸方式有原碼、反碼、補碼三種。
- 方式1:發送方計算數據的累加和,然后將其作為校驗和直接發送。接收方將接收到的所有數據(不包括校驗和)進行累加,如果沒有錯誤,則累加結果應該與校驗和一致。
- 方式1:發送方計算數據的累加和,然后取反碼作為校驗和進行發送。接收方將接收到的所有數據(包括校驗和)進行累加,如果沒有錯誤,則結果應為全1(即0xFFFF,對于16位校驗和)。因為:原碼+反碼=全1。
- 方式2:發送方計算數據的累加和,然后取補碼作為校驗和進行發送。接收方將接收到的所有數據(包括校驗和)進行累加,如果沒有錯誤,則結果應為全0。因為:原碼+補碼=全0
二、舉個例子
??以反碼形式傳輸校驗和為例,假如傳輸的4個16比特數據分別為0x1234、0x5678、0x9ABC、0xDEF0。
2.1 進位累加
??若是使用進位累加的方式,采用32位累加器(保證累加和不溢出),則在發送端:
??取累加和的低16比特0xE258,取反得到校驗和0x1DA7進行發送。在接收端:
??累加結果的低16比特為全1,累加和校驗通過。
2.2 回卷累加
??若是使用進位累加的方式,采用17位累加器,則在發送端:
??取累加和的低16比特0xE258,取反得到校驗和0x1DA6進行發送。在接收端:
??累加結果的低16比特為全1,累加和校驗通過。
三、FPGA實現
3.1 發送端(產生校驗和)
module tx_checksum
(input clk ,input rst_n ,input [15 :0] data_in , // 輸入數據input data_valid , // 數據有效信號input start , // 數據起始標志input finish , // 數據結束標志output [15 :0] checksum , // 生成的校驗和output checksum_valid // 校驗和有效信號
);//----------------------------------------------------------------// REG//----------------------------------------------------------------reg [31 :0] accumulator ; // 32位累加器(防溢出)reg finish_d ;//----------------------------------------------------------------// LOGIC//----------------------------------------------------------------always @(posedge clk or negedge rst_n) beginif(!rst_n)accumulator <= 32'd0;else if(start && data_valid)accumulator <= {16'd0,data_in};else if(data_valid)accumulator <= accumulator[31:16] + accumulator[15:0] + data_in; // 回卷+累加elseaccumulator <= accumulator;endalways @(posedge clk or negedge rst_n) beginif(!rst_n)finish_d <= 1'b0;elsefinish_d <= finish;endassign checksum = ~accumulator[15:0];assign checksum_valid = finish_d ;endmodule
3.2 接收端(累加和校驗)
module rx_checksum
(input clk ,input rst_n ,input [15 :0] data_in , // 輸入數據input data_valid , // 數據有效信號input start , // 數據起始標志input finish , // 數據結束標志output check_pass // 數據校驗通過
);//----------------------------------------------------------------// REG//----------------------------------------------------------------reg [31 :0] accumulator ; // 32位累加器(防溢出)reg finish_d ;//----------------------------------------------------------------// LOGIC//----------------------------------------------------------------always @(posedge clk or negedge rst_n) beginif(!rst_n)accumulator <= 32'd0;else if(start && data_valid)accumulator <= {16'd0,data_in};else if(data_valid)accumulator <= accumulator[31:16] + accumulator[15:0] + data_in; // 回卷+累加elseaccumulator <= accumulator;endalways @(posedge clk or negedge rst_n) beginif(!rst_n)finish_d <= 1'b0;elsefinish_d <= finish;endassign check_pass = (finish_d && (accumulator == 32'h0000FFFF)) ? 1'b1 : 1'b0;endmodule
3.3 仿真結果
??在發送端,依次發送0x1234、0x5678、0x9ABC、0xDEF0,得到的校驗和為0x1DA6,與前面所舉例子理論值一致。
??在發送端,對序列0x1234、0x5678、0x9ABC、0xDEF0、0x1DA6進行累加,得到的累加和為0xFFFF,校驗通過。
寫在后面
??在本文中,講解了累加和校驗的基本原理,包括:
- 累加和的三種傳輸方式以及在接收端相應的校驗方法(原碼、反碼、補碼)
- 累加的兩種方式(進位累加、回卷累加)
??同時,舉例計算進位累加與回卷累加的累加過程與校驗過程,并給出了回卷累加的發送端、接收端代碼與仿真結果。
🧐:以上為個人學習筆記,如有疑問,歡迎評論區交流探討 !!!
