OpenCores
URL https://opencores.org/ocsvn/bch_configurable/bch_configurable/trunk

Subversion Repositories bch_configurable

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/bch_configurable/trunk/src/test_bch_syndrome.v
0,0 → 1,275
///-----------------------------------------
///introduce:
///bch syndrome generation in decoder
///author:jiml
///record:
///2015.1.31 initial
///-----------------------------------------
`timescale 1ns/100ps
module test_bch_syndrome
#(
parameter C_DWIDTH = 128, //input data width
parameter C_COEF_NUM = 43, //correct threshold
parameter C_PRIMPOLY_ORDER = 14, //order of eigenpolynomial
parameter C_PRIM_POLY = 15'h4443 //eigenpolynomial
)
(
input I_clk ,
input I_rst ,
input [C_DWIDTH-1:0] I_data , //input data
input I_data_v , //input data available
input I_data_sof , //input data frame start
input I_data_eof , //input data frame end
output reg [C_COEF_NUM*C_PRIMPOLY_ORDER-1:0] O_syndrome , //syndrome
output reg O_syndrome_v //syndrome available
);
 
//------------------------------------------
//parameter and variable
//------------------------------------------
localparam [C_PRIMPOLY_ORDER*C_PRIMPOLY_ORDER*C_COEF_NUM-1:0] C_TRANS_MATRIX = F_transform(0);
localparam C_UPP_WIDTH = GETASIZE(C_PRIMPOLY_ORDER);
localparam C_GEN_UPP = F_GEN_NUM(0);
localparam C_GEN_POLY = F_GEN_POLY2(0);
localparam C_SHIFT_NUM = F_shift_cal(0);
 
reg [C_PRIMPOLY_ORDER-1:0] S_reg [C_COEF_NUM-1:0];
reg S_data_eof = 0;
reg [C_DWIDTH-1:0] S_data = 0;
reg S_data_eof_d = 0;
reg S_data_v = 0;
reg S_data_sof = 0;
 
//--------------------------------------------
//function
//--------------------------------------------
//element generation in Galois Field
function [C_PRIMPOLY_ORDER-1:0] F_gen;
input [C_PRIMPOLY_ORDER-1:0] S_init;
input integer S_times;
integer i;
begin
F_gen = S_init;
for(i=0;i<S_times;i=i+1)
begin
if(F_gen[C_PRIMPOLY_ORDER-1])
F_gen = (F_gen<<1) ^ C_PRIM_POLY[C_PRIMPOLY_ORDER-1:0];
else
F_gen = (F_gen<<1);
end
end
endfunction
 
//2*t-1 power of element transform to 1 power of element
function [C_PRIMPOLY_ORDER*C_PRIMPOLY_ORDER*C_COEF_NUM-1:0] F_transform;
input red;
integer i,j,k;
reg [C_PRIMPOLY_ORDER-1:0] S_reg;
begin
for(i=0;i<C_COEF_NUM;i=i+1)
begin
for(j=0;j<C_PRIMPOLY_ORDER;j=j+1)
begin
S_reg = F_gen(1,j*(2*i+1));
for(k=0;k<C_PRIMPOLY_ORDER;k=k+1)
begin
F_transform[C_PRIMPOLY_ORDER*C_PRIMPOLY_ORDER*i+C_PRIMPOLY_ORDER*k+j] = S_reg[k];
end
end
end
end
endfunction
 
//when length of encode polynomial is not exactly divided into C_DWIDTH, data should shift right to occupy C_DWIDTH bits fully
function integer F_shift_cal;
input red;
integer i;
integer temp;
begin
F_shift_cal = 0;
for(i=0;i<C_COEF_NUM;i=i+1)
F_shift_cal=F_shift_cal+C_GEN_UPP[i*C_UPP_WIDTH+:C_UPP_WIDTH];
while(F_shift_cal>C_DWIDTH)
F_shift_cal = F_shift_cal - C_DWIDTH;
F_shift_cal = C_DWIDTH-F_shift_cal;
end
endfunction
 
//generated polynomial cascaded
function [C_PRIMPOLY_ORDER*C_COEF_NUM-1:0] F_GEN_POLY2;
input red;
integer i,j,k;
integer pointer;
reg [2**C_PRIMPOLY_ORDER-2:0] S_flag;
reg [C_PRIMPOLY_ORDER-1:0] S_temp [C_PRIMPOLY_ORDER:0];
reg [C_PRIMPOLY_ORDER-1:0] S_temp2;
begin
F_GEN_POLY2 = 0;
for(i=0;i<C_PRIMPOLY_ORDER;i=i+1) //least bits are eigenpolynomial
F_GEN_POLY2[i] = C_PRIM_POLY[i];
for(i=1;i<C_COEF_NUM;i=i+1) //there are C_COEF_NUM generated polynomial
begin
for(j=1;j<=C_PRIMPOLY_ORDER;j=j+1)
S_temp[j] = 0;
S_temp[0]=1;
S_flag = 0;
for(j=1;j<=C_PRIMPOLY_ORDER;j=j+1) //each polynomial have at most C_PRIMPOLY_ORDER element
begin
pointer = (2*i+1)*(2**(j-1));
while(pointer>(2**C_PRIMPOLY_ORDER-2))
pointer = pointer - (2**C_PRIMPOLY_ORDER-1);
if(!S_flag[pointer])
begin
S_flag[pointer] = 1;
S_temp2 = F_gen(1,pointer);
for(k=C_PRIMPOLY_ORDER-1;k>0;k=k-1)
begin
S_temp[k]= F_mult(S_temp[k],S_temp2) ^ S_temp[k-1];
end
S_temp[0] = F_mult(S_temp[0],S_temp2);
S_temp[C_PRIMPOLY_ORDER] = S_temp[C_PRIMPOLY_ORDER-1];
end
end
for(j=0;j<C_PRIMPOLY_ORDER;j=j+1)
F_GEN_POLY2[i*C_PRIMPOLY_ORDER+j] = (S_temp[j] == 1);
end
end
endfunction
 
//polynomial multiplication in Galois Field
function [C_PRIMPOLY_ORDER-1:0] F_mult;
input [C_PRIMPOLY_ORDER-1:0] S_data1;
input [C_PRIMPOLY_ORDER-1:0] S_data2;
reg [C_PRIMPOLY_ORDER*2-1:0] S_temp;
integer i;
begin
S_temp = 0;
F_mult = 0;
for(i=0;i<C_PRIMPOLY_ORDER;i=i+1)
begin
S_temp = S_temp ^ ({(C_PRIMPOLY_ORDER*2){S_data1[i]}} & (S_data2<<i));
end
for(i=0;i<C_PRIMPOLY_ORDER*2;i=i+1)
begin
F_mult = {F_mult[C_PRIMPOLY_ORDER-2:0],S_temp[C_PRIMPOLY_ORDER*2-1-i]} ^ (C_PRIM_POLY[C_PRIMPOLY_ORDER-1:0] & {C_PRIMPOLY_ORDER{F_mult[C_PRIMPOLY_ORDER-1]}});
end
end
endfunction
 
//width calculation
function integer GETASIZE;
input integer a;
integer i;
begin
for(i=1;(2**i)<=a;i=i+1)
begin
end
GETASIZE = i;
end
endfunction
 
//length of generated polynomial cascaded
function [C_UPP_WIDTH*C_COEF_NUM-1:0] F_GEN_NUM;
input red;
integer i,j;
integer temp;
reg [2**C_PRIMPOLY_ORDER-2:0] S_flag;
begin
F_GEN_NUM = 0;
for(i=0;i<C_COEF_NUM;i=i+1)
begin
S_flag = 0;
for(j=1;j<=C_PRIMPOLY_ORDER;j=j+1)
begin
temp = (2*i+1)*(2**(j-1));
while(temp > 2**C_PRIMPOLY_ORDER-2)
temp = temp - (2**C_PRIMPOLY_ORDER-1);
if(!S_flag[temp])
begin
S_flag[temp] = 1;
F_GEN_NUM[i*C_UPP_WIDTH+:C_UPP_WIDTH]=F_GEN_NUM[i*C_UPP_WIDTH+:C_UPP_WIDTH]+'d1;
end
end
end
end
endfunction
 
//polynomial division in Galois Field
function [C_PRIMPOLY_ORDER-1:0] F_reg_update;
input [C_PRIMPOLY_ORDER-1:0] S_reg_ori;
input [C_DWIDTH-1:0] S_data;
input [C_PRIMPOLY_ORDER-1:0] S_poly;
input integer S_upp;
integer i;
reg S_temp1;
reg S_temp2;
begin
F_reg_update = S_reg_ori;
for(i=0;i<C_DWIDTH;i=i+1)
begin
S_temp1 = F_reg_update[S_upp];
S_temp2 = S_temp1 ^ S_data[C_DWIDTH-1-i];
F_reg_update[C_PRIMPOLY_ORDER-1:1] = {F_reg_update[C_PRIMPOLY_ORDER-2:0]} ^ ({(C_PRIMPOLY_ORDER-1){S_temp1}} & S_poly[C_PRIMPOLY_ORDER-1:1]);
F_reg_update[0] = S_temp2;
end
end
endfunction
 
//---------------------------------------
//syndrome calculation
//---------------------------------------
genvar S_i;
generate
for(S_i=0;S_i<C_COEF_NUM;S_i=S_i+1) //parallel calculation
begin:test
 
wire [C_PRIMPOLY_ORDER-1:0] S_para1;
reg [C_DWIDTH-1:0] S_para2;
 
localparam C_POLY = C_GEN_POLY[S_i*C_PRIMPOLY_ORDER+:C_PRIMPOLY_ORDER];
localparam C_UPP = C_GEN_UPP[S_i*C_UPP_WIDTH+:C_UPP_WIDTH]-1;
 
always @(posedge I_clk)
begin
S_para2 <= (C_SHIFT_NUM != 0) ? (I_data_sof ? {{C_SHIFT_NUM{1'b0}},I_data[C_DWIDTH-1-:(C_DWIDTH-C_SHIFT_NUM)]} : {S_data,I_data[C_DWIDTH-1-:(C_DWIDTH-C_SHIFT_NUM)]}) : I_data;
end
 
assign S_para1 = S_data_sof ? 'd0 : S_reg[S_i];
 
always @(posedge I_clk)
begin
if(S_data_v)
begin
S_reg[S_i] <= F_reg_update(S_para1,S_para2,C_POLY,C_UPP);
end
end
 
end
endgenerate
 
always @(posedge I_clk)
begin
S_data <= I_data;
end
 
integer j,k;
always @(posedge I_clk)
begin
S_data_eof <= I_data_eof;
S_data_eof_d <= S_data_eof;
O_syndrome_v <= S_data_eof_d;
S_data_v <= I_data_v;
S_data_sof <= I_data_sof;
if(S_data_eof_d)
begin
for(j=0;j<C_COEF_NUM;j=j+1)
for(k=0;k<C_PRIMPOLY_ORDER;k=k+1)
begin
O_syndrome[j*C_PRIMPOLY_ORDER+k] <= ^(S_reg[j] & C_TRANS_MATRIX[j*C_PRIMPOLY_ORDER*C_PRIMPOLY_ORDER+k*C_PRIMPOLY_ORDER+:C_PRIMPOLY_ORDER]);
end
end
end
 
 
endmodule
/bch_configurable/trunk/src/test_correct.v
0,0 → 1,202
///-----------------------------------------
///introduce:
///bch correct in decoder
///author:jiml
///record:
///2015.3.15 initial
///-----------------------------------------
`timescale 1ns/100ps
module test_correct
#(
parameter C_INPUT_NUM = 128, //length of input bit
parameter C_DWIDTH = 16, //input data width
parameter C_ECCWIDTH = 16 //check data width
)
(
input I_clk ,
input I_rst ,
input [C_DWIDTH-1:0] I_data , //input data
input I_data_sof , //input data frame start
input I_data_eof , //input data frame end
input I_data_v , //input data available
input [C_ECCWIDTH-1:0] I_ecc , //check data
input I_ecc_v , //check data available
input I_ecc_sof , //check data frame start
input I_ecc_eof , //check data frame end
output reg [C_DWIDTH-1:0] O_data , //corrected data
output reg O_data_v , //corrected data available
output reg O_data_sof , //corrected data frame start
output reg O_data_eof //corrected data frame end
);
 
//----------------------------------------
//parameter and variable
//----------------------------------------
localparam C_OVERFLOW_THRESHOLD = C_DWIDTH-C_ECCWIDTH+1;
localparam C_DIF = C_DWIDTH - C_ECCWIDTH;
localparam C_SLR_CNT_WIDTH = GETASIZE(C_DWIDTH)+1;
localparam C_CHIP_NUM = C_INPUT_NUM/C_DWIDTH;
localparam C_CHIP_NUM_WIDTH = GETASIZE(C_CHIP_NUM);
 
reg [2*C_DWIDTH-1:0] S_data_slr = 0;
reg [C_SLR_CNT_WIDTH-1:0] S_slr_cnt = 0;
reg S_ov_id = 0;
reg [C_DWIDTH-1:0] S_data_tran = 0;
reg S_ecc_eof = 0;
reg S_ecc_eof_d = 0;
reg S_ecc_v = 0;
reg [C_ECCWIDTH-1:0] S_ecc = 0;
reg S_data_tran_v = 0;
reg [C_DWIDTH-1:0] S_ecc_ram [2**C_CHIP_NUM_WIDTH-1:0];
reg [C_DWIDTH-1:0] S_data_ram [2**C_CHIP_NUM_WIDTH-1:0];
reg [C_CHIP_NUM_WIDTH-1:0] S_ecc_waddr = 0;
reg [C_CHIP_NUM_WIDTH:0] S_data_waddr = 0;
reg [C_CHIP_NUM_WIDTH-1:0] S_ecc_raddr = 0;
reg S_ecc_r = 0;
reg [C_DWIDTH-1:0] S_ecc_dout;
reg [C_DWIDTH-1:0] S_dataout;
reg S_ecc_r_d = 0;
reg S_data_eof = 0;
//-------------------------------------------
//function
//-------------------------------------------
//width calculation
function integer GETASIZE;
input integer a;
integer i;
begin
for(i=1;(2**i)<=a;i=i+1)
begin
end
GETASIZE = i;
end
endfunction
 
//big endian change to little endian
function [C_DWIDTH-1:0] F_data_inv;
input [C_DWIDTH-1:0] S_datain;
integer i;
begin
for(i=0;i<C_DWIDTH;i=i+1)
F_data_inv[i] = S_datain[C_DWIDTH-1-i];
end
endfunction
 
//-----------------------------------------
//check data alignment
//-----------------------------------------
always @(posedge I_clk)
begin
S_ecc_eof <= I_ecc_eof;
S_ecc_eof_d <= S_ecc_eof;
S_ecc_v <= I_ecc_v;
S_ecc <= I_ecc;
end
 
always @(posedge I_clk)
begin
if(S_ecc_eof)
begin
S_slr_cnt <= 'd0;
S_ov_id <= 1'b0;
end
else if(I_ecc_v)
begin
if(S_slr_cnt <= C_OVERFLOW_THRESHOLD)
begin
S_slr_cnt <= S_slr_cnt + C_ECCWIDTH;
S_ov_id <= 1'b0;
end
else
begin
S_slr_cnt <= S_slr_cnt - C_DIF;
S_ov_id <= 1'b1;
end
end
end
 
always @(posedge I_clk)
begin
if(S_ecc_eof_d)
S_data_slr <= 'd0;
else if(I_ecc_v || S_ecc_v)
begin
if(!S_ov_id)
S_data_slr <= (I_ecc<<S_slr_cnt) | S_data_slr;
else
S_data_slr <= (S_data_slr>>C_DWIDTH) | (I_ecc<<S_slr_cnt);
end
end
 
always @(posedge I_clk)
begin
if(S_ecc_v && S_ov_id)
S_data_tran <= F_data_inv(S_data_slr[0+:C_DWIDTH]);
else if(S_ecc_eof_d)
S_data_tran <= F_data_inv(S_data_slr[0+:C_DWIDTH]);
end
 
always @(posedge I_clk)
begin
S_data_tran_v <= (S_ecc_v && S_ov_id) || S_ecc_eof_d;
end
 
//--------------------------------------------------
//original data save
//--------------------------------------------------
always @(posedge I_clk)
begin
if(I_data_v)
S_data_ram[S_data_waddr[C_CHIP_NUM_WIDTH-1:0]] <= I_data;
S_dataout <= S_data_ram[S_ecc_raddr];
if(I_data_eof)
S_data_waddr <= 'd0;
else if(I_data_v && (S_data_waddr<C_CHIP_NUM))
S_data_waddr <= S_data_waddr + 'd1;
end
 
always @(posedge I_clk)
begin
if(S_data_tran_v)
S_ecc_ram[S_ecc_waddr] <= S_data_tran;
S_ecc_dout <= S_ecc_ram[S_ecc_raddr];
if(I_ecc_sof)
S_ecc_waddr <= 'd0;
else if(S_data_tran_v)
S_ecc_waddr <= S_ecc_waddr + 'd1;
end
 
always @(posedge I_clk)
begin
if(S_ecc_waddr == C_CHIP_NUM-1 && S_data_tran_v)
S_ecc_r <= 1'b1;
else if(S_ecc_raddr == C_CHIP_NUM-1)
S_ecc_r <= 1'b0;
S_ecc_r_d <= S_ecc_r;
end
 
always @(posedge I_clk)
begin
if(I_ecc_sof)
S_ecc_raddr <= 'd0;
else if(S_ecc_r)
S_ecc_raddr <= S_ecc_raddr + 'd1;
end
 
//---------------------------------------
//correct
//---------------------------------------
always @(posedge I_clk)
begin
O_data_sof <= S_ecc_raddr == 'd1;
S_data_eof <= S_ecc_raddr == C_CHIP_NUM-1;
O_data_eof <= S_data_eof;
end
 
always @(posedge I_clk)
begin
O_data <= S_dataout ^ S_ecc_dout;
O_data_v <= S_ecc_r_d;
end
 
endmodule
/bch_configurable/trunk/src/test_chian_search.v
0,0 → 1,174
///-----------------------------------------
///introduce:
///bch error position search in decoder
///author:jiml
///record:
///2015.1.31 initial
///-----------------------------------------
`timescale 1ns/100ps
module test_chian_search
#(
parameter C_PRIMPOLY_ORDER = 14, //order of eigenpolynomial
parameter C_COEF_NUM = 43, //correct threshold
parameter C_TOTALBIT_NUM = 8832, //total bit length include original and correct bits
parameter C_THREAD_NUM = 8, //parallel search thread
parameter C_PRIMPOLY = 15'h4443 //eigenpolynomial
)
(
input I_clk ,
input I_rst ,
input [C_PRIMPOLY_ORDER*C_COEF_NUM-1+C_PRIMPOLY_ORDER:0] I_coef , //error position polynomial
input I_coef_v , //error position polynomial available
output reg [C_THREAD_NUM-1:0] O_data , //check data
output reg O_data_v , //check data available
output reg O_data_sof , //check data frame start
output reg O_data_eof //check data frame end
);
 
//--------------------------------------------
//parameter and variable
//--------------------------------------------
localparam C_SEARCH_START = 2**C_PRIMPOLY_ORDER - 1 - C_TOTALBIT_NUM;
localparam C_CNT_LIMIT = (C_TOTALBIT_NUM-1)/C_THREAD_NUM;
localparam C_CNT_LIMIT_WIDTH = GETASIZE(C_CNT_LIMIT);
 
reg S_search_v = 0;
reg [C_PRIMPOLY_ORDER-1:0] S_const = 0;
reg S_search_v_d = 0;
reg S_search_v_2d = 0;
reg S_search_v_3d = 0;
reg [C_CNT_LIMIT_WIDTH:0] S_search_cnt = 0;
reg [C_PRIMPOLY_ORDER*C_COEF_NUM-1:0] S_var [C_THREAD_NUM-1:0];
reg [C_PRIMPOLY_ORDER*C_COEF_NUM-1+C_PRIMPOLY_ORDER:0] S_var_xor [C_THREAD_NUM-1:0];
reg [C_PRIMPOLY_ORDER-1:0] S_var_xor_result [C_THREAD_NUM-1:0];
reg [C_THREAD_NUM-1:0] S_err_id = 0;
wire [C_PRIMPOLY_ORDER*C_COEF_NUM-1:0] S_coef1;
wire integer S_coef2 [C_THREAD_NUM-1:0];
 
//--------------------------------------------
//function
//--------------------------------------------
//element multiplication in Galois Field
function [C_PRIMPOLY_ORDER-1:0] F_var_upgrade;
input [C_PRIMPOLY_ORDER-1:0] S_mult;
input integer S_times;
integer i;
reg [C_PRIMPOLY_ORDER-1:0] S_temp;
reg [C_PRIMPOLY_ORDER-1:0] S_temp2;
reg S_temp_upp;
begin
S_temp = S_mult;
for(i=0;i<S_times;i=i+1)
begin
S_temp_upp = S_temp[C_PRIMPOLY_ORDER-1];
S_temp2 = S_temp<<1;
S_temp = S_temp2 ^ (C_PRIMPOLY[C_PRIMPOLY_ORDER-1:0] & {C_PRIMPOLY_ORDER{S_temp_upp}});
end
F_var_upgrade = S_temp;
end
endfunction
 
//width calculation
function integer GETASIZE;
input integer a;
integer i;
begin
for(i=1;(2**i)<a;i=i+1)
begin
end
GETASIZE = i;
end
endfunction
 
///-------------------------------
///search
///-------------------------------
always @(posedge I_clk)
begin
if(I_rst)
S_search_v <= 'd0;
else if(I_coef_v)
S_search_v <= 'd1;
else if(S_search_cnt == C_CNT_LIMIT)
S_search_v <= 'd0;
end
 
always @(posedge I_clk)
begin
if(S_search_v)
S_search_cnt <= S_search_cnt + 'd1;
else
S_search_cnt <= 'd0;
end
 
always @(posedge I_clk)
begin
S_search_v_d <= S_search_v;
S_search_v_2d <= S_search_v_d;
S_search_v_3d <= S_search_v_2d;
end
 
always @(posedge I_clk)
begin
if(I_coef_v)
S_const <= I_coef[C_PRIMPOLY_ORDER-1:0];
end
 
assign S_coef1 = I_coef_v ? I_coef[C_PRIMPOLY_ORDER+:C_PRIMPOLY_ORDER*C_COEF_NUM] : S_var[C_THREAD_NUM-1];
 
genvar S_k;
integer k,kk;
generate
for(S_k=0;S_k<C_THREAD_NUM;S_k=S_k+1) //parallel search
begin:process
 
assign S_coef2[S_k] = I_coef_v ? C_SEARCH_START : (S_k+1);
 
always @(posedge I_clk)
begin
for(k=0;k<C_COEF_NUM;k=k+1)
S_var[S_k][C_PRIMPOLY_ORDER*k+:C_PRIMPOLY_ORDER] <= F_var_upgrade(S_coef1[C_PRIMPOLY_ORDER*k+:C_PRIMPOLY_ORDER],S_coef2[S_k]*(k+1));
end
 
always @(*)
begin
S_var_xor[S_k][0+:C_PRIMPOLY_ORDER] = S_const;
end
 
always @(*)
begin
for(kk=0;kk<C_COEF_NUM;kk=kk+1)
S_var_xor[S_k][C_PRIMPOLY_ORDER*(kk+1)+:C_PRIMPOLY_ORDER] = I_coef_v ? 'd0 : (S_var_xor[S_k][C_PRIMPOLY_ORDER*(kk)+:C_PRIMPOLY_ORDER] ^ S_var[S_k][C_PRIMPOLY_ORDER*kk+:C_PRIMPOLY_ORDER]);
end
 
always @(posedge I_clk)
begin
S_var_xor_result[S_k] <= S_var_xor[S_k][C_PRIMPOLY_ORDER*C_COEF_NUM+:C_PRIMPOLY_ORDER];
end
 
always @(posedge I_clk)
begin
S_err_id[S_k] <= (S_var_xor_result[S_k] == 'd0); //zero means error position
end
 
end
endgenerate
 
//-------------------------------------------
//check data output
//-------------------------------------------
always @(posedge I_clk)
begin
O_data <= S_err_id;
O_data_v <= S_search_v_3d;
end
 
always @(posedge I_clk)
begin
O_data_sof <= S_search_v_3d && (!O_data_v);
O_data_eof <= (!S_search_v_2d) && S_search_v_3d;
end
 
endmodule
 
 
/bch_configurable/trunk/src/test_bch_encode.v
0,0 → 1,226
///-----------------------------------------
///introduce:
///bch encoder
///author:jiml
///record:
///2015.1.31 initial
///-----------------------------------------
`timescale 1ns/100ps
module test_bch_encode
#(
parameter C_DWIDTH = 128, //input data width
parameter C_COEF_NUM = 43, //correct threshold
parameter C_PRIMPOLY_ORDER = 14, //order of eigenpolynomial
parameter C_PRIM_POLY = 15'h4443 //eigenpolynomial
)
(
input I_clk ,
input I_rst ,
input [C_DWIDTH-1:0] I_data , //input data
input I_data_v , //input data available
input I_data_sof , //input data frame start
input I_data_eof , //input data frame end
output reg [C_DWIDTH-1:0] O_data , //output data
output reg O_data_v , //output data available
output reg O_data_sof , //output data frame start
output reg O_data_eof //output data frame end
);
 
///----------------------------------------
///parameter and variable
///----------------------------------------
localparam C_REG_LEN = C_COEF_NUM*C_PRIMPOLY_ORDER;
localparam C_GEN_WIDTH = F_TOTAL_NUM(0);
localparam C_ECC_PERIOD = F_DIV(C_GEN_WIDTH,C_DWIDTH);
localparam C_CNT_WIDTH = GETASIZE(C_ECC_PERIOD);
localparam C_GENPOLY = F_GEN_POLY(0);
 
reg [C_GEN_WIDTH-1:0] S_reg = 0;
reg [C_CNT_WIDTH-1:0] S_ecc_cnt = 0;
reg S_ecc_v = 0;
 
//---------------------------------------------
//function
//---------------------------------------------
//calculate length of encode polynomial
function integer F_TOTAL_NUM;
input red;
integer i,j;
integer temp;
reg [2**C_PRIMPOLY_ORDER-2:0] S_flag;
begin
F_TOTAL_NUM = 0;
for(i=0;i<C_COEF_NUM;i=i+1)
begin
S_flag = 0;
for(j=1;j<=C_PRIMPOLY_ORDER;j=j+1)
begin
temp = (2*i+1)*(2**(j-1));
while(temp > 2**C_PRIMPOLY_ORDER-2)
temp = temp - (2**C_PRIMPOLY_ORDER-1);
if(!S_flag[temp])
begin
S_flag[temp] = 1;
F_TOTAL_NUM=F_TOTAL_NUM+1;
end
end
end
end
endfunction
 
//integer division
function integer F_DIV;
input integer S_DIVIDEND;
input integer S_DIVIDER;
begin
F_DIV = (S_DIVIDEND-1)/S_DIVIDER;
end
endfunction
 
//polynomial multiplication in Galois Field
function [C_PRIMPOLY_ORDER-1:0] F_mult;
input [C_PRIMPOLY_ORDER-1:0] S_data1;
input [C_PRIMPOLY_ORDER-1:0] S_data2;
reg [C_PRIMPOLY_ORDER*2-1:0] S_temp;
integer i;
begin
S_temp = 0;
F_mult = 0;
for(i=0;i<C_PRIMPOLY_ORDER;i=i+1)
begin
S_temp = S_temp ^ ({(C_PRIMPOLY_ORDER*2){S_data1[i]}} & (S_data2<<i));
end
for(i=0;i<C_PRIMPOLY_ORDER*2;i=i+1)
begin
F_mult = {F_mult[C_PRIMPOLY_ORDER-2:0],S_temp[C_PRIMPOLY_ORDER*2-1-i]} ^ (C_PRIM_POLY[C_PRIMPOLY_ORDER-1:0] & {C_PRIMPOLY_ORDER{F_mult[C_PRIMPOLY_ORDER-1]}});
end
end
endfunction
 
//element generation in Galois Field
function [C_PRIMPOLY_ORDER-1:0] F_gen;
input [C_PRIMPOLY_ORDER-1:0] S_init;
input integer S_times;
integer i;
begin
F_gen = S_init;
for(i=0;i<S_times;i=i+1)
begin
if(F_gen[C_PRIMPOLY_ORDER-1])
F_gen = (F_gen<<1) ^ C_PRIM_POLY[C_PRIMPOLY_ORDER-1:0];
else
F_gen = (F_gen<<1);
end
end
endfunction
 
//encode polynomial generation
function [C_GEN_WIDTH:0] F_GEN_POLY;
input red;
integer i,j,k;
integer pointer;
reg [2**C_PRIMPOLY_ORDER-2:0] S_flag;
reg [C_PRIMPOLY_ORDER-1:0] S_temp [C_GEN_WIDTH:0]; //every reg is C_PRIMPOLY_ORDER width, represent a element
reg [C_PRIMPOLY_ORDER-1:0] S_temp2;
begin
F_GEN_POLY = 0;
for(i=0;i<=C_PRIMPOLY_ORDER;i=i+1)
S_temp[i] = C_PRIM_POLY[i]; //least C_PRIMPOLY_ORDER bits are eigenpolynomial
for(i=C_PRIMPOLY_ORDER+1;i<=C_GEN_WIDTH;i=i+1)
S_temp[i] = 0;
for(i=1;i<C_COEF_NUM;i=i+1) //encode polynomial include C_COEF_NUM polynomials
begin
S_flag = 0;
for(j=1;j<=C_PRIMPOLY_ORDER;j=j+1) //each polynomial have at most C_PRIMPOLY_ORDER element
begin
pointer = (2*i+1)*(2**(j-1));
while(pointer>(2**C_PRIMPOLY_ORDER-2))
pointer = pointer - (2**C_PRIMPOLY_ORDER-1);
if(!S_flag[pointer]) //flag is a marker to indicate element exists or not
begin
S_flag[pointer] = 1;
S_temp2 = F_gen(1,pointer);
for(k=C_GEN_WIDTH-1;k>0;k=k-1) //each polynomial have at most C_PRIMPOLY_ORDER multiplication
begin
S_temp[k]= F_mult(S_temp[k],S_temp2) ^ S_temp[k-1]; //all the reg need to shift in each multiplication
end
S_temp[0] = F_mult(S_temp[0],S_temp2);
S_temp[C_GEN_WIDTH] = S_temp[C_GEN_WIDTH-1];
end
end
end
for(i=0;i<C_GEN_WIDTH;i=i+1)
F_GEN_POLY[i] = (S_temp[i] == 1); //finally the S_temp should only be 1 or 0
end
endfunction
 
//width calculation
function integer GETASIZE;
input integer a;
integer i;
begin
for(i=1;(2**i)<=a;i=i+1)
begin
end
GETASIZE = i;
end
endfunction
 
//polynomial multiplication between encode polynomial and input data
function [C_GEN_WIDTH-1:0] F_reg_update;
input [C_GEN_WIDTH-1:0] S_reg_ori;
input [C_DWIDTH-1:0] S_data;
integer i;
reg S_temp1;
begin
F_reg_update = S_reg_ori;
for(i=0;i<C_DWIDTH;i=i+1)
begin
S_temp1 = F_reg_update[C_GEN_WIDTH-1] ^ S_data[C_DWIDTH-1-i];
F_reg_update[C_GEN_WIDTH-1:0] = {F_reg_update[C_GEN_WIDTH-2:0],1'b0} ^ ({C_GEN_WIDTH{S_temp1}} & C_GENPOLY[C_GEN_WIDTH-1:0]);
end
end
endfunction
 
//-----------------------------------------------
//encode
//-----------------------------------------------
always @(posedge I_clk)
begin
if(I_data_v)
S_reg <= F_reg_update(S_reg,I_data);
else if(S_ecc_v)
S_reg <= S_reg << C_DWIDTH;
end
 
//output counter
always @(posedge I_clk)
begin
if(S_ecc_v)
S_ecc_cnt <= S_ecc_cnt + 'd1;
else
S_ecc_cnt <= 'd0;
end
 
always @(posedge I_clk)
begin
if(I_data_eof && I_data_v)
S_ecc_v <= 1'b1;
else if(S_ecc_cnt == C_ECC_PERIOD && S_ecc_v)
S_ecc_v <= 1'b0;
end
 
//data out
always @(posedge I_clk)
begin
if(S_ecc_v)
O_data <= (C_GEN_WIDTH >= C_DWIDTH) ? S_reg[C_GEN_WIDTH-1-:C_DWIDTH] : (S_reg << (C_DWIDTH-C_GEN_WIDTH));
else
O_data <= I_data;
O_data_v <= I_data_v || S_ecc_v;
O_data_sof <= I_data_sof;
O_data_eof <= (S_ecc_cnt == C_ECC_PERIOD) && S_ecc_v;
end
 
endmodule
/bch_configurable/trunk/src/test_bch_bm.v
0,0 → 1,381
///-----------------------------------------
///introduce:
///bch error position polynomial calculate by bm algorithm
///author:jiml
///record:
///2015.1.31 initial
///2015.2.2 S_syndrome modified from parallel to serial
///-----------------------------------------
`timescale 1ns/100ps
module test_bch_bm
#(
parameter C_PRIMPOLY_ORDER = 14, //order of eigenpolynomial
parameter C_COEF_NUM = 43, //correct threshold
parameter C_PRIMPOLY = 15'h4443 //eigenpolynomial
)
(
input I_clk ,
input I_rst ,
input [C_PRIMPOLY_ORDER*C_COEF_NUM-1:0] I_syndrome , //syndrome cascaded
input I_syndrome_v , //syndrome available
output reg [C_PRIMPOLY_ORDER*C_COEF_NUM-1+C_PRIMPOLY_ORDER:0] O_err_pos , //error position polynomial
(* MAX_FANOUT=30 *)output reg O_err_pos_v //error position polynomial available
);
 
//--------------------------------
//parameter and variable
//--------------------------------
localparam C_CYCLE = GETASIZE(C_COEF_NUM);
integer i,j,jj;
reg [C_CYCLE+1:0] S_syndrome_v_slr = 0;
reg S_syndrome_v_all = 0;
reg [C_PRIMPOLY_ORDER-1:0] S_syndrome [2*C_COEF_NUM-1:0];
reg S_syndrome_v = 0;
reg S_syndrome_v_d = 0;
reg S_syndrome_v_2d = 0;
reg S_syndrome_v_3d = 0;
reg S_bm_cnt2_d = 0;
reg [C_PRIMPOLY_ORDER*C_COEF_NUM-1:0] S_syndrome_seq = 0;
reg [C_PRIMPOLY_ORDER*C_COEF_NUM-1:0] S_syndrome_seq2 = 0;
reg [C_PRIMPOLY_ORDER-1:0] S_syndrome_new = 0;
reg [C_PRIMPOLY_ORDER-1:0] S_syndrome_seq_sel = 0;
reg [C_PRIMPOLY_ORDER-1:0] S_syndrome_new_d = 0;
reg [C_PRIMPOLY_ORDER*(C_COEF_NUM+1)-1:0] S_syndrome_slr = 0;
(* MAX_FANOUT=8 *)reg [C_PRIMPOLY_ORDER-1:0] S_poly_v [C_COEF_NUM-1+1:0];
reg [C_PRIMPOLY_ORDER-1:0] S_poly_deltav [C_COEF_NUM-1+1:0];
(* MAX_FANOUT=16 *)reg [C_PRIMPOLY_ORDER-1:0] S_poly_k [C_COEF_NUM-1+2:0];
(* MAX_FANOUT=50 *)reg [C_PRIMPOLY_ORDER-1:0] S_delta;
reg [C_PRIMPOLY_ORDER-1:0] S_d_uint [C_COEF_NUM-1+1:0];
(* MAX_FANOUT=36 *)reg [C_PRIMPOLY_ORDER-1:0] S_d;
wire [C_PRIMPOLY_ORDER-1:0] S_d_xor [C_COEF_NUM+1:0];
reg [C_PRIMPOLY_ORDER-1:0] S_mult_result [C_COEF_NUM-1:0];
reg S_bm_v = 0;
reg S_bm_v_d = 0;
reg S_bm_v_2d = 0;
(* MAX_FANOUT=36 *)reg [1:0] S_bm_cnt = 0;
reg [C_CYCLE-1:0] S_bm_cnt2 = 0;
reg S_d_nozero = 0;
reg S_kdelta_v = 0;
reg [C_COEF_NUM-1:0] S_poly_v_exist = 0;
reg S_poly_v_exist_all = 0;
reg S_syndrome_ram_we = 0;
reg [C_PRIMPOLY_ORDER-1:0] S_syndrome_ram [2**C_CYCLE-1:0];
reg [C_CYCLE-1:0] S_syndrome_waddr = 0;
reg [C_CYCLE-1:0] S_syndrome_raddr = 0;
reg [C_PRIMPOLY_ORDER-1:0] S_syndrome_ram_dout = 0;
reg S_k_v = 0;
 
 
///----------------------------
///function
///----------------------------
//width calculation
function integer GETASIZE;
input integer a;
integer i;
begin
for(i=1;(2**i)<=a;i=i+1)
begin
end
GETASIZE = i;
end
endfunction
 
//two elements in Galois Field multiplication
function [C_PRIMPOLY_ORDER-1:0] F_var_upgrade;
input [C_PRIMPOLY_ORDER-1:0] S_mult1;
input [C_PRIMPOLY_ORDER-1:0] S_mult2;
integer i;
reg [C_PRIMPOLY_ORDER-1:0] S_temp1;
reg [C_PRIMPOLY_ORDER-1:0] S_temp2;
begin
F_var_upgrade = {C_PRIMPOLY_ORDER{1'b0}};
for(i=0;i<C_PRIMPOLY_ORDER;i=i+1)
begin
S_temp1 = {C_PRIMPOLY_ORDER{F_var_upgrade[C_PRIMPOLY_ORDER-1]}} & C_PRIMPOLY[C_PRIMPOLY_ORDER-1:0];
S_temp2 = {C_PRIMPOLY_ORDER{S_mult1[C_PRIMPOLY_ORDER-1-i]}} & S_mult2;
F_var_upgrade = {F_var_upgrade[C_PRIMPOLY_ORDER-2:0],1'b0} ^ S_temp1 ^ S_temp2;
end
end
endfunction
 
///----------------------------
///syndrome
///----------------------------
always @(posedge I_clk)
begin
S_syndrome_v_slr <= {S_syndrome_v_slr[C_CYCLE:0],I_syndrome_v};
S_syndrome_v_all <= |S_syndrome_v_slr;
S_syndrome_v <= I_syndrome_v;
S_syndrome_v_d <= S_syndrome_v;
S_syndrome_v_2d <= S_syndrome_v_d;
S_syndrome_v_3d <= S_syndrome_v_2d;
S_bm_cnt2_d <= S_bm_cnt2[0];
end
 
//an odd order syndrome used to calculate even order syndrome
always @(posedge I_clk)
begin
if(I_syndrome_v)
S_syndrome_seq <= I_syndrome;
else if((S_bm_cnt == 'd2 && S_bm_cnt2_d) || S_syndrome_v)
S_syndrome_seq <= S_syndrome_seq>>C_PRIMPOLY_ORDER;
end
 
//every iteration need an odd order syndrome
always @(posedge I_clk)
begin
if(I_syndrome_v)
S_syndrome_seq2 <= I_syndrome;
else if(S_bm_cnt == 'd1)
S_syndrome_seq2 <= S_syndrome_seq2>>C_PRIMPOLY_ORDER;
end
 
//even order syndrome generation by multiplication, multiplier is odd order or even order
always @(posedge I_clk)
begin
S_syndrome_new <= F_var_upgrade(S_syndrome_seq_sel,S_syndrome_seq_sel);
end
 
//multiplier selection, S_syndrome_seq[C_PRIMPOLY_ORDER-1:0] is odd order, and S_syndrome_ram_dout is even order
always @(posedge I_clk)
begin
if(I_syndrome_v)
S_syndrome_seq_sel <= I_syndrome[C_PRIMPOLY_ORDER-1:0];
else if(S_syndrome_v_3d)
S_syndrome_seq_sel <= S_syndrome_new_d;
else if(S_bm_cnt == 'd2)
begin
S_syndrome_seq_sel <= (S_bm_cnt2_d) ? S_syndrome_seq[C_PRIMPOLY_ORDER-1:0] : S_syndrome_ram_dout;
end
end
 
//every iteration need an even order syndrome
always @(posedge I_clk)
begin
if(S_bm_cnt == 'd1 || S_syndrome_v_d)
S_syndrome_new_d <= S_syndrome_new;
end
 
//even order syndrome are saved into ram for further even order syndrome calculation
always @(posedge I_clk)
begin
S_syndrome_ram_we <= (S_bm_cnt == 'd1) && S_bm_v_2d;
if(S_syndrome_ram_we)
S_syndrome_ram[S_syndrome_waddr] <= S_syndrome_new_d;
if(I_syndrome_v)
S_syndrome_waddr <= 'd0;
else if(S_syndrome_ram_we)
S_syndrome_waddr <= S_syndrome_waddr + 'd1;
S_syndrome_ram_dout <= S_syndrome_ram[S_syndrome_raddr];
if(I_syndrome_v)
S_syndrome_raddr <= 'd0;
else if((S_bm_cnt == 'd1) && (!S_bm_cnt2_d) && S_bm_v_2d)
S_syndrome_raddr <= S_syndrome_raddr + 'd1;
end
 
//syndrome update every iteration
always @(posedge I_clk)
begin
if(I_syndrome_v)
begin
S_syndrome_slr <= 'd0;
S_syndrome_slr[C_PRIMPOLY_ORDER-1:0] <= I_syndrome[C_PRIMPOLY_ORDER-1:0];
S_syndrome_slr[2*C_PRIMPOLY_ORDER-1:C_PRIMPOLY_ORDER] <= 'd1;
end
else if(S_bm_cnt == 'd2)
begin
S_syndrome_slr <= S_syndrome_slr<<(C_PRIMPOLY_ORDER*2);
S_syndrome_slr[0+:C_PRIMPOLY_ORDER*2] <= {S_syndrome_new_d,S_syndrome_seq2[C_PRIMPOLY_ORDER-1:0]};
end
end
 
///-------------------------------
///bm
///-------------------------------
///bm algorithm
///v(0)=1,k(0)=1,delta(-2)=1
///for k=0:1:C_COEF_NUM-1
///v(2k+2)=delta(2k-2)*v(2k)+d(2k)*k(2k)*z
///k(2k+2)=z^2*k(2k) if d(2k) == 0 or if deg v(2k)>k
///k(2k+2)=z*v(2k) if d(2k) != 0 and if deg v(2k)<=k
///delta(2k)=delta(2k-2) if d(2k) == 0 or if deg v(2k)>k
///delta(2k)=d(2k) if d(2k) != 0 and if deg v(2k)<=k
 
always @(posedge I_clk)
begin
if(S_syndrome_v)
S_bm_v <= 'b1;
else if(S_bm_cnt2 == C_COEF_NUM)
S_bm_v <= 'b0;
end
 
always @(posedge I_clk)
begin
O_err_pos_v <= (!S_bm_v) && S_bm_v_d;
end
 
always @(posedge I_clk)
begin
if(S_bm_v)
begin
if(S_bm_cnt=='d2)
S_bm_cnt <= 'd0;
else
S_bm_cnt <= S_bm_cnt + 'd1;
end
else
S_bm_cnt <= 'd0;
end
 
always @(posedge I_clk)
begin
if(S_bm_v)
begin
if(S_bm_cnt=='d1)
S_bm_cnt2 <= S_bm_cnt2 + 'd1;
end
else
S_bm_cnt2 <= 'd0;
end
 
//variable d generation
always @(posedge I_clk)
begin
if(S_bm_cnt[1:0]=='d1)
S_d <= S_d_xor[C_COEF_NUM+1];
end
 
always @(posedge I_clk)
begin
S_d_nozero <= (S_d != 'd0);
S_kdelta_v <= (S_bm_cnt[1:0]=='d2);
S_k_v <= (S_bm_cnt[1:0]=='d1);
S_bm_v_d <= S_bm_v;
S_bm_v_2d <= S_bm_v_d;
if(S_bm_cnt[1:0]=='d1)
S_poly_deltav[C_COEF_NUM] <= F_var_upgrade(S_delta,S_poly_v[C_COEF_NUM]);
end
 
assign S_d_xor[0] = 0;
 
genvar S_jj;
generate
for(S_jj=0;S_jj<=C_COEF_NUM;S_jj=S_jj+1)
begin:bm2
 
assign S_d_xor[S_jj+1] = S_d_xor[S_jj] ^ S_d_uint[S_jj];
 
always @(posedge I_clk)
begin
if(S_bm_cnt[1:0]=='d0)
begin
S_d_uint[S_jj] <= F_var_upgrade(S_syndrome_slr[S_jj*C_PRIMPOLY_ORDER+:C_PRIMPOLY_ORDER],S_poly_v[S_jj]);
end
end
end
endgenerate
 
 
genvar S_j;
generate
for(S_j=0;S_j<C_COEF_NUM;S_j=S_j+1)
begin:bm
 
always @(posedge I_clk)
begin
if(S_bm_cnt[1:0]=='d1)
S_poly_deltav[S_j] <= F_var_upgrade(S_delta,S_poly_v[S_j]);
end
 
//variable v generation
always @(posedge I_clk)
begin
if(I_syndrome_v)
S_poly_v[S_j+1] <= 'd0;
else if(S_bm_cnt[1:0]=='d2)
S_poly_v[S_j+1] <= S_poly_deltav[S_j+1] ^ F_var_upgrade(S_poly_k[S_j],S_d);
end
 
always @(posedge I_clk)
begin
S_poly_v_exist[S_j] <= (S_poly_v[S_j] != 'd0) && (S_j > S_bm_cnt2);
end
 
always @(posedge I_clk)
begin
O_err_pos[C_PRIMPOLY_ORDER*S_j+C_PRIMPOLY_ORDER-1-:C_PRIMPOLY_ORDER] <= S_poly_v[S_j];
end
 
end
endgenerate
 
always @(posedge I_clk)
begin
S_poly_v_exist_all <= |S_poly_v_exist;
O_err_pos[C_PRIMPOLY_ORDER*C_COEF_NUM+C_PRIMPOLY_ORDER-1-:C_PRIMPOLY_ORDER] <= S_poly_v[C_COEF_NUM];
end
 
always @(posedge I_clk)
begin
if(I_syndrome_v)
S_poly_v[0] <= 'd1;
else if(S_bm_cnt[1:0]=='d2)
S_poly_v[0] <= S_poly_deltav[0];
end
 
//variable k generation
genvar S_k;
generate
for(S_k=1;S_k<C_COEF_NUM;S_k=S_k+1)
begin:think
always @(posedge I_clk)
begin
if(I_syndrome_v)
S_poly_k[S_k+1] <= 'd0;
else if(S_k_v)
begin
if(!((S_d != 'd0) && !S_poly_v_exist_all))
S_poly_k[S_k+1] <= S_poly_k[S_k-1];
else
S_poly_k[S_k+1] <= S_poly_v[S_k];
end
end
end
endgenerate
 
always @(posedge I_clk)
begin
if(I_syndrome_v)
begin
S_poly_k[0] <= 'd1;
S_poly_k[1] <= 'd0;
S_poly_k[C_COEF_NUM+1] <= 'd0;
end
else if(S_k_v)
begin
if(!((S_d != 'd0) && !S_poly_v_exist_all))
begin
S_poly_k[0] <= 'd0;
S_poly_k[1] <= 'd0;
S_poly_k[C_COEF_NUM+1] <= S_poly_k[C_COEF_NUM-1];
end
else
begin
S_poly_k[1] <= S_poly_v[0];
S_poly_k[0] <= 'd0;
S_poly_k[C_COEF_NUM+1] <= S_poly_v[C_COEF_NUM];
end
end
end
 
//variable delta generation
always @(posedge I_clk)
begin
if(I_syndrome_v)
S_delta <= 'd1;
else if(S_kdelta_v && S_d_nozero && !S_poly_v_exist_all)
S_delta <= S_d;
end
 
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.