目录:
1: ECC原理
2: ECC校验-列校验
3: ECC校验-行校验
4: ECC校验结果的分析
5: 算法实现
6: 实例分析
7: 校验流程总结
8:硬件verilog代码
1.ECC校验原理
先看下奇偶校验:
奇校验: 一个字节有8位, 校验位1位, 共9位, 使9位中“ 1” 的个数为奇数;
偶校验: 同理。
奇偶校验缺点 : 1.奇偶校验每传输一个字节都需要加一位校验位, 对传输效率影响很大。
2.不能把纠正错误。
ECC校验:
从NAND Flash读取数据时, Page( 存储数据的基本单元, 如256+8 byte) 中的1个或几个bit可能会出现错误, 每256字节我们生成一个ECC校验和, 称之为新ECC校验和。 ECC能纠正单比特错误和检测双比特错误, 而且计算速度很快, 但对1比特以上的错误无法纠正, 对2比特以上的错误不保证能检测。
生成ECC校验码的算法:
ECC 校验每次对 256 Byte的数据进行操作, 包含列校验和行校验。 对每个待校验的 Bit 位求异或, 若结果为 0 , 则表明含有偶数个 1 ; 若结果为 1 , 则表明含有奇数个 1 。 256 字节数据形成 256 行、 8 列的矩阵, 矩阵每个元素表示一个 Bit 位。
8.硬件verilog实现
module ECCChckMod(
input clk50M,
input rst,
input [7:0] DataIn,
input DataInEn,
input EccStart,
input [15:0]DataNum,
output reg [31:0]ECCDataOut,
output reg ECCDaOutEn
);
reg [2:0 ] state;
reg ecc_P1, ecc_P2, ecc_P4, ecc_P8, ecc_P16, ecc_P32, ecc_P64, ecc_P128, ecc_P256, ecc_P512, ecc_P1024, ecc_P2048, ecc_P4096, ecc_P8192;
reg ecc_P1x,ecc_P2x,ecc_P4x,ecc_P8x,ecc_P16x,ecc_P32x,ecc_P64x,ecc_P128x,ecc_P256x,ecc_P512x,ecc_P1024x,ecc_P2048x,ecc_P4096x,ecc_P8192x;
reg S_P8,S_P16,S_P32,S_P64,S_P128,S_P256,S_P512,S_P1024,S_P2048,S_P4096;
reg [15:0] DataCnt;
wire [7:0] d;
assign d= DataIn;
always@(posedge clk50M or posedge rst)
if(rst)begin
state<=3'h0;
ecc_P1<=1'b0;
ecc_P2<=1'b0;
ecc_P4<=1'b0;
ecc_P8<=1'b0;
ecc_P16<=1'b0;
ecc_P32<=1'b0;
ecc_P64<=1'b0;
ecc_P128<=1'b0;
ecc_P256<=1'b0;
ecc_P512<=1'b0;
ecc_P1024<=1'b0;
ecc_P2048<=1'b0;
ecc_P4096<=1'b0;
ecc_P8192<=1'b0;
ecc_P1x<=1'b0;
ecc_P2x<=1'b0;
ecc_P4x<=1'b0;
ecc_P8x<=1'b0;
ecc_P16x<=1'b0;
ecc_P32x<=1'b0;
ecc_P64x<=1'b0;
ecc_P128x<=1'b0;
ecc_P256x<=1'b0;
ecc_P512x<=1'b0;
ecc_P1024x<=1'b0;
ecc_P2048x<=1'b0;
ecc_P4096x<=1'b0;
ecc_P8192x<=1'b0;
S_P8<=1'b0;
S_P16<=1'b0;
S_P32<=1'b0;
S_P64<=1'b0;
S_P128<=1'b0;
S_P256<=1'b0;
S_P512<=1'b0;
S_P1024<=1'b0;
S_P2048<=1'b0;
S_P4096<=1'b0;
DataCnt<=16'h0;
ECCDataOut<=32'h0;
ECCDaOutEn<=1'b0;
end
else begin
case(state)
3'h0:
if(EccStart==1'b1)
state<=3'h1;
else
state<=3'h0;
3'h1:
if(DataNum==16'd2052)begin //计数满2K
state<=3'h2;
ecc_P1<=1'b0;
ecc_P2<=1'b0;
ecc_P4<=1'b0;
ecc_P8<=1'b0;
ecc_P16<=1'b0;
ecc_P32<=1'b0;
ecc_P64<=1'b0;
ecc_P128<=1'b0;
ecc_P256<=1'b0;
ecc_P512<=1'b0;
ecc_P1024<=1'b0;
ecc_P2048<=1'b0;
ecc_P4096<=1'b0;
ecc_P8192<=1'b0;
ecc_P1x<=1'b0;
ecc_P2x<=1'b0;
ecc_P4x<=1'b0;
ecc_P8x<=1'b0;
ecc_P16x<=1'b0;
ecc_P32x<=1'b0;
ecc_P64x<=1'b0;
ecc_P128x<=1'b0;
ecc_P256x<=1'b0;
ecc_P512x<=1'b0;
ecc_P1024x<=1'b0;
ecc_P2048x<=1'b0;
ecc_P4096x<=1'b0;
ecc_P8192x<=1'b0;
DataCnt<=16'h0;
end
else
state<=3'h0;
3'h2:begin
if(DataCnt==16'd2048)begin //校验2k数据
state<=3'h3;
DataCnt<=16'h0;
ECCDataOut<={ecc_P8192, ecc_P4096, ecc_P2048, ecc_P1024, ecc_P512, ecc_P256, ecc_P128, ecc_P64, ecc_P32, ecc_P16, ecc_P8, ecc_P4,ecc_P2,ecc_P1,
ecc_P8192x,ecc_P4096x,ecc_P2048x,ecc_P1024x,ecc_P512x,ecc_P256x,ecc_P128x,ecc_P64x,ecc_P32x,ecc_P16x,ecc_P8x,ecc_P4x,
ecc_P2x,ecc_P1x,1'b1,1'b1,1'b1,1'b1};
ECCDaOutEn<=1'b1;
end
else if(DataInEn==1'b1)begin //计数直到2K个数据进来
DataCnt<=DataCnt + 1'b1;
state<=3'h2;
end
//P1,P2,P4,P1x,P2x,P4x
if(DataInEn==1'b1)begin //列校验
ecc_P1<=d[1]^d[3]^d[5]^d[7]^ecc_P1;
ecc_P1x<=d[0]^d[2]^d[4]^d[6]^ecc_P1x;
ecc_P2<=d[2]^d[3]^d[6]^d[7]^ecc_P2;
ecc_P2x<=d[0]^d[1]^d[4]^d[5]^ecc_P2x;
ecc_P4<=d[4]^d[5]^d[6]^d[7]^ecc_P4;
ecc_P4x<=d[0]^d[1]^d[2]^d[3]^ecc_P4x;
end
//P8 以下是行校验
if(DataInEn==1'b1 && DataCnt[0]==1'b1)begin
ecc_P8<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^ecc_P8;
end
//P8x
if(DataInEn==1'b1 && DataCnt[0]==1'b0)begin
ecc_P8x<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^ecc_P8x;
S_P8<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7];
end
//P16
if(DataInEn==1'b1 && DataCnt[1:0]==2'b11)begin
ecc_P16<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^ecc_P16;
end
//P16x
if(DataInEn==1'b1 && DataCnt[1:0]==2'b01)begin
ecc_P16x<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^ecc_P16x;
S_P16<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8;
end
//P32
if(DataInEn==1'b1 && DataCnt[2:0]==3'b111)begin
ecc_P32<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^ecc_P32;
end
//P32x
if(DataInEn==1'b1 && DataCnt[2:0]==3'b011)begin
ecc_P32x<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^ecc_P32x;
S_P32<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16;
end
//P64
if(DataInEn==1'b1 && DataCnt[3:0]==4'b1111)begin
ecc_P64<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^ecc_P64;
end
//P64x
if(DataInEn==1'b1 && DataCnt[3:0]==4'b0111)begin
ecc_P64x<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^ecc_P64x;
S_P64<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32;
end
//P128
if(DataInEn==1'b1 && DataCnt[4:0]==5'b11111)begin
ecc_P128<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^ecc_P128;
end
//P128x
if(DataInEn==1'b1 && DataCnt[4:0]==5'b01111)begin
ecc_P128x<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^ecc_P128x;
S_P128<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64;
end
//P256
if(DataInEn==1'b1 && DataCnt[5:0]==6'b111111)begin
ecc_P256<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^S_P128^ecc_P256;
end
//P256x
if(DataInEn==1'b1 && DataCnt[5:0]==6'b011111)begin
ecc_P256x<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^S_P128^ecc_P256x;
S_P256<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^S_P128;
end
//P512
if(DataInEn==1'b1 && DataCnt[6:0]==7'b1111111)begin
ecc_P512<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^S_P128^S_P256^ecc_P512;
end
//P512x
if(DataInEn==1'b1 && DataCnt[6:0]==7'b0111111)begin
ecc_P512x<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^S_P128^S_P256^ecc_P512x;
S_P512<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^S_P128^S_P256;
end
//P1024
if(DataInEn==1'b1 && DataCnt[7:0]==8'b11111111)begin
ecc_P1024<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^S_P128^S_P256^S_P512^ecc_P1024;
end
//P1024x
if(DataInEn==1'b1 && DataCnt[7:0]==8'b01111111)begin
ecc_P1024x<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^S_P128^S_P256^S_P512^ecc_P1024x;
S_P1024<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^S_P128^S_P256^S_P512;
end
//P2048
if(DataInEn==1'b1 && DataCnt[8:0]==9'b111111111)begin
ecc_P2048<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^S_P128^S_P256^S_P512^S_P1024^ecc_P2048;
end
//P2048x
if(DataInEn==1'b1 && DataCnt[8:0]==9'b011111111)begin
ecc_P2048x<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^S_P128^S_P256^S_P512^S_P1024^ecc_P2048x;
S_P2048<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^S_P128^S_P256^S_P512^S_P1024;
end
//P4096
if(DataInEn==1'b1 && DataCnt[9:0]==10'b1111111111)begin
ecc_P4096<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^S_P128^S_P256^S_P512^S_P1024^S_P2048^ecc_P4096;
end
//P4096x
if(DataInEn==1'b1 && DataCnt[9:0]==10'b0111111111)begin
ecc_P4096x<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^S_P128^S_P256^S_P512^S_P1024^S_P2048^ecc_P4096x;
S_P4096<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^S_P128^S_P256^S_P512^S_P1024^S_P2048;
end
//P8192
if(DataInEn==1'b1 && DataCnt[10:0]==11'b11111111111)begin
ecc_P8192<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^S_P128^S_P256^S_P512^S_P1024^S_P2048^S_P4096^ecc_P8192;
end
//P4096x
if(DataInEn==1'b1 && DataCnt[10:0]==11'b01111111111)begin
ecc_P8192x<=d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]^S_P8^S_P16^S_P32^S_P64^S_P128^S_P256^S_P512^S_P1024^S_P2048^S_P4096^ecc_P8192x;
end
end
3'h3:begin
ECCDaOutEn<=1'b0;
state<=3'h4;
end
3'h4:
state<=3'h0;
default:
state<=3'h0;
endcase
end
endmodule