一、CRC校驗碼的產生原理
循環冗餘編碼(CRC)是二進制通信系統中一種常用的差錯檢測方法,它是通過在原始數據後面添加冗餘校驗碼來實現檢測差錯的目的。CRC編碼的基本原理就是:CRC可由原始數據流的二進制去除以一稱作爲生成多項式的常數,將得到的商拋棄,餘數加到原始數據流二進制數的後面得到,在接收端,用接收的數據再去除以該生成多項式,如果餘數爲0則校驗通過,否則校驗不通過。
這裏我們採用CRC16編碼作爲典型例子進行講解,首先我們先講解一下二進制數的多項式表示,二進制數可以表示成多項式的係數,如10 0100 0101用多項式就可以表示成:。另外,在CRC校驗碼的生成過程中需要用到除法操作,那麼對於非常大的數字時,用數字邏輯來實現除法操作既消耗資源且操作麻煩,所以我們就需要將除數二進制數按照前面所講解的規則轉換爲多項式,然後利用該多項式藉助線性移位寄存器來實現複雜的除法操作。
國際上對於不同類型的CRC校驗編碼是有相應的國際標準的,比如CRC8,CRC16,在這些標準中對除數(或者叫做生成多項式)都有明確的規定,我們只需要查閱相關標準手冊,然後根據相應的生成多項式編碼實現不同類型的CRC校驗碼,這裏以CRC16爲例,CRC16的生成多項式可以表示爲:
該生成多項式對應的線性反饋移位寄存器可以表示爲:
圖中的crc[0]-crc[15]分別代表CRC16校驗碼的第0-15位,data表示輸入數據流,待校驗碼生成完畢之後,將16位校驗碼加到輸入數據流的末尾就得到了生成的發送序列,圖中的數據運算爲異或操作,通過如上圖所示的線性移位寄存器就實現了除法操作。
二、CRC16的Verilog實現
編碼如下:
module crc16_para (
//system signals
input sclk ,
input s_rst_n ,
//
input [7:0] data ,
output reg [15:0] out
);
reg [15:0] crc16_out ;
reg [15:0] crc_reg ;
reg temp;
integer i,j,m,n ;
always @ (posedge sclk or negedge s_rst_n) begin
if(s_rst_n == 1'b0)
crc16_out<=16'b0;
else
crc16_out<=crc_reg;
end
always @ (crc16_out or data) begin
crc_reg=crc16_out;
for (i = 7; i >= 0; i = i - 1)
begin
temp=data[i]^crc_reg[15];
for (j = 15; j > 12; j = j - 1)
begin
crc_reg[j]=crc_reg[j-1];
end
crc_reg[12]=temp^crc_reg[11];
for (m = 11; m >5 ; m = m - 1)
begin
crc_reg[m]=crc_reg[m-1];
end
crc_reg[5]=temp^crc_reg[4];
for (n = 4; n >0 ; n = n - 1)
begin
crc_reg[n]=crc_reg[n-1];
end
crc_reg[0]=temp^0;
end
out=crc_reg;
end
endmodule
testbench如下:
`timescale 1ns/1ps
module tb ();
reg sclk;
reg s_rst_n;
reg [7:0] data ;
wire [15:0] out ;
initial
begin
sclk=1'b1;
s_rst_n=1'b1;
data=8'b1011_0110;
#5 s_rst_n=1'b0;
#5 s_rst_n=1'b1;
end
always #5 sclk=~sclk;
crc16_para crc16_para_instance(
//system signals
.sclk(sclk),
.s_rst_n(s_rst_n),
.data(data),
.out(out)
);
endmodule
Modelsim仿真結果:
CRC計算器計算結果:
由兩圖中結果比較可知,計算結果正確,校驗通過。