OpenCores
URL https://opencores.org/ocsvn/bluespec-80211atransmitter/bluespec-80211atransmitter/trunk

Subversion Repositories bluespec-80211atransmitter

[/] [bluespec-80211atransmitter/] [trunk/] [IFFT_Library.bsv] - Rev 3

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

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.