URL
https://opencores.org/ocsvn/reed_solomon_coder/reed_solomon_coder/trunk
Subversion Repositories reed_solomon_coder
Compare Revisions
- This comparison shows the changes necessary to convert path
/reed_solomon_coder
- from Rev 5 to Rev 6
- ↔ Reverse comparison
Rev 5 → Rev 6
/trunk/forney.v
0,0 → 1,303
`timescale 1ns / 1ps |
////////////////////////////////////////////////////////////////////////////////// |
//Company: University of Hamburg, University of Kiel, Germany |
|
// |
// 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 |