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

Subversion Repositories dblclockfft

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

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 39 dgisselq
//      through the data at one sample per clock.
10 36 dgisselq
//
11
//
12
// Creator:     Dan Gisselquist, Ph.D.
13
//              Gisselquist Technology, LLC
14
//
15
////////////////////////////////////////////////////////////////////////////////
16
//
17
// Copyright (C) 2015-2018, Gisselquist Technology, LLC
18
//
19 39 dgisselq
// This file is part of the general purpose pipelined FFT project.
20 36 dgisselq
//
21 39 dgisselq
// The pipelined FFT project is free software (firmware): you can redistribute
22
// it and/or modify it under the terms of the GNU Lesser General Public License
23
// as published by the Free Software Foundation, either version 3 of the
24
// License, or (at your option) any later version.
25 36 dgisselq
//
26 39 dgisselq
// The pipelined FFT project is distributed in the hope that it will be useful,
27
// but WITHOUT ANY WARRANTY; without even the implied warranty of
28
// MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
29
// General Public License for more details.
30
//
31
// You should have received a copy of the GNU Lesser General Public License
32
// along with this program.  (It's in the $(ROOT)/doc directory.  Run make
33
// with no target there if the PDF file isn't present.)  If not, see
34 36 dgisselq
// <http://www.gnu.org/licenses/> for a copy.
35
//
36 39 dgisselq
// License:     LGPL, v3, as defined and found on www.gnu.org,
37
//              http://www.gnu.org/licenses/lgpl.html
38 36 dgisselq
//
39
//
40
////////////////////////////////////////////////////////////////////////////////
41
//
42
//
43
`default_nettype        none
44
//
45 39 dgisselq
module  laststage(i_clk, i_reset, i_ce, i_sync, i_val, o_val, o_sync);
46 36 dgisselq
        parameter       IWIDTH=16,OWIDTH=IWIDTH+1, SHIFT=0;
47 39 dgisselq
        input   wire                            i_clk, i_reset, i_ce, i_sync;
48
        input   wire    [(2*IWIDTH-1):0] i_val;
49
        output  wire    [(2*OWIDTH-1):0] o_val;
50
        output  reg                             o_sync;
51 36 dgisselq
 
52 39 dgisselq
        reg     signed  [(IWIDTH-1):0]   m_r, m_i;
53
        wire    signed  [(IWIDTH-1):0]   i_r, i_i;
54 36 dgisselq
 
55 39 dgisselq
        assign  i_r = i_val[(2*IWIDTH-1):(IWIDTH)];
56
        assign  i_i = i_val[(IWIDTH-1):0];
57 36 dgisselq
 
58 39 dgisselq
        // Don't forget that we accumulate a bit by adding two values
59
        // together. Therefore our intermediate value must have one more
60
        // bit than the two originals.
61
        reg     signed  [(IWIDTH):0]     rnd_r, rnd_i, sto_r, sto_i;
62
        reg                             wait_for_sync, stage;
63
        reg             [1:0]            sync_pipe;
64 36 dgisselq
 
65 39 dgisselq
        initial wait_for_sync = 1'b1;
66
        initial stage         = 1'b0;
67 36 dgisselq
        always @(posedge i_clk)
68
                if (i_reset)
69
                begin
70 39 dgisselq
                        wait_for_sync <= 1'b1;
71
                        stage         <= 1'b0;
72
                end else if ((i_ce)&&((!wait_for_sync)||(i_sync))&&(!stage))
73
                begin
74
                        wait_for_sync <= 1'b0;
75
                        //
76
                        stage <= 1'b1;
77
                        //
78 36 dgisselq
                end else if (i_ce)
79 39 dgisselq
                        stage <= 1'b0;
80 36 dgisselq
 
81 39 dgisselq
        initial sync_pipe = 0;
82
        always @(posedge i_clk)
83
        if (i_reset)
84
                sync_pipe <= 0;
85
        else if (i_ce)
86
                sync_pipe <= { sync_pipe[0], i_sync };
87 36 dgisselq
 
88 39 dgisselq
        initial o_sync = 1'b0;
89 36 dgisselq
        always @(posedge i_clk)
90 39 dgisselq
        if (i_reset)
91
                o_sync <= 1'b0;
92
        else if (i_ce)
93
                o_sync <= sync_pipe[1];
94
 
95
        always @(posedge i_clk)
96
        if (i_ce)
97
        begin
98
                if (!stage)
99 36 dgisselq
                begin
100 39 dgisselq
                        // Clock 1
101
                        m_r <= i_r;
102
                        m_i <= i_i;
103
                        // Clock 3
104
                        rnd_r <= sto_r;
105
                        rnd_i <= sto_i;
106 36 dgisselq
                        //
107 39 dgisselq
                end else begin
108
                        // Clock 2
109
                        rnd_r <= m_r + i_r;
110
                        rnd_i <= m_i + i_i;
111 36 dgisselq
                        //
112 39 dgisselq
                        sto_r <= m_r - i_r;
113
                        sto_i <= m_i - i_i;
114 36 dgisselq
                        //
115
                end
116 39 dgisselq
        end
117 36 dgisselq
 
118 39 dgisselq
        // Now that we have our results, let's round them and report them
119
        wire    signed  [(OWIDTH-1):0]   o_r, o_i;
120 36 dgisselq
 
121 39 dgisselq
        convround #(IWIDTH+1,OWIDTH,SHIFT) do_rnd_r(i_clk, i_ce, rnd_r, o_r);
122
        convround #(IWIDTH+1,OWIDTH,SHIFT) do_rnd_i(i_clk, i_ce, rnd_i, o_i);
123 36 dgisselq
 
124 39 dgisselq
        assign  o_val  = { o_r, o_i };
125 36 dgisselq
 
126 39 dgisselq
`ifdef  FORMAL
127
        reg     f_past_valid;
128
        initial f_past_valid = 1'b0;
129
        always @(posedge i_clk)
130
                f_past_valid <= 1'b1;
131 36 dgisselq
 
132 39 dgisselq
`ifdef  LASTSTAGE
133
        always @(posedge i_clk)
134
                assume((i_ce)||($past(i_ce))||($past(i_ce,2)));
135
`endif
136 36 dgisselq
 
137 39 dgisselq
        initial assert(IWIDTH+1 == OWIDTH);
138
 
139
        reg     signed  [IWIDTH-1:0]     f_piped_real    [0:3];
140
        reg     signed  [IWIDTH-1:0]     f_piped_imag    [0:3];
141 36 dgisselq
        always @(posedge i_clk)
142 39 dgisselq
        if (i_ce)
143
        begin
144
                f_piped_real[0] <= i_val[2*IWIDTH-1:IWIDTH];
145
                f_piped_imag[0] <= i_val[  IWIDTH-1:0];
146 36 dgisselq
 
147 39 dgisselq
                f_piped_real[1] <= f_piped_real[0];
148
                f_piped_imag[1] <= f_piped_imag[0];
149
 
150
                f_piped_real[2] <= f_piped_real[1];
151
                f_piped_imag[2] <= f_piped_imag[1];
152
 
153
                f_piped_real[3] <= f_piped_real[2];
154
                f_piped_imag[3] <= f_piped_imag[2];
155
        end
156
 
157
        wire    f_syncd;
158
        reg     f_rsyncd;
159
 
160
        initial f_rsyncd        = 0;
161 36 dgisselq
        always @(posedge i_clk)
162 39 dgisselq
        if (i_reset)
163
                f_rsyncd <= 1'b0;
164
        else if (!f_rsyncd)
165
                f_rsyncd <= o_sync;
166
        assign  f_syncd = (f_rsyncd)||(o_sync);
167 36 dgisselq
 
168 39 dgisselq
        reg     f_state;
169
        initial f_state = 0;
170
        always @(posedge i_clk)
171
        if (i_reset)
172
                f_state <= 0;
173
        else if ((i_ce)&&((!wait_for_sync)||(i_sync)))
174
                f_state <= f_state + 1;
175
 
176
        always @(*)
177
        if (f_state != 0)
178
                assume(!i_sync);
179
 
180
        always @(*)
181
                assert(stage == f_state[0]);
182
 
183
        always @(posedge i_clk)
184
        if ((f_state == 1'b1)&&(f_syncd))
185
        begin
186
                assert(o_r == f_piped_real[2] + f_piped_real[1]);
187
                assert(o_i == f_piped_imag[2] + f_piped_imag[1]);
188
        end
189
 
190
        always @(posedge i_clk)
191
        if ((f_state == 1'b0)&&(f_syncd))
192
        begin
193
                assert(!o_sync);
194
                assert(o_r == f_piped_real[3] - f_piped_real[2]);
195
                assert(o_i == f_piped_imag[3] - f_piped_imag[2]);
196
        end
197
 
198
        always @(*)
199
        if (wait_for_sync)
200
        begin
201
                assert(!f_rsyncd);
202
                assert(!o_sync);
203
                assert(f_state == 0);
204
        end
205
 
206
`endif // FORMAL
207 36 dgisselq
endmodule

powered by: WebSVN 2.1.0

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