OpenCores
URL https://opencores.org/ocsvn/fft2_size/fft2_size/trunk

Subversion Repositories fft2_size

[/] [fft2_size/] [fft_int_size/] [fft_int_size.sv] - Blame information for rev 7

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 7 Papayaved
/*
2
Streaming FFT module with resizable FFT length
3
*/
4
 
5
`ifndef _fft_int_size_
6
`define _fft_int_size_
7
`include "size_ctrl.sv"
8
`include "cascade_0.sv"
9
`include "cascade_n.sv"
10
 
11
// Integer resizable streaming FFT
12
module fft_int_size #(parameter
13
        POW = 9, // max fft size 2**POW
14
        DATA_WIDTH = 32,
15
        POW_WIDTH = (2**$clog2(POW) > POW - 1) ? $clog2(POW) : $clog2(POW) + 1,
16
        RES_WIDTH = DATA_WIDTH + POW
17
)(
18
        input clk, aclr,
19
 
20
        // input data stream
21
        input sink_sop, sink_eop, sink_valid, // valid signal must be solid between sop and eop
22
        input signed [DATA_WIDTH-1:0] sink_Re, sink_Im,
23
 
24
        // FFT length 2**pow
25
        input [POW_WIDTH-1:0] pow, // 4..POW
26
        output pow_ready, // pow ready to change
27
 
28
        // Result data stream
29
        output reg source_sop, source_eop, source_valid,
30
        output reg signed [RES_WIDTH-1:0] source_Re, source_Im,
31
 
32
        output error
33
);
34
        wire [POW-1:0][POW-1:0] fft_rdaddr;
35
        wire [POW-1:0] fft_rdack;
36
        wire [POW:0] ready;
37
 
38
        logic [POW:0][POW-1:0] rdaddr;
39
        logic [POW:0] rdack;
40
 
41
        genvar k;
42
        generate for (k = 0; k <= POW; k++)
43
                begin :res
44
                        wire signed [DATA_WIDTH + k - 1:0] re, im;
45
                end
46
        endgenerate
47
 
48
        wire [POW_WIDTH-1:0] pow_reg;
49
        wire [POW-1:0] addr_max;
50
        wire [1:0] err;
51
 
52
        wire sop_reg, eop_reg, valid_reg;
53
        wire signed [DATA_WIDTH-1:0] re_reg, im_reg;
54
 
55
        size_ctrl #(.POW(POW), .DATA_WIDTH(DATA_WIDTH)) size_inst(
56
                .clk, .aclr, .pow, .source_eop,
57
                .pow_reg, .addr_max,    .pow_ready, .error(err[0]),
58
 
59
                .sink_sop, .sink_eop, .sink_valid, .sink_Re, .sink_Im,
60
                .sop_reg, .eop_reg, .valid_reg, .re_reg, .im_reg
61
        );
62
 
63
        // input controller
64
        cascade_0 #(.ADDR_WIDTH(POW), .DATA_WIDTH(DATA_WIDTH)) c0(
65
                .clk, .aclr,
66
                .sink_sop(sop_reg), .sink_eop(eop_reg), .sink_valid(valid_reg), .sink_Re(re_reg), .sink_Im(im_reg),
67
                .pow(pow_reg), .addr_max,
68
 
69
                .rdaddr(rdaddr[0]),
70
                .q_Re(res[0].re), .q_Im(res[0].im),
71
                .ready(ready[0]),
72
                .rdack(rdack[0]),
73
                .error(err[1])
74
        );
75
 
76
        always_comb begin
77
                rdaddr[0] = fft_rdaddr[0];
78
                rdack[0] = fft_rdack[0];
79
        end
80
 
81
        reg [POW-1:0] cnt = '0;
82
        genvar i;
83
        generate
84
                for (i = 1; i <= POW; i++)
85
                        begin :gen
86
                                cascade_n #(.ADDR_WIDTH(POW), .DATA_WIDTH(DATA_WIDTH + i - 1), .POW(i)) cn(
87
                                        .clk, .aclr, .sink_ready(ready[i-1] && pow_reg >= i),
88
                                        .sink_rdaddr(fft_rdaddr[i-1]),
89
                                        .sink_Re(res[i-1].re), .sink_Im(res[i-1].im),
90
                                        .sink_rdack(fft_rdack[i-1]),
91
                                        .pow(pow_reg), .addr_max,
92
 
93
                                        .source_rdaddr(rdaddr[i]),
94
                                        .source_rdack(rdack[i]),
95
                                        .source_Re(res[i].re), .source_Im(res[i].im),
96
                                        .source_ready(ready[i])
97
                                );
98
 
99
                                if (i < 4)
100
                                        begin
101
                                                always_comb
102
                                                        begin
103
                                                                rdaddr[i] = fft_rdaddr[i];
104
                                                                rdack[i] = fft_rdack[i];
105
                                                        end
106
                                        end
107
                                else if (i == POW)
108
                                        begin
109
                                                always_comb begin
110
                                                        rdaddr[POW] = cnt;
111
                                                        rdack[POW] = cnt == '1;
112
                                                end
113
                                        end
114
                                else
115
                                        begin
116
                                                always_comb
117
                                                        if (pow_reg > i)
118
                                                                begin // todo: use 2 ports memory to read data
119
                                                                        rdaddr[i] = fft_rdaddr[i];
120
                                                                        rdack[i] = fft_rdack[i];
121
                                                                end
122
                                                        else
123
                                                                begin
124
                                                                        rdaddr[i] = cnt;
125
                                                                        rdack[i] = cnt == addr_max;
126
                                                                end
127
                                        end
128
                        end
129
        endgenerate
130
 
131
        // Read data from last cascade
132
        always_ff @(posedge clk, posedge aclr)
133
                if (aclr)
134
                        cnt <= '0;
135
                else if (!ready[pow_reg] || cnt == addr_max)
136
                        cnt <= '0;
137
                else
138
                        cnt <= cnt + 1'b1;
139
 
140
        reg res_sop, res_eop, res_valid = 1'b0;
141
 
142
        always_ff @(posedge clk) begin
143
                res_sop <= ready[pow_reg] && cnt == '0;
144
                res_eop <= cnt == addr_max;
145
        end
146
 
147
        always_ff @(posedge clk, posedge aclr)
148
                res_valid <= (aclr) ? 1'b0 : ready[pow_reg] || rdack[pow_reg];
149
 
150
        // form result
151
        // todo: 2 regs
152
        wire signed [RES_WIDTH - 1:0] res_re[2**POW_WIDTH], res_im[2**POW_WIDTH];
153
 
154
        genvar m;
155
        generate for (m = 0; m < 2**POW_WIDTH; m++)
156
                begin :gen_res
157
                        if (m >= 4 && m <= POW)
158
                                begin
159
                                        assign res_re[m] = RES_WIDTH'('sh0) + signed'(res[m].re);
160
                                        assign res_im[m] = RES_WIDTH'('sh0) + signed'(res[m].im);
161
                                end
162
                        else
163
                                begin
164
                                        assign res_re[m] = 'sh0;
165
                                        assign res_im[m] = 'sh0;
166
                                end
167
                end
168
        endgenerate
169
 
170
        always_ff @(posedge clk) begin
171
                source_sop <= res_sop;
172
                source_eop <= res_eop;
173
 
174
                source_Re <= res_re[pow_reg];
175
                source_Im <= res_im[pow_reg];
176
        end
177
 
178
        always_ff @(posedge clk, posedge aclr)
179
                source_valid <= (aclr) ? 1'b0 : res_valid;
180
 
181
        assign error = |err;
182
 
183
endmodule :fft_int_size
184
 
185
`endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.