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

Subversion Repositories dblclockfft

[/] [dblclockfft/] [trunk/] [rtl/] [butterfly.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:    butterfly.v
4
//
5
// Project:     A General Purpose Pipelined FFT Implementation
6
//
7
// Purpose:     This routine caculates a butterfly for a decimation
8
//              in frequency version of an FFT.  Specifically, given
9
//      complex Left and Right values together with a coefficient, the output
10
//      of this routine is given by:
11
//
12
//              L' = L + R
13
//              R' = (L - R)*C
14
//
15
//      The rest of the junk below handles timing (mostly), to make certain
16
//      that L' and R' reach the output at the same clock.  Further, just to
17
//      make certain that is the case, an 'aux' input exists.  This aux value
18
//      will come out of this routine synchronized to the values it came in
19
//      with.  (i.e., both L', R', and aux all have the same delay.)  Hence,
20
//      a caller of this routine may set aux on the first input with valid
21
//      data, and then wait to see aux set on the output to know when to find
22
//      the first output with valid data.
23
//
24
//      All bits are preserved until the very last clock, where any more bits
25
//      than OWIDTH will be quietly discarded.
26
//
27
//      This design features no overflow checking.
28
//
29
// Notes:
30
//      CORDIC:
31
//              Much as we might like, we can't use a cordic here.
32
//              The goal is to accomplish an FFT, as defined, and a
33
//              CORDIC places a scale factor onto the data.  Removing
34
//              the scale factor would cost two multiplies, which
35
//              is precisely what we are trying to avoid.
36
//
37
//
38
//      3-MULTIPLIES:
39
//              It should also be possible to do this with three multiplies
40
//              and an extra two addition cycles.
41
//
42
//              We want
43
//                      R+I = (a + jb) * (c + jd)
44
//                      R+I = (ac-bd) + j(ad+bc)
45
//              We multiply
46
//                      P1 = ac
47
//                      P2 = bd
48
//                      P3 = (a+b)(c+d)
49
//              Then
50
//                      R+I=(P1-P2)+j(P3-P2-P1)
51
//
52
//              WIDTHS:
53
//              On multiplying an X width number by an
54
//              Y width number, X>Y, the result should be (X+Y)
55
//              bits, right?
56
//              -2^(X-1) <= a <= 2^(X-1) - 1
57
//              -2^(Y-1) <= b <= 2^(Y-1) - 1
58
//              (2^(Y-1)-1)*(-2^(X-1)) <= ab <= 2^(X-1)2^(Y-1)
59
//              -2^(X+Y-2)+2^(X-1) <= ab <= 2^(X+Y-2) <= 2^(X+Y-1) - 1
60
//              -2^(X+Y-1) <= ab <= 2^(X+Y-1)-1
61
//              YUP!  But just barely.  Do this and you'll really want
62
//              to drop a bit, although you will risk overflow in so
63
//              doing.
64
//
65
//      20150602 -- The sync logic lines have been completely redone.  The
66
//              synchronization lines no longer go through the FIFO with the
67
//              left hand sum, but are kept out of memory.  This allows the
68
//              butterfly to use more optimal memory resources, while also
69
//              guaranteeing that the sync lines can be properly reset upon
70
//              any reset signal.
71
//
72
//
73
// Creator:     Dan Gisselquist, Ph.D.
74
//              Gisselquist Technology, LLC
75
//
76
////////////////////////////////////////////////////////////////////////////////
77
//
78
// Copyright (C) 2015-2018, Gisselquist Technology, LLC
79
//
80
// This program is free software (firmware): you can redistribute it and/or
81
// modify it under the terms of  the GNU General Public License as published
82
// by the Free Software Foundation, either version 3 of the License, or (at
83
// your option) any later version.
84
//
85
// This program is distributed in the hope that it will be useful, but WITHOUT
86
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
87
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
88
// for more details.
89
//
90
// You should have received a copy of the GNU General Public License along
91
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
92
// target there if the PDF file isn't present.)  If not, see
93
// <http://www.gnu.org/licenses/> for a copy.
94
//
95
// License:     GPL, v3, as defined and found on www.gnu.org,
96
//              http://www.gnu.org/licenses/gpl.html
97
//
98
//
99
////////////////////////////////////////////////////////////////////////////////
100
//
101
//
102
`default_nettype        none
103
//
104
module  butterfly(i_clk, i_reset, i_ce, i_coef, i_left, i_right, i_aux,
105
                o_left, o_right, o_aux);
106
        // Public changeable parameters ...
107
        parameter IWIDTH=16,CWIDTH=20,OWIDTH=17;
108
        parameter       SHIFT=0;
109
        // The number of clocks per each i_ce.  The actual number can be
110
        // more, but the algorithm depends upon at least this many for
111
        // extra internal processing.
112
        parameter       CKPCE=1;
113
        //
114
        // Local/derived parameters that are calculated from the above
115
        // params.  Apart from algorithmic changes below, these should not
116
        // be adjusted
117
        //
118
        // The first step is to calculate how many clocks it takes our
119
        // multiply to come back with an answer within.  The time in the
120
        // multiply depends upon the input value with the fewest number of
121
        // bits--to keep the pipeline depth short.  So, let's find the
122
        // fewest number of bits here.
123
        localparam MXMPYBITS =
124
                ((IWIDTH+2)>(CWIDTH+1)) ? (CWIDTH+1) : (IWIDTH + 2);
125
        //
126
        // Given this "fewest" number of bits, we can calculate the
127
        // number of clocks the multiply itself will take.
128
        localparam      MPYDELAY=((MXMPYBITS+1)/2)+2;
129
        //
130
        // In an environment when CKPCE > 1, the multiply delay isn't
131
        // necessarily the delay felt by this algorithm--measured in
132
        // i_ce's.  In particular, if the multiply can operate with more
133
        // operations per clock, it can appear to finish "faster".
134
        // Since most of the logic in this core operates on the slower
135
        // clock, we'll need to map that speed into the number of slower
136
        // clock ticks that it takes.
137
        localparam      LCLDELAY = (CKPCE == 1) ? MPYDELAY
138
                : (CKPCE == 2) ? (MPYDELAY/2+2)
139
                : (MPYDELAY/3 + 2);
140
        localparam      LGDELAY = (MPYDELAY>64) ? 7
141
                        : (MPYDELAY > 32) ? 6
142
                        : (MPYDELAY > 16) ? 5
143
                        : (MPYDELAY >  8) ? 4
144
                        : (MPYDELAY >  4) ? 3
145
                        : 2;
146
        localparam      AUXLEN=(LCLDELAY+3);
147
        localparam      MPYREMAINDER = MPYDELAY - CKPCE*(MPYDELAY/CKPCE);
148
 
149
 
150
        input           i_clk, i_reset, i_ce;
151
        input           [(2*CWIDTH-1):0] i_coef;
152
        input           [(2*IWIDTH-1):0] i_left, i_right;
153
        input           i_aux;
154
        output  wire    [(2*OWIDTH-1):0] o_left, o_right;
155
        output  reg     o_aux;
156
 
157
        reg     [(2*IWIDTH-1):0] r_left, r_right;
158
        reg     [(2*CWIDTH-1):0] r_coef, r_coef_2;
159
        wire    signed  [(IWIDTH-1):0]   r_left_r, r_left_i, r_right_r, r_right_i;
160
        assign  r_left_r  = r_left[ (2*IWIDTH-1):(IWIDTH)];
161
        assign  r_left_i  = r_left[ (IWIDTH-1):0];
162
        assign  r_right_r = r_right[(2*IWIDTH-1):(IWIDTH)];
163
        assign  r_right_i = r_right[(IWIDTH-1):0];
164
 
165
        reg     signed  [(IWIDTH):0]     r_sum_r, r_sum_i, r_dif_r, r_dif_i;
166
 
167
        reg     [(LGDELAY-1):0]  fifo_addr;
168
        wire    [(LGDELAY-1):0]  fifo_read_addr;
169
        assign  fifo_read_addr = fifo_addr - LCLDELAY[(LGDELAY-1):0];
170
        reg     [(2*IWIDTH+1):0] fifo_left [ 0:((1<<LGDELAY)-1)];
171
 
172
        // Set up the input to the multiply
173
        always @(posedge i_clk)
174
                if (i_ce)
175
                begin
176
                        // One clock just latches the inputs
177
                        r_left <= i_left;       // No change in # of bits
178
                        r_right <= i_right;
179
                        r_coef  <= i_coef;
180
                        // Next clock adds/subtracts
181
                        r_sum_r <= r_left_r + r_right_r; // Now IWIDTH+1 bits
182
                        r_sum_i <= r_left_i + r_right_i;
183
                        r_dif_r <= r_left_r - r_right_r;
184
                        r_dif_i <= r_left_i - r_right_i;
185
                        // Other inputs are simply delayed on second clock
186
                        r_coef_2<= r_coef;
187
                end
188
 
189
        // Don't forget to record the even side, since it doesn't need
190
        // to be multiplied, but yet we still need the results in sync
191
        // with the answer when it is ready.
192
        initial fifo_addr = 0;
193
        always @(posedge i_clk)
194
                if (i_reset)
195
                        fifo_addr <= 0;
196
                else if (i_ce)
197
                        // Need to delay the sum side--nothing else happens
198
                        // to it, but it needs to stay synchronized with the
199
                        // right side.
200
                        fifo_addr <= fifo_addr + 1;
201
 
202
        always @(posedge i_clk)
203
                if (i_ce)
204
                        fifo_left[fifo_addr] <= { r_sum_r, r_sum_i };
205
 
206
        wire    signed  [(CWIDTH-1):0]   ir_coef_r, ir_coef_i;
207
        assign  ir_coef_r = r_coef_2[(2*CWIDTH-1):CWIDTH];
208
        assign  ir_coef_i = r_coef_2[(CWIDTH-1):0];
209
        wire    signed  [((IWIDTH+2)+(CWIDTH+1)-1):0]    p_one, p_two, p_three;
210
 
211
 
212
        // Multiply output is always a width of the sum of the widths of
213
        // the two inputs.  ALWAYS.  This is independent of the number of
214
        // bits in p_one, p_two, or p_three.  These values needed to
215
        // accumulate a bit (or two) each.  However, this approach to a
216
        // three multiply complex multiply cannot increase the total
217
        // number of bits in our final output.  We'll take care of
218
        // dropping back down to the proper width, OWIDTH, in our routine
219
        // below.
220
 
221
 
222
        // We accomplish here "Karatsuba" multiplication.  That is,
223
        // by doing three multiplies we accomplish the work of four.
224
        // Let's prove to ourselves that this works ... We wish to
225
        // multiply: (a+jb) * (c+jd), where a+jb is given by
226
        //      a + jb = r_dif_r + j r_dif_i, and
227
        //      c + jd = ir_coef_r + j ir_coef_i.
228
        // We do this by calculating the intermediate products P1, P2,
229
        // and P3 as
230
        //      P1 = ac
231
        //      P2 = bd
232
        //      P3 = (a + b) * (c + d)
233
        // and then complete our final answer with
234
        //      ac - bd = P1 - P2 (this checks)
235
        //      ad + bc = P3 - P2 - P1
236
        //              = (ac + bc + ad + bd) - bd - ac
237
        //              = bc + ad (this checks)
238
 
239
 
240
        // This should really be based upon an IF, such as in
241
        // if (IWIDTH < CWIDTH) then ...
242
        // However, this is the only (other) way I know to do it.
243
        generate if (CKPCE <= 1)
244
        begin
245
 
246
                wire    [(CWIDTH):0]     p3c_in;
247
                wire    [(IWIDTH+1):0]   p3d_in;
248
                assign  p3c_in = ir_coef_i + ir_coef_r;
249
                assign  p3d_in = r_dif_r + r_dif_i;
250
 
251
                // We need to pad these first two multiplies by an extra
252
                // bit just to keep them aligned with the third,
253
                // simpler, multiply.
254
                longbimpy #(CWIDTH+1,IWIDTH+2) p1(i_clk, i_ce,
255
                                {ir_coef_r[CWIDTH-1],ir_coef_r},
256
                                {r_dif_r[IWIDTH],r_dif_r}, p_one);
257
                longbimpy #(CWIDTH+1,IWIDTH+2) p2(i_clk, i_ce,
258
                                {ir_coef_i[CWIDTH-1],ir_coef_i},
259
                                {r_dif_i[IWIDTH],r_dif_i}, p_two);
260
                longbimpy #(CWIDTH+1,IWIDTH+2) p3(i_clk, i_ce,
261
                                p3c_in, p3d_in, p_three);
262
 
263
        end else if (CKPCE == 2)
264
        begin : CKPCE_TWO
265
                // Coefficient multiply inputs
266
                reg             [2*(CWIDTH)-1:0] mpy_pipe_c;
267
                // Data multiply inputs
268
                reg             [2*(IWIDTH+1)-1:0]       mpy_pipe_d;
269
                wire    signed  [(CWIDTH-1):0]   mpy_pipe_vc;
270
                wire    signed  [(IWIDTH):0]     mpy_pipe_vd;
271
                //
272
                reg     signed  [(CWIDTH+1)-1:0] mpy_cof_sum;
273
                reg     signed  [(IWIDTH+2)-1:0] mpy_dif_sum;
274
 
275
                assign  mpy_pipe_vc =  mpy_pipe_c[2*(CWIDTH)-1:CWIDTH];
276
                assign  mpy_pipe_vd =  mpy_pipe_d[2*(IWIDTH+1)-1:IWIDTH+1];
277
 
278
                reg                     mpy_pipe_v;
279
                reg                     ce_phase;
280
 
281
                reg     signed  [(CWIDTH+IWIDTH+3)-1:0]  mpy_pipe_out;
282
                reg     signed [IWIDTH+CWIDTH+3-1:0]     longmpy;
283
 
284
 
285
                initial ce_phase = 1'b0;
286
                always @(posedge i_clk)
287
                if (i_reset)
288
                        ce_phase <= 1'b0;
289
                else if (i_ce)
290
                        ce_phase <= 1'b1;
291
                else
292
                        ce_phase <= 1'b0;
293
 
294
                always @(*)
295
                        mpy_pipe_v = (i_ce)||(ce_phase);
296
 
297
                always @(posedge i_clk)
298
                if (ce_phase)
299
                begin
300
                        mpy_pipe_c[2*CWIDTH-1:0] <=
301
                                        { ir_coef_r, ir_coef_i };
302
                        mpy_pipe_d[2*(IWIDTH+1)-1:0] <=
303
                                        { r_dif_r, r_dif_i };
304
 
305
                        mpy_cof_sum  <= ir_coef_i + ir_coef_r;
306
                        mpy_dif_sum <= r_dif_r + r_dif_i;
307
 
308
                end else if (i_ce)
309
                begin
310
                        mpy_pipe_c[2*(CWIDTH)-1:0] <= {
311
                                mpy_pipe_c[(CWIDTH)-1:0], {(CWIDTH){1'b0}} };
312
                        mpy_pipe_d[2*(IWIDTH+1)-1:0] <= {
313
                                mpy_pipe_d[(IWIDTH+1)-1:0], {(IWIDTH+1){1'b0}} };
314
                end
315
 
316
                longbimpy #(CWIDTH+1,IWIDTH+2) mpy0(i_clk, mpy_pipe_v,
317
                                mpy_cof_sum, mpy_dif_sum, longmpy);
318
 
319
                longbimpy #(CWIDTH+1,IWIDTH+2) mpy1(i_clk, mpy_pipe_v,
320
                                { mpy_pipe_vc[CWIDTH-1], mpy_pipe_vc },
321
                                { mpy_pipe_vd[IWIDTH  ], mpy_pipe_vd },
322
                                mpy_pipe_out);
323
 
324
                reg     signed  [((IWIDTH+2)+(CWIDTH+1)-1):0]
325
                                        rp_one, rp_two, rp_three,
326
                                        rp2_one, rp2_two, rp2_three;
327
 
328
                always @(posedge i_clk)
329
                if (((i_ce)&&(!MPYDELAY[0]))
330
                        ||((ce_phase)&&(MPYDELAY[0])))
331
                        rp_one <= mpy_pipe_out;
332
                always @(posedge i_clk)
333
                if (((i_ce)&&(MPYDELAY[0]))
334
                        ||((ce_phase)&&(!MPYDELAY[0])))
335
                        rp_two <= mpy_pipe_out;
336
                always @(posedge i_clk)
337
                if (i_ce)
338
                        rp_three <= longmpy;
339
 
340
                // Our outputs *MUST* be set on a clock where i_ce is
341
                // true for the following logic to work.  Make that
342
                // happen here.
343
                always @(posedge i_clk)
344
                if (i_ce)
345
                        rp2_one<= rp_one;
346
                always @(posedge i_clk)
347
                if (i_ce)
348
                        rp2_two <= rp_two;
349
                always @(posedge i_clk)
350
                if (i_ce)
351
                        rp2_three<= rp_three;
352
 
353
                assign  p_one   = rp2_one;
354
                assign  p_two   = (!MPYDELAY[0])? rp2_two  : rp_two;
355
                assign  p_three = ( MPYDELAY[0])? rp_three : rp2_three;
356
 
357
                // verilator lint_off UNUSED
358
                wire    [2*(IWIDTH+CWIDTH+3)-1:0]        unused;
359
                assign  unused = { rp2_two, rp2_three };
360
                // verilator lint_on  UNUSED
361
 
362
        end else if (CKPCE <= 3)
363
        begin : CKPCE_THREE
364
                // Coefficient multiply inputs
365
                reg             [3*(CWIDTH+1)-1:0]       mpy_pipe_c;
366
                // Data multiply inputs
367
                reg             [3*(IWIDTH+2)-1:0]       mpy_pipe_d;
368
                wire    signed  [(CWIDTH):0]     mpy_pipe_vc;
369
                wire    signed  [(IWIDTH+1):0]   mpy_pipe_vd;
370
 
371
                assign  mpy_pipe_vc =  mpy_pipe_c[3*(CWIDTH+1)-1:2*(CWIDTH+1)];
372
                assign  mpy_pipe_vd =  mpy_pipe_d[3*(IWIDTH+2)-1:2*(IWIDTH+2)];
373
 
374
                reg                     mpy_pipe_v;
375
                reg             [2:0]    ce_phase;
376
 
377
                reg     signed  [  (CWIDTH+IWIDTH+3)-1:0]        mpy_pipe_out;
378
 
379
                initial ce_phase = 3'b011;
380
                always @(posedge i_clk)
381
                if (i_reset)
382
                        ce_phase <= 3'b011;
383
                else if (i_ce)
384
                        ce_phase <= 3'b000;
385
                else if (ce_phase != 3'b011)
386
                        ce_phase <= ce_phase + 1'b1;
387
 
388
                always @(*)
389
                        mpy_pipe_v = (i_ce)||(ce_phase < 3'b010);
390
 
391
                always @(posedge i_clk)
392
                        if (ce_phase == 3'b000)
393
                        begin
394
                                // Second clock
395
                                mpy_pipe_c[3*(CWIDTH+1)-1:(CWIDTH+1)] <= {
396
                                        ir_coef_r[CWIDTH-1], ir_coef_r,
397
                                        ir_coef_i[CWIDTH-1], ir_coef_i };
398
                                mpy_pipe_c[CWIDTH:0] <= ir_coef_i + ir_coef_r;
399
                                mpy_pipe_d[3*(IWIDTH+2)-1:(IWIDTH+2)] <= {
400
                                        r_dif_r[IWIDTH], r_dif_r,
401
                                        r_dif_i[IWIDTH], r_dif_i };
402
                                mpy_pipe_d[(IWIDTH+2)-1:0] <= r_dif_r + r_dif_i;
403
 
404
                        end else if (mpy_pipe_v)
405
                        begin
406
                                mpy_pipe_c[3*(CWIDTH+1)-1:0] <= {
407
                                        mpy_pipe_c[2*(CWIDTH+1)-1:0], {(CWIDTH+1){1'b0}} };
408
                                mpy_pipe_d[3*(IWIDTH+2)-1:0] <= {
409
                                        mpy_pipe_d[2*(IWIDTH+2)-1:0], {(IWIDTH+2){1'b0}} };
410
                        end
411
 
412
                longbimpy #(CWIDTH+1,IWIDTH+2) mpy(i_clk, mpy_pipe_v,
413
                                mpy_pipe_vc, mpy_pipe_vd, mpy_pipe_out);
414
 
415
                reg     signed  [((IWIDTH+2)+(CWIDTH+1)-1):0]
416
                                rp_one,  rp_two,  rp_three,
417
                                rp2_one, rp2_two, rp2_three,
418
                                rp3_one;
419
 
420
                always @(posedge i_clk)
421
                if (MPYREMAINDER == 0)
422
                begin
423
 
424
                        if (i_ce)
425
                                rp_two   <= mpy_pipe_out;
426
                        else if (ce_phase == 3'b000)
427
                                rp_three <= mpy_pipe_out;
428
                        else if (ce_phase == 3'b001)
429
                                rp_one   <= mpy_pipe_out;
430
 
431
                end else if (MPYREMAINDER == 1)
432
                begin
433
 
434
                        if (i_ce)
435
                                rp_one   <= mpy_pipe_out;
436
                        else if (ce_phase == 3'b000)
437
                                rp_two   <= mpy_pipe_out;
438
                        else if (ce_phase == 3'b001)
439
                                rp_three <= mpy_pipe_out;
440
 
441
                end else // if (MPYREMAINDER == 2)
442
                begin
443
 
444
                        if (i_ce)
445
                                rp_three <= mpy_pipe_out;
446
                        else if (ce_phase == 3'b000)
447
                                rp_one   <= mpy_pipe_out;
448
                        else if (ce_phase == 3'b001)
449
                                rp_two   <= mpy_pipe_out;
450
 
451
                end
452
 
453
                always @(posedge i_clk)
454
                if (i_ce)
455
                begin
456
                        rp2_one   <= rp_one;
457
                        rp2_two   <= rp_two;
458
                        rp2_three <= (MPYREMAINDER == 2) ? mpy_pipe_out : rp_three;
459
                        rp3_one   <= (MPYREMAINDER == 0) ? rp2_one : rp_one;
460
                end
461
                assign  p_one   = rp3_one;
462
                assign  p_two   = rp2_two;
463
                assign  p_three = rp2_three;
464
 
465
        end endgenerate
466
        // These values are held in memory and delayed during the
467
        // multiply.  Here, we recover them.  During the multiply,
468
        // values were multiplied by 2^(CWIDTH-2)*exp{-j*2*pi*...},
469
        // therefore, the left_x values need to be right shifted by
470
        // CWIDTH-2 as well.  The additional bits come from a sign
471
        // extension.
472
        wire    signed  [(IWIDTH+CWIDTH):0]      fifo_i, fifo_r;
473
        reg             [(2*IWIDTH+1):0] fifo_read;
474
        assign  fifo_r = { {2{fifo_read[2*(IWIDTH+1)-1]}}, fifo_read[(2*(IWIDTH+1)-1):(IWIDTH+1)], {(CWIDTH-2){1'b0}} };
475
        assign  fifo_i = { {2{fifo_read[(IWIDTH+1)-1]}}, fifo_read[((IWIDTH+1)-1):0], {(CWIDTH-2){1'b0}} };
476
 
477
 
478
        reg     signed  [(CWIDTH+IWIDTH+3-1):0]  mpy_r, mpy_i;
479
 
480
        // Let's do some rounding and remove unnecessary bits.
481
        // We have (IWIDTH+CWIDTH+3) bits here, we need to drop down to
482
        // OWIDTH, and SHIFT by SHIFT bits in the process.  The trick is
483
        // that we don't need (IWIDTH+CWIDTH+3) bits.  We've accumulated
484
        // them, but the actual values will never fill all these bits.
485
        // In particular, we only need:
486
        //       IWIDTH bits for the input
487
        //           +1 bit for the add/subtract
488
        //      +CWIDTH bits for the coefficient multiply
489
        //           +1 bit for the add/subtract in the complex multiply
490
        //       ------
491
        //       (IWIDTH+CWIDTH+2) bits at full precision.
492
        //
493
        // However, the coefficient multiply multiplied by a maximum value
494
        // of 2^(CWIDTH-2).  Thus, we only have
495
        //         IWIDTH bits for the input
496
        //             +1 bit for the add/subtract
497
        //      +CWIDTH-2 bits for the coefficient multiply
498
        //             +1 (optional) bit for the add/subtract in the cpx mpy.
499
        //       -------- ... multiply.  (This last bit may be shifted out.)
500
        //       (IWIDTH+CWIDTH) valid output bits.
501
        // Now, if the user wants to keep any extras of these (via OWIDTH),
502
        // or if he wishes to arbitrarily shift some of these off (via
503
        // SHIFT) we accomplish that here.
504
 
505
        wire    signed  [(OWIDTH-1):0]   rnd_left_r, rnd_left_i, rnd_right_r, rnd_right_i;
506
 
507
        wire    signed  [(CWIDTH+IWIDTH+3-1):0]  left_sr, left_si;
508
        assign  left_sr = { {(2){fifo_r[(IWIDTH+CWIDTH)]}}, fifo_r };
509
        assign  left_si = { {(2){fifo_i[(IWIDTH+CWIDTH)]}}, fifo_i };
510
 
511
        convround #(CWIDTH+IWIDTH+3,OWIDTH,SHIFT+4) do_rnd_left_r(i_clk, i_ce,
512
                                left_sr, rnd_left_r);
513
 
514
        convround #(CWIDTH+IWIDTH+3,OWIDTH,SHIFT+4) do_rnd_left_i(i_clk, i_ce,
515
                                left_si, rnd_left_i);
516
 
517
        convround #(CWIDTH+IWIDTH+3,OWIDTH,SHIFT+4) do_rnd_right_r(i_clk, i_ce,
518
                                mpy_r, rnd_right_r);
519
 
520
        convround #(CWIDTH+IWIDTH+3,OWIDTH,SHIFT+4) do_rnd_right_i(i_clk, i_ce,
521
                                mpy_i, rnd_right_i);
522
 
523
        always @(posedge i_clk)
524
                if (i_ce)
525
                begin
526
                        // First clock, recover all values
527
                        fifo_read <= fifo_left[fifo_read_addr];
528
                        // These values are IWIDTH+CWIDTH+3 bits wide
529
                        // although they only need to be (IWIDTH+1)
530
                        // + (CWIDTH) bits wide.  (We've got two
531
                        // extra bits we need to get rid of.)
532
                        mpy_r <= p_one - p_two;
533
                        mpy_i <= p_three - p_one - p_two;
534
                end
535
 
536
        reg     [(AUXLEN-1):0]   aux_pipeline;
537
        initial aux_pipeline = 0;
538
        always @(posedge i_clk)
539
                if (i_reset)
540
                        aux_pipeline <= 0;
541
                else if (i_ce)
542
                        aux_pipeline <= { aux_pipeline[(AUXLEN-2):0], i_aux };
543
 
544
        initial o_aux = 1'b0;
545
        always @(posedge i_clk)
546
                if (i_reset)
547
                        o_aux <= 1'b0;
548
                else if (i_ce)
549
                begin
550
                        // Second clock, latch for final clock
551
                        o_aux <= aux_pipeline[AUXLEN-1];
552
                end
553
 
554
        // As a final step, we pack our outputs into two packed two's
555
        // complement numbers per output word, so that each output word
556
        // has (2*OWIDTH) bits in it, with the top half being the real
557
        // portion and the bottom half being the imaginary portion.
558
        assign  o_left = { rnd_left_r, rnd_left_i };
559
        assign  o_right= { rnd_right_r,rnd_right_i};
560
 
561
`ifdef  VERILATOR
562
`define FORMAL
563
`endif
564
`ifdef  FORMAL
565
        localparam      F_LGDEPTH = (AUXLEN > 64) ? 7
566
                        : (AUXLEN > 32) ? 6
567
                        : (AUXLEN > 16) ? 5
568
                        : (AUXLEN >  8) ? 4
569
                        : (AUXLEN >  4) ? 3 : 2;
570
 
571
        localparam      F_DEPTH = AUXLEN;
572
        localparam      [F_LGDEPTH-1:0]  F_D = F_DEPTH[F_LGDEPTH-1:0]-1;
573
 
574
        reg     signed  [IWIDTH-1:0]     f_dlyleft_r  [0:F_DEPTH-1];
575
        reg     signed  [IWIDTH-1:0]     f_dlyleft_i  [0:F_DEPTH-1];
576
        reg     signed  [IWIDTH-1:0]     f_dlyright_r [0:F_DEPTH-1];
577
        reg     signed  [IWIDTH-1:0]     f_dlyright_i [0:F_DEPTH-1];
578
        reg     signed  [CWIDTH-1:0]     f_dlycoeff_r [0:F_DEPTH-1];
579
        reg     signed  [CWIDTH-1:0]     f_dlycoeff_i [0:F_DEPTH-1];
580
        reg     signed  [F_DEPTH-1:0]    f_dlyaux;
581
 
582
        initial f_dlyaux[0] = 0;
583
        always @(posedge i_clk)
584
        if (i_reset)
585
                f_dlyaux        <= 0;
586
        else if (i_ce)
587
                f_dlyaux        <= { f_dlyaux[F_DEPTH-2:0], i_aux };
588
 
589
        always @(posedge i_clk)
590
        if (i_ce)
591
        begin
592
                f_dlyleft_r[0]   <= i_left[ (2*IWIDTH-1):IWIDTH];
593
                f_dlyleft_i[0]   <= i_left[ (  IWIDTH-1):0];
594
                f_dlyright_r[0]  <= i_right[(2*IWIDTH-1):IWIDTH];
595
                f_dlyright_i[0]  <= i_right[(  IWIDTH-1):0];
596
                f_dlycoeff_r[0]  <= i_coef[ (2*CWIDTH-1):CWIDTH];
597
                f_dlycoeff_i[0]  <= i_coef[ (  CWIDTH-1):0];
598
        end
599
 
600
        genvar  k;
601
        generate for(k=1; k<F_DEPTH; k=k+1)
602
        begin : F_PROPAGATE_DELAY_LINES
603
 
604
 
605
                always @(posedge i_clk)
606
                if (i_ce)
607
                begin
608
                        f_dlyleft_r[k]  <= f_dlyleft_r[ k-1];
609
                        f_dlyleft_i[k]  <= f_dlyleft_i[ k-1];
610
                        f_dlyright_r[k] <= f_dlyright_r[k-1];
611
                        f_dlyright_i[k] <= f_dlyright_i[k-1];
612
                        f_dlycoeff_r[k] <= f_dlycoeff_r[k-1];
613
                        f_dlycoeff_i[k] <= f_dlycoeff_i[k-1];
614
                end
615
 
616
        end endgenerate
617
 
618
`ifndef VERILATOR
619
        always @(posedge i_clk)
620
        if ((!$past(i_ce))&&(!$past(i_ce,2))&&(!$past(i_ce,3))
621
                        &&(!$past(i_ce,4)))
622
                assume(i_ce);
623
 
624
        generate if (CKPCE <= 1)
625
        begin
626
 
627
                // i_ce is allowed to be anything in this mode
628
 
629
        end else if (CKPCE == 2)
630
        begin : F_CKPCE_TWO
631
 
632
                always @(posedge i_clk)
633
                        if ($past(i_ce))
634
                                assume(!i_ce);
635
 
636
        end else if (CKPCE == 3)
637
        begin : F_CKPCE_THREE
638
 
639
                always @(posedge i_clk)
640
                        if (($past(i_ce))||($past(i_ce,2)))
641
                                assume(!i_ce);
642
 
643
        end endgenerate
644
`endif
645
 
646
        reg     [F_LGDEPTH:0]    f_startup_counter;
647
        initial f_startup_counter = 0;
648
        always @(posedge i_clk)
649
        if (i_reset)
650
                f_startup_counter <= 0;
651
        else if ((i_ce)&&(!(&f_startup_counter)))
652
                f_startup_counter <= f_startup_counter + 1;
653
 
654
        wire    signed  [IWIDTH:0]       f_sumr, f_sumi;
655
        always @(*)
656
        begin
657
                f_sumr = f_dlyleft_r[F_D] + f_dlyright_r[F_D];
658
                f_sumi = f_dlyleft_i[F_D] + f_dlyright_i[F_D];
659
        end
660
 
661
        wire    signed  [IWIDTH+CWIDTH+3-1:0]    f_sumrx, f_sumix;
662
        assign  f_sumrx = { {(4){f_sumr[IWIDTH]}}, f_sumr, {(CWIDTH-2){1'b0}} };
663
        assign  f_sumix = { {(4){f_sumi[IWIDTH]}}, f_sumi, {(CWIDTH-2){1'b0}} };
664
 
665
        wire    signed  [IWIDTH:0]       f_difr, f_difi;
666
        always @(*)
667
        begin
668
                f_difr = f_dlyleft_r[F_D] - f_dlyright_r[F_D];
669
                f_difi = f_dlyleft_i[F_D] - f_dlyright_i[F_D];
670
        end
671
 
672
        wire    signed  [IWIDTH+CWIDTH+3-1:0]    f_difrx, f_difix;
673
        assign  f_difrx = { {(CWIDTH+2){f_difr[IWIDTH]}}, f_difr };
674
        assign  f_difix = { {(CWIDTH+2){f_difi[IWIDTH]}}, f_difi };
675
 
676
        wire    signed  [IWIDTH+CWIDTH+3-1:0]    f_widecoeff_r, f_widecoeff_i;
677
        assign  f_widecoeff_r ={ {(IWIDTH+3){f_dlycoeff_r[F_D][CWIDTH-1]}},
678
                                                f_dlycoeff_r[F_D] };
679
        assign  f_widecoeff_i ={ {(IWIDTH+3){f_dlycoeff_i[F_D][CWIDTH-1]}},
680
                                                f_dlycoeff_i[F_D] };
681
 
682
        always @(posedge i_clk)
683
        if (f_startup_counter > {1'b0, F_D})
684
        begin
685
                assert(aux_pipeline == f_dlyaux);
686
                assert(left_sr == f_sumrx);
687
                assert(left_si == f_sumix);
688
                assert(aux_pipeline[AUXLEN-1] == f_dlyaux[F_D]);
689
 
690
                if ((f_difr == 0)&&(f_difi == 0))
691
                begin
692
                        assert(mpy_r == 0);
693
                        assert(mpy_i == 0);
694
                end else if ((f_dlycoeff_r[F_D] == 0)
695
                                &&(f_dlycoeff_i[F_D] == 0))
696
                begin
697
                        assert(mpy_r == 0);
698
                        assert(mpy_i == 0);
699
                end
700
 
701
                if ((f_dlycoeff_r[F_D] == 1)&&(f_dlycoeff_i[F_D] == 0))
702
                begin
703
                        assert(mpy_r == f_difrx);
704
                        assert(mpy_i == f_difix);
705
                end
706
 
707
                if ((f_dlycoeff_r[F_D] == 0)&&(f_dlycoeff_i[F_D] == 1))
708
                begin
709
                        assert(mpy_r == -f_difix);
710
                        assert(mpy_i ==  f_difrx);
711
                end
712
 
713
                if ((f_difr == 1)&&(f_difi == 0))
714
                begin
715
                        assert(mpy_r == f_widecoeff_r);
716
                        assert(mpy_i == f_widecoeff_i);
717
                end
718
 
719
                if ((f_difr == 0)&&(f_difi == 1))
720
                begin
721
                        assert(mpy_r == -f_widecoeff_i);
722
                        assert(mpy_i ==  f_widecoeff_r);
723
                end
724
        end
725
 
726
        // Let's see if we can improve our performance at all by
727
        // moving our test one clock earlier.  If nothing else, it should
728
        // help induction finish one (or more) clocks ealier than
729
        // otherwise
730
 
731
 
732
        wire    signed  [IWIDTH:0]       f_predifr, f_predifi;
733
        always @(*)
734
        begin
735
                f_predifr = f_dlyleft_r[F_D-1] - f_dlyright_r[F_D-1];
736
                f_predifi = f_dlyleft_i[F_D-1] - f_dlyright_i[F_D-1];
737
        end
738
 
739
        wire    signed  [IWIDTH+CWIDTH+3-1:0]    f_predifrx, f_predifix;
740
        assign  f_predifrx = { {(CWIDTH+2){f_predifr[IWIDTH]}}, f_predifr };
741
        assign  f_predifix = { {(CWIDTH+2){f_predifi[IWIDTH]}}, f_predifi };
742
 
743
        wire    signed  [CWIDTH:0]       f_sumcoef;
744
        wire    signed  [IWIDTH+1:0]     f_sumdiff;
745
        always @(*)
746
        begin
747
                f_sumcoef = f_dlycoeff_r[F_D-1] + f_dlycoeff_i[F_D-1];
748
                f_sumdiff = f_predifr + f_predifi;
749
        end
750
 
751
        // Induction helpers
752
        always @(posedge i_clk)
753
        if (f_startup_counter >= { 1'b0, F_D })
754
        begin
755
                if (f_dlycoeff_r[F_D-1] == 0)
756
                        assert(p_one == 0);
757
                if (f_dlycoeff_i[F_D-1] == 0)
758
                        assert(p_two == 0);
759
 
760
                if (f_dlycoeff_r[F_D-1] == 1)
761
                        assert(p_one == f_predifrx);
762
                if (f_dlycoeff_i[F_D-1] == 1)
763
                        assert(p_two == f_predifix);
764
 
765
                if (f_predifr == 0)
766
                        assert(p_one == 0);
767
                if (f_predifi == 0)
768
                        assert(p_two == 0);
769
 
770
                // verilator lint_off WIDTH
771
                if (f_predifr == 1)
772
                        assert(p_one == f_dlycoeff_r[F_D-1]);
773
                if (f_predifi == 1)
774
                        assert(p_two == f_dlycoeff_i[F_D-1]);
775
                // verilator lint_on  WIDTH
776
 
777
                if (f_sumcoef == 0)
778
                        assert(p_three == 0);
779
                if (f_sumdiff == 0)
780
                        assert(p_three == 0);
781
                // verilator lint_off WIDTH
782
                if (f_sumcoef == 1)
783
                        assert(p_three == f_sumdiff);
784
                if (f_sumdiff == 1)
785
                        assert(p_three == f_sumcoef);
786
                // verilator lint_on  WIDTH
787
`ifdef  VERILATOR
788
                assert(p_one   == f_predifr * f_dlycoeff_r[F_D-1]);
789
                assert(p_two   == f_predifi * f_dlycoeff_i[F_D-1]);
790
                assert(p_three == f_sumdiff * f_sumcoef);
791
`endif  // VERILATOR
792
        end
793
 
794
        // F_CHECK will be set externally by the solver, so that we can
795
        // double check that the solver is actually testing what we think
796
        // it is testing.  We'll set it here to MPYREMAINDER, which will
797
        // essentially eliminate the check--unless overridden by the
798
        // solver.
799
        parameter       F_CHECK = MPYREMAINDER;
800
        initial assert(MPYREMAINDER == F_CHECK);
801
 
802
`endif // FORMAL
803
endmodule

powered by: WebSVN 2.1.0

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