// Copyright 2007 Altera Corporation. All rights reserved. // Altera products are protected under numerous U.S. and foreign patents, // maskwork rights, copyrights and other intellectual property laws. // // This reference design file, and your use thereof, is subject to and governed // by the terms and conditions of the applicable Altera Reference Design // License Agreement (either as signed by you or found at www.altera.com). By // using this reference design file, you indicate your acceptance of such terms // and conditions between you and Altera Corporation. In the event that you do // not agree with such terms and conditions, you may not use the reference // design file and please promptly destroy any copies you have made. // // This reference design file is being provided on an "as-is" basis and as an // accommodation and therefore all warranties, representations or guarantees of // any kind (whether express, implied or statutory) including, without // limitation, warranties of merchantability, non-infringement, or fitness for // a particular purpose, are specifically disclaimed. By making this reference // design file available, Altera expressly does not recommend, suggest or // require that this reference design file be used in combination with any // other product not provided by Altera. ///////////////////////////////////////////////////////////////////////////// // baeckler - 08-01-2006 #include #include int const MAX_SIZE = 256; // 2^symbol size /////////////////////////////////////////// int gf_mult ( int bits, int a, int b, int mod_poly ) { int result = 0; while (b != 0) { if ((b & 1) != 0) { result ^= a; } a = a << 1; if ((a & (1<> 1; } return (result); } /////////////////////////////////////////// // XOR all of the bits of this integer int reduce_xor (int dat) { int result = 0; while (dat != 0) { result ^= (dat & 1); dat >>= 1; } return (result); } /////////////////////////////////////////// void build_gf_const_mult ( int symbol_size, int const_val, int mod_poly ) { int table [MAX_SIZE]; int xor_ins = 0; int i = 0,j=0; bool first = false; // build a cheat sheet for (i=0; i<(1<=0; j--) { fprintf (stdout,"^(a & %d'h%x)",symbol_size,table[j]); if (j != 0) fprintf (stdout,","); } fprintf (stdout,"};\n\n"); // update to the next power fbk = table[symbol_size-1]; for (j=symbol_size-1; j>0; j--) { table[j] = table[j-1]; } table[0] = 0; for (j=symbol_size-1; j>=0; j--) { if ((mod_poly & (1< signal_use[q]) { q = j; } } // find the AND terms using the most popular signal for (j=0; j0; j--) { g[j] = gf_mult (symbol_size,g[j],alpha[i-1+b],mod_poly) ^ g[j-1]; } g[0] = gf_mult (symbol_size,g[0],alpha[i-1+b],mod_poly); } fprintf (stdout,"\n"); for (i=0; i<(n-k+1); i++) { fprintf (stdout,"// gen_poly [%d] = %02x\n",i,g[i]); } fprintf (stdout,"\n"); // build a full rack of GF constant multipliers for (i=1; i<=n; i++) { build_gf_const_mult (symbol_size,i,mod_poly); } fprintf (stdout,"\n///////////////////////////////////////////\n\n"); // main encoder fprintf (stdout,"// first din zeros the accumulator on the first data symbol\n"); fprintf (stdout,"// shift is for reading out the parity register, overrides\n"); fprintf (stdout,"// the first_din signal\n"); fprintf (stdout,"module encoder (clk,rst,shift,ena,first_din,din,parity);\n"); fprintf (stdout,"input clk,rst,shift,ena,first_din;\n"); fprintf (stdout,"input [%d:0] din;\n",symbol_size-1); fprintf (stdout,"output [%d:0] parity;\n",t*2*symbol_size-1); fprintf (stdout,"reg [%d:0] parity;\n\n",t*2*symbol_size-1); fprintf (stdout," wire [%d:0] feedback;\n",symbol_size-1); fprintf (stdout," assign feedback = din ^ (first_din ? %d'b0 : parity[%d:%d]);\n\n", symbol_size, t*2*symbol_size-1, t*2*symbol_size-symbol_size); fprintf (stdout," wire [%d:0] gen_fn;\n",t*2*symbol_size-1); for (i=0; i<(n-k); i++) { fprintf (stdout," gf_mult_by_%02x m%d (.i(feedback),.o(gen_fn[%d:%d]));\n" ,g[i],i,(i+1)*symbol_size-1,i*symbol_size); } fprintf (stdout,"\n"); fprintf (stdout," always @(posedge clk or posedge rst) begin\n"); fprintf (stdout," if (rst) begin\n"); fprintf (stdout," parity <= 0;\n"); fprintf (stdout," end\n"); fprintf (stdout," else if (ena) begin\n"); fprintf (stdout," parity <= ((!shift & first_din) ? %d'b0 : (parity << %d)) ^\n", t*2*symbol_size,symbol_size); fprintf (stdout," (shift ? %d'b0 : gen_fn);\n", t*2*symbol_size,symbol_size); fprintf (stdout," end\n"); fprintf (stdout," end\n"); fprintf (stdout,"endmodule\n\n"); } /////////////////////////////////////////// void build_syndrome_flat ( int symbol_size, int data_symbols, int mod_poly ) { int n = (1 << symbol_size) - 1; int k = data_symbols; int t = (n - k) / 2; int alpha [MAX_SIZE]; int const b = 0; int i,j; int mult_num = 0; fprintf (stdout,"\n///////////////////////////////////////////\n\n"); // build up the values of alpha^(i) mod poly alpha[0] = 1; for (i=1; i<=n; i++) { alpha[i] = gf_mult (symbol_size,alpha[i-1],2,mod_poly); } fprintf (stdout,"// No latency syndrome computation\n"); fprintf (stdout,"module syndrome_flat (rx_data,syndrome);\n"); fprintf (stdout,"input [%d:0] rx_data;\n",n * symbol_size-1); fprintf (stdout,"output [%d:0] syndrome;\n",2*t*symbol_size-1); fprintf (stdout,"wire [%d:0] syndrome;\n\n",2*t*symbol_size-1); for (i=0; i<2*t; i=i+1) { fprintf (stdout,"\n// syndrome %d\n",i); fprintf (stdout," wire [%d:0] syn_%d_tmp;\n",n*symbol_size-1,i); for (j=0; j>= 1; lg++; } return (lg); } /////////////////////////////////////////// void build_error_loc_poly ( int symbol_size, int data_symbols, int mod_poly ) { int n = (1 << symbol_size) - 1; int k = data_symbols; int t = (n - k) / 2; int i = 0; int mult_num = 0; fprintf (stdout,"\n///////////////////////////////////////////\n"); fprintf (stdout,"// Error Location poly computation\n"); fprintf (stdout,"// 1 tick per round version\n"); fprintf (stdout,"///////////////////////////////////////////\n\n"); fprintf (stdout,"// initial ELP_in is 1 at word 0 (meaning 1)\n"); fprintf (stdout,"// initial correction is 1 at word 1 (meaning x)\n"); fprintf (stdout,"// step = 1..2t\n"); fprintf (stdout,"// This is using the Berlekamp method\n"); fprintf (stdout,"module error_loc_poly_round (step,order_in,order_out,elp_in,elp_out,step_syndrome,\n"); fprintf (stdout," correction_in,correction_out);\n"); fprintf (stdout,"input [%d:0] step;\n",log_2(2*t)-1); fprintf (stdout,"input [%d:0] order_in;\n",log_2(2*t-1)-1); fprintf (stdout,"output [%d:0] order_out;\n",log_2(2*t-1)-1); fprintf (stdout,"input [%d:0] elp_in;\n",symbol_size*2*t-1); fprintf (stdout,"output [%d:0] elp_out;\n",symbol_size*2*t-1); fprintf (stdout,"input [%d:0] step_syndrome;\n",symbol_size*2*t-1); fprintf (stdout,"input [%d:0] correction_in;\n",symbol_size*2*t-1); fprintf (stdout,"output [%d:0] correction_out;\n\n",symbol_size*2*t-1); fprintf (stdout,"reg [%d:0] order_out;\n",log_2(2*t-1)-1); fprintf (stdout,"reg [%d:0] correction_out;\n\n",symbol_size*2*t-1); fprintf (stdout,"wire [%d:0] discrepancy;\n\n",symbol_size-1); fprintf (stdout,"wire [%d:0] disc_mult;\n",symbol_size*2*t-1); for (i=0; i<2*t; i=i+1) { fprintf (stdout,"gf_mult m%d (.a(elp_in[%d:%d]),.b(step_syndrome[%d:%d]),.o(disc_mult[%d:%d]));\n", mult_num, (i+1)*symbol_size-1,i*symbol_size, (i+1)*symbol_size-1,i*symbol_size, (i+1)*symbol_size-1,i*symbol_size ); mult_num++; } fprintf (stdout,"\nassign discrepancy = \n"); for (i=0; i<2*t; i=i+1) { fprintf (stdout," disc_mult [%d:%d]", (i+1)*symbol_size-1,i*symbol_size); if (i != 2*t-1) { fprintf (stdout," ^"); } fprintf (stdout,"\n"); } fprintf (stdout,";\n\n"); fprintf (stdout,"wire [%d:0] disc_mult_correction;\n",symbol_size*2*t-1); for (i=0; i<2*t; i=i+1) { fprintf (stdout,"gf_mult m%d (.a(discrepancy)," ".b(correction_in[%d:%d]),.o(disc_mult_correction[%d:%d]));\n", mult_num, (i+1)*symbol_size-1,i*symbol_size, (i+1)*symbol_size-1,i*symbol_size ); mult_num++; } fprintf (stdout,"\nassign elp_out = elp_in ^ disc_mult_correction;\n\n"); fprintf (stdout,"// build the elp divided by the discrepancy\n"); fprintf (stdout,"// by inverse then multiply...\n"); fprintf (stdout,"wire [%d:0] inv_discrepancy;\n",symbol_size-1); fprintf (stdout,"gf_inverse id (.i(discrepancy),.o(inv_discrepancy));\n\n"); fprintf (stdout,"wire [%d:0] elp_div_disc;\n",symbol_size*2*t-1); for (i=0; i<2*t; i=i+1) { fprintf (stdout,"gf_mult d%d (.a(elp_in[%d:%d])," ".b(inv_discrepancy),.o(elp_div_disc[%d:%d]));\n", mult_num, (i+1)*symbol_size-1,i*symbol_size, (i+1)*symbol_size-1,i*symbol_size ); mult_num++; } fprintf (stdout,"\n"); fprintf (stdout,"// update the order and correction poly\n"); fprintf (stdout,"always @(*) begin\n"); fprintf (stdout," if ((|discrepancy) && ((order_in << 1) < step)) begin\n"); fprintf (stdout," order_out = step - order_in;\n"); fprintf (stdout," correction_out = {elp_div_disc[%d:%d],%d'b0};\n", symbol_size*2*t-1-symbol_size, 0, symbol_size); fprintf (stdout," end\n"); fprintf (stdout," else begin\n"); fprintf (stdout," order_out = order_in;\n"); fprintf (stdout," correction_out = {correction_in[%d:%d],%d'b0} ;\n", symbol_size*2*t-1-symbol_size, 0, symbol_size); fprintf (stdout," end\n"); fprintf (stdout,"end\n\n"); fprintf (stdout,"endmodule\n"); } /////////////////////////////////////////// void build_error_loc_poly_multi_step ( int symbol_size, int data_symbols, int mod_poly ) { int n = (1 << symbol_size) - 1; int k = data_symbols; int t = (n - k) / 2; int i = 0; int mult_num = 0; fprintf (stdout,"\n/////////////////////////////////////////////////\n"); fprintf (stdout,"// Error Location poly computation\n"); fprintf (stdout,"// Multiple ticks per round version\n"); fprintf (stdout,"///////////////////////////////////////////////////\n\n"); fprintf (stdout,"// initial ELP_in is 1 at word 0 (meaning 1)\n"); fprintf (stdout,"// initial correction is 1 at word 1 (meaning x)\n"); fprintf (stdout,"// step = 1..2t\n"); fprintf (stdout,"// This is using the Berlekamp method\n"); fprintf (stdout,"module error_loc_poly_round_multi_step (step,order_in,order_out,elp_in,elp_out,step_syndrome,\n"); fprintf (stdout," correction_in,correction_out,clk,rst,sync,elpr_wait);\n"); fprintf (stdout,"input [%d:0] step;\n",log_2(2*t)-1); fprintf (stdout,"input [%d:0] order_in;\n",log_2(2*t-1)-1); fprintf (stdout,"output [%d:0] order_out;\n",log_2(2*t-1)-1); fprintf (stdout,"input [%d:0] elp_in;\n",symbol_size*2*t-1); fprintf (stdout,"output [%d:0] elp_out;\n",symbol_size*2*t-1); fprintf (stdout,"input [%d:0] step_syndrome;\n",symbol_size*2*t-1); fprintf (stdout,"input [%d:0] correction_in;\n",symbol_size*2*t-1); fprintf (stdout,"output [%d:0] correction_out;\n\n",symbol_size*2*t-1); fprintf (stdout,"input clk,rst,sync;\n"); fprintf (stdout,"output elpr_wait;\n\n"); fprintf (stdout,"reg [%d:0] order_out;\n",log_2(2*t-1)-1); fprintf (stdout,"reg [%d:0] correction_out;\n\n",symbol_size*2*t-1); fprintf (stdout,"wire [%d:0] discrepancy;\n\n",symbol_size-1); fprintf (stdout,"// state 0 : (upper) discrepancy_reg <= ^ (elp_in * step_syn)\n"); fprintf (stdout,"// state 1 : (lower) discrepancy_reg <= ^ (elp_in * step_syn)\n"); fprintf (stdout,"// state 2 : (upper) disc_cor_reg <= (dicrepancy_reg * correction)\n"); fprintf (stdout,"// state 3 : (lower) disc_cor_reg <= (dicrepancy_reg * correction)\n"); fprintf (stdout,"// state 4 : (upper) elp_div_disc_reg <= elp_in * inverse discrepancy\n"); fprintf (stdout,"// state 5 : (lower) elp_div_disc_reg <= elp_in * inverse discrepancy\n"); fprintf (stdout,"// state 6 : settling time\n"); fprintf (stdout,"reg [6:0] wait_state;\n\n"); fprintf (stdout,"always @(posedge clk or posedge rst) begin\n"); fprintf (stdout," if (rst) wait_state <= 7'b1;\n"); fprintf (stdout," else begin\n"); fprintf (stdout," if (sync) wait_state <= 7'b000001;\n"); fprintf (stdout," else wait_state <= {wait_state[5:0],wait_state[6]};\n"); fprintf (stdout," end\n"); fprintf (stdout,"end\n\n"); fprintf (stdout,"assign elpr_wait = !wait_state[6];\n\n"); fprintf (stdout,"wire [%d:0] mult_in_a, mult_in_b, mult_o, disc_inv_repeat;\n",symbol_size*t-1); fprintf (stdout,"wire [%d:0] disc_inv_mux;\n",symbol_size-1); fprintf (stdout,"assign disc_inv_repeat = {%d{disc_inv_mux}};\n\n",t); fprintf (stdout,"// multi purpose Galois mult (half size)\n"); //printf (stdout,"assign mult_in_a = ((wait_state[0] || wait_state[1] || wait_state[4] || wait_state[5]) ? elp_in : correction_in);\n"); //printf (stdout,"assign mult_in_b = ((wait_state[0] || wait_state[1]) ? step_syndrome : disc_inv_repeat);\n"); fprintf (stdout,"wire [%d:0] elp_in_hi, elp_in_lo, correction_in_hi, correction_in_lo;\n",symbol_size*t-1); fprintf (stdout,"wire [%d:0] step_syndrome_hi, step_syndrome_lo;\n",symbol_size*t-1); fprintf (stdout,"assign {step_syndrome_hi,step_syndrome_lo} = step_syndrome;\n"); fprintf (stdout,"assign {elp_in_hi,elp_in_lo} = elp_in;\n"); fprintf (stdout,"assign {correction_in_hi,correction_in_lo} = correction_in;\n\n"); fprintf (stdout,"assign mult_in_a = (wait_state[0] | wait_state[4]) ? elp_in_hi :\n"); fprintf (stdout," (wait_state[1] | wait_state[5]) ? elp_in_lo :\n"); fprintf (stdout," (wait_state[2]) ? correction_in_hi :\n"); fprintf (stdout," correction_in_lo;\n"); fprintf (stdout,"assign mult_in_b = (wait_state[0]) ? step_syndrome_hi :\n"); fprintf (stdout," (wait_state[1]) ? step_syndrome_lo :\n"); fprintf (stdout," disc_inv_repeat;\n\n"); for (i=0; i> %d;\n",symbol_size); fprintf (stdout," if (final_emp) emp_ready <= 1'b1;\n",t-1); fprintf (stdout," emp <= {emp_term,emp[%d:%d]};\n", symbol_size*t-1,symbol_size); fprintf (stdout," end\n"); fprintf (stdout," end\n"); fprintf (stdout,"end\n\n"); fprintf (stdout,"///////////////////////////////////////////////\n"); fprintf (stdout,"// ELP Roots (bad symbols in the word)\n"); fprintf (stdout,"// and Error values (bad bits in the symbol)\n"); fprintf (stdout,"///////////////////////////////////////////////\n\n"); fprintf (stdout,"reg [%d:0] root_step_elp;\n",symbol_size*(t+1)-1); fprintf (stdout,"wire [%d:0] next_root_step_elp;\n",symbol_size*(t+1)-1); fprintf (stdout,"wire root_match;\n"); fprintf (stdout,"reg last_root_match;\n"); fprintf (stdout,"reg last_emp_ready;\n"); fprintf (stdout,"reg [%d:0] root_cntr;\n",log_2(k)-1); fprintf (stdout,"reg roots_pending;\n"); fprintf (stdout,"wire root_ena = 1'b1;\n\n"); fprintf (stdout,"// generate a pulse when the new EMP is available\n"); fprintf (stdout,"always @(posedge clk or posedge rst) begin\n"); fprintf (stdout," if (rst) last_emp_ready <= 1'b0;\n"); fprintf (stdout," else last_emp_ready <= emp_ready;\n"); fprintf (stdout,"end\n\n"); fprintf (stdout,"// find the roots of the error location poly.\n"); fprintf (stdout,"// The ELP will be stable before the EMP is ready\n"); fprintf (stdout,"error_loc_poly_roots root (\n"); fprintf (stdout," .elp_in(root_step_elp),\n"); fprintf (stdout," .elp_out(next_root_step_elp),\n"); fprintf (stdout," .match(root_match));\n\n"); fprintf (stdout,"always @(posedge clk or posedge rst) begin\n"); fprintf (stdout," if (rst) begin\n"); fprintf (stdout," last_root_match <= 0;\n"); fprintf (stdout," root_step_elp <= 0;\n"); fprintf (stdout," root_cntr <= 0;\n"); fprintf (stdout," roots_pending <= 0;\n"); fprintf (stdout," end\n"); fprintf (stdout," else if (root_ena) begin\n"); fprintf (stdout," if (final_emp) begin\n"); fprintf (stdout," // while waiting for the the last EMP, load the ELP\n"); fprintf (stdout," root_step_elp <= elp[%d:0];\n", symbol_size*(t+1)-1); fprintf (stdout," root_cntr <= 0;\n"); fprintf (stdout," roots_pending <= 1'b1;\n"); fprintf (stdout," end\n"); fprintf (stdout," else begin\n"); fprintf (stdout," if (roots_pending) begin\n"); fprintf (stdout," // Advancing through the roots...\n"); fprintf (stdout," root_step_elp <= next_root_step_elp;\n"); fprintf (stdout," if (root_cntr == %d) begin\n",n); //here fprintf (stdout," root_cntr <= 0;\n"); fprintf (stdout," roots_pending <= 1'b0;\n"); fprintf (stdout," end\n"); fprintf (stdout," else begin\n"); fprintf (stdout," root_cntr <= root_cntr + 1'b1;\n"); fprintf (stdout," end\n"); fprintf (stdout," end\n"); fprintf (stdout," end\n"); fprintf (stdout," last_root_match <= root_match;\n"); fprintf (stdout," end\n"); fprintf (stdout,"end\n\n"); fprintf (stdout,"reg [%d:0] step_emp;\n",symbol_size*(t+1)-1); fprintf (stdout,"wire [%d:0] next_step_emp;\n\n",symbol_size*(t+1)-1); fprintf (stdout,"// the derivitive term is equal to the sum of the \n"); fprintf (stdout,"// odd terms of the working ELP from the root search\n"); fprintf (stdout,"wire [%d:0] deriv_term =\n",symbol_size-1); first = true; for (h=symbol_size; h