forked from mit-plv/koika
-
Notifications
You must be signed in to change notification settings - Fork 0
/
fft.bsv
127 lines (106 loc) · 4.52 KB
/
fft.bsv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*! A Bluespec implementation of the fft.v example !*/
// Adapted from MIT 6.375 it is not actually an FFT because the bitReverse has been removed
import ClientServer::*;
import Complex::*;
import Real::*;
import Vector::*;
import MiscTypes::*;
typedef Server#(
Vector#(FFT_POINTS, ComplexSample),
Vector#(FFT_POINTS, ComplexSample)
) FFT;
// Get the appropriate twiddle factor for the given stage and index.
// This computes the twiddle factor statically.
function ComplexSample getTwiddle(Integer stage, Integer index, Integer points);
Integer i = ((2*index)/(2 ** (log2(points)-stage))) * (2 ** (log2(points)-stage));
return cmplx(fromReal(cos(fromInteger(i)*pi/fromInteger(points))),
fromReal(-1*sin(fromInteger(i)*pi/fromInteger(points))));
endfunction
// Generate a table of all the needed twiddle factors.
// The table can be used for looking up a twiddle factor dynamically.
typedef Vector#(FFT_LOG_POINTS, Vector#(TDiv#(FFT_POINTS, 2), ComplexSample)) TwiddleTable;
function TwiddleTable genTwiddles();
TwiddleTable twids = newVector;
for (Integer s = 0; s < valueof(FFT_LOG_POINTS); s = s+1) begin
for (Integer i = 0; i < valueof(TDiv#(FFT_POINTS, 2)); i = i+1) begin
twids[s][i] = getTwiddle(s, i, valueof(FFT_POINTS));
end
end
return twids;
endfunction
// Given the destination location and the number of points in the fft, return
// the source index for the permutation.
function Integer permute(Integer dst, Integer points);
Integer src = ?;
if (dst < points/2) begin
src = dst*2;
end else begin
src = (dst - points/2)*2 + 1;
end
return src;
endfunction
// Reorder the given vector by swapping words at positions
// corresponding to the bit-reversal of their indices.
// The reordering can be done either as as the
// first or last phase of the FFT transformation.
function Vector#(FFT_POINTS, ComplexSample) bitReverse(Vector#(FFT_POINTS,ComplexSample) inVector);
Vector#(FFT_POINTS, ComplexSample) outVector = newVector();
for(Integer i = 0; i < valueof(FFT_POINTS); i = i+1) begin
Bit#(FFT_LOG_POINTS) reversal = reverseBits(fromInteger(i));
outVector[reversal] = inVector[i];
end
return outVector;
endfunction
// 2-way Butterfly
function Vector#(2, ComplexSample) bfly2(Vector#(2, ComplexSample) t, ComplexSample k);
ComplexSample m = t[1] * k;
Vector#(2, ComplexSample) z = newVector();
z[0] = t[0] + m;
z[1] = t[0] - m;
return z;
endfunction
// Perform a single stage of the FFT, consisting of butterflys and a single
// permutation.
// We pass the table of twiddles as an argument so we can look those up
// dynamically if need be.
function Vector#(FFT_POINTS, ComplexSample) stage_ft(TwiddleTable twiddles, Bit#(TLog#(FFT_LOG_POINTS)) stage, Vector#(FFT_POINTS, ComplexSample) stage_in);
Vector#(FFT_POINTS, ComplexSample) stage_temp = newVector();
for(Integer i = 0; i < (valueof(FFT_POINTS)/2); i = i+1) begin
Integer idx = i * 2;
let twid = twiddles[stage][i];
let y = bfly2(takeAt(idx, stage_in), twid);
stage_temp[idx] = y[0];
stage_temp[idx+1] = y[1];
end
Vector#(FFT_POINTS, ComplexSample) stage_out = newVector();
for (Integer i = 0; i < valueof(FFT_POINTS); i = i+1) begin
stage_out[i] = stage_temp[permute(i, valueof(FFT_POINTS))];
end
return stage_out;
endfunction
interface Peak;
method Vector#(FFT_POINTS, ComplexSample) rd();
endinterface
module mkfft(Peak);
// Statically generate the twiddle factors table.
TwiddleTable twiddles = genTwiddles();
// Define the stage_f function which uses the generated twiddles.
function Vector#(FFT_POINTS, ComplexSample) stage_f(Bit#(TLog#(FFT_LOG_POINTS)) stage, Vector#(FFT_POINTS, ComplexSample) stage_in);
return stage_ft(twiddles, stage, stage_in);
endfunction
ComplexSample cst = unpack(4039543289543432);
Reg#(Vector#(FFT_POINTS, ComplexSample)) itself <- mkReg(replicate(cst));
// This rule performs fft using a big mass of combinational logic.
rule comb_fft;
Vector#(TAdd#(1, FFT_LOG_POINTS), Vector#(FFT_POINTS, ComplexSample)) stage_data = newVector();
stage_data[0] = itself;
for(Integer stage = 0; stage < valueof(FFT_LOG_POINTS); stage=stage+1) begin
stage_data[stage+1] = stage_f(fromInteger(stage), stage_data[stage]);
end
itself <= stage_data[valueof(FFT_LOG_POINTS)];
// $display(fshow(itself));
endrule
method Vector#(FFT_POINTS, ComplexSample) rd();
return itself;
endmethod
endmodule