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

Subversion Repositories dblclockfft

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

powered by: WebSVN 2.1.0

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