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

Subversion Repositories dblclockfft

[/] [dblclockfft/] [trunk/] [rtl/] [laststage.v] - Blame information for rev 36

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 36 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    laststage.v
4
//
5
// Project:     A General Purpose Pipelined FFT Implementation
6
//
7
// Purpose:     This is part of an FPGA implementation that will process
8
//              the final stage of a decimate-in-frequency FFT, running
9
//      through the data at two samples per clock.  If you notice from the
10
//      derivation of an FFT, the only time both even and odd samples are
11
//      used at the same time is in this stage.  Therefore, other than this
12
//      stage and these twiddles, all of the other stages can run two stages
13
//      at a time at one sample per clock.
14
//
15
// Operation:
16
//      Given a stream of values, operate upon them as though they were
17
//      value pairs, x[2n] and x[2n+1].  The stream begins when n=0, and ends
18
//      when n=1.  When the first x[0] value enters, the synchronization
19
//      input, i_sync, must be true as well.
20
//
21
//      For this stream, produce outputs
22
//      y[2n  ] = x[2n] + x[2n+1], and
23
//      y[2n+1] = x[2n] - x[2n+1]
24
//
25
//      When y[0] is output, a synchronization bit o_sync will be true as
26
//      well, otherwise it will be zero.
27
//
28
//
29
//      In this implementation, the output is valid one clock after the input
30
//      is valid.  The output also accumulates one bit above and beyond the
31
//      number of bits in the input.
32
//
33
//              i_clk   A system clock
34
//              i_reset A synchronous reset
35
//              i_ce    Circuit enable--nothing happens unless this line is high
36
//              i_sync  A synchronization signal, high once per FFT at the start
37
//              i_left  The first (even) complex sample input.  The higher order
38
//                      bits contain the real portion, low order bits the
39
//                      imaginary portion, all in two's complement.
40
//              i_right The next (odd) complex sample input, same format as
41
//                      i_left.
42
//              o_left  The first (even) complex output.
43
//              o_right The next (odd) complex output.
44
//              o_sync  Output synchronization signal.
45
//
46
// Creator:     Dan Gisselquist, Ph.D.
47
//              Gisselquist Technology, LLC
48
//
49
////////////////////////////////////////////////////////////////////////////////
50
//
51
// Copyright (C) 2015-2018, Gisselquist Technology, LLC
52
//
53
// This program is free software (firmware): you can redistribute it and/or
54
// modify it under the terms of  the GNU General Public License as published
55
// by the Free Software Foundation, either version 3 of the License, or (at
56
// your option) any later version.
57
//
58
// This program is distributed in the hope that it will be useful, but WITHOUT
59
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
60
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
61
// for more details.
62
//
63
// You should have received a copy of the GNU General Public License along
64
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
65
// target there if the PDF file isn't present.)  If not, see
66
// <http://www.gnu.org/licenses/> for a copy.
67
//
68
// License:     GPL, v3, as defined and found on www.gnu.org,
69
//              http://www.gnu.org/licenses/gpl.html
70
//
71
//
72
////////////////////////////////////////////////////////////////////////////////
73
//
74
//
75
`default_nettype        none
76
//
77
module  laststage(i_clk, i_reset, i_ce, i_sync, i_left, i_right, o_left, o_right, o_sync);
78
        parameter       IWIDTH=16,OWIDTH=IWIDTH+1, SHIFT=0;
79
        input           i_clk, i_reset, i_ce, i_sync;
80
        input           [(2*IWIDTH-1):0] i_left, i_right;
81
        output  reg     [(2*OWIDTH-1):0] o_left, o_right;
82
        output  reg                     o_sync;
83
 
84
        wire    signed  [(IWIDTH-1):0]   i_in_0r, i_in_0i, i_in_1r, i_in_1i;
85
        assign  i_in_0r = i_left[(2*IWIDTH-1):(IWIDTH)];
86
        assign  i_in_0i = i_left[(IWIDTH-1):0];
87
        assign  i_in_1r = i_right[(2*IWIDTH-1):(IWIDTH)];
88
        assign  i_in_1i = i_right[(IWIDTH-1):0];
89
        wire    [(OWIDTH-1):0]           o_out_0r, o_out_0i,
90
                                        o_out_1r, o_out_1i;
91
 
92
 
93
        // Handle a potential rounding situation, when IWIDTH>=OWIDTH.
94
 
95
 
96
 
97
        // As with any register connected to the sync pulse, these must
98
        // have initial values and be reset on the i_reset signal.
99
        // Other data values need only restrict their updates to i_ce
100
        // enabled clocks, but sync's must obey resets and initial
101
        // conditions as well.
102
        reg     rnd_sync, r_sync;
103
 
104
        initial rnd_sync      = 1'b0; // Sync into rounding
105
        initial r_sync        = 1'b0; // Sync coming out
106
        always @(posedge i_clk)
107
                if (i_reset)
108
                begin
109
                        rnd_sync <= 1'b0;
110
                        r_sync <= 1'b0;
111
                end else if (i_ce)
112
                begin
113
                        rnd_sync <= i_sync;
114
                        r_sync <= rnd_sync;
115
                end
116
 
117
        // As with other variables, these are really only updated when in
118
        // the processing pipeline, after the first i_sync.  However, to
119
        // eliminate as much unnecessary logic as possible, we toggle
120
        // these any time the i_ce line is enabled, and don't reset.
121
        // them on i_reset.
122
        // Don't forget that we accumulate a bit by adding two values
123
        // together. Therefore our intermediate value must have one more
124
        // bit than the two originals.
125
        reg     signed  [(IWIDTH):0]     rnd_in_0r, rnd_in_0i;
126
        reg     signed  [(IWIDTH):0]     rnd_in_1r, rnd_in_1i;
127
 
128
        always @(posedge i_clk)
129
                if (i_ce)
130
                begin
131
                        //
132
                        rnd_in_0r <= i_in_0r + i_in_1r;
133
                        rnd_in_0i <= i_in_0i + i_in_1i;
134
                        //
135
                        rnd_in_1r <= i_in_0r - i_in_1r;
136
                        rnd_in_1i <= i_in_0i - i_in_1i;
137
                        //
138
                end
139
 
140
        convround #(IWIDTH+1,OWIDTH,SHIFT) do_rnd_0r(i_clk, i_ce,
141
                                                        rnd_in_0r, o_out_0r);
142
 
143
        convround #(IWIDTH+1,OWIDTH,SHIFT) do_rnd_0i(i_clk, i_ce,
144
                                                        rnd_in_0i, o_out_0i);
145
 
146
        convround #(IWIDTH+1,OWIDTH,SHIFT) do_rnd_1r(i_clk, i_ce,
147
                                                        rnd_in_1r, o_out_1r);
148
 
149
        convround #(IWIDTH+1,OWIDTH,SHIFT) do_rnd_1i(i_clk, i_ce,
150
                                                        rnd_in_1i, o_out_1i);
151
 
152
 
153
        // Prior versions of this routine did not include the extra
154
        // clock and register/flip-flops that this routine requires.
155
        // These are placed in here to correct a bug in Verilator, that
156
        // otherwise struggles.  (Hopefully this will fix the problem ...)
157
        always @(posedge i_clk)
158
                if (i_ce)
159
                begin
160
                        o_left  <= { o_out_0r, o_out_0i };
161
                        o_right <= { o_out_1r, o_out_1i };
162
                end
163
 
164
        initial o_sync = 1'b0; // Final sync coming out of module
165
        always @(posedge i_clk)
166
                if (i_reset)
167
                        o_sync <= 1'b0;
168
                else if (i_ce)
169
                        o_sync <= r_sync;
170
 
171
endmodule

powered by: WebSVN 2.1.0

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