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

Subversion Repositories dblclockfft

[/] [dblclockfft/] [trunk/] [rtl/] [hwbfly.v] - Blame information for rev 39

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 36 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    hwbfly.v
4
//
5
// Project:     A General Purpose Pipelined FFT Implementation
6
//
7
// Purpose:     This routine is identical to the butterfly.v routine found
8
//              in 'butterfly.v', save only that it uses the verilog
9
//      operator '*' in hopes that the synthesizer would be able to optimize
10
//      it with hardware resources.
11
//
12
//      It is understood that a hardware multiply can complete its operation in
13
//      a single clock.
14
//
15
// Operation:
16
//
17
//      Given two inputs, A (i_left) and B (i_right), and a complex
18
//      coefficient C (i_coeff), return two outputs, O1 and O2, where:
19
//
20
//              O1 = A + B, and
21
//              O2 = (A - B)*C
22
//
23
//      This operation is commonly known as a Decimation in Frequency (DIF)
24
//      Radix-2 Butterfly.
25
//      O1 and O2 are rounded before being returned in (o_left) and o_right
26
//      to OWIDTH bits.  If SHIFT is one, an extra bit is dropped from these
27
//      values during the rounding process.
28
//
29
//      Further, since these outputs will take some number of clocks to
30
//      calculate, we'll pipe a value (i_aux) through the system and return
31
//      it with the results (o_aux), so you can synchronize to the outgoing
32
//      output stream.
33
//
34
//
35
// Creator:     Dan Gisselquist, Ph.D.
36
//              Gisselquist Technology, LLC
37
//
38
////////////////////////////////////////////////////////////////////////////////
39
//
40
// Copyright (C) 2015-2018, Gisselquist Technology, LLC
41
//
42 39 dgisselq
// This file is part of the general purpose pipelined FFT project.
43 36 dgisselq
//
44 39 dgisselq
// The pipelined FFT project is free software (firmware): you can redistribute
45
// it and/or modify it under the terms of the GNU Lesser General Public License
46
// as published by the Free Software Foundation, either version 3 of the
47
// License, or (at your option) any later version.
48 36 dgisselq
//
49 39 dgisselq
// The pipelined FFT project is distributed in the hope that it will be useful,
50
// but WITHOUT ANY WARRANTY; without even the implied warranty of
51
// MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
52
// General Public License for more details.
53
//
54
// You should have received a copy of the GNU Lesser General Public License
55
// along with this program.  (It's in the $(ROOT)/doc directory.  Run make
56
// with no target there if the PDF file isn't present.)  If not, see
57 36 dgisselq
// <http://www.gnu.org/licenses/> for a copy.
58
//
59 39 dgisselq
// License:     LGPL, v3, as defined and found on www.gnu.org,
60
//              http://www.gnu.org/licenses/lgpl.html
61 36 dgisselq
//
62
//
63
////////////////////////////////////////////////////////////////////////////////
64
//
65
//
66
`default_nettype        none
67
//
68
module  hwbfly(i_clk, i_reset, i_ce, i_coef, i_left, i_right, i_aux,
69
                o_left, o_right, o_aux);
70
        // Public changeable parameters ...
71
        //      - IWIDTH, number of bits in each component of the input
72
        //      - CWIDTH, number of bits in each component of the twiddle factor
73
        //      - OWIDTH, number of bits in each component of the output
74
        parameter IWIDTH=16,CWIDTH=IWIDTH+4,OWIDTH=IWIDTH+1;
75
        // Drop an additional bit on the output?
76
        parameter               SHIFT=0;
77
        // The number of clocks per clock enable, 1, 2, or 3.
78
        parameter       [1:0]    CKPCE=1;
79
        //
80 39 dgisselq
        input   wire    i_clk, i_reset, i_ce;
81
        input   wire    [(2*CWIDTH-1):0] i_coef;
82
        input   wire    [(2*IWIDTH-1):0] i_left, i_right;
83
        input   wire    i_aux;
84 36 dgisselq
        output  wire    [(2*OWIDTH-1):0] o_left, o_right;
85
        output  reg     o_aux;
86
 
87
 
88
        reg     [(2*IWIDTH-1):0] r_left, r_right;
89
        reg                             r_aux, r_aux_2;
90
        reg     [(2*CWIDTH-1):0] r_coef;
91
        wire    signed  [(IWIDTH-1):0]   r_left_r, r_left_i, r_right_r, r_right_i;
92
        assign  r_left_r  = r_left[ (2*IWIDTH-1):(IWIDTH)];
93
        assign  r_left_i  = r_left[ (IWIDTH-1):0];
94
        assign  r_right_r = r_right[(2*IWIDTH-1):(IWIDTH)];
95
        assign  r_right_i = r_right[(IWIDTH-1):0];
96
        reg     signed  [(CWIDTH-1):0]   ir_coef_r, ir_coef_i;
97
 
98
        reg     signed  [(IWIDTH):0]     r_sum_r, r_sum_i, r_dif_r, r_dif_i;
99
 
100
        reg     [(2*IWIDTH+2):0] leftv, leftvv;
101
 
102
        // Set up the input to the multiply
103
        initial r_aux   = 1'b0;
104
        initial r_aux_2 = 1'b0;
105
        always @(posedge i_clk)
106
                if (i_reset)
107
                begin
108
                        r_aux <= 1'b0;
109
                        r_aux_2 <= 1'b0;
110
                end else if (i_ce)
111
                begin
112
                        // One clock just latches the inputs
113
                        r_aux <= i_aux;
114
                        // Next clock adds/subtracts
115
                        // Other inputs are simply delayed on second clock
116
                        r_aux_2 <= r_aux;
117
                end
118
        always @(posedge i_clk)
119
                if (i_ce)
120
                begin
121
                        // One clock just latches the inputs
122
                        r_left <= i_left;       // No change in # of bits
123
                        r_right <= i_right;
124
                        r_coef  <= i_coef;
125
                        // Next clock adds/subtracts
126
                        r_sum_r <= r_left_r + r_right_r; // Now IWIDTH+1 bits
127
                        r_sum_i <= r_left_i + r_right_i;
128
                        r_dif_r <= r_left_r - r_right_r;
129
                        r_dif_i <= r_left_i - r_right_i;
130
                        // Other inputs are simply delayed on second clock
131
                        ir_coef_r <= r_coef[(2*CWIDTH-1):CWIDTH];
132
                        ir_coef_i <= r_coef[(CWIDTH-1):0];
133
                end
134
 
135
 
136
        // See comments in the butterfly.v source file for a discussion of
137
        // these operations and the appropriate bit widths.
138
 
139
        wire    signed  [((IWIDTH+1)+(CWIDTH)-1):0]      p_one, p_two;
140
        wire    signed  [((IWIDTH+2)+(CWIDTH+1)-1):0]    p_three;
141
 
142
        initial leftv    = 0;
143
        initial leftvv   = 0;
144
        always @(posedge i_clk)
145
                if (i_reset)
146
                begin
147
                        leftv <= 0;
148
                        leftvv <= 0;
149
                end else if (i_ce)
150
                begin
151
                        // Second clock, pipeline = 1
152
                        leftv <= { r_aux_2, r_sum_r, r_sum_i };
153
 
154
                        // Third clock, pipeline = 3
155
                        //   As desired, each of these lines infers a DSP48
156
                        leftvv <= leftv;
157
                end
158
 
159
        generate if (CKPCE <= 1)
160
        begin : CKPCE_ONE
161
                // Coefficient multiply inputs
162
                reg     signed  [(CWIDTH-1):0]   p1c_in, p2c_in;
163
                // Data multiply inputs
164
                reg     signed  [(IWIDTH):0]     p1d_in, p2d_in;
165
                // Product 3, coefficient input
166
                reg     signed  [(CWIDTH):0]     p3c_in;
167
                // Product 3, data input
168
                reg     signed  [(IWIDTH+1):0]   p3d_in;
169
 
170
                reg     signed  [((IWIDTH+1)+(CWIDTH)-1):0]      rp_one, rp_two;
171
                reg     signed  [((IWIDTH+2)+(CWIDTH+1)-1):0]    rp_three;
172
 
173
                always @(posedge i_clk)
174
                if (i_ce)
175
                begin
176
                        // Second clock, pipeline = 1
177
                        p1c_in <= ir_coef_r;
178
                        p2c_in <= ir_coef_i;
179
                        p1d_in <= r_dif_r;
180
                        p2d_in <= r_dif_i;
181
                        p3c_in <= ir_coef_i + ir_coef_r;
182
                        p3d_in <= r_dif_r + r_dif_i;
183
                end
184
 
185
`ifndef FORMAL
186
                always @(posedge i_clk)
187
                if (i_ce)
188
                begin
189
                        // Third clock, pipeline = 3
190
                        //   As desired, each of these lines infers a DSP48
191
                        rp_one   <= p1c_in * p1d_in;
192
                        rp_two   <= p2c_in * p2d_in;
193
                        rp_three <= p3c_in * p3d_in;
194
                end
195
`else
196
                wire    signed  [((IWIDTH+1)+(CWIDTH)-1):0]      pre_rp_one, pre_rp_two;
197
                wire    signed  [((IWIDTH+2)+(CWIDTH+1)-1):0]    pre_rp_three;
198
 
199
                abs_mpy #(CWIDTH,IWIDTH+1,1'b1)
200
                        onei(p1c_in, p1d_in, pre_rp_one);
201
                abs_mpy #(CWIDTH,IWIDTH+1,1'b1)
202
                        twoi(p2c_in, p2d_in, pre_rp_two);
203
                abs_mpy #(CWIDTH+1,IWIDTH+2,1'b1)
204
                        threei(p3c_in, p3d_in, pre_rp_three);
205
 
206
                always @(posedge i_clk)
207
                if (i_ce)
208
                begin
209
                        rp_one   = pre_rp_one;
210
                        rp_two   = pre_rp_two;
211
                        rp_three = pre_rp_three;
212
                end
213
`endif // FORMAL
214
 
215
                assign  p_one   = rp_one;
216
                assign  p_two   = rp_two;
217
                assign  p_three = rp_three;
218
 
219
        end else if (CKPCE <= 2)
220
        begin : CKPCE_TWO
221
                // Coefficient multiply inputs
222
                reg             [2*(CWIDTH)-1:0] mpy_pipe_c;
223
                // Data multiply inputs
224
                reg             [2*(IWIDTH+1)-1:0]       mpy_pipe_d;
225
                wire    signed  [(CWIDTH-1):0]   mpy_pipe_vc;
226
                wire    signed  [(IWIDTH):0]     mpy_pipe_vd;
227
                //
228
                reg     signed  [(CWIDTH+1)-1:0] mpy_cof_sum;
229
                reg     signed  [(IWIDTH+2)-1:0] mpy_dif_sum;
230
 
231
                assign  mpy_pipe_vc =  mpy_pipe_c[2*(CWIDTH)-1:CWIDTH];
232
                assign  mpy_pipe_vd =  mpy_pipe_d[2*(IWIDTH+1)-1:IWIDTH+1];
233
 
234
                reg                     mpy_pipe_v;
235
                reg                     ce_phase;
236
 
237
                reg     signed  [(CWIDTH+IWIDTH+1)-1:0]  mpy_pipe_out;
238
                reg     signed [IWIDTH+CWIDTH+3-1:0]     longmpy;
239
 
240
 
241
                initial ce_phase = 1'b1;
242
                always @(posedge i_clk)
243
                if (i_reset)
244
                        ce_phase <= 1'b1;
245
                else if (i_ce)
246
                        ce_phase <= 1'b0;
247
                else
248
                        ce_phase <= 1'b1;
249
 
250
                always @(*)
251
                        mpy_pipe_v = (i_ce)||(!ce_phase);
252
 
253
                always @(posedge i_clk)
254
                if (!ce_phase)
255
                begin
256
                        // Pre-clock
257
                        mpy_pipe_c[2*CWIDTH-1:0] <=
258
                                        { ir_coef_r, ir_coef_i };
259
                        mpy_pipe_d[2*(IWIDTH+1)-1:0] <=
260
                                        { r_dif_r, r_dif_i };
261
 
262
                        mpy_cof_sum  <= ir_coef_i + ir_coef_r;
263
                        mpy_dif_sum <= r_dif_r + r_dif_i;
264
 
265
                end else if (i_ce)
266
                begin
267
                        // First clock
268
                        mpy_pipe_c[2*(CWIDTH)-1:0] <= {
269
                                mpy_pipe_c[(CWIDTH)-1:0], {(CWIDTH){1'b0}} };
270
                        mpy_pipe_d[2*(IWIDTH+1)-1:0] <= {
271
                                mpy_pipe_d[(IWIDTH+1)-1:0], {(IWIDTH+1){1'b0}} };
272
                end
273
 
274
`ifndef FORMAL
275
                always @(posedge i_clk)
276
                if (i_ce) // First clock
277
                        longmpy <= mpy_cof_sum * mpy_dif_sum;
278
 
279
                always @(posedge i_clk)
280
                if (mpy_pipe_v)
281
                        mpy_pipe_out <= mpy_pipe_vc * mpy_pipe_vd;
282
`else
283
                wire    signed [IWIDTH+CWIDTH+3-1:0]     pre_longmpy;
284
                wire    signed  [(CWIDTH+IWIDTH+1)-1:0]  pre_mpy_pipe_out;
285
 
286
                abs_mpy #(CWIDTH+1,IWIDTH+2,1)
287
                        longmpyi(mpy_cof_sum, mpy_dif_sum, pre_longmpy);
288
 
289
                always @(posedge i_clk)
290
                if (i_ce)
291
                        longmpy <= pre_longmpy;
292
 
293
 
294
                abs_mpy #(CWIDTH,IWIDTH+1,1)
295
                        mpy_pipe_outi(mpy_pipe_vc, mpy_pipe_vd, pre_mpy_pipe_out);
296
 
297
                always @(posedge i_clk)
298
                if (mpy_pipe_v)
299
                        mpy_pipe_out <= pre_mpy_pipe_out;
300
`endif
301
 
302
                reg     signed  [((IWIDTH+1)+(CWIDTH)-1):0]      rp_one,
303
                                                        rp2_one, rp_two;
304
                reg     signed  [((IWIDTH+2)+(CWIDTH+1)-1):0]    rp_three;
305
 
306
                always @(posedge i_clk)
307
                if (!ce_phase) // 1.5 clock
308
                        rp_one <= mpy_pipe_out;
309
                always @(posedge i_clk)
310
                if (i_ce) // two clocks
311
                        rp_two <= mpy_pipe_out;
312
                always @(posedge i_clk)
313
                if (i_ce) // Second clock
314
                        rp_three<= longmpy;
315
                always @(posedge i_clk)
316
                if (i_ce)
317
                        rp2_one<= rp_one;
318
 
319
                assign  p_one  = rp2_one;
320
                assign  p_two  = rp_two;
321
                assign  p_three= rp_three;
322
 
323
        end else if (CKPCE <= 2'b11)
324
        begin : CKPCE_THREE
325
                // Coefficient multiply inputs
326
                reg             [3*(CWIDTH+1)-1:0]       mpy_pipe_c;
327
                // Data multiply inputs
328
                reg             [3*(IWIDTH+2)-1:0]       mpy_pipe_d;
329
                wire    signed  [(CWIDTH):0]     mpy_pipe_vc;
330
                wire    signed  [(IWIDTH+1):0]   mpy_pipe_vd;
331
 
332
                assign  mpy_pipe_vc =  mpy_pipe_c[3*(CWIDTH+1)-1:2*(CWIDTH+1)];
333
                assign  mpy_pipe_vd =  mpy_pipe_d[3*(IWIDTH+2)-1:2*(IWIDTH+2)];
334
 
335
                reg                     mpy_pipe_v;
336
                reg             [2:0]    ce_phase;
337
 
338
                reg     signed  [  (CWIDTH+IWIDTH+3)-1:0]        mpy_pipe_out;
339
 
340
                initial ce_phase = 3'b011;
341
                always @(posedge i_clk)
342
                if (i_reset)
343
                        ce_phase <= 3'b011;
344
                else if (i_ce)
345
                        ce_phase <= 3'b000;
346
                else if (ce_phase != 3'b011)
347
                        ce_phase <= ce_phase + 1'b1;
348
 
349
                always @(*)
350
                        mpy_pipe_v = (i_ce)||(ce_phase < 3'b010);
351
 
352
                always @(posedge i_clk)
353
                        if (ce_phase == 3'b000)
354
                        begin
355
                                // Second clock
356
                                mpy_pipe_c[3*(CWIDTH+1)-1:(CWIDTH+1)] <= {
357
                                        ir_coef_r[CWIDTH-1], ir_coef_r,
358
                                        ir_coef_i[CWIDTH-1], ir_coef_i };
359
                                mpy_pipe_c[CWIDTH:0] <= ir_coef_i + ir_coef_r;
360
                                mpy_pipe_d[3*(IWIDTH+2)-1:(IWIDTH+2)] <= {
361
                                        r_dif_r[IWIDTH], r_dif_r,
362
                                        r_dif_i[IWIDTH], r_dif_i };
363
                                mpy_pipe_d[(IWIDTH+2)-1:0] <= r_dif_r + r_dif_i;
364
 
365
                        end else if (mpy_pipe_v)
366
                        begin
367
                                mpy_pipe_c[3*(CWIDTH+1)-1:0] <= {
368
                                        mpy_pipe_c[2*(CWIDTH+1)-1:0], {(CWIDTH+1){1'b0}} };
369
                                mpy_pipe_d[3*(IWIDTH+2)-1:0] <= {
370
                                        mpy_pipe_d[2*(IWIDTH+2)-1:0], {(IWIDTH+2){1'b0}} };
371
                        end
372
 
373
`ifndef FORMAL
374
                always @(posedge i_clk)
375
                        if (mpy_pipe_v)
376
                                mpy_pipe_out <= mpy_pipe_vc * mpy_pipe_vd;
377
 
378
`else   // FORMAL
379
                wire    signed  [  (CWIDTH+IWIDTH+3)-1:0] pre_mpy_pipe_out;
380
 
381
                abs_mpy #(CWIDTH+1,IWIDTH+2,1)
382
                        mpy_pipe_outi(mpy_pipe_vc, mpy_pipe_vd, pre_mpy_pipe_out);
383
                always @(posedge i_clk)
384
                        if (mpy_pipe_v)
385
                                mpy_pipe_out <= pre_mpy_pipe_out;
386
`endif  // FORMAL
387
 
388
                reg     signed  [((IWIDTH+1)+(CWIDTH)-1):0]      rp_one, rp_two,
389
                                                rp2_one, rp2_two;
390
                reg     signed  [((IWIDTH+2)+(CWIDTH+1)-1):0]    rp_three, rp2_three;
391
 
392
                always @(posedge i_clk)
393
                if(i_ce)
394
                        rp_one <= mpy_pipe_out[(CWIDTH+IWIDTH):0];
395
                always @(posedge i_clk)
396
                if(ce_phase == 3'b000)
397
                        rp_two <= mpy_pipe_out[(CWIDTH+IWIDTH):0];
398
                always @(posedge i_clk)
399
                if(ce_phase == 3'b001)
400
                        rp_three <= mpy_pipe_out;
401
                always @(posedge i_clk)
402
                if (i_ce)
403
                begin
404
                        rp2_one<= rp_one;
405
                        rp2_two<= rp_two;
406
                        rp2_three<= rp_three;
407
                end
408
                assign  p_one   = rp2_one;
409
                assign  p_two   = rp2_two;
410
                assign  p_three = rp2_three;
411
 
412
        end endgenerate
413
        wire    signed  [((IWIDTH+2)+(CWIDTH+1)-1):0]    w_one, w_two;
414
        assign  w_one = { {(2){p_one[((IWIDTH+1)+(CWIDTH)-1)]}}, p_one };
415
        assign  w_two = { {(2){p_two[((IWIDTH+1)+(CWIDTH)-1)]}}, p_two };
416
 
417
        // These values are held in memory and delayed during the
418
        // multiply.  Here, we recover them.  During the multiply,
419
        // values were multiplied by 2^(CWIDTH-2)*exp{-j*2*pi*...},
420
        // therefore, the left_x values need to be right shifted by
421
        // CWIDTH-2 as well.  The additional bits come from a sign
422
        // extension.
423
        wire    aux_s;
424
        wire    signed  [(IWIDTH+CWIDTH):0]      left_si, left_sr;
425
        reg             [(2*IWIDTH+2):0] left_saved;
426
        assign  left_sr = { {2{left_saved[2*(IWIDTH+1)-1]}}, left_saved[(2*(IWIDTH+1)-1):(IWIDTH+1)], {(CWIDTH-2){1'b0}} };
427
        assign  left_si = { {2{left_saved[(IWIDTH+1)-1]}}, left_saved[((IWIDTH+1)-1):0], {(CWIDTH-2){1'b0}} };
428
        assign  aux_s = left_saved[2*IWIDTH+2];
429
 
430
        (* use_dsp48="no" *)
431
        reg     signed  [(CWIDTH+IWIDTH+3-1):0]  mpy_r, mpy_i;
432
 
433
        initial left_saved = 0;
434
        initial o_aux      = 1'b0;
435
        always @(posedge i_clk)
436
                if (i_reset)
437
                begin
438
                        left_saved <= 0;
439
                        o_aux <= 1'b0;
440
                end else if (i_ce)
441
                begin
442
                        // First clock, recover all values
443
                        left_saved <= leftvv;
444
 
445
                        // Second clock, round and latch for final clock
446
                        o_aux <= aux_s;
447
                end
448
        always @(posedge i_clk)
449
                if (i_ce)
450
                begin
451
                        // These values are IWIDTH+CWIDTH+3 bits wide
452
                        // although they only need to be (IWIDTH+1)
453
                        // + (CWIDTH) bits wide.  (We've got two
454
                        // extra bits we need to get rid of.)
455
 
456
                        // These two lines also infer DSP48's.
457
                        // To keep from using extra DSP48 resources,
458
                        // they are prevented from using DSP48's
459
                        // by the (* use_dsp48 ... *) comment above.
460
                        mpy_r <= w_one - w_two;
461
                        mpy_i <= p_three - w_one - w_two;
462
                end
463
 
464
        // Round the results
465
        wire    signed  [(OWIDTH-1):0]   rnd_left_r, rnd_left_i, rnd_right_r, rnd_right_i;
466
 
467
        convround #(CWIDTH+IWIDTH+1,OWIDTH,SHIFT+2) do_rnd_left_r(i_clk, i_ce,
468
                                left_sr, rnd_left_r);
469
 
470
        convround #(CWIDTH+IWIDTH+1,OWIDTH,SHIFT+2) do_rnd_left_i(i_clk, i_ce,
471
                                left_si, rnd_left_i);
472
 
473
        convround #(CWIDTH+IWIDTH+3,OWIDTH,SHIFT+4) do_rnd_right_r(i_clk, i_ce,
474
                                mpy_r, rnd_right_r);
475
 
476
        convround #(CWIDTH+IWIDTH+3,OWIDTH,SHIFT+4) do_rnd_right_i(i_clk, i_ce,
477
                                mpy_i, rnd_right_i);
478
 
479
        // As a final step, we pack our outputs into two packed two's
480
        // complement numbers per output word, so that each output word
481
        // has (2*OWIDTH) bits in it, with the top half being the real
482
        // portion and the bottom half being the imaginary portion.
483
        assign  o_left = { rnd_left_r, rnd_left_i };
484
        assign  o_right= { rnd_right_r,rnd_right_i};
485
 
486
`ifdef  FORMAL
487
        localparam      F_LGDEPTH = 3;
488
        localparam      F_DEPTH = 5;
489
        localparam      [F_LGDEPTH-1:0]  F_D = F_DEPTH-1;
490
 
491
        reg     signed  [IWIDTH-1:0]     f_dlyleft_r  [0:F_DEPTH-1];
492
        reg     signed  [IWIDTH-1:0]     f_dlyleft_i  [0:F_DEPTH-1];
493
        reg     signed  [IWIDTH-1:0]     f_dlyright_r [0:F_DEPTH-1];
494
        reg     signed  [IWIDTH-1:0]     f_dlyright_i [0:F_DEPTH-1];
495
        reg     signed  [CWIDTH-1:0]     f_dlycoeff_r [0:F_DEPTH-1];
496
        reg     signed  [CWIDTH-1:0]     f_dlycoeff_i [0:F_DEPTH-1];
497
        reg     signed  [F_DEPTH-1:0]    f_dlyaux;
498
 
499
        always @(posedge i_clk)
500
        if (i_reset)
501
                f_dlyaux <= 0;
502
        else if (i_ce)
503
                f_dlyaux <= { f_dlyaux[F_DEPTH-2:0], i_aux };
504
 
505
        always @(posedge i_clk)
506
        if (i_ce)
507
        begin
508
                f_dlyleft_r[0]   <= i_left[ (2*IWIDTH-1):IWIDTH];
509
                f_dlyleft_i[0]   <= i_left[ (  IWIDTH-1):0];
510
                f_dlyright_r[0]  <= i_right[(2*IWIDTH-1):IWIDTH];
511
                f_dlyright_i[0]  <= i_right[(  IWIDTH-1):0];
512
                f_dlycoeff_r[0]  <= i_coef[ (2*CWIDTH-1):CWIDTH];
513
                f_dlycoeff_i[0]  <= i_coef[ (  CWIDTH-1):0];
514
        end
515
 
516
        genvar  k;
517
        generate for(k=1; k<F_DEPTH; k=k+1)
518
 
519
                always @(posedge i_clk)
520
                if (i_ce)
521
                begin
522
                        f_dlyleft_r[k]  <= f_dlyleft_r[ k-1];
523
                        f_dlyleft_i[k]  <= f_dlyleft_i[ k-1];
524
                        f_dlyright_r[k] <= f_dlyright_r[k-1];
525
                        f_dlyright_i[k] <= f_dlyright_i[k-1];
526
                        f_dlycoeff_r[k] <= f_dlycoeff_r[k-1];
527
                        f_dlycoeff_i[k] <= f_dlycoeff_i[k-1];
528
                end
529
 
530
        endgenerate
531
 
532
`ifdef  VERILATOR
533
`else
534
        always @(posedge i_clk)
535
        if ((!$past(i_ce))&&(!$past(i_ce,2))&&(!$past(i_ce,3))
536
                        &&(!$past(i_ce,4)))
537
                assume(i_ce);
538
 
539
        generate if (CKPCE <= 1)
540
        begin
541
 
542
                // i_ce is allowed to be anything in this mode
543
 
544
        end else if (CKPCE == 2)
545
        begin : F_CKPCE_TWO
546
 
547
                always @(posedge i_clk)
548
                        if ($past(i_ce))
549
                                assume(!i_ce);
550
 
551
        end else if (CKPCE == 3)
552
        begin : F_CKPCE_THREE
553
 
554
                always @(posedge i_clk)
555
                        if (($past(i_ce))||($past(i_ce,2)))
556
                                assume(!i_ce);
557
 
558
        end endgenerate
559
`endif
560
        reg     [F_LGDEPTH-1:0]  f_startup_counter;
561
        initial f_startup_counter = 0;
562
        always @(posedge i_clk)
563
        if (i_reset)
564
                f_startup_counter <= 0;
565
        else if ((i_ce)&&(!(&f_startup_counter)))
566
                f_startup_counter <= f_startup_counter + 1;
567
 
568
        wire    signed  [IWIDTH:0]       f_sumr, f_sumi;
569
        always @(*)
570
        begin
571
                f_sumr = f_dlyleft_r[F_D] + f_dlyright_r[F_D];
572
                f_sumi = f_dlyleft_i[F_D] + f_dlyright_i[F_D];
573
        end
574
 
575
        wire    signed  [IWIDTH+CWIDTH:0]        f_sumrx, f_sumix;
576
        assign  f_sumrx = { {(2){f_sumr[IWIDTH]}}, f_sumr, {(CWIDTH-2){1'b0}} };
577
        assign  f_sumix = { {(2){f_sumi[IWIDTH]}}, f_sumi, {(CWIDTH-2){1'b0}} };
578
 
579
        wire    signed  [IWIDTH:0]       f_difr, f_difi;
580
        always @(*)
581
        begin
582
                f_difr = f_dlyleft_r[F_D] - f_dlyright_r[F_D];
583
                f_difi = f_dlyleft_i[F_D] - f_dlyright_i[F_D];
584
        end
585
 
586
        wire    signed  [IWIDTH+CWIDTH+3-1:0]    f_difrx, f_difix;
587
        assign  f_difrx = { {(CWIDTH+2){f_difr[IWIDTH]}}, f_difr };
588
        assign  f_difix = { {(CWIDTH+2){f_difi[IWIDTH]}}, f_difi };
589
 
590
        wire    signed  [IWIDTH+CWIDTH+3-1:0]    f_widecoeff_r, f_widecoeff_i;
591
        assign  f_widecoeff_r = {{(IWIDTH+3){f_dlycoeff_r[F_D][CWIDTH-1]}},
592
                        f_dlycoeff_r[F_D] };
593
        assign  f_widecoeff_i = {{(IWIDTH+3){f_dlycoeff_i[F_D][CWIDTH-1]}},
594
                        f_dlycoeff_i[F_D] };
595
 
596
        always @(posedge i_clk)
597
        if (f_startup_counter > F_D)
598
        begin
599
                assert(left_sr == f_sumrx);
600
                assert(left_si == f_sumix);
601
                assert(aux_s == f_dlyaux[F_D]);
602
 
603
                if ((f_difr == 0)&&(f_difi == 0))
604
                begin
605
                        assert(mpy_r == 0);
606
                        assert(mpy_i == 0);
607
                end else if ((f_dlycoeff_r[F_D] == 0)
608
                                &&(f_dlycoeff_i[F_D] == 0))
609
                begin
610
                        assert(mpy_r == 0);
611
                        assert(mpy_i == 0);
612
                end
613
 
614
                if ((f_dlycoeff_r[F_D] == 1)&&(f_dlycoeff_i[F_D] == 0))
615
                begin
616
                        assert(mpy_r == f_difrx);
617
                        assert(mpy_i == f_difix);
618
                end
619
 
620
                if ((f_dlycoeff_r[F_D] == 0)&&(f_dlycoeff_i[F_D] == 1))
621
                begin
622
                        assert(mpy_r == -f_difix);
623
                        assert(mpy_i ==  f_difrx);
624
                end
625
 
626
                if ((f_difr == 1)&&(f_difi == 0))
627
                begin
628
                        assert(mpy_r == f_widecoeff_r);
629
                        assert(mpy_i == f_widecoeff_i);
630
                end
631
 
632
                if ((f_difr == 0)&&(f_difi == 1))
633
                begin
634
                        assert(mpy_r == -f_widecoeff_i);
635
                        assert(mpy_i ==  f_widecoeff_r);
636
                end
637
        end
638
 
639
        // Let's see if we can improve our performance at all by
640
        // moving our test one clock earlier.  If nothing else, it should
641
        // help induction finish one (or more) clocks ealier than
642
        // otherwise
643
 
644
 
645
        wire    signed  [IWIDTH:0]       f_predifr, f_predifi;
646
        always @(*)
647
        begin
648
                f_predifr = f_dlyleft_r[F_D-1] - f_dlyright_r[F_D-1];
649
                f_predifi = f_dlyleft_i[F_D-1] - f_dlyright_i[F_D-1];
650
        end
651
 
652
        wire    signed  [IWIDTH+CWIDTH+1-1:0]    f_predifrx, f_predifix;
653
        assign  f_predifrx = { {(CWIDTH){f_predifr[IWIDTH]}}, f_predifr };
654
        assign  f_predifix = { {(CWIDTH){f_predifi[IWIDTH]}}, f_predifi };
655
 
656
        wire    signed  [CWIDTH:0]       f_sumcoef;
657
        wire    signed  [IWIDTH+1:0]     f_sumdiff;
658
        always @(*)
659
        begin
660
                f_sumcoef = f_dlycoeff_r[F_D-1] + f_dlycoeff_i[F_D-1];
661
                f_sumdiff = f_predifr + f_predifi;
662
        end
663
 
664
        // Induction helpers
665
        always @(posedge i_clk)
666
        if (f_startup_counter >= F_D)
667
        begin
668
                if (f_dlycoeff_r[F_D-1] == 0)
669
                        assert(p_one == 0);
670
                if (f_dlycoeff_i[F_D-1] == 0)
671
                        assert(p_two == 0);
672
 
673
                if (f_dlycoeff_r[F_D-1] == 1)
674
                        assert(p_one == f_predifrx);
675
                if (f_dlycoeff_i[F_D-1] == 1)
676
                        assert(p_two == f_predifix);
677
 
678
                if (f_predifr == 0)
679
                        assert(p_one == 0);
680
                if (f_predifi == 0)
681
                        assert(p_two == 0);
682
 
683
                // verilator lint_off WIDTH
684
                if (f_predifr == 1)
685
                        assert(p_one == f_dlycoeff_r[F_D-1]);
686
                if (f_predifi == 1)
687
                        assert(p_two == f_dlycoeff_i[F_D-1]);
688
                // verilator lint_on  WIDTH
689
 
690
                if (f_sumcoef == 0)
691
                        assert(p_three == 0);
692
                if (f_sumdiff == 0)
693
                        assert(p_three == 0);
694
                // verilator lint_off WIDTH
695
                if (f_sumcoef == 1)
696
                        assert(p_three == f_sumdiff);
697
                if (f_sumdiff == 1)
698
                        assert(p_three == f_sumcoef);
699
                // verilator lint_on  WIDTH
700
`ifdef  VERILATOR
701
                assert(p_one   == f_predifr * f_dlycoeff_r[F_D-1]);
702
                assert(p_two   == f_predifi * f_dlycoeff_i[F_D-1]);
703
                assert(p_three == f_sumdiff * f_sumcoef);
704
`endif  // VERILATOR
705
        end
706
 
707
`endif // FORMAL
708
endmodule

powered by: WebSVN 2.1.0

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