URL
https://opencores.org/ocsvn/bluespec-80211atransmitter/bluespec-80211atransmitter/trunk
Subversion Repositories bluespec-80211atransmitter
[/] [bluespec-80211atransmitter/] [trunk/] [IFFT_Library.bsv] - Rev 5
Go to most recent revision | Compare with Previous | Blame | View Log
// The MIT License
//
// Copyright (c) 2006 Nirav Dave (ndave@csail.mit.edu)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import ComplexF::*;
import DataTypes::*;
import LibraryFunctions::*;
import Vector::*;
//This function just serves as a short hand for grabbing 4 consecutive indices in
//a vector
function Vector#(4, a) take4(Vector#(n, a) sv, alpha idx)
provisos (Add#(4,k,n), Log#(n,logn),
Eq#(alpha), Literal#(alpha), Arith#(alpha), Ord#(alpha),
PrimIndex#(alpha, beta)
);
Vector#(4,a) retval = newVector();
for(alpha i = 0; i < 4; i = i + 1)
retval[i] = sv[idx+i];
return retval;
endfunction
// The Radix function. Note that it is noinlined, because
// there's no point in doing a per-instance optimizations
(* noinline *)
function Radix4Data radix4(OmegaData omegas,
Radix4Data xs);
Radix4Data retval = newVector();
ComplexF#(16) alpha = xs[0];
ComplexF#(16) beta = omegas[0] * xs[1];
ComplexF#(16) gamma = omegas[1] * xs[2];
ComplexF#(16) delta = omegas[2] * xs[3];
ComplexF#(16) tao_0 = alpha + gamma;
ComplexF#(16) tao_1 = alpha - gamma;
ComplexF#(16) tao_2 = beta + delta;
ComplexF#(16) tao_3 = beta - delta;
// rotate tao_3 by 90 degrees
ComplexF#(16) tao_3_rot90;
tao_3_rot90.i = -tao_3.q;
tao_3_rot90.q = tao_3.i;
retval[0] = tao_0 + tao_2;
retval[1] = tao_1 - tao_3_rot90;
retval[2] = tao_0 - tao_2;
retval[3] = tao_1 + tao_3_rot90;
return retval;
endfunction
//This describes a permutation such that
//If the ith value in this is j, then the
//ith value of the output will be the jth
// input value.
// This permutation is used on the values directly into the IFFT
function Vector#(64, Integer) reorder();
Vector#(64, Integer) retval = replicate(?);
retval[ 0] = 0;
retval[ 1] = 16;
retval[ 2] = 32;
retval[ 3] = 48;
retval[ 4] = 4;
retval[ 5] = 20;
retval[ 6] = 36;
retval[ 7] = 52;
retval[ 8] = 8;
retval[ 9] = 24;
retval[10] = 40;
retval[11] = 56;
retval[12] = 12;
retval[13] = 28;
retval[14] = 44;
retval[15] = 60;
retval[16] = 1;
retval[17] = 17;
retval[18] = 33;
retval[19] = 49;
retval[20] = 5;
retval[21] = 21;
retval[22] = 37;
retval[23] = 53;
retval[24] = 9;
retval[25] = 25;
retval[26] = 41;
retval[27] = 57;
retval[28] = 13;
retval[29] = 29;
retval[30] = 45;
retval[31] = 61;
retval[32] = 2;
retval[33] = 18;
retval[34] = 34;
retval[35] = 50;
retval[36] = 6;
retval[37] = 22;
retval[38] = 38;
retval[39] = 54;
retval[40] = 10;
retval[41] = 26;
retval[42] = 42;
retval[43] = 58;
retval[44] = 14;
retval[45] = 30;
retval[46] = 46;
retval[47] = 62;
retval[48] = 3;
retval[49] = 19;
retval[50] = 35;
retval[51] = 51;
retval[52] = 7;
retval[53] = 23;
retval[54] = 39;
retval[55] = 55;
retval[56] = 11;
retval[57] = 27;
retval[58] = 43;
retval[59] = 59;
retval[60] = 15;
retval[61] = 31;
retval[62] = 47;
retval[63] = 63;
return retval;
endfunction
// Similiar to the reorder ipermuation. However, this is used after each set of 16 radices
function Vector#(64, Integer) permute();
Vector#(64, Integer) retval = replicate(?);
retval[ 0] = 0;
retval[ 1] = 4;
retval[ 2] = 8;
retval[ 3] = 12;
retval[ 4] = 16;
retval[ 5] = 20;
retval[ 6] = 24;
retval[ 7] = 28;
retval[ 8] = 32;
retval[ 9] = 36;
retval[10] = 40;
retval[11] = 44;
retval[12] = 48;
retval[13] = 52;
retval[14] = 56;
retval[15] = 60;
retval[16] = 1;
retval[17] = 5;
retval[18] = 9;
retval[19] = 13;
retval[20] = 17;
retval[21] = 21;
retval[22] = 25;
retval[23] = 29;
retval[24] = 33;
retval[25] = 37;
retval[26] = 41;
retval[27] = 45;
retval[28] = 49;
retval[29] = 53;
retval[30] = 57;
retval[31] = 61;
retval[32] = 2;
retval[33] = 6;
retval[34] = 10;
retval[35] = 14;
retval[36] = 18;
retval[37] = 22;
retval[38] = 26;
retval[39] = 30;
retval[40] = 34;
retval[41] = 38;
retval[42] = 42;
retval[43] = 46;
retval[44] = 50;
retval[45] = 54;
retval[46] = 58;
retval[47] = 62;
retval[48] = 3;
retval[49] = 7;
retval[50] = 11;
retval[51] = 15;
retval[52] = 19;
retval[53] = 23;
retval[54] = 27;
retval[55] = 31;
retval[56] = 35;
retval[57] = 39;
retval[58] = 43;
retval[59] = 47;
retval[60] = 51;
retval[61] = 55;
retval[62] = 59;
retval[63] = 63;
return retval;
endfunction
// Calculate the correct omegas. This gets sent into the
// radix4 block
function Vector#(3, ComplexF#(16)) omega(Bit#(2) stage, Bit#(4) index);
Vector#(3, ComplexF#(16)) retval = replicate(?);
case(stage)
// stage 1
0:
begin
retval[0].i = 16'h7fff; retval[0].q = 16'h0000;
retval[1].i = 16'h7fff; retval[1].q = 16'h0000;
retval[2].i = 16'h7fff; retval[2].q = 16'h0000;
end
// stage 2
1:
case(index >> 2)
0: begin
retval[0].i = 16'h7fff; retval[0].q = 16'h0000;
retval[1].i = 16'h7fff; retval[1].q = 16'h0000;
retval[2].i = 16'h7fff; retval[2].q = 16'h0000;
end
1: begin
retval[0].i = 16'h7640; retval[0].q = 16'hcf05;
retval[1].i = 16'h5a81; retval[1].q = 16'ha57f;
retval[2].i = 16'h30fb; retval[2].q = 16'h89c0;
end
2: begin
retval[0].i = 16'h5a81; retval[0].q = 16'ha57f;
retval[1].i = 16'h0000; retval[1].q = 16'h8000;
retval[2].i = 16'ha57f; retval[2].q = 16'ha57f;
end
3: begin
retval[0].i = 16'h30fb; retval[0].q = 16'h89c0;
retval[1].i = 16'ha57f; retval[1].q = 16'ha57f;
retval[2].i = 16'h89c0; retval[2].q = 16'h30fb;
end
endcase
// stage 3
2:
case(index)
0: begin
retval[0].i = 16'h7fff; retval[0].q = 16'h0000;
retval[1].i = 16'h7fff; retval[1].q = 16'h0000;
retval[2].i = 16'h7fff; retval[2].q = 16'h0000;
end
1: begin
retval[0].i = 16'h7f61; retval[0].q = 16'hf375;
retval[1].i = 16'h7d89; retval[1].q = 16'he708;
retval[2].i = 16'h7a7c; retval[2].q = 16'hdad9;
end
2: begin
retval[0].i = 16'h7d89; retval[0].q = 16'he708;
retval[1].i = 16'h7640; retval[1].q = 16'hcf05;
retval[2].i = 16'h6a6c; retval[2].q = 16'hb8e4;
end
3: begin
retval[0].i = 16'h7a7c; retval[0].q = 16'hdad9;
retval[1].i = 16'h6a6c; retval[1].q = 16'hb8e4;
retval[2].i = 16'h5133; retval[2].q = 16'h9d0f;
end
4: begin
retval[0].i = 16'h7640; retval[0].q = 16'hcf05;
retval[1].i = 16'h5a81; retval[1].q = 16'ha57f;
retval[2].i = 16'h30fb; retval[2].q = 16'h89c0;
end
5: begin
retval[0].i = 16'h70e1; retval[0].q = 16'hc3aa;
retval[1].i = 16'h471c; retval[1].q = 16'h9594;
retval[2].i = 16'h0c8b; retval[2].q = 16'h809f;
end
6: begin
retval[0].i = 16'h6a6c; retval[0].q = 16'hb8e4;
retval[1].i = 16'h30fb; retval[1].q = 16'h89c0;
retval[2].i = 16'he708; retval[2].q = 16'h8277;
end
7: begin
retval[0].i = 16'h62f1; retval[0].q = 16'haecd;
retval[1].i = 16'h18f8; retval[1].q = 16'h8277;
retval[2].i = 16'hc3aa; retval[2].q = 16'h8f1f;
end
8: begin
retval[0].i = 16'h5a81; retval[0].q = 16'ha57f;
retval[1].i = 16'h0000; retval[1].q = 16'h8000;
retval[2].i = 16'ha57f; retval[2].q = 16'ha57f;
end
9: begin
retval[0].i = 16'h5133; retval[0].q = 16'h9d0f;
retval[1].i = 16'he708; retval[1].q = 16'h8277;
retval[2].i = 16'h8f1f; retval[2].q = 16'hc3aa;
end
10: begin
retval[0].i = 16'h471c; retval[0].q = 16'h9594;
retval[1].i = 16'hcf05; retval[1].q = 16'h89c0;
retval[2].i = 16'h8277; retval[2].q = 16'he708;
end
11: begin
retval[0].i = 16'h3c56; retval[0].q = 16'h8f1f;
retval[1].i = 16'hb8e4; retval[1].q = 16'h9594;
retval[2].i = 16'h809f; retval[2].q = 16'h0c8b;
end
12: begin
retval[0].i = 16'h30fb; retval[0].q = 16'h89c0;
retval[1].i = 16'ha57f; retval[1].q = 16'ha57f;
retval[2].i = 16'h89c0; retval[2].q = 16'h30fb;
end
13: begin
retval[0].i = 16'h2527; retval[0].q = 16'h8584;
retval[1].i = 16'h9594; retval[1].q = 16'hb8e4;
retval[2].i = 16'h9d0f; retval[2].q = 16'h5133;
end
14: begin
retval[0].i = 16'h18f8; retval[0].q = 16'h8277;
retval[1].i = 16'h89c0; retval[1].q = 16'hcf05;
retval[2].i = 16'hb8e4; retval[2].q = 16'h6a6c;
end
15: begin
retval[0].i = 16'h0c8b; retval[0].q = 16'h809f;
retval[1].i = 16'h8277; retval[1].q = 16'he708;
retval[2].i = 16'hdad9; retval[2].q = 16'h7a7c;
end
endcase
endcase
return retval;
endfunction
// This is the stage function which does the IFFT in 3 stages
(* noinline *)
function IFFTData stagefunction(Bit#(2) stage, IFFTData s_in);
IFFTData s_mid = newVector();
for(Integer i = 0; i < 16; i = i + 1)
begin
Nat four_i = fromInteger(4*i);
Radix4Data temp = radix4(omega(stage, fromInteger(i)),
take4(s_in, four_i));
for(Integer j = 0; j < 4; j = j + 1)
s_mid[4*i+j] = temp[j];
end
// permute
IFFTData s_out = newVector();
for(Integer i = 0; i < 64; i = i + 1)
s_out[i] = s_mid[permute[i]];
return (s_out);
endfunction
//These two functions are little hacks which prevent the compiler
//from optimizing past these function boundaries.
(* noinline *)
function IFFTData stopOpt64(IFFTData s_in);
return s_in;
endfunction
function Vector#(4, ComplexF#(16)) stopOpt4(Vector#(4, ComplexF#(16)) s_in);
return s_in;
endfunction
// This is a stage function which does the IFFT in 48 stages, doing
// 1 radix4 each stage and permuting the values every 16 cycles.
(* noinline *)
function IFFTData stagefunction2(Bit#(6) stage, IFFTData s_in);
IFFTData s_mid = stopOpt64(s_in);
Bit#(4) step = stage[3:0];
Bit#(6) step4 = {step,2'b00};
Radix4Data temp = radix4(omega(stage[5:4],step),
take4(s_in, step4));
for(Bit#(6) j = 0; j < 4; j = j + 1)
s_mid = update(s_mid, step4+j,temp[j]);
// permute
IFFTData s_mid2 = stopOpt64(s_mid);
IFFTData s_out = newVector();
for(Integer i = 0; i < 64; i = i + 1)
s_out[i] = s_mid2[permute[i]];
return ((step == 15) ? s_out : s_mid2);
endfunction
Go to most recent revision | Compare with Previous | Blame | View Log