//look-up table for GF(256) elements generated by p(x)= 1 + x^2 + x^3 + x^4 + x^8
module GF_256_elements (
						reset,
						read_alpha_inverse,
						gf_table_ready,
						alpha_inverse,
						clock,
						decode_strobe,
						err_loc_derivativative,
						);
parameter width = 5;

output reg gf_table_ready,decode_strobe;
output reg [7:0] alpha_inverse;

input read_alpha_inverse,clock,reset;
input [7:0] err_loc_derivativative;

reg [7:0] alpha_to[0:255];
reg [7:0] mask;
reg [7:0] addr,inverse_addr;
reg [0:8] prim_polyn;
reg gf_flag;

integer i,j,k;

always @(posedge reset)
begin
gf_flag=1'b0;
prim_polyn= 9'b101110001; //primitive polynomial p(x)
mask=8'd1;
alpha_to[8]=8'd0;
for(i=0;i<8;i=i+1)
begin
alpha_to[i] = mask;
if(prim_polyn[i] != 1'b0) //if prim_polyn[i]==1 then alpha_to [i] occurs in polynomial rep. of alpha_to[8]
	alpha_to[8]= alpha_to[8]^mask; //generate alpha_to[8]
mask = mask << 1; // left-shift by one bit
end
mask = 8'b10000000;//mask >> 1;
for(i=9; i<255;i=i+1)
	begin
		if(alpha_to[i-1] >= mask)
			alpha_to[i] = alpha_to[8]^((alpha_to[i-1]^mask)<<1);
		else
			alpha_to[i] = alpha_to[i-1]<<1;
	end
alpha_to[255]=alpha_to[0];
gf_flag=1'b1;
decode_strobe=gf_flag;
end
	
always @(posedge clock)
begin
gf_table_ready = 1'b0;
if((gf_flag==1'b1)&&(reset==1'b0))
begin
	if(read_alpha_inverse==1'b1)//sends the inverse of the recieved derivatives
		begin
			gf_table_ready = 1'b0;
			for(j=0; j<255;j=j+1)
			begin
			 if (err_loc_derivativative==alpha_to[j])
				begin
				inverse_addr = 8'd255 - j;
				alpha_inverse = alpha_to[inverse_addr];
				gf_table_ready = 1'b1;
				end
			else if (err_loc_derivativative== 8'd0)
				begin
				alpha_inverse = 8'd0;
				gf_table_ready = 1'b1;
				end
			end
		end
end
else if(reset==1'b1)
	begin
	gf_table_ready = 1'b0;
	end
end
endmodule
