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

Subversion Repositories reed_solomon_coder

[/] [reed_solomon_coder/] [trunk/] [forney.v] - Rev 6

Compare with Previous | Blame | View Log

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
//Company: University of Hamburg, University of Kiel, Germany
// Engineer: Cagil Gümüs, Andreas Bahr
// 
// Create Date:    13:01:04 01/04/2016 
// Design Name: 
// Module Name: Forney
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: By using the error locations, error locator algorithm and syndromes,this module finds the magnitude of errors.
// It uses the Forney Algorithm. Error evaluator polynomial is found as well as formal derivative of error locator polynomial. 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module forney(
    	input	wire			clk,
		input wire 			reset,
		input wire [3:0] 	errorlocation_1, 
		input wire [3:0] 	errorlocation_2,
		output reg [3:0] 	error_magnitude_1,
		output reg [3:0] 	error_magnitude_2,
		input wire [15:0] errorlocator,
		input wire [3:0] 	syndrome_1,
		input wire [3:0] 	syndrome_2,
		input wire [3:0] 	syndrome_3,
		input wire [3:0] 	syndrome_4,
		input wire			go,
		input wire 			job_done,
		output reg			ready
	 );
 
reg [2:0] state;
 
reg [19:0] product1;
reg [19:0] product2;
 
reg [19:0] errorevaluator_polynomial;
reg [11:0] locatorderivative ;
 
reg [3:0] product1_1 , product1_2 , product2_1 , product2_2 , root1_4, root1_3 , root1_2, root1_1, root2_4, root2_3 , root2_2, root2_1;
 
 
 
parameter [2:0] IDLE 						= 3'b000,  // Idle state where it waits for "go" signal to go high
					 CALCULATE					= 3'b001,  // It calculates the error evaluator polynomial, derivative of error locator polynomial and as well as roots which go inside these polynomial
					 PREPARE						= 3'b011,  // It places the error location into the error evaluator and derivative of error locator. These two things are called product1 and product2 respectively.
					 DIVIDE						= 3'b111,  // It divides product1 with product2 to get the final result for both error locations
					 FINISH						= 3'b110;  // Ready goes high.
 
 
 
always@(posedge clk or negedge reset)
begin
 
	if(!reset)
		begin
 
			state 							<= IDLE; 
			ready 							<= 0; 
 
			errorevaluator_polynomial 	<= 0; 
			error_magnitude_1				<= 0;
			error_magnitude_2				<= 0;
 
		end	
	else
		begin
 
			case(state)
 
				IDLE:
					begin
 
						ready <= 0;
 
						error_magnitude_1 	<= 0; // Put all output to 0 since new data is incoming
						error_magnitude_2 	<= 0;
 
						root1_4 					<= 0; // First error location to the power of minus 4
						root1_3 					<= 0; // First error location to the power of minus 3
						root1_2 					<= 0; // First error location to the power of minus 2
						root1_1					<= 0; // First error location to the power of minus 1
						root2_4 					<= 0; // Second error location to the power of minus 4
						root2_3 					<= 0; // Second error location to the power of minus 3
						root2_2 					<= 0; // Second error location to the power of minus 2
						root2_1 					<= 0; // Second error location to the power of minus 1
 
 
						root1_1 <= GFInverse_fn(errorlocation_1);
						root2_1 <= GFInverse_fn(errorlocation_2);
 
						if(go)
							state <= CALCULATE;
						else
							state <= IDLE; 
 
					end
 
 
				CALCULATE:
					begin
 
 
						locatorderivative  	<= 0;
 
 
						// Error evaluator polynomial = (1+S(x))*ErrorLocatorPolynomial modx^5
						errorevaluator_polynomial <= {	GFMult_fn(syndrome_1,errorlocator[15:12])	^ 	GFMult_fn(syndrome_2,errorlocator[11:8])	^	GFMult_fn(syndrome_3,errorlocator[7:4])	^ GFMult_fn(syndrome_4,errorlocator[3:0]),   //x^4
																	GFMult_fn(syndrome_1,errorlocator[11:8])	^ 	GFMult_fn(syndrome_2,errorlocator[7:4])	^	GFMult_fn(syndrome_3,errorlocator[3:0]) 	^ errorlocator[15:12] ,							//x^3
																	GFMult_fn(syndrome_1,errorlocator[7:4]) 	^ 	GFMult_fn(syndrome_2,errorlocator[3:0])	^ 	errorlocator[11:8],																							//x^2
																	GFMult_fn(syndrome_1,errorlocator[3:0])	^	errorlocator[7:4],																																						//x^1
																 	errorlocator[3:0] } ;																																					//x^0
 
 
						locatorderivative [3:0]			<= errorlocator[7:4] ;
 
						locatorderivative [7:4]			<= errorlocator[11:8] 	^ 	errorlocator[11:8] ;
 
						locatorderivative [11:8]		<= errorlocator[15:12]	^	errorlocator[15:12]	^	errorlocator[15:12] ;
 
 
						// Prepares the powers of error locations which will go inside the polynomials soon
						root1_4 <= GFMult_fn(GFMult_fn(root1_1,root1_1)	,	GFMult_fn(root1_1,root1_1));				
						root1_3 <= GFMult_fn(GFMult_fn(root1_1,root1_1)	,	root1_1);			
						root1_2 <= GFMult_fn(root1_1,root1_1);
 
						root2_4 <= GFMult_fn(	GFMult_fn(root2_1,root2_1)	,	GFMult_fn(root2_1,root2_1)	);
						root2_3 <= GFMult_fn(	GFMult_fn(root2_1,root2_1)	,	root2_1	);				
						root2_2 <= GFMult_fn(	root2_1	,	root2_1	);
 
						state <= PREPARE;
 
					end 
 
				PREPARE:
					begin
 
						product1_2 <= GFMult_fn(root1_2,locatorderivative[11:8])^ GFMult_fn(root1_1,locatorderivative[7:4]) ^ locatorderivative[3:0] ;
						product2_2 <= GFMult_fn(root2_2,locatorderivative[11:8])^ GFMult_fn(root2_1,locatorderivative[7:4]) ^ locatorderivative[3:0] ;
 
 
						product1_1 <=	GFMult_fn( GFMult_fn(root1_4,errorevaluator_polynomial[19:16]) ^ GFMult_fn(root1_3,errorevaluator_polynomial[15:12]) ^ GFMult_fn(root1_2,errorevaluator_polynomial[11:8]) ^
												GFMult_fn(root1_1,errorevaluator_polynomial[7:4]) ^ errorevaluator_polynomial[3:0] , errorlocation_1 ) ;				 				  
						product2_1 <= 	GFMult_fn(GFMult_fn(root2_4,errorevaluator_polynomial[19:16]) ^ GFMult_fn(root2_3,errorevaluator_polynomial[15:12]) ^ GFMult_fn(root2_2,errorevaluator_polynomial[11:8]) ^
												GFMult_fn(root2_1,errorevaluator_polynomial[7:4]) ^ errorevaluator_polynomial[3:0] , errorlocation_2 ) ;
 
						state <= DIVIDE;
 
					end
 
 
				DIVIDE:
					begin
 
						error_magnitude_1 <= GFMult_fn(product1_1,GFInverse_fn(product1_2));
 
						error_magnitude_2 <= GFMult_fn(product2_1,GFInverse_fn(product2_2));
 
						state <= FINISH;
 
					end
 
				FINISH:
					begin
 
						ready <= 1 ; // Process is finished now go back to IDLE and wait for go signal.
 
						if(job_done)
							state <= IDLE; 
						else
							state <= FINISH; 
 
					end
 
				default: state <= IDLE;
 
 
			endcase
 
		end
end
 
 
 
//// GALOIS FIELD OPERATION FUNCTIONS // Multiplication and Inversion on GF(16)
// For implementation of the GF(2^4) Multiplier function GFMult_fn, please refer to: 
// Design of a Synthesisable Reed-Solomon ECC Core
// David Banks
// Publishing Systems and Solutions Laboratory
// HP Laboratories Bristol
// https://www.hpl.hp.com/techreports/2001/HPL-2001-124.html
//
// parameter WIDTH = 4;
// parameter PRIMITIVE = 5'b10011;
 
// function [...]GFMult_fn;
// [...]
// [...]
// [...]
// endfunction
 
parameter WIDTH = 4;
parameter PRIMITIVE = 5'b10011;
 
 
function [WIDTH - 1 : 0] GFMult_fn;
 
	input [WIDTH - 1 : 0] a;
	input [WIDTH - 1 : 0] b;
 
	reg [WIDTH * WIDTH - 1 : 0] andarray;
	reg [WIDTH * 2 - 2 : 0] product;
 
	reg [WIDTH - 1 : 0] tmp;
 
	integer i,j,prbs ;
 
	begin
 
		andarray = 0;
		product = 0;
		tmp = 0;
 
		for (i = 0; i < WIDTH; i = i + 1)
			for (j = 0; j < WIDTH; j = j + 1)
				andarray[i * WIDTH + j] = a[i] & b[j];
 
		for (i = 0; i < WIDTH * 2 - 1; i = i + 1)
			begin
 
				product[i] = 0;
 
				for (j = ((i < WIDTH) ? 0 : i - WIDTH + 1);j <= ((i < WIDTH) ? i : WIDTH - 1);j = j + 1)
					product[i] = product[i] ^ andarray[WIDTH * j + i - j];
 
			end
 
			for (i = 0; i < WIDTH; i = i + 1)
				begin
 
					tmp[i] = 0;
					prbs = 1;
 
					for (j = 0; j < WIDTH * 2 - 1; j = j + 1)
						begin
 
							if (prbs & (1 << i))
								tmp[i] = tmp[i] ^ product[j];
 
							prbs = prbs << 1;
 
							if (prbs & (1 << WIDTH))
								prbs = prbs ^ PRIMITIVE;
						end
				end
 
			GFMult_fn = tmp;
		end
 
endfunction
 
 
function [WIDTH - 1 : 0] GFInverse_fn;
 
	input [WIDTH - 1 : 0] a;
	reg [WIDTH - 1 : 0]	res, prbstable [0 : (1 << WIDTH) - 1];
 
	integer i,prbs;
 
	begin
 
		prbs = 1;
 
		for (i = 0; i < (1 << WIDTH); i = i + 1) 
			begin
 
				prbstable[i] = prbs;
				prbs = prbs << 1;
 
				if (prbs & (1 << WIDTH))
					prbs = prbs ^ PRIMITIVE;
			end
 
		res = 0;
 
		for (i = 0; i < (1 << WIDTH) - 1; i = i + 1)
			if (a == prbstable[i])
 
		res = prbstable[(1 << WIDTH) - 1 - i];
 
		GFInverse_fn = res;
 
	end
endfunction
 
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.