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

Subversion Repositories bch_configurable

[/] [bch_configurable/] [trunk/] [src/] [test_bch_syndrome.v] - Rev 2

Compare with Previous | Blame | View Log

///-----------------------------------------
///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

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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