├── img
├── sdfunit.png
├── butterfly.png
├── fft64_wave.png
├── fft64_block.png
└── fft64_wave.json
├── sim
├── fft_64
│ ├── vsim.do
│ ├── vsim.sh
│ ├── vlog.sh
│ ├── vsim.log
│ ├── stim.v
│ ├── stim1.v
│ ├── input.pl
│ ├── output4.txt
│ ├── output5.txt
│ ├── input4.txt
│ ├── input5.txt
│ ├── TB64.v
│ └── modelsim.mpf
└── fft_128_tc
│ ├── vsim.do
│ ├── vsim.sh
│ ├── vlog.sh
│ ├── vsim.log
│ ├── stim.v
│ ├── stim1.v
│ ├── input.pl
│ ├── output4.txt
│ ├── output5.txt
│ ├── TB128.v
│ ├── input4.txt
│ ├── input5.txt
│ └── modelsim.mpf
├── quartus
├── fft_64
│ ├── FFT.fit.rpt
│ ├── FFT.qsf
│ └── FFT.qpf
├── fft_128
│ ├── FFT.fit.rpt
│ ├── FFT.qsf
│ └── FFT.qpf
└── fft_1024_32b
│ ├── FFT.fit.rpt
│ ├── FFT.qsf
│ └── FFT.qpf
├── verilog
├── DelayBuffer.v
├── Multiply.v
├── Butterfly.v
├── FFT64.v
├── TwiddleConvert4.v
├── FFT128.v
├── TwiddleConvert8.v
├── FFT1024_32B.v
├── SdfUnit2.v
├── Twiddle64.v
├── SdfUnit.v
├── Twiddle128.v
└── SdfUnit_TC.v
├── LICENSE
├── tool
└── twiddle.pl
└── README.md
/img/sdfunit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nanamake/r22sdf/HEAD/img/sdfunit.png
--------------------------------------------------------------------------------
/img/butterfly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nanamake/r22sdf/HEAD/img/butterfly.png
--------------------------------------------------------------------------------
/img/fft64_wave.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nanamake/r22sdf/HEAD/img/fft64_wave.png
--------------------------------------------------------------------------------
/img/fft64_block.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nanamake/r22sdf/HEAD/img/fft64_block.png
--------------------------------------------------------------------------------
/sim/fft_64/vsim.do:
--------------------------------------------------------------------------------
1 | onerror {quit}
2 | transcript on
3 | add wave -r /*
4 | run -all
5 | quit
6 |
--------------------------------------------------------------------------------
/quartus/fft_64/FFT.fit.rpt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nanamake/r22sdf/HEAD/quartus/fft_64/FFT.fit.rpt
--------------------------------------------------------------------------------
/sim/fft_128_tc/vsim.do:
--------------------------------------------------------------------------------
1 | onerror {quit}
2 | transcript on
3 | add wave -r /*
4 | run -all
5 | quit
6 |
--------------------------------------------------------------------------------
/quartus/fft_128/FFT.fit.rpt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nanamake/r22sdf/HEAD/quartus/fft_128/FFT.fit.rpt
--------------------------------------------------------------------------------
/quartus/fft_1024_32b/FFT.fit.rpt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nanamake/r22sdf/HEAD/quartus/fft_1024_32b/FFT.fit.rpt
--------------------------------------------------------------------------------
/sim/fft_64/vsim.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh -x
2 |
3 | vsim TB \
4 | -c \
5 | -do vsim.do \
6 | -l vsim.log \
7 | +nowarnTSCALE
8 |
--------------------------------------------------------------------------------
/sim/fft_128_tc/vsim.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh -x
2 |
3 | vsim TB \
4 | -c \
5 | -do vsim.do \
6 | -l vsim.log \
7 | +nowarnTSCALE
8 |
--------------------------------------------------------------------------------
/sim/fft_64/vlog.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh -x
2 |
3 | if [ -d work ]; then
4 | rm -rf work
5 | fi
6 | vlib work
7 |
8 | rtl_dir="./rtl"
9 | tb_dir="."
10 |
11 | vlog \
12 | $rtl_dir/FFT64.v \
13 | $rtl_dir/SdfUnit.v \
14 | $rtl_dir/Butterfly.v \
15 | $rtl_dir/DelayBuffer.v \
16 | $rtl_dir/Multiply.v \
17 | $rtl_dir/Twiddle64.v \
18 | $tb_dir/TB64.v
19 |
--------------------------------------------------------------------------------
/sim/fft_64/vsim.log:
--------------------------------------------------------------------------------
1 | # vsim +nowarnTSCALE -do vsim.do -l vsim.log -c TB
2 | # Loading work.TB
3 | # Loading work.FFT
4 | # Loading work.SdfUnit
5 | # Loading work.Butterfly
6 | # Loading work.DelayBuffer
7 | # Loading work.Twiddle
8 | # Loading work.Multiply
9 | # do vsim.do
10 | # add wave -r /*
11 | # run -all
12 | # ** Note: $finish : stim.v(29)
13 | # Time: 4490 ns Iteration: 1 Instance: /TB
14 |
--------------------------------------------------------------------------------
/sim/fft_128_tc/vlog.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh -x
2 |
3 | if [ -d work ]; then
4 | rm -rf work
5 | fi
6 | vlib work
7 |
8 | rtl_dir="./rtl"
9 | tb_dir="."
10 |
11 | vlog \
12 | $rtl_dir/FFT128.v \
13 | $rtl_dir/SdfUnit_TC.v \
14 | $rtl_dir/SdfUnit2.v \
15 | $rtl_dir/Butterfly.v \
16 | $rtl_dir/DelayBuffer.v \
17 | $rtl_dir/Multiply.v \
18 | $rtl_dir/TwiddleConvert8.v \
19 | $rtl_dir/Twiddle128.v \
20 | $tb_dir/TB128.v
21 |
--------------------------------------------------------------------------------
/sim/fft_128_tc/vsim.log:
--------------------------------------------------------------------------------
1 | # vsim +nowarnTSCALE -do vsim.do -l vsim.log -c TB
2 | # Loading work.TB
3 | # Loading work.FFT
4 | # Loading work.SdfUnit
5 | # Loading work.Butterfly
6 | # Loading work.DelayBuffer
7 | # Loading work.Twiddle
8 | # Loading work.Multiply
9 | # Loading work.SdfUnit2
10 | # Loading work.TwiddleConvert8
11 | # do vsim.do
12 | # add wave -r /*
13 | # run -all
14 | # ** Note: $finish : stim.v(29)
15 | # Time: 8370 ns Iteration: 1 Instance: /TB
16 |
--------------------------------------------------------------------------------
/img/fft64_wave.json:
--------------------------------------------------------------------------------
1 | { signal: [
2 | { name: 'di_en' , wave: '0.1...|.0.........', node: '..a...............' },
3 | { name: 'di_re/im', wave: 'x.===x|=x.........', data: 'D0 D1 D2 D63' },
4 | { node: '..b.......c.......' },
5 | { name: 'do_en' , wave: '0........|1...|.0.', node: '..........d.......' },
6 | { name: 'do_re/im', wave: 'x........|===x|=x.', data: 'D0 D1 D2 D63' },
7 | ],
8 | edge: ['a|b', 'b<->c 71 clock cycles', 'c|d'],
9 | }
10 |
--------------------------------------------------------------------------------
/quartus/fft_64/FFT.qsf:
--------------------------------------------------------------------------------
1 | set_global_assignment -name FAMILY "Cyclone IV E"
2 | set_global_assignment -name DEVICE EP4CE22F17C6
3 | set_global_assignment -name TOP_LEVEL_ENTITY FFT
4 | set_global_assignment -name VERILOG_FILE rtl/FFT64.v
5 | set_global_assignment -name VERILOG_FILE rtl/SdfUnit.v
6 | set_global_assignment -name VERILOG_FILE rtl/Butterfly.v
7 | set_global_assignment -name VERILOG_FILE rtl/DelayBuffer.v
8 | set_global_assignment -name VERILOG_FILE rtl/Multiply.v
9 | set_global_assignment -name VERILOG_FILE rtl/Twiddle64.v
10 |
11 | set_global_assignment -name LAST_QUARTUS_VERSION 14.0
12 | set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
13 | set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
14 | set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
15 | set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
--------------------------------------------------------------------------------
/sim/fft_64/stim.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // Test Stimuli
3 | //----------------------------------------------------------------------
4 | initial begin : STIM
5 | wait (reset == 1);
6 | wait (reset == 0);
7 | repeat(10) @(posedge clock);
8 |
9 | fork
10 | begin
11 | LoadInputData("input4.txt");
12 | GenerateInputWave;
13 | // @(posedge clock);
14 | LoadInputData("input5.txt");
15 | GenerateInputWave;
16 | end
17 | begin
18 | wait (do_en == 1);
19 | repeat(64) @(posedge clock);
20 | SaveOutputData("output4.txt");
21 | @(negedge clock);
22 | wait (do_en == 1);
23 | repeat(64) @(posedge clock);
24 | SaveOutputData("output5.txt");
25 | end
26 | join
27 |
28 | repeat(10) @(posedge clock);
29 | $finish;
30 | end
31 | initial begin : TIMEOUT
32 | repeat(1000) #20; // 1000 Clock Cycle Time
33 | $display("[FAILED] Simulation timed out.");
34 | $finish;
35 | end
36 |
--------------------------------------------------------------------------------
/sim/fft_64/stim1.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // Test Stimuli
3 | //----------------------------------------------------------------------
4 | initial begin : STIM
5 | wait (reset == 1);
6 | wait (reset == 0);
7 | repeat(10) @(posedge clock);
8 |
9 | fork
10 | begin
11 | LoadInputData("input4.txt");
12 | GenerateInputWave;
13 | @(posedge clock);
14 | LoadInputData("input5.txt");
15 | GenerateInputWave;
16 | end
17 | begin
18 | wait (do_en == 1);
19 | repeat(64) @(posedge clock);
20 | SaveOutputData("output4.txt");
21 | @(negedge clock);
22 | wait (do_en == 1);
23 | repeat(64) @(posedge clock);
24 | SaveOutputData("output5.txt");
25 | end
26 | join
27 |
28 | repeat(10) @(posedge clock);
29 | $finish;
30 | end
31 | initial begin : TIMEOUT
32 | repeat(1000) #20; // 1000 Clock Cycle Time
33 | $display("[FAILED] Simulation timed out.");
34 | $finish;
35 | end
36 |
--------------------------------------------------------------------------------
/sim/fft_128_tc/stim.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // Test Stimuli
3 | //----------------------------------------------------------------------
4 | initial begin : STIM
5 | wait (reset == 1);
6 | wait (reset == 0);
7 | repeat(10) @(posedge clock);
8 |
9 | fork
10 | begin
11 | LoadInputData("input4.txt");
12 | GenerateInputWave;
13 | // @(posedge clock);
14 | LoadInputData("input5.txt");
15 | GenerateInputWave;
16 | end
17 | begin
18 | wait (do_en == 1);
19 | repeat(N) @(posedge clock);
20 | SaveOutputData("output4.txt");
21 | @(negedge clock);
22 | wait (do_en == 1);
23 | repeat(N) @(posedge clock);
24 | SaveOutputData("output5.txt");
25 | end
26 | join
27 |
28 | repeat(10) @(posedge clock);
29 | $finish;
30 | end
31 | initial begin : TIMEOUT
32 | repeat(1000) #20; // 1000 Clock Cycle Time
33 | $display("[FAILED] Simulation timed out.");
34 | $finish;
35 | end
36 |
--------------------------------------------------------------------------------
/sim/fft_128_tc/stim1.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // Test Stimuli
3 | //----------------------------------------------------------------------
4 | initial begin : STIM
5 | wait (reset == 1);
6 | wait (reset == 0);
7 | repeat(10) @(posedge clock);
8 |
9 | fork
10 | begin
11 | LoadInputData("input4.txt");
12 | GenerateInputWave;
13 | @(posedge clock);
14 | LoadInputData("input5.txt");
15 | GenerateInputWave;
16 | end
17 | begin
18 | wait (do_en == 1);
19 | repeat(N) @(posedge clock);
20 | SaveOutputData("output4.txt");
21 | @(negedge clock);
22 | wait (do_en == 1);
23 | repeat(N) @(posedge clock);
24 | SaveOutputData("output5.txt");
25 | end
26 | join
27 |
28 | repeat(10) @(posedge clock);
29 | $finish;
30 | end
31 | initial begin : TIMEOUT
32 | repeat(1000) #20; // 1000 Clock Cycle Time
33 | $display("[FAILED] Simulation timed out.");
34 | $finish;
35 | end
36 |
--------------------------------------------------------------------------------
/quartus/fft_128/FFT.qsf:
--------------------------------------------------------------------------------
1 | set_global_assignment -name FAMILY "Cyclone IV E"
2 | set_global_assignment -name DEVICE EP4CE22F17C6
3 | set_global_assignment -name TOP_LEVEL_ENTITY FFT
4 | set_global_assignment -name VERILOG_FILE rtl/FFT128.v
5 | set_global_assignment -name VERILOG_FILE rtl/SdfUnit.v
6 | set_global_assignment -name VERILOG_FILE rtl/SdfUnit2.v
7 | set_global_assignment -name VERILOG_FILE rtl/Butterfly.v
8 | set_global_assignment -name VERILOG_FILE rtl/DelayBuffer.v
9 | set_global_assignment -name VERILOG_FILE rtl/Multiply.v
10 | set_global_assignment -name VERILOG_FILE rtl/Twiddle128.v
11 |
12 | set_global_assignment -name LAST_QUARTUS_VERSION 14.0
13 | set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
14 | set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
15 | set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
16 | set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
--------------------------------------------------------------------------------
/quartus/fft_1024_32b/FFT.qsf:
--------------------------------------------------------------------------------
1 | set_global_assignment -name FAMILY "Cyclone IV E"
2 | set_global_assignment -name DEVICE EP4CE22F17C6
3 | set_global_assignment -name TOP_LEVEL_ENTITY FFT
4 | set_global_assignment -name VERILOG_FILE rtl/FFT1024_32B.v
5 | set_global_assignment -name VERILOG_FILE rtl/SdfUnit_TC.v
6 | set_global_assignment -name VERILOG_FILE rtl/Butterfly.v
7 | set_global_assignment -name VERILOG_FILE rtl/DelayBuffer.v
8 | set_global_assignment -name VERILOG_FILE rtl/Multiply.v
9 | set_global_assignment -name VERILOG_FILE rtl/TwiddleConvert8.v
10 | set_global_assignment -name VERILOG_FILE rtl/Twiddle1024_32B.v
11 |
12 | set_global_assignment -name LAST_QUARTUS_VERSION 14.0
13 | set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
14 | set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
15 | set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
16 | set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
--------------------------------------------------------------------------------
/verilog/DelayBuffer.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // DelayBuffer: Generate Constant Delay
3 | //----------------------------------------------------------------------
4 | module DelayBuffer #(
5 | parameter DEPTH = 32,
6 | parameter WIDTH = 16
7 | )(
8 | input clock, // Master Clock
9 | input [WIDTH-1:0] di_re, // Data Input (Real)
10 | input [WIDTH-1:0] di_im, // Data Input (Imag)
11 | output [WIDTH-1:0] do_re, // Data Output (Real)
12 | output [WIDTH-1:0] do_im // Data Output (Imag)
13 | );
14 |
15 | reg [WIDTH-1:0] buf_re[0:DEPTH-1];
16 | reg [WIDTH-1:0] buf_im[0:DEPTH-1];
17 | integer n;
18 |
19 | // Shift Buffer
20 | always @(posedge clock) begin
21 | for (n = DEPTH-1; n > 0; n = n - 1) begin
22 | buf_re[n] <= buf_re[n-1];
23 | buf_im[n] <= buf_im[n-1];
24 | end
25 | buf_re[0] <= di_re;
26 | buf_im[0] <= di_im;
27 | end
28 |
29 | assign do_re = buf_re[DEPTH-1];
30 | assign do_im = buf_im[DEPTH-1];
31 |
32 | endmodule
33 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Nanamaru Namake
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/verilog/Multiply.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // Multiply: Complex Multiplier
3 | //----------------------------------------------------------------------
4 | module Multiply #(
5 | parameter WIDTH = 16
6 | )(
7 | input signed [WIDTH-1:0] a_re,
8 | input signed [WIDTH-1:0] a_im,
9 | input signed [WIDTH-1:0] b_re,
10 | input signed [WIDTH-1:0] b_im,
11 | output signed [WIDTH-1:0] m_re,
12 | output signed [WIDTH-1:0] m_im
13 | );
14 |
15 | wire signed [WIDTH*2-1:0] arbr, arbi, aibr, aibi;
16 | wire signed [WIDTH-1:0] sc_arbr, sc_arbi, sc_aibr, sc_aibi;
17 |
18 | // Signed Multiplication
19 | assign arbr = a_re * b_re;
20 | assign arbi = a_re * b_im;
21 | assign aibr = a_im * b_re;
22 | assign aibi = a_im * b_im;
23 |
24 | // Scaling
25 | assign sc_arbr = arbr >>> (WIDTH-1);
26 | assign sc_arbi = arbi >>> (WIDTH-1);
27 | assign sc_aibr = aibr >>> (WIDTH-1);
28 | assign sc_aibi = aibi >>> (WIDTH-1);
29 |
30 | // Sub/Add
31 | // These sub/add may overflow if unnormalized data is input.
32 | assign m_re = sc_arbr - sc_aibi;
33 | assign m_im = sc_arbi + sc_aibr;
34 |
35 | endmodule
36 |
--------------------------------------------------------------------------------
/sim/fft_64/input.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | use strict;
4 | use warnings;
5 | use POSIX 'floor';
6 |
7 | my $pi = atan2(1, 1) * 4;
8 |
9 | my $N = 64; # Number of FFT Points
10 | my $NB = 16; # Number of Twiddle Data Bits
11 |
12 | my $ND = int(log(2**($NB-1))/log(10)) + 2; # Number of Decimal Digits
13 | my $NX = int(($NB + 3) / 4); # Number of Hexadecimal Digits
14 |
15 | for (my $n = 0; $n < $N; ++$n) {
16 | # my $wr = 1; my $wi = 0;
17 | # my $wr = cos(2 * $pi * $n / $N); my $wi = sin(2 * $pi * $n / $N);
18 | # my $wr = sin(2 * $pi * $n / $N); my $wi = -cos(2 * $pi * $n / $N);
19 | # my $wr = cos(2 * $pi * $n / $N); my $wi = 0;
20 | my $wr = cos(15 * 2*$pi * $n/$N); my $wi = sin(15 * 2*$pi * $n/$N);
21 | $wr *= 0.9999;
22 | $wi *= 0.9999;
23 |
24 | my $wr_d = floor($wr * 2**($NB-1) + 0.5); $wr_d -= 1 if ($wr_d == 2**($NB-1));
25 | my $wi_d = floor($wi * 2**($NB-1) + 0.5); $wi_d -= 1 if ($wi_d == 2**($NB-1));
26 | my $wr_u = ($wr_d < 0) ? ($wr_d + 2**$NB) : $wr_d;
27 | my $wi_u = ($wi_d < 0) ? ($wi_d + 2**$NB) : $wi_d;
28 |
29 | # printf("%${ND}d %${ND}d ", $wr_d, $wi_d);
30 | # printf("%0${NB}b %0${NB}b ", $wr_u, $wi_u);
31 | printf("%0${NX}X %0${NX}X ", $wr_u, $wi_u);
32 | printf("// %2d", $n);
33 | printf(" % .3f % .3f", $wr, $wi);
34 | print "\n";
35 | }
36 |
--------------------------------------------------------------------------------
/sim/fft_128_tc/input.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | use strict;
4 | use warnings;
5 | use POSIX 'floor';
6 |
7 | my $pi = atan2(1, 1) * 4;
8 |
9 | my $N = 128; # Number of FFT Points
10 | my $NB = 16; # Number of Twiddle Data Bits
11 |
12 | my $ND = int(log(2**($NB-1))/log(10)) + 2; # Number of Decimal Digits
13 | my $NX = int(($NB + 3) / 4); # Number of Hexadecimal Digits
14 |
15 | for (my $n = 0; $n < $N; ++$n) {
16 | # my $wr = 1; my $wi = 0;
17 | # my $wr = cos(2 * $pi * $n / $N); my $wi = sin(2 * $pi * $n / $N);
18 | # my $wr = sin(2 * $pi * $n / $N); my $wi = -cos(2 * $pi * $n / $N);
19 | # my $wr = cos(2 * $pi * $n / $N); my $wi = 0;
20 | my $wr = cos(15 * 2*$pi * $n/$N); my $wi = sin(15 * 2*$pi * $n/$N);
21 | $wr *= 0.9999;
22 | $wi *= 0.9999;
23 |
24 | my $wr_d = floor($wr * 2**($NB-1) + 0.5); $wr_d -= 1 if ($wr_d == 2**($NB-1));
25 | my $wi_d = floor($wi * 2**($NB-1) + 0.5); $wi_d -= 1 if ($wi_d == 2**($NB-1));
26 | my $wr_u = ($wr_d < 0) ? ($wr_d + 2**$NB) : $wr_d;
27 | my $wi_u = ($wi_d < 0) ? ($wi_d + 2**$NB) : $wi_d;
28 |
29 | # printf("%${ND}d %${ND}d ", $wr_d, $wi_d);
30 | # printf("%0${NB}b %0${NB}b ", $wr_u, $wi_u);
31 | printf("%0${NX}X %0${NX}X ", $wr_u, $wi_u);
32 | printf("// %2d", $n);
33 | printf(" % .3f % .3f", $wr, $wi);
34 | print "\n";
35 | }
36 |
--------------------------------------------------------------------------------
/verilog/Butterfly.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // Butterfly: Add/Sub and Scaling
3 | //----------------------------------------------------------------------
4 | module Butterfly #(
5 | parameter WIDTH = 16,
6 | parameter RH = 0 // Round Half Up
7 | )(
8 | input signed [WIDTH-1:0] x0_re, // Input Data #0 (Real)
9 | input signed [WIDTH-1:0] x0_im, // Input Data #0 (Imag)
10 | input signed [WIDTH-1:0] x1_re, // Input Data #1 (Real)
11 | input signed [WIDTH-1:0] x1_im, // Input Data #1 (Imag)
12 | output signed [WIDTH-1:0] y0_re, // Output Data #0 (Real)
13 | output signed [WIDTH-1:0] y0_im, // Output Data #0 (Imag)
14 | output signed [WIDTH-1:0] y1_re, // Output Data #1 (Real)
15 | output signed [WIDTH-1:0] y1_im // Output Data #1 (Imag)
16 | );
17 |
18 | wire signed [WIDTH:0] add_re, add_im, sub_re, sub_im;
19 |
20 | // Add/Sub
21 | assign add_re = x0_re + x1_re;
22 | assign add_im = x0_im + x1_im;
23 | assign sub_re = x0_re - x1_re;
24 | assign sub_im = x0_im - x1_im;
25 |
26 | // Scaling
27 | assign y0_re = (add_re + RH) >>> 1;
28 | assign y0_im = (add_im + RH) >>> 1;
29 | assign y1_re = (sub_re + RH) >>> 1;
30 | assign y1_im = (sub_im + RH) >>> 1;
31 |
32 | endmodule
33 |
--------------------------------------------------------------------------------
/quartus/fft_128/FFT.qpf:
--------------------------------------------------------------------------------
1 | # -------------------------------------------------------------------------- #
2 | #
3 | # Copyright (C) 1991-2014 Altera Corporation. All rights reserved.
4 | # Your use of Altera Corporation's design tools, logic functions
5 | # and other software and tools, and its AMPP partner logic
6 | # functions, and any output files from any of the foregoing
7 | # (including device programming or simulation files), and any
8 | # associated documentation or information are expressly subject
9 | # to the terms and conditions of the Altera Program License
10 | # Subscription Agreement, the Altera Quartus II License Agreement,
11 | # the Altera MegaCore Function License Agreement, or other
12 | # applicable license agreement, including, without limitation,
13 | # that your use is for the sole purpose of programming logic
14 | # devices manufactured by Altera and sold by Altera or its
15 | # authorized distributors. Please refer to the applicable
16 | # agreement for further details.
17 | #
18 | # -------------------------------------------------------------------------- #
19 | #
20 | # Quartus II 64-Bit
21 | # Version 14.0.0 Build 200 06/17/2014 SJ Web Edition
22 | # Date created = 11:05:04 April 14, 2019
23 | #
24 | # -------------------------------------------------------------------------- #
25 |
26 | QUARTUS_VERSION = "14.0"
27 | DATE = "11:05:04 April 14, 2019"
28 |
29 | # Revisions
30 |
31 | PROJECT_REVISION = "FFT"
32 |
--------------------------------------------------------------------------------
/quartus/fft_64/FFT.qpf:
--------------------------------------------------------------------------------
1 | # -------------------------------------------------------------------------- #
2 | #
3 | # Copyright (C) 1991-2014 Altera Corporation. All rights reserved.
4 | # Your use of Altera Corporation's design tools, logic functions
5 | # and other software and tools, and its AMPP partner logic
6 | # functions, and any output files from any of the foregoing
7 | # (including device programming or simulation files), and any
8 | # associated documentation or information are expressly subject
9 | # to the terms and conditions of the Altera Program License
10 | # Subscription Agreement, the Altera Quartus II License Agreement,
11 | # the Altera MegaCore Function License Agreement, or other
12 | # applicable license agreement, including, without limitation,
13 | # that your use is for the sole purpose of programming logic
14 | # devices manufactured by Altera and sold by Altera or its
15 | # authorized distributors. Please refer to the applicable
16 | # agreement for further details.
17 | #
18 | # -------------------------------------------------------------------------- #
19 | #
20 | # Quartus II 64-Bit
21 | # Version 14.0.0 Build 200 06/17/2014 SJ Web Edition
22 | # Date created = 10:50:42 April 14, 2019
23 | #
24 | # -------------------------------------------------------------------------- #
25 |
26 | QUARTUS_VERSION = "14.0"
27 | DATE = "10:50:42 April 14, 2019"
28 |
29 | # Revisions
30 |
31 | PROJECT_REVISION = "FFT"
32 |
--------------------------------------------------------------------------------
/quartus/fft_1024_32b/FFT.qpf:
--------------------------------------------------------------------------------
1 | # -------------------------------------------------------------------------- #
2 | #
3 | # Copyright (C) 1991-2014 Altera Corporation. All rights reserved.
4 | # Your use of Altera Corporation's design tools, logic functions
5 | # and other software and tools, and its AMPP partner logic
6 | # functions, and any output files from any of the foregoing
7 | # (including device programming or simulation files), and any
8 | # associated documentation or information are expressly subject
9 | # to the terms and conditions of the Altera Program License
10 | # Subscription Agreement, the Altera Quartus II License Agreement,
11 | # the Altera MegaCore Function License Agreement, or other
12 | # applicable license agreement, including, without limitation,
13 | # that your use is for the sole purpose of programming logic
14 | # devices manufactured by Altera and sold by Altera or its
15 | # authorized distributors. Please refer to the applicable
16 | # agreement for further details.
17 | #
18 | # -------------------------------------------------------------------------- #
19 | #
20 | # Quartus II 64-Bit
21 | # Version 14.0.0 Build 200 06/17/2014 SJ Web Edition
22 | # Date created = 11:26:49 April 14, 2019
23 | #
24 | # -------------------------------------------------------------------------- #
25 |
26 | QUARTUS_VERSION = "14.0"
27 | DATE = "11:26:49 April 14, 2019"
28 |
29 | # Revisions
30 |
31 | PROJECT_REVISION = "FFT"
32 |
--------------------------------------------------------------------------------
/sim/fft_64/output4.txt:
--------------------------------------------------------------------------------
1 | 0000 0000 // 0
2 | 3fff ffff // 1
3 | 0000 0000 // 2
4 | 0000 ffff // 3
5 | 0000 0000 // 4
6 | 0000 0000 // 5
7 | 0000 0000 // 6
8 | 0000 0000 // 7
9 | 0000 0000 // 8
10 | 0000 0000 // 9
11 | 0000 0000 // 10
12 | 0000 0000 // 11
13 | 0000 0000 // 12
14 | 0000 0000 // 13
15 | 0000 0000 // 14
16 | 0001 ffff // 15
17 | 0000 0000 // 16
18 | 0000 0000 // 17
19 | 0000 0000 // 18
20 | 0000 0000 // 19
21 | 0000 0000 // 20
22 | 0000 0000 // 21
23 | 0000 0000 // 22
24 | 0000 0000 // 23
25 | 0000 0000 // 24
26 | 0000 0001 // 25
27 | 0000 0000 // 26
28 | 0000 0000 // 27
29 | 0000 0000 // 28
30 | 0000 0000 // 29
31 | 0000 0000 // 30
32 | 0000 0001 // 31
33 | 0000 0000 // 32
34 | 0000 0000 // 33
35 | 0000 0000 // 34
36 | 0000 0000 // 35
37 | 0000 0000 // 36
38 | 0000 0001 // 37
39 | 0000 0000 // 38
40 | 0000 0000 // 39
41 | 0000 0000 // 40
42 | 0000 0001 // 41
43 | 0000 0000 // 42
44 | 0001 0001 // 43
45 | 0000 0000 // 44
46 | 0000 0001 // 45
47 | 0000 0000 // 46
48 | 0000 0000 // 47
49 | 0000 0000 // 48
50 | 0000 0000 // 49
51 | 0000 0000 // 50
52 | 0000 0000 // 51
53 | 0000 0000 // 52
54 | 0001 0000 // 53
55 | 0000 0000 // 54
56 | 0000 0000 // 55
57 | 0000 0000 // 56
58 | 0000 0000 // 57
59 | 0000 0000 // 58
60 | 0000 0000 // 59
61 | 0000 0000 // 60
62 | 0000 0000 // 61
63 | 0000 0000 // 62
64 | 3fff 0001 // 63
65 |
--------------------------------------------------------------------------------
/sim/fft_64/output5.txt:
--------------------------------------------------------------------------------
1 | 0000 0000 // 0
2 | 0000 0000 // 1
3 | 0000 0000 // 2
4 | 0000 ffff // 3
5 | 0000 0000 // 4
6 | 0000 0000 // 5
7 | 0000 0000 // 6
8 | 0000 0000 // 7
9 | 0000 0000 // 8
10 | 0000 0000 // 9
11 | 0000 0000 // 10
12 | 0000 0000 // 11
13 | 0000 0000 // 12
14 | 0000 0000 // 13
15 | 0000 0000 // 14
16 | 7ffd ffff // 15
17 | 0000 0000 // 16
18 | 0000 0000 // 17
19 | 0000 0000 // 18
20 | 0000 0000 // 19
21 | 0000 0000 // 20
22 | 0000 0000 // 21
23 | 0000 0000 // 22
24 | 0000 0001 // 23
25 | 0000 0000 // 24
26 | 0000 0000 // 25
27 | 0000 0000 // 26
28 | 0000 0000 // 27
29 | 0000 0000 // 28
30 | 0000 0000 // 29
31 | 0000 0000 // 30
32 | 0001 0000 // 31
33 | 0000 0000 // 32
34 | 0000 0000 // 33
35 | 0000 0000 // 34
36 | 0000 0000 // 35
37 | 0000 0000 // 36
38 | 0000 0000 // 37
39 | 0000 0000 // 38
40 | 0000 0000 // 39
41 | 0000 0000 // 40
42 | 0000 0000 // 41
43 | 0000 0000 // 42
44 | 0000 0000 // 43
45 | 0000 0000 // 44
46 | 0000 0000 // 45
47 | 0000 0000 // 46
48 | 0000 0000 // 47
49 | 0000 0000 // 48
50 | 0000 0000 // 49
51 | 0000 0000 // 50
52 | 0000 0000 // 51
53 | 0000 0000 // 52
54 | 0000 0000 // 53
55 | 0000 0000 // 54
56 | 0000 0000 // 55
57 | 0000 0000 // 56
58 | 0000 0000 // 57
59 | 0000 0000 // 58
60 | 0000 0000 // 59
61 | 0000 0000 // 60
62 | 0000 0000 // 61
63 | 0000 0000 // 62
64 | 0000 0000 // 63
65 |
--------------------------------------------------------------------------------
/tool/twiddle.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | use strict;
4 | use warnings;
5 | use POSIX 'floor';
6 |
7 | my $pi = atan2(1, 1) * 4;
8 |
9 | my $N = 1024; # Number of FFT Points
10 | my $NB = 32; # Number of Twiddle Data Bits
11 |
12 | my $ND = int(log(2**($NB-1))/log(10)) + 2; # Number of Decimal Digits
13 | my $NX = int(($NB + 3) / 4); # Number of Hexadecimal Digits
14 |
15 | my $XX = "x" x $NX; # Hexadecimal Unknown Value String
16 |
17 | printf("// wn_re = cos(-2pi*n/%2d) ", $N);
18 | printf(" wn_im = sin(-2pi*n/%2d)\n", $N);
19 |
20 | for (my $n = 0; $n < $N; ++$n) {
21 | my $wr = cos(-2 * $pi * $n / $N);
22 | my $wi = sin(-2 * $pi * $n / $N);
23 |
24 | my $wr_d = floor($wr * 2**($NB-1) + 0.5); $wr_d -= 1 if ($wr_d == 2**($NB-1));
25 | my $wi_d = floor($wi * 2**($NB-1) + 0.5); $wi_d -= 1 if ($wi_d == 2**($NB-1));
26 | my $wr_u = ($wr_d < 0) ? ($wr_d + 2**$NB) : $wr_d;
27 | my $wi_u = ($wi_d < 0) ? ($wi_d + 2**$NB) : $wi_d;
28 |
29 | # printf("%${ND}d %${ND}d ", $wr_d, $wi_d);
30 | # printf("%0${NB}b %0${NB}b ", $wr_u, $wi_u);
31 | # printf("%0${NX}X %0${NX}X ", $wr_u, $wi_u);
32 | my $dontcare = 1;
33 | $dontcare = 0 if ($n < $N/4);
34 | $dontcare = 0 if (($n < 2*$N/4) && ($n % 2 == 0));
35 | $dontcare = 0 if (($n < 3*$N/4) && ($n % 3 == 0));
36 | $wr_u = 0 if ($n == 0);
37 | my $wr_s = ($dontcare) ? $XX : sprintf("%0${NX}X", $wr_u);
38 | my $wi_s = ($dontcare) ? $XX : sprintf("%0${NX}X", $wi_u);
39 | printf("assign wn_re[%2d] = ${NB}'h$wr_s; ", $n);
40 | printf("assign wn_im[%2d] = ${NB}'h$wi_s; ", $n);
41 | printf("// %2d", $n);
42 | printf(" % .3f % .3f", $wr, $wi);
43 | print "\n";
44 | }
45 |
--------------------------------------------------------------------------------
/sim/fft_64/input4.txt:
--------------------------------------------------------------------------------
1 | 7FFD 0000 // 0 1.000 0.000
2 | 7F5F 0000 // 1 0.995 0.000
3 | 7D87 0000 // 2 0.981 0.000
4 | 7A7A 0000 // 3 0.957 0.000
5 | 763F 0000 // 4 0.924 0.000
6 | 70E0 0000 // 5 0.882 0.000
7 | 6A6B 0000 // 6 0.831 0.000
8 | 62EF 0000 // 7 0.773 0.000
9 | 5A80 0000 // 8 0.707 0.000
10 | 5132 0000 // 9 0.634 0.000
11 | 471B 0000 // 10 0.556 0.000
12 | 3C55 0000 // 11 0.471 0.000
13 | 30FB 0000 // 12 0.383 0.000
14 | 2527 0000 // 13 0.290 0.000
15 | 18F8 0000 // 14 0.195 0.000
16 | 0C8C 0000 // 15 0.098 0.000
17 | 0000 0000 // 16 0.000 0.000
18 | F374 0000 // 17 -0.098 0.000
19 | E708 0000 // 18 -0.195 0.000
20 | DAD9 0000 // 19 -0.290 0.000
21 | CF05 0000 // 20 -0.383 0.000
22 | C3AB 0000 // 21 -0.471 0.000
23 | B8E5 0000 // 22 -0.556 0.000
24 | AECE 0000 // 23 -0.634 0.000
25 | A580 0000 // 24 -0.707 0.000
26 | 9D11 0000 // 25 -0.773 0.000
27 | 9595 0000 // 26 -0.831 0.000
28 | 8F20 0000 // 27 -0.882 0.000
29 | 89C1 0000 // 28 -0.924 0.000
30 | 8586 0000 // 29 -0.957 0.000
31 | 8279 0000 // 30 -0.981 0.000
32 | 80A1 0000 // 31 -0.995 0.000
33 | 8003 0000 // 32 -1.000 0.000
34 | 80A1 0000 // 33 -0.995 0.000
35 | 8279 0000 // 34 -0.981 0.000
36 | 8586 0000 // 35 -0.957 0.000
37 | 89C1 0000 // 36 -0.924 0.000
38 | 8F20 0000 // 37 -0.882 0.000
39 | 9595 0000 // 38 -0.831 0.000
40 | 9D11 0000 // 39 -0.773 0.000
41 | A580 0000 // 40 -0.707 0.000
42 | AECE 0000 // 41 -0.634 0.000
43 | B8E5 0000 // 42 -0.556 0.000
44 | C3AB 0000 // 43 -0.471 0.000
45 | CF05 0000 // 44 -0.383 0.000
46 | DAD9 0000 // 45 -0.290 0.000
47 | E708 0000 // 46 -0.195 0.000
48 | F374 0000 // 47 -0.098 0.000
49 | 0000 0000 // 48 -0.000 0.000
50 | 0C8C 0000 // 49 0.098 0.000
51 | 18F8 0000 // 50 0.195 0.000
52 | 2527 0000 // 51 0.290 0.000
53 | 30FB 0000 // 52 0.383 0.000
54 | 3C55 0000 // 53 0.471 0.000
55 | 471B 0000 // 54 0.556 0.000
56 | 5132 0000 // 55 0.634 0.000
57 | 5A80 0000 // 56 0.707 0.000
58 | 62EF 0000 // 57 0.773 0.000
59 | 6A6B 0000 // 58 0.831 0.000
60 | 70E0 0000 // 59 0.882 0.000
61 | 763F 0000 // 60 0.924 0.000
62 | 7A7A 0000 // 61 0.957 0.000
63 | 7D87 0000 // 62 0.981 0.000
64 | 7F5F 0000 // 63 0.995 0.000
65 |
--------------------------------------------------------------------------------
/sim/fft_64/input5.txt:
--------------------------------------------------------------------------------
1 | 7FFD 0000 // 0 1.000 0.000
2 | 0C8C 7F5F // 1 0.098 0.995
3 | 8279 18F8 // 2 -0.981 0.195
4 | DAD9 8586 // 3 -0.290 -0.957
5 | 763F CF05 // 4 0.924 -0.383
6 | 3C55 70E0 // 5 0.471 0.882
7 | 9595 471B // 6 -0.831 0.556
8 | AECE 9D11 // 7 -0.634 -0.773
9 | 5A80 A580 // 8 0.707 -0.707
10 | 62EF 5132 // 9 0.773 0.634
11 | B8E5 6A6B // 10 -0.556 0.831
12 | 8F20 C3AB // 11 -0.882 -0.471
13 | 30FB 89C1 // 12 0.383 -0.924
14 | 7A7A 2527 // 13 0.957 0.290
15 | E708 7D87 // 14 -0.195 0.981
16 | 80A1 F374 // 15 -0.995 -0.098
17 | 0000 8003 // 16 -0.000 -1.000
18 | 7F5F F374 // 17 0.995 -0.098
19 | 18F8 7D87 // 18 0.195 0.981
20 | 8586 2527 // 19 -0.957 0.290
21 | CF05 89C1 // 20 -0.383 -0.924
22 | 70E0 C3AB // 21 0.882 -0.471
23 | 471B 6A6B // 22 0.556 0.831
24 | 9D11 5132 // 23 -0.773 0.634
25 | A580 A580 // 24 -0.707 -0.707
26 | 5132 9D11 // 25 0.634 -0.773
27 | 6A6B 471B // 26 0.831 0.556
28 | C3AB 70E0 // 27 -0.471 0.882
29 | 89C1 CF05 // 28 -0.924 -0.383
30 | 2527 8586 // 29 0.290 -0.957
31 | 7D87 18F8 // 30 0.981 0.195
32 | F374 7F5F // 31 -0.098 0.995
33 | 8003 0000 // 32 -1.000 0.000
34 | F374 80A1 // 33 -0.098 -0.995
35 | 7D87 E708 // 34 0.981 -0.195
36 | 2527 7A7A // 35 0.290 0.957
37 | 89C1 30FB // 36 -0.924 0.383
38 | C3AB 8F20 // 37 -0.471 -0.882
39 | 6A6B B8E5 // 38 0.831 -0.556
40 | 5132 62EF // 39 0.634 0.773
41 | A580 5A80 // 40 -0.707 0.707
42 | 9D11 AECE // 41 -0.773 -0.634
43 | 471B 9595 // 42 0.556 -0.831
44 | 70E0 3C55 // 43 0.882 0.471
45 | CF05 763F // 44 -0.383 0.924
46 | 8586 DAD9 // 45 -0.957 -0.290
47 | 18F8 8279 // 46 0.195 -0.981
48 | 7F5F 0C8C // 47 0.995 0.098
49 | 0000 7FFD // 48 0.000 1.000
50 | 80A1 0C8C // 49 -0.995 0.098
51 | E708 8279 // 50 -0.195 -0.981
52 | 7A7A DAD9 // 51 0.957 -0.290
53 | 30FB 763F // 52 0.383 0.924
54 | 8F20 3C55 // 53 -0.882 0.471
55 | B8E5 9595 // 54 -0.556 -0.831
56 | 62EF AECE // 55 0.773 -0.634
57 | 5A80 5A80 // 56 0.707 0.707
58 | AECE 62EF // 57 -0.634 0.773
59 | 9595 B8E5 // 58 -0.831 -0.556
60 | 3C55 8F20 // 59 0.471 -0.882
61 | 763F 30FB // 60 0.924 0.383
62 | DAD9 7A7A // 61 -0.290 0.957
63 | 8279 E708 // 62 -0.981 -0.195
64 | 0C8C 80A1 // 63 0.098 -0.995
65 |
--------------------------------------------------------------------------------
/verilog/FFT64.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // FFT: 64-Point FFT Using Radix-2^2 Single-Path Delay Feedback
3 | //----------------------------------------------------------------------
4 | module FFT #(
5 | parameter WIDTH = 16
6 | )(
7 | input clock, // Master Clock
8 | input reset, // Active High Asynchronous Reset
9 | input di_en, // Input Data Enable
10 | input [WIDTH-1:0] di_re, // Input Data (Real)
11 | input [WIDTH-1:0] di_im, // Input Data (Imag)
12 | output do_en, // Output Data Enable
13 | output [WIDTH-1:0] do_re, // Output Data (Real)
14 | output [WIDTH-1:0] do_im // Output Data (Imag)
15 | );
16 | //----------------------------------------------------------------------
17 | // Data must be input consecutively in natural order.
18 | // The result is scaled to 1/N and output in bit-reversed order.
19 | // The output latency is 71 clock cycles.
20 | //----------------------------------------------------------------------
21 |
22 | wire su1_do_en;
23 | wire[WIDTH-1:0] su1_do_re;
24 | wire[WIDTH-1:0] su1_do_im;
25 | wire su2_do_en;
26 | wire[WIDTH-1:0] su2_do_re;
27 | wire[WIDTH-1:0] su2_do_im;
28 |
29 | SdfUnit #(.N(64),.M(64),.WIDTH(WIDTH)) SU1 (
30 | .clock (clock ), // i
31 | .reset (reset ), // i
32 | .di_en (di_en ), // i
33 | .di_re (di_re ), // i
34 | .di_im (di_im ), // i
35 | .do_en (su1_do_en ), // o
36 | .do_re (su1_do_re ), // o
37 | .do_im (su1_do_im ) // o
38 | );
39 |
40 | SdfUnit #(.N(64),.M(16),.WIDTH(WIDTH)) SU2 (
41 | .clock (clock ), // i
42 | .reset (reset ), // i
43 | .di_en (su1_do_en ), // i
44 | .di_re (su1_do_re ), // i
45 | .di_im (su1_do_im ), // i
46 | .do_en (su2_do_en ), // o
47 | .do_re (su2_do_re ), // o
48 | .do_im (su2_do_im ) // o
49 | );
50 |
51 | SdfUnit #(.N(64),.M(4),.WIDTH(WIDTH)) SU3 (
52 | .clock (clock ), // i
53 | .reset (reset ), // i
54 | .di_en (su2_do_en ), // i
55 | .di_re (su2_do_re ), // i
56 | .di_im (su2_do_im ), // i
57 | .do_en (do_en ), // o
58 | .do_re (do_re ), // o
59 | .do_im (do_im ) // o
60 | );
61 |
62 | endmodule
63 |
--------------------------------------------------------------------------------
/verilog/TwiddleConvert4.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // TwiddleConvert4: Convert Twiddle Value to Reduce Table Size to 1/4
3 | //----------------------------------------------------------------------
4 | module TwiddleConvert4 #(
5 | parameter LOG_N = 6, // Address Bit Length
6 | parameter WIDTH = 16, // Data Bit Length
7 | parameter TW_FF = 1, // Use Twiddle Output Register
8 | parameter TC_FF = 1 // Use Output Register
9 | )(
10 | input clock, // Master Clock
11 | input [LOG_N-1:0] tw_addr, // Twiddle Number
12 | input [WIDTH-1:0] tw_re, // Twiddle Value (Real)
13 | input [WIDTH-1:0] tw_im, // Twiddle Value (Imag)
14 | output [LOG_N-1:0] tc_addr, // Converted Twiddle Number
15 | output [WIDTH-1:0] tc_re, // Converted Twiddle Value (Real)
16 | output [WIDTH-1:0] tc_im // Converted Twiddle Value (Imag)
17 | );
18 |
19 | // Internal Nets
20 | reg [LOG_N-1:0] ff_addr;
21 | wire[LOG_N-1:0] sel_addr;
22 | reg [WIDTH-1:0] mx_re;
23 | reg [WIDTH-1:0] mx_im;
24 | reg [WIDTH-1:0] ff_re;
25 | reg [WIDTH-1:0] ff_im;
26 |
27 | // Convert Twiddle Number
28 | assign tc_addr[LOG_N-1:LOG_N-2] = 2'd0;
29 | assign tc_addr[LOG_N-3:0] = tw_addr[LOG_N-3:0];
30 |
31 | // Convert Twiddle Value
32 | always @(posedge clock) begin
33 | ff_addr <= tw_addr;
34 | end
35 | assign sel_addr = TW_FF ? ff_addr : tw_addr;
36 |
37 | always @* begin
38 | if (sel_addr[LOG_N-3:0] == {LOG_N-2{1'b0}}) begin
39 | case (sel_addr[LOG_N-1:LOG_N-2])
40 | 2'd0 : {mx_re, mx_im} <= {{WIDTH{1'b0}}, {WIDTH{1'b0}}};
41 | 2'd1 : {mx_re, mx_im} <= {{WIDTH{1'b0}}, {1'b1,{WIDTH-1{1'b0}}}};
42 | default : {mx_re, mx_im} <= {{WIDTH{1'bx}}, {WIDTH{1'bx}}};
43 | endcase
44 | end else begin
45 | case (sel_addr[LOG_N-1:LOG_N-2])
46 | 2'd0 : {mx_re, mx_im} <= { tw_re, tw_im};
47 | 2'd1 : {mx_re, mx_im} <= { tw_im, -tw_re};
48 | 2'd2 : {mx_re, mx_im} <= {-tw_re, -tw_im};
49 | default : {mx_re, mx_im} <= {{WIDTH{1'bx}}, {WIDTH{1'bx}}};
50 | endcase
51 | end
52 | end
53 | always @(posedge clock) begin
54 | ff_re <= mx_re;
55 | ff_im <= mx_im;
56 | end
57 |
58 | assign tc_re = TC_FF ? ff_re : mx_re;
59 | assign tc_im = TC_FF ? ff_im : mx_im;
60 |
61 | endmodule
62 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | r22sdf
2 | ======
3 |
4 | Implementation of pipeline FFT described in Verilog HDL.
5 |
6 | * Radix-22 single-path delay feedback (R22SDF) architecture
7 | * Scaled fixed-point arithmetic
8 | * Synthesizable with FPGA implementation software
9 |
10 |
11 | Interface
12 | ---------
13 |
14 | module FFT #(
15 | parameter WIDTH = 16
16 | )(
17 | input clock, // Master Clock
18 | input reset, // Active High Asynchronous Reset
19 | input di_en, // Input Data Enable
20 | input [WIDTH-1:0] di_re, // Input Data (Real)
21 | input [WIDTH-1:0] di_im, // Input Data (Imag)
22 | output do_en, // Output Data Enable
23 | output [WIDTH-1:0] do_re, // Output Data (Real)
24 | output [WIDTH-1:0] do_im // Output Data (Imag)
25 | );
26 |
27 | Data must be input consecutively in natural order.
28 | The result is scaled to 1/N and output in bit-reversed order.
29 | The output latency differs depending on the transform size.
30 | For 64-point FFT, it is 71 clock cycles.
31 |
32 | *64-point FFT timing diagram*
33 | 
34 |
35 |
36 | Source Files
37 | ------------
38 |
39 | There are two kinds of configurations.
40 |
41 | * Basic configuration for small size FFT
42 | * Resource saving configuration for large size FFT
43 |
44 | In my environment, when the number of FFT points is greater than or equal to 256
45 | it is better to use the resource saving configuration.
46 |
47 | For the basic configuration, use the following files.
48 |
49 | FFT.v
50 | SdfUnit.v
51 | SdfUnit2.v
52 | Butterfly.v
53 | DelayBuffer.v
54 | Multiply.v
55 | Twiddle.v
56 |
57 | *FFT.v* and *Twiddle.v* must be created according to the number of FFT points
58 | and the data bit length.
59 | *SdfUnit2.v* is required if the number of FFT points is not a power of 4.
60 | To make a resource saving configuration, replace *SdfUnit.v* with *SdfUnit_TC.v*
61 | and add *TwiddleConvert4.v* or *TwiddleConvert8.v*.
62 |
63 | *TwiddleConvert4* reduces the table size of *Twiddle* to 1/4.
64 | Likewise, *TwiddleConvert8* reduces it to 1/8, but requires more additional logic
65 | than *TwiddleConvert4*.
66 | *TwiddleConvert8* is used by default, but *TwiddleConvert4* may be better in some cases.
67 |
68 |
69 | Architecture
70 | ------------
71 |
72 | Radix-22 single-path delay feedback (R22SDF)
73 | is known as an efficient implementation of pipeline FFT.
74 | There is radix-2 single-path delay feedback (R2SDF) in a similar architecture,
75 | but R22SDF uses fewer multipliers.
76 |
77 | 
78 |
79 | 
80 |
81 | 
82 |
--------------------------------------------------------------------------------
/verilog/FFT128.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // FFT: 128-Point FFT Using Radix-2^2 Single-Path Delay Feedback
3 | //----------------------------------------------------------------------
4 | module FFT #(
5 | parameter WIDTH = 16
6 | )(
7 | input clock, // Master Clock
8 | input reset, // Active High Asynchronous Reset
9 | input di_en, // Input Data Enable
10 | input [WIDTH-1:0] di_re, // Input Data (Real)
11 | input [WIDTH-1:0] di_im, // Input Data (Imag)
12 | output do_en, // Output Data Enable
13 | output [WIDTH-1:0] do_re, // Output Data (Real)
14 | output [WIDTH-1:0] do_im // Output Data (Imag)
15 | );
16 | //----------------------------------------------------------------------
17 | // Data must be input consecutively in natural order.
18 | // The result is scaled to 1/N and output in bit-reversed order.
19 | // The output latency is 137 clock cycles.
20 | //----------------------------------------------------------------------
21 |
22 | wire su1_do_en;
23 | wire[WIDTH-1:0] su1_do_re;
24 | wire[WIDTH-1:0] su1_do_im;
25 | wire su2_do_en;
26 | wire[WIDTH-1:0] su2_do_re;
27 | wire[WIDTH-1:0] su2_do_im;
28 | wire su3_do_en;
29 | wire[WIDTH-1:0] su3_do_re;
30 | wire[WIDTH-1:0] su3_do_im;
31 |
32 | SdfUnit #(.N(128),.M(128),.WIDTH(WIDTH)) SU1 (
33 | .clock (clock ), // i
34 | .reset (reset ), // i
35 | .di_en (di_en ), // i
36 | .di_re (di_re ), // i
37 | .di_im (di_im ), // i
38 | .do_en (su1_do_en ), // o
39 | .do_re (su1_do_re ), // o
40 | .do_im (su1_do_im ) // o
41 | );
42 |
43 | SdfUnit #(.N(128),.M(32),.WIDTH(WIDTH)) SU2 (
44 | .clock (clock ), // i
45 | .reset (reset ), // i
46 | .di_en (su1_do_en ), // i
47 | .di_re (su1_do_re ), // i
48 | .di_im (su1_do_im ), // i
49 | .do_en (su2_do_en ), // o
50 | .do_re (su2_do_re ), // o
51 | .do_im (su2_do_im ) // o
52 | );
53 |
54 | SdfUnit #(.N(128),.M(8),.WIDTH(WIDTH)) SU3 (
55 | .clock (clock ), // i
56 | .reset (reset ), // i
57 | .di_en (su2_do_en ), // i
58 | .di_re (su2_do_re ), // i
59 | .di_im (su2_do_im ), // i
60 | .do_en (su3_do_en ), // o
61 | .do_re (su3_do_re ), // o
62 | .do_im (su3_do_im ) // o
63 | );
64 |
65 | SdfUnit2 #(.WIDTH(WIDTH)) SU4 (
66 | .clock (clock ), // i
67 | .reset (reset ), // i
68 | .di_en (su3_do_en ), // i
69 | .di_re (su3_do_re ), // i
70 | .di_im (su3_do_im ), // i
71 | .do_en (do_en ), // o
72 | .do_re (do_re ), // o
73 | .do_im (do_im ) // o
74 | );
75 |
76 | endmodule
77 |
--------------------------------------------------------------------------------
/verilog/TwiddleConvert8.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // TwiddleConvert8: Convert Twiddle Value to Reduce Table Size to 1/8
3 | //----------------------------------------------------------------------
4 | module TwiddleConvert8 #(
5 | parameter LOG_N = 6, // Address Bit Length
6 | parameter WIDTH = 16, // Data Bit Length
7 | parameter TW_FF = 1, // Use Twiddle Output Register
8 | parameter TC_FF = 1 // Use Output Register
9 | )(
10 | input clock, // Master Clock
11 | input [LOG_N-1:0] tw_addr, // Twiddle Number
12 | input [WIDTH-1:0] tw_re, // Twiddle Value (Real)
13 | input [WIDTH-1:0] tw_im, // Twiddle Value (Imag)
14 | output [LOG_N-1:0] tc_addr, // Converted Twiddle Number
15 | output [WIDTH-1:0] tc_re, // Converted Twiddle Value (Real)
16 | output [WIDTH-1:0] tc_im // Converted Twiddle Value (Imag)
17 | );
18 |
19 | // Define Constants
20 | localparam[WIDTH-1:0] COSMQ = (((32'h5A82799A<<1) >> (32-WIDTH)) + 1)>>1; // cos(-pi/4)
21 | localparam[WIDTH-1:0] SINMH = 32'h80000000 >> (32-WIDTH); // sin(-pi/2)
22 |
23 | // Internal Nets
24 | reg [LOG_N-1:0] ff_addr;
25 | wire[LOG_N-1:0] sel_addr;
26 | reg [WIDTH-1:0] mx_re;
27 | reg [WIDTH-1:0] mx_im;
28 | reg [WIDTH-1:0] ff_re;
29 | reg [WIDTH-1:0] ff_im;
30 |
31 | // Convert Twiddle Number
32 | assign tc_addr[LOG_N-1:LOG_N-3] = 3'd0;
33 | assign tc_addr[LOG_N-4:0] = tw_addr[LOG_N-3] ? -tw_addr[LOG_N-4:0] : tw_addr[LOG_N-4:0];
34 |
35 | // Convert Twiddle Value
36 | always @(posedge clock) begin
37 | ff_addr <= tw_addr;
38 | end
39 | assign sel_addr = TW_FF ? ff_addr : tw_addr;
40 |
41 | always @* begin
42 | if (sel_addr[LOG_N-4:0] == {LOG_N-3{1'b0}}) begin
43 | case (sel_addr[LOG_N-1:LOG_N-3])
44 | 3'd0 : {mx_re, mx_im} <= {{WIDTH{1'b0}}, {WIDTH{1'b0}}};
45 | 3'd1 : {mx_re, mx_im} <= { COSMQ , -COSMQ };
46 | 3'd2 : {mx_re, mx_im} <= {{WIDTH{1'b0}}, SINMH };
47 | 3'd3 : {mx_re, mx_im} <= {-COSMQ , -COSMQ };
48 | default : {mx_re, mx_im} <= {{WIDTH{1'bx}}, {WIDTH{1'bx}}};
49 | endcase
50 | end else begin
51 | case (sel_addr[LOG_N-1:LOG_N-3])
52 | 3'd0 : {mx_re, mx_im} <= { tw_re, tw_im};
53 | 3'd1 : {mx_re, mx_im} <= {-tw_im, -tw_re};
54 | 3'd2 : {mx_re, mx_im} <= { tw_im, -tw_re};
55 | 3'd3 : {mx_re, mx_im} <= {-tw_re, tw_im};
56 | 3'd4 : {mx_re, mx_im} <= {-tw_re, -tw_im};
57 | 3'd5 : {mx_re, mx_im} <= { tw_im, tw_re};
58 | default : {mx_re, mx_im} <= {{WIDTH{1'bx}}, {WIDTH{1'bx}}};
59 | endcase
60 | end
61 | end
62 | always @(posedge clock) begin
63 | ff_re <= mx_re;
64 | ff_im <= mx_im;
65 | end
66 |
67 | assign tc_re = TC_FF ? ff_re : mx_re;
68 | assign tc_im = TC_FF ? ff_im : mx_im;
69 |
70 | endmodule
71 |
--------------------------------------------------------------------------------
/sim/fft_64/TB64.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // TB: FftTop Testbench
3 | //----------------------------------------------------------------------
4 | `timescale 1ns/1ns
5 | module TB;
6 |
7 | reg clock;
8 | reg reset;
9 | reg di_en;
10 | reg [15:0] di_re;
11 | reg [15:0] di_im;
12 | wire do_en;
13 | wire[15:0] do_re;
14 | wire[15:0] do_im;
15 |
16 | reg [15:0] imem[0:127];
17 | reg [15:0] omem[0:127];
18 |
19 | //----------------------------------------------------------------------
20 | // Clock and Reset
21 | //----------------------------------------------------------------------
22 | always begin
23 | clock = 0; #10;
24 | clock = 1; #10;
25 | end
26 |
27 | initial begin
28 | reset = 0; #20;
29 | reset = 1; #100;
30 | reset = 0;
31 | end
32 |
33 | //----------------------------------------------------------------------
34 | // Functional Blocks
35 | //----------------------------------------------------------------------
36 |
37 | // Input Control Initialize
38 | initial begin
39 | wait (reset == 1);
40 | di_en = 0;
41 | end
42 |
43 | // Output Data Capture
44 | initial begin : OCAP
45 | integer n;
46 | forever begin
47 | n = 0;
48 | while (do_en !== 1) @(negedge clock);
49 | while ((do_en == 1) && (n < 64)) begin
50 | omem[2*n ] = do_re;
51 | omem[2*n+1] = do_im;
52 | n = n + 1;
53 | @(negedge clock);
54 | end
55 | end
56 | end
57 |
58 | //----------------------------------------------------------------------
59 | // Tasks
60 | //----------------------------------------------------------------------
61 | task LoadInputData;
62 | input[80*8:1] filename;
63 | begin
64 | $readmemh(filename, imem);
65 | end
66 | endtask
67 |
68 | task GenerateInputWave;
69 | integer n;
70 | begin
71 | di_en <= 1;
72 | for (n = 0; n < 64; n = n + 1) begin
73 | di_re <= imem[2*n];
74 | di_im <= imem[2*n+1];
75 | @(posedge clock);
76 | end
77 | di_en <= 0;
78 | di_re <= 'bx;
79 | di_im <= 'bx;
80 | end
81 | endtask
82 |
83 | task SaveOutputData;
84 | input[80*8:1] filename;
85 | integer fp, n, m;
86 | begin
87 | fp = $fopen(filename);
88 | m = 0;
89 | for (n = 0; n < 64; n = n + 1) begin
90 | m[5] = n[0];
91 | m[4] = n[1];
92 | m[3] = n[2];
93 | m[2] = n[3];
94 | m[1] = n[4];
95 | m[0] = n[5];
96 | $fdisplay(fp, "%h %h // %d", omem[2*m], omem[2*m+1], n[5:0]);
97 | end
98 | $fclose(fp);
99 | end
100 | endtask
101 |
102 | //----------------------------------------------------------------------
103 | // Module Instances
104 | //----------------------------------------------------------------------
105 | FFT FFT (
106 | .clock (clock ), // i
107 | .reset (reset ), // i
108 | .di_en (di_en ), // i
109 | .di_re (di_re ), // i
110 | .di_im (di_im ), // i
111 | .do_en (do_en ), // o
112 | .do_re (do_re ), // o
113 | .do_im (do_im ) // o
114 | );
115 |
116 | //----------------------------------------------------------------------
117 | // Include Stimuli
118 | //----------------------------------------------------------------------
119 | `include "stim.v"
120 |
121 | endmodule
122 |
--------------------------------------------------------------------------------
/sim/fft_128_tc/output4.txt:
--------------------------------------------------------------------------------
1 | 0000 0000 // 0
2 | 3ffe ffff // 1
3 | 0000 0000 // 2
4 | 0000 ffff // 3
5 | 0000 0000 // 4
6 | 0000 0000 // 5
7 | 0000 0000 // 6
8 | 0000 0000 // 7
9 | 0000 0000 // 8
10 | 0000 0000 // 9
11 | 0000 0000 // 10
12 | 0000 0000 // 11
13 | 0000 0000 // 12
14 | 0000 0000 // 13
15 | 0000 0000 // 14
16 | 0000 ffff // 15
17 | 0000 0000 // 16
18 | 0000 0000 // 17
19 | 0000 0000 // 18
20 | 0000 0000 // 19
21 | 0000 0000 // 20
22 | 0000 0000 // 21
23 | 0000 0000 // 22
24 | 0000 0000 // 23
25 | 0000 0000 // 24
26 | 0000 0000 // 25
27 | 0000 0000 // 26
28 | 0000 0000 // 27
29 | 0000 0000 // 28
30 | 0000 0000 // 29
31 | 0000 0000 // 30
32 | 0000 0000 // 31
33 | 0000 0000 // 32
34 | 0000 0000 // 33
35 | 0000 0000 // 34
36 | 0000 ffff // 35
37 | 0000 0000 // 36
38 | 0000 0000 // 37
39 | 0000 0000 // 38
40 | 0000 0000 // 39
41 | 0000 0000 // 40
42 | 0000 0000 // 41
43 | 0000 0000 // 42
44 | 0001 0000 // 43
45 | 0000 0000 // 44
46 | 0000 0000 // 45
47 | 0000 0000 // 46
48 | 0000 0000 // 47
49 | 0000 0000 // 48
50 | 0000 0000 // 49
51 | 0000 0000 // 50
52 | 0000 0000 // 51
53 | 0000 0000 // 52
54 | 0000 0000 // 53
55 | 0000 0000 // 54
56 | 0000 0000 // 55
57 | 0000 0000 // 56
58 | 0000 0000 // 57
59 | 0000 0000 // 58
60 | 0000 0000 // 59
61 | 0000 0000 // 60
62 | 0000 0000 // 61
63 | 0000 0000 // 62
64 | 0000 ffff // 63
65 | 0000 0000 // 64
66 | 0000 0000 // 65
67 | 0000 0000 // 66
68 | 0000 0000 // 67
69 | 0000 0000 // 68
70 | 0000 0000 // 69
71 | 0000 0000 // 70
72 | 0000 0000 // 71
73 | 0000 0000 // 72
74 | ffff 0000 // 73
75 | 0000 0000 // 74
76 | ffff 0000 // 75
77 | 0000 0000 // 76
78 | 0000 0000 // 77
79 | 0000 0000 // 78
80 | 0000 0000 // 79
81 | 0000 0000 // 80
82 | ffff 0000 // 81
83 | 0000 0000 // 82
84 | 0000 0000 // 83
85 | 0000 0000 // 84
86 | 0000 0000 // 85
87 | 0000 0000 // 86
88 | 0000 0000 // 87
89 | 0000 0000 // 88
90 | 0000 0000 // 89
91 | 0000 0000 // 90
92 | 0000 0000 // 91
93 | 0000 0000 // 92
94 | 0000 0000 // 93
95 | 0000 0000 // 94
96 | 0000 0000 // 95
97 | 0000 0000 // 96
98 | 0000 0000 // 97
99 | 0000 0000 // 98
100 | 0000 0000 // 99
101 | 0000 0000 // 100
102 | 0000 0000 // 101
103 | 0000 0000 // 102
104 | 0000 0000 // 103
105 | 0000 0000 // 104
106 | ffff 0000 // 105
107 | 0000 0000 // 106
108 | 0000 0000 // 107
109 | 0000 0000 // 108
110 | 0000 0000 // 109
111 | 0000 0000 // 110
112 | 0000 0000 // 111
113 | 0000 0000 // 112
114 | 0000 0000 // 113
115 | 0000 0000 // 114
116 | 0000 0000 // 115
117 | 0000 0000 // 116
118 | 0000 0000 // 117
119 | 0000 0000 // 118
120 | 0000 0000 // 119
121 | 0000 0000 // 120
122 | 0000 0000 // 121
123 | 0000 0000 // 122
124 | 0000 0000 // 123
125 | 0000 0000 // 124
126 | 0000 0000 // 125
127 | 0000 0000 // 126
128 | 3ffe 0001 // 127
129 |
--------------------------------------------------------------------------------
/sim/fft_128_tc/output5.txt:
--------------------------------------------------------------------------------
1 | 0000 0000 // 0
2 | 0000 0000 // 1
3 | 0000 0000 // 2
4 | 0000 ffff // 3
5 | 0000 0000 // 4
6 | 0000 0000 // 5
7 | 0000 0000 // 6
8 | 0000 0000 // 7
9 | 0000 0000 // 8
10 | 0000 0000 // 9
11 | 0000 0000 // 10
12 | ffff ffff // 11
13 | 0000 0000 // 12
14 | 0000 0000 // 13
15 | 0000 0000 // 14
16 | 7ffd ffff // 15
17 | 0000 0000 // 16
18 | 0000 0000 // 17
19 | 0000 0000 // 18
20 | 0000 0000 // 19
21 | 0000 0000 // 20
22 | 0000 0000 // 21
23 | 0000 0000 // 22
24 | 0000 0000 // 23
25 | 0000 0000 // 24
26 | 0000 0000 // 25
27 | 0000 0000 // 26
28 | 0000 0000 // 27
29 | 0000 0000 // 28
30 | 0000 0000 // 29
31 | 0000 0000 // 30
32 | 0000 0000 // 31
33 | 0000 0000 // 32
34 | 0000 0000 // 33
35 | 0000 0000 // 34
36 | 0000 0000 // 35
37 | 0000 0000 // 36
38 | 0000 0000 // 37
39 | 0000 0000 // 38
40 | 0000 0000 // 39
41 | 0000 0000 // 40
42 | 0000 0000 // 41
43 | 0000 0000 // 42
44 | 0000 0000 // 43
45 | 0000 0000 // 44
46 | 0000 0000 // 45
47 | 0000 0000 // 46
48 | 0000 0000 // 47
49 | 0000 0000 // 48
50 | 0000 0000 // 49
51 | 0000 0000 // 50
52 | 0000 0000 // 51
53 | 0000 0000 // 52
54 | 0000 0000 // 53
55 | 0000 0000 // 54
56 | 0000 0000 // 55
57 | 0000 0000 // 56
58 | 0000 0000 // 57
59 | 0000 0000 // 58
60 | 0000 0000 // 59
61 | 0000 0000 // 60
62 | 0000 0000 // 61
63 | 0000 0000 // 62
64 | ffff ffff // 63
65 | 0000 0000 // 64
66 | 0000 0000 // 65
67 | 0000 0000 // 66
68 | 0000 0000 // 67
69 | 0000 0000 // 68
70 | 0000 0000 // 69
71 | 0000 0000 // 70
72 | 0000 0000 // 71
73 | 0000 0000 // 72
74 | 0000 0000 // 73
75 | 0000 0000 // 74
76 | 0000 0000 // 75
77 | 0000 0000 // 76
78 | 0000 0000 // 77
79 | 0000 0000 // 78
80 | 0000 0000 // 79
81 | 0000 0000 // 80
82 | 0000 0000 // 81
83 | 0000 0000 // 82
84 | 0000 0000 // 83
85 | 0000 0000 // 84
86 | 0000 0000 // 85
87 | 0000 0000 // 86
88 | 0000 0000 // 87
89 | 0000 0000 // 88
90 | 0000 0000 // 89
91 | 0000 0000 // 90
92 | 0000 0000 // 91
93 | 0000 0000 // 92
94 | 0000 0000 // 93
95 | 0000 0000 // 94
96 | 0000 0000 // 95
97 | 0000 0000 // 96
98 | 0000 0000 // 97
99 | 0000 0000 // 98
100 | 0000 0000 // 99
101 | 0000 0000 // 100
102 | 0000 0000 // 101
103 | 0000 0000 // 102
104 | 0000 0000 // 103
105 | 0000 0000 // 104
106 | 0000 0000 // 105
107 | 0000 0000 // 106
108 | 0000 0000 // 107
109 | 0000 0000 // 108
110 | 0000 0000 // 109
111 | 0000 0000 // 110
112 | 0000 0000 // 111
113 | 0000 0000 // 112
114 | 0000 0000 // 113
115 | 0000 0000 // 114
116 | 0000 0000 // 115
117 | 0000 0000 // 116
118 | 0000 0000 // 117
119 | 0000 0000 // 118
120 | 0000 0000 // 119
121 | 0000 0000 // 120
122 | 0000 0000 // 121
123 | 0000 0000 // 122
124 | 0000 0000 // 123
125 | 0000 0000 // 124
126 | 0000 0000 // 125
127 | 0000 0000 // 126
128 | 0000 0000 // 127
129 |
--------------------------------------------------------------------------------
/verilog/FFT1024_32B.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // FFT: 1024-Point FFT Using Radix-2^2 Single-Path Delay Feedback
3 | //----------------------------------------------------------------------
4 | module FFT #(
5 | parameter WIDTH = 32
6 | )(
7 | input clock, // Master Clock
8 | input reset, // Active High Asynchronous Reset
9 | input di_en, // Input Data Enable
10 | input [WIDTH-1:0] di_re, // Input Data (Real)
11 | input [WIDTH-1:0] di_im, // Input Data (Imag)
12 | output do_en, // Output Data Enable
13 | output [WIDTH-1:0] do_re, // Output Data (Real)
14 | output [WIDTH-1:0] do_im // Output Data (Imag)
15 | );
16 | //----------------------------------------------------------------------
17 | // Data must be input consecutively in natural order.
18 | // The result is scaled to 1/N and output in bit-reversed order.
19 | //----------------------------------------------------------------------
20 |
21 | wire su1_do_en;
22 | wire[WIDTH-1:0] su1_do_re;
23 | wire[WIDTH-1:0] su1_do_im;
24 | wire su2_do_en;
25 | wire[WIDTH-1:0] su2_do_re;
26 | wire[WIDTH-1:0] su2_do_im;
27 | wire su3_do_en;
28 | wire[WIDTH-1:0] su3_do_re;
29 | wire[WIDTH-1:0] su3_do_im;
30 | wire su4_do_en;
31 | wire[WIDTH-1:0] su4_do_re;
32 | wire[WIDTH-1:0] su4_do_im;
33 |
34 | SdfUnit #(.N(1024),.M(1024),.WIDTH(WIDTH)) SU1 (
35 | .clock (clock ), // i
36 | .reset (reset ), // i
37 | .di_en (di_en ), // i
38 | .di_re (di_re ), // i
39 | .di_im (di_im ), // i
40 | .do_en (su1_do_en ), // o
41 | .do_re (su1_do_re ), // o
42 | .do_im (su1_do_im ) // o
43 | );
44 |
45 | SdfUnit #(.N(1024),.M(256),.WIDTH(WIDTH)) SU2 (
46 | .clock (clock ), // i
47 | .reset (reset ), // i
48 | .di_en (su1_do_en ), // i
49 | .di_re (su1_do_re ), // i
50 | .di_im (su1_do_im ), // i
51 | .do_en (su2_do_en ), // o
52 | .do_re (su2_do_re ), // o
53 | .do_im (su2_do_im ) // o
54 | );
55 |
56 | SdfUnit #(.N(1024),.M(64),.WIDTH(WIDTH)) SU3 (
57 | .clock (clock ), // i
58 | .reset (reset ), // i
59 | .di_en (su2_do_en ), // i
60 | .di_re (su2_do_re ), // i
61 | .di_im (su2_do_im ), // i
62 | .do_en (su3_do_en ), // o
63 | .do_re (su3_do_re ), // o
64 | .do_im (su3_do_im ) // o
65 | );
66 |
67 | SdfUnit #(.N(1024),.M(16),.WIDTH(WIDTH)) SU4 (
68 | .clock (clock ), // i
69 | .reset (reset ), // i
70 | .di_en (su3_do_en ), // i
71 | .di_re (su3_do_re ), // i
72 | .di_im (su3_do_im ), // i
73 | .do_en (su4_do_en ), // o
74 | .do_re (su4_do_re ), // o
75 | .do_im (su4_do_im ) // o
76 | );
77 |
78 | SdfUnit #(.N(1024),.M(4),.WIDTH(WIDTH)) SU5 (
79 | .clock (clock ), // i
80 | .reset (reset ), // i
81 | .di_en (su4_do_en ), // i
82 | .di_re (su4_do_re ), // i
83 | .di_im (su4_do_im ), // i
84 | .do_en (do_en ), // o
85 | .do_re (do_re ), // o
86 | .do_im (do_im ) // o
87 | );
88 |
89 | endmodule
90 |
--------------------------------------------------------------------------------
/sim/fft_128_tc/TB128.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // TB: FftTop Testbench
3 | //----------------------------------------------------------------------
4 | `timescale 1ns/1ns
5 | module TB #(
6 | parameter N = 128
7 | );
8 |
9 | localparam NN = log2(N); // Count Bit Width of FFT Point
10 |
11 | // log2 constant function
12 | function integer log2;
13 | input integer x;
14 | integer value;
15 | begin
16 | value = x-1;
17 | for (log2=0; value>0; log2=log2+1)
18 | value = value>>1;
19 | end
20 | endfunction
21 |
22 | // Internal Regs and Nets
23 | reg clock;
24 | reg reset;
25 | reg di_en;
26 | reg [15:0] di_re;
27 | reg [15:0] di_im;
28 | wire do_en;
29 | wire[15:0] do_re;
30 | wire[15:0] do_im;
31 |
32 | reg [15:0] imem[0:2*N-1];
33 | reg [15:0] omem[0:2*N-1];
34 |
35 | //----------------------------------------------------------------------
36 | // Clock and Reset
37 | //----------------------------------------------------------------------
38 | always begin
39 | clock = 0; #10;
40 | clock = 1; #10;
41 | end
42 |
43 | initial begin
44 | reset = 0; #20;
45 | reset = 1; #100;
46 | reset = 0;
47 | end
48 |
49 | //----------------------------------------------------------------------
50 | // Functional Blocks
51 | //----------------------------------------------------------------------
52 |
53 | // Input Control Initialize
54 | initial begin
55 | wait (reset == 1);
56 | di_en = 0;
57 | end
58 |
59 | // Output Data Capture
60 | initial begin : OCAP
61 | integer n;
62 | forever begin
63 | n = 0;
64 | while (do_en !== 1) @(negedge clock);
65 | while ((do_en == 1) && (n < N)) begin
66 | omem[2*n ] = do_re;
67 | omem[2*n+1] = do_im;
68 | n = n + 1;
69 | @(negedge clock);
70 | end
71 | end
72 | end
73 |
74 | //----------------------------------------------------------------------
75 | // Tasks
76 | //----------------------------------------------------------------------
77 | task LoadInputData;
78 | input[80*8:1] filename;
79 | begin
80 | $readmemh(filename, imem);
81 | end
82 | endtask
83 |
84 | task GenerateInputWave;
85 | integer n;
86 | begin
87 | di_en <= 1;
88 | for (n = 0; n < N; n = n + 1) begin
89 | di_re <= imem[2*n];
90 | di_im <= imem[2*n+1];
91 | @(posedge clock);
92 | end
93 | di_en <= 0;
94 | di_re <= 'bx;
95 | di_im <= 'bx;
96 | end
97 | endtask
98 |
99 | task SaveOutputData;
100 | input[80*8:1] filename;
101 | integer fp, n, m, i;
102 | begin
103 | fp = $fopen(filename);
104 | m = 0;
105 | for (n = 0; n < N; n = n + 1) begin
106 | for (i = 0; i < NN; i = i + 1) m[NN-1-i] = n[i];
107 | $fdisplay(fp, "%h %h // %d", omem[2*m], omem[2*m+1], n[NN-1:0]);
108 | end
109 | $fclose(fp);
110 | end
111 | endtask
112 |
113 | //----------------------------------------------------------------------
114 | // Module Instances
115 | //----------------------------------------------------------------------
116 | FFT FFT (
117 | .clock (clock ), // i
118 | .reset (reset ), // i
119 | .di_en (di_en ), // i
120 | .di_re (di_re ), // i
121 | .di_im (di_im ), // i
122 | .do_en (do_en ), // o
123 | .do_re (do_re ), // o
124 | .do_im (do_im ) // o
125 | );
126 |
127 | //----------------------------------------------------------------------
128 | // Include Stimuli
129 | //----------------------------------------------------------------------
130 | `include "stim.v"
131 |
132 | endmodule
133 |
--------------------------------------------------------------------------------
/verilog/SdfUnit2.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // SdfUnit2: Radix-2 SDF Dedicated for Twiddle Resolution M = 2
3 | //----------------------------------------------------------------------
4 | module SdfUnit2 #(
5 | parameter WIDTH = 16, // Data Bit Length
6 | parameter BF_RH = 0 // Butterfly Round Half Up
7 | )(
8 | input clock, // Master Clock
9 | input reset, // Active High Asynchronous Reset
10 | input di_en, // Input Data Enable
11 | input [WIDTH-1:0] di_re, // Input Data (Real)
12 | input [WIDTH-1:0] di_im, // Input Data (Imag)
13 | output reg do_en, // Output Data Enable
14 | output reg [WIDTH-1:0] do_re, // Output Data (Real)
15 | output reg [WIDTH-1:0] do_im // Output Data (Imag)
16 | );
17 |
18 | //----------------------------------------------------------------------
19 | // Internal Regs and Nets
20 | //----------------------------------------------------------------------
21 | reg bf_en; // Butterfly Add/Sub Enable
22 | wire[WIDTH-1:0] x0_re; // Data #0 to Butterfly (Real)
23 | wire[WIDTH-1:0] x0_im; // Data #0 to Butterfly (Imag)
24 | wire[WIDTH-1:0] x1_re; // Data #1 to Butterfly (Real)
25 | wire[WIDTH-1:0] x1_im; // Data #1 to Butterfly (Imag)
26 | wire[WIDTH-1:0] y0_re; // Data #0 from Butterfly (Real)
27 | wire[WIDTH-1:0] y0_im; // Data #0 from Butterfly (Imag)
28 | wire[WIDTH-1:0] y1_re; // Data #1 from Butterfly (Real)
29 | wire[WIDTH-1:0] y1_im; // Data #1 from Butterfly (Imag)
30 | wire[WIDTH-1:0] db_di_re; // Data to DelayBuffer (Real)
31 | wire[WIDTH-1:0] db_di_im; // Data to DelayBuffer (Imag)
32 | wire[WIDTH-1:0] db_do_re; // Data from DelayBuffer (Real)
33 | wire[WIDTH-1:0] db_do_im; // Data from DelayBuffer (Imag)
34 | wire[WIDTH-1:0] bf_sp_re; // Single-Path Data Output (Real)
35 | wire[WIDTH-1:0] bf_sp_im; // Single-Path Data Output (Imag)
36 | reg bf_sp_en; // Single-Path Data Enable
37 |
38 | //----------------------------------------------------------------------
39 | // Butterfly Add/Sub
40 | //----------------------------------------------------------------------
41 | always @(posedge clock or posedge reset) begin
42 | if (reset) begin
43 | bf_en <= 1'b0;
44 | end else begin
45 | bf_en <= di_en ? ~bf_en : 1'b0;
46 | end
47 | end
48 |
49 | // Set unknown value x for verification
50 | assign x0_re = bf_en ? db_do_re : {WIDTH{1'bx}};
51 | assign x0_im = bf_en ? db_do_im : {WIDTH{1'bx}};
52 | assign x1_re = bf_en ? di_re : {WIDTH{1'bx}};
53 | assign x1_im = bf_en ? di_im : {WIDTH{1'bx}};
54 |
55 | Butterfly #(.WIDTH(WIDTH),.RH(BF_RH)) BF (
56 | .x0_re (x0_re ), // i
57 | .x0_im (x0_im ), // i
58 | .x1_re (x1_re ), // i
59 | .x1_im (x1_im ), // i
60 | .y0_re (y0_re ), // o
61 | .y0_im (y0_im ), // o
62 | .y1_re (y1_re ), // o
63 | .y1_im (y1_im ) // o
64 | );
65 |
66 | DelayBuffer #(.DEPTH(1),.WIDTH(WIDTH)) DB (
67 | .clock (clock ), // i
68 | .di_re (db_di_re ), // i
69 | .di_im (db_di_im ), // i
70 | .do_re (db_do_re ), // o
71 | .do_im (db_do_im ) // o
72 | );
73 |
74 | assign db_di_re = bf_en ? y1_re : di_re;
75 | assign db_di_im = bf_en ? y1_im : di_im;
76 | assign bf_sp_re = bf_en ? y0_re : db_do_re;
77 | assign bf_sp_im = bf_en ? y0_im : db_do_im;
78 |
79 | always @(posedge clock or posedge reset) begin
80 | if (reset) begin
81 | bf_sp_en <= 1'b0;
82 | do_en <= 1'b0;
83 | end else begin
84 | bf_sp_en <= di_en;
85 | do_en <= bf_sp_en;
86 | end
87 | end
88 |
89 | always @(posedge clock) begin
90 | do_re <= bf_sp_re;
91 | do_im <= bf_sp_im;
92 | end
93 |
94 | endmodule
95 |
--------------------------------------------------------------------------------
/sim/fft_128_tc/input4.txt:
--------------------------------------------------------------------------------
1 | 7FFD 0000 // 0 1.000 0.000
2 | 7FD5 0000 // 1 0.999 0.000
3 | 7F5F 0000 // 2 0.995 0.000
4 | 7E9A 0000 // 3 0.989 0.000
5 | 7D87 0000 // 4 0.981 0.000
6 | 7C27 0000 // 5 0.970 0.000
7 | 7A7A 0000 // 6 0.957 0.000
8 | 7881 0000 // 7 0.941 0.000
9 | 763F 0000 // 8 0.924 0.000
10 | 73B3 0000 // 9 0.904 0.000
11 | 70E0 0000 // 10 0.882 0.000
12 | 6DC7 0000 // 11 0.858 0.000
13 | 6A6B 0000 // 12 0.831 0.000
14 | 66CD 0000 // 13 0.803 0.000
15 | 62EF 0000 // 14 0.773 0.000
16 | 5ED5 0000 // 15 0.741 0.000
17 | 5A80 0000 // 16 0.707 0.000
18 | 55F3 0000 // 17 0.671 0.000
19 | 5132 0000 // 18 0.634 0.000
20 | 4C3E 0000 // 19 0.596 0.000
21 | 471B 0000 // 20 0.556 0.000
22 | 41CC 0000 // 21 0.514 0.000
23 | 3C55 0000 // 22 0.471 0.000
24 | 36B9 0000 // 23 0.428 0.000
25 | 30FB 0000 // 24 0.383 0.000
26 | 2B1E 0000 // 25 0.337 0.000
27 | 2527 0000 // 26 0.290 0.000
28 | 1F19 0000 // 27 0.243 0.000
29 | 18F8 0000 // 28 0.195 0.000
30 | 12C8 0000 // 29 0.147 0.000
31 | 0C8C 0000 // 30 0.098 0.000
32 | 0648 0000 // 31 0.049 0.000
33 | 0000 0000 // 32 0.000 0.000
34 | F9B8 0000 // 33 -0.049 0.000
35 | F374 0000 // 34 -0.098 0.000
36 | ED38 0000 // 35 -0.147 0.000
37 | E708 0000 // 36 -0.195 0.000
38 | E0E7 0000 // 37 -0.243 0.000
39 | DAD9 0000 // 38 -0.290 0.000
40 | D4E2 0000 // 39 -0.337 0.000
41 | CF05 0000 // 40 -0.383 0.000
42 | C947 0000 // 41 -0.428 0.000
43 | C3AB 0000 // 42 -0.471 0.000
44 | BE34 0000 // 43 -0.514 0.000
45 | B8E5 0000 // 44 -0.556 0.000
46 | B3C2 0000 // 45 -0.596 0.000
47 | AECE 0000 // 46 -0.634 0.000
48 | AA0D 0000 // 47 -0.671 0.000
49 | A580 0000 // 48 -0.707 0.000
50 | A12B 0000 // 49 -0.741 0.000
51 | 9D11 0000 // 50 -0.773 0.000
52 | 9933 0000 // 51 -0.803 0.000
53 | 9595 0000 // 52 -0.831 0.000
54 | 9239 0000 // 53 -0.858 0.000
55 | 8F20 0000 // 54 -0.882 0.000
56 | 8C4D 0000 // 55 -0.904 0.000
57 | 89C1 0000 // 56 -0.924 0.000
58 | 877F 0000 // 57 -0.941 0.000
59 | 8586 0000 // 58 -0.957 0.000
60 | 83D9 0000 // 59 -0.970 0.000
61 | 8279 0000 // 60 -0.981 0.000
62 | 8166 0000 // 61 -0.989 0.000
63 | 80A1 0000 // 62 -0.995 0.000
64 | 802B 0000 // 63 -0.999 0.000
65 | 8003 0000 // 64 -1.000 0.000
66 | 802B 0000 // 65 -0.999 0.000
67 | 80A1 0000 // 66 -0.995 0.000
68 | 8166 0000 // 67 -0.989 0.000
69 | 8279 0000 // 68 -0.981 0.000
70 | 83D9 0000 // 69 -0.970 0.000
71 | 8586 0000 // 70 -0.957 0.000
72 | 877F 0000 // 71 -0.941 0.000
73 | 89C1 0000 // 72 -0.924 0.000
74 | 8C4D 0000 // 73 -0.904 0.000
75 | 8F20 0000 // 74 -0.882 0.000
76 | 9239 0000 // 75 -0.858 0.000
77 | 9595 0000 // 76 -0.831 0.000
78 | 9933 0000 // 77 -0.803 0.000
79 | 9D11 0000 // 78 -0.773 0.000
80 | A12B 0000 // 79 -0.741 0.000
81 | A580 0000 // 80 -0.707 0.000
82 | AA0D 0000 // 81 -0.671 0.000
83 | AECE 0000 // 82 -0.634 0.000
84 | B3C2 0000 // 83 -0.596 0.000
85 | B8E5 0000 // 84 -0.556 0.000
86 | BE34 0000 // 85 -0.514 0.000
87 | C3AB 0000 // 86 -0.471 0.000
88 | C947 0000 // 87 -0.428 0.000
89 | CF05 0000 // 88 -0.383 0.000
90 | D4E2 0000 // 89 -0.337 0.000
91 | DAD9 0000 // 90 -0.290 0.000
92 | E0E7 0000 // 91 -0.243 0.000
93 | E708 0000 // 92 -0.195 0.000
94 | ED38 0000 // 93 -0.147 0.000
95 | F374 0000 // 94 -0.098 0.000
96 | F9B8 0000 // 95 -0.049 0.000
97 | 0000 0000 // 96 -0.000 0.000
98 | 0648 0000 // 97 0.049 0.000
99 | 0C8C 0000 // 98 0.098 0.000
100 | 12C8 0000 // 99 0.147 0.000
101 | 18F8 0000 // 100 0.195 0.000
102 | 1F19 0000 // 101 0.243 0.000
103 | 2527 0000 // 102 0.290 0.000
104 | 2B1E 0000 // 103 0.337 0.000
105 | 30FB 0000 // 104 0.383 0.000
106 | 36B9 0000 // 105 0.428 0.000
107 | 3C55 0000 // 106 0.471 0.000
108 | 41CC 0000 // 107 0.514 0.000
109 | 471B 0000 // 108 0.556 0.000
110 | 4C3E 0000 // 109 0.596 0.000
111 | 5132 0000 // 110 0.634 0.000
112 | 55F3 0000 // 111 0.671 0.000
113 | 5A80 0000 // 112 0.707 0.000
114 | 5ED5 0000 // 113 0.741 0.000
115 | 62EF 0000 // 114 0.773 0.000
116 | 66CD 0000 // 115 0.803 0.000
117 | 6A6B 0000 // 116 0.831 0.000
118 | 6DC7 0000 // 117 0.858 0.000
119 | 70E0 0000 // 118 0.882 0.000
120 | 73B3 0000 // 119 0.904 0.000
121 | 763F 0000 // 120 0.924 0.000
122 | 7881 0000 // 121 0.941 0.000
123 | 7A7A 0000 // 122 0.957 0.000
124 | 7C27 0000 // 123 0.970 0.000
125 | 7D87 0000 // 124 0.981 0.000
126 | 7E9A 0000 // 125 0.989 0.000
127 | 7F5F 0000 // 126 0.995 0.000
128 | 7FD5 0000 // 127 0.999 0.000
129 |
--------------------------------------------------------------------------------
/sim/fft_128_tc/input5.txt:
--------------------------------------------------------------------------------
1 | 7FFD 0000 // 0 1.000 0.000
2 | 5ED5 55F3 // 1 0.741 0.671
3 | 0C8C 7F5F // 2 0.098 0.995
4 | B3C2 66CD // 3 -0.596 0.803
5 | 8279 18F8 // 4 -0.981 0.195
6 | 9239 BE34 // 5 -0.858 -0.514
7 | DAD9 8586 // 6 -0.290 -0.957
8 | 36B9 8C4D // 7 0.428 -0.904
9 | 763F CF05 // 8 0.924 -0.383
10 | 7881 2B1E // 9 0.941 0.337
11 | 3C55 70E0 // 10 0.471 0.882
12 | E0E7 7C27 // 11 -0.243 0.970
13 | 9595 471B // 12 -0.831 0.556
14 | 8166 ED38 // 13 -0.989 -0.147
15 | AECE 9D11 // 14 -0.634 -0.773
16 | 0648 802B // 15 0.049 -0.999
17 | 5A80 A580 // 16 0.707 -0.707
18 | 7FD5 F9B8 // 17 0.999 -0.049
19 | 62EF 5132 // 18 0.773 0.634
20 | 12C8 7E9A // 19 0.147 0.989
21 | B8E5 6A6B // 20 -0.556 0.831
22 | 83D9 1F19 // 21 -0.970 0.243
23 | 8F20 C3AB // 22 -0.882 -0.471
24 | D4E2 877F // 23 -0.337 -0.941
25 | 30FB 89C1 // 24 0.383 -0.924
26 | 73B3 C947 // 25 0.904 -0.428
27 | 7A7A 2527 // 26 0.957 0.290
28 | 41CC 6DC7 // 27 0.514 0.858
29 | E708 7D87 // 28 -0.195 0.981
30 | 9933 4C3E // 29 -0.803 0.596
31 | 80A1 F374 // 30 -0.995 -0.098
32 | AA0D A12B // 31 -0.671 -0.741
33 | 0000 8003 // 32 -0.000 -1.000
34 | 55F3 A12B // 33 0.671 -0.741
35 | 7F5F F374 // 34 0.995 -0.098
36 | 66CD 4C3E // 35 0.803 0.596
37 | 18F8 7D87 // 36 0.195 0.981
38 | BE34 6DC7 // 37 -0.514 0.858
39 | 8586 2527 // 38 -0.957 0.290
40 | 8C4D C947 // 39 -0.904 -0.428
41 | CF05 89C1 // 40 -0.383 -0.924
42 | 2B1E 877F // 41 0.337 -0.941
43 | 70E0 C3AB // 42 0.882 -0.471
44 | 7C27 1F19 // 43 0.970 0.243
45 | 471B 6A6B // 44 0.556 0.831
46 | ED38 7E9A // 45 -0.147 0.989
47 | 9D11 5132 // 46 -0.773 0.634
48 | 802B F9B8 // 47 -0.999 -0.049
49 | A580 A580 // 48 -0.707 -0.707
50 | F9B8 802B // 49 -0.049 -0.999
51 | 5132 9D11 // 50 0.634 -0.773
52 | 7E9A ED38 // 51 0.989 -0.147
53 | 6A6B 471B // 52 0.831 0.556
54 | 1F19 7C27 // 53 0.243 0.970
55 | C3AB 70E0 // 54 -0.471 0.882
56 | 877F 2B1E // 55 -0.941 0.337
57 | 89C1 CF05 // 56 -0.924 -0.383
58 | C947 8C4D // 57 -0.428 -0.904
59 | 2527 8586 // 58 0.290 -0.957
60 | 6DC7 BE34 // 59 0.858 -0.514
61 | 7D87 18F8 // 60 0.981 0.195
62 | 4C3E 66CD // 61 0.596 0.803
63 | F374 7F5F // 62 -0.098 0.995
64 | A12B 55F3 // 63 -0.741 0.671
65 | 8003 0000 // 64 -1.000 0.000
66 | A12B AA0D // 65 -0.741 -0.671
67 | F374 80A1 // 66 -0.098 -0.995
68 | 4C3E 9933 // 67 0.596 -0.803
69 | 7D87 E708 // 68 0.981 -0.195
70 | 6DC7 41CC // 69 0.858 0.514
71 | 2527 7A7A // 70 0.290 0.957
72 | C947 73B3 // 71 -0.428 0.904
73 | 89C1 30FB // 72 -0.924 0.383
74 | 877F D4E2 // 73 -0.941 -0.337
75 | C3AB 8F20 // 74 -0.471 -0.882
76 | 1F19 83D9 // 75 0.243 -0.970
77 | 6A6B B8E5 // 76 0.831 -0.556
78 | 7E9A 12C8 // 77 0.989 0.147
79 | 5132 62EF // 78 0.634 0.773
80 | F9B8 7FD5 // 79 -0.049 0.999
81 | A580 5A80 // 80 -0.707 0.707
82 | 802B 0648 // 81 -0.999 0.049
83 | 9D11 AECE // 82 -0.773 -0.634
84 | ED38 8166 // 83 -0.147 -0.989
85 | 471B 9595 // 84 0.556 -0.831
86 | 7C27 E0E7 // 85 0.970 -0.243
87 | 70E0 3C55 // 86 0.882 0.471
88 | 2B1E 7881 // 87 0.337 0.941
89 | CF05 763F // 88 -0.383 0.924
90 | 8C4D 36B9 // 89 -0.904 0.428
91 | 8586 DAD9 // 90 -0.957 -0.290
92 | BE34 9239 // 91 -0.514 -0.858
93 | 18F8 8279 // 92 0.195 -0.981
94 | 66CD B3C2 // 93 0.803 -0.596
95 | 7F5F 0C8C // 94 0.995 0.098
96 | 55F3 5ED5 // 95 0.671 0.741
97 | 0000 7FFD // 96 0.000 1.000
98 | AA0D 5ED5 // 97 -0.671 0.741
99 | 80A1 0C8C // 98 -0.995 0.098
100 | 9933 B3C2 // 99 -0.803 -0.596
101 | E708 8279 // 100 -0.195 -0.981
102 | 41CC 9239 // 101 0.514 -0.858
103 | 7A7A DAD9 // 102 0.957 -0.290
104 | 73B3 36B9 // 103 0.904 0.428
105 | 30FB 763F // 104 0.383 0.924
106 | D4E2 7881 // 105 -0.337 0.941
107 | 8F20 3C55 // 106 -0.882 0.471
108 | 83D9 E0E7 // 107 -0.970 -0.243
109 | B8E5 9595 // 108 -0.556 -0.831
110 | 12C8 8166 // 109 0.147 -0.989
111 | 62EF AECE // 110 0.773 -0.634
112 | 7FD5 0648 // 111 0.999 0.049
113 | 5A80 5A80 // 112 0.707 0.707
114 | 0648 7FD5 // 113 0.049 0.999
115 | AECE 62EF // 114 -0.634 0.773
116 | 8166 12C8 // 115 -0.989 0.147
117 | 9595 B8E5 // 116 -0.831 -0.556
118 | E0E7 83D9 // 117 -0.243 -0.970
119 | 3C55 8F20 // 118 0.471 -0.882
120 | 7881 D4E2 // 119 0.941 -0.337
121 | 763F 30FB // 120 0.924 0.383
122 | 36B9 73B3 // 121 0.428 0.904
123 | DAD9 7A7A // 122 -0.290 0.957
124 | 9239 41CC // 123 -0.858 0.514
125 | 8279 E708 // 124 -0.981 -0.195
126 | B3C2 9933 // 125 -0.596 -0.803
127 | 0C8C 80A1 // 126 0.098 -0.995
128 | 5ED5 AA0D // 127 0.741 -0.671
129 |
--------------------------------------------------------------------------------
/verilog/Twiddle64.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // Twiddle: 64-Point Twiddle Table for Radix-2^2 Butterfly
3 | //----------------------------------------------------------------------
4 | module Twiddle #(
5 | parameter TW_FF = 1 // Use Output Register
6 | )(
7 | input clock, // Master Clock
8 | input [5:0] addr, // Twiddle Factor Number
9 | output [15:0] tw_re, // Twiddle Factor (Real)
10 | output [15:0] tw_im // Twiddle Factor (Imag)
11 | );
12 |
13 | wire[15:0] wn_re[0:63]; // Twiddle Table (Real)
14 | wire[15:0] wn_im[0:63]; // Twiddle Table (Imag)
15 | wire[15:0] mx_re; // Multiplexer output (Real)
16 | wire[15:0] mx_im; // Multiplexer output (Imag)
17 | reg [15:0] ff_re; // Register output (Real)
18 | reg [15:0] ff_im; // Register output (Imag)
19 |
20 | assign mx_re = wn_re[addr];
21 | assign mx_im = wn_im[addr];
22 |
23 | always @(posedge clock) begin
24 | ff_re <= mx_re;
25 | ff_im <= mx_im;
26 | end
27 |
28 | assign tw_re = TW_FF ? ff_re : mx_re;
29 | assign tw_im = TW_FF ? ff_im : mx_im;
30 |
31 | //----------------------------------------------------------------------
32 | // Twiddle Factor Value
33 | //----------------------------------------------------------------------
34 | // Multiplication is bypassed when twiddle address is 0.
35 | // Setting wn_re[0] = 0 and wn_im[0] = 0 makes it easier to check the waveform.
36 | // It may also reduce power consumption slightly.
37 | //
38 | // wn_re = cos(-2pi*n/64) wn_im = sin(-2pi*n/64)
39 | assign wn_re[ 0] = 16'h0000; assign wn_im[ 0] = 16'h0000; // 0 1.000 -0.000
40 | assign wn_re[ 1] = 16'h7F62; assign wn_im[ 1] = 16'hF374; // 1 0.995 -0.098
41 | assign wn_re[ 2] = 16'h7D8A; assign wn_im[ 2] = 16'hE707; // 2 0.981 -0.195
42 | assign wn_re[ 3] = 16'h7A7D; assign wn_im[ 3] = 16'hDAD8; // 3 0.957 -0.290
43 | assign wn_re[ 4] = 16'h7642; assign wn_im[ 4] = 16'hCF04; // 4 0.924 -0.383
44 | assign wn_re[ 5] = 16'h70E3; assign wn_im[ 5] = 16'hC3A9; // 5 0.882 -0.471
45 | assign wn_re[ 6] = 16'h6A6E; assign wn_im[ 6] = 16'hB8E3; // 6 0.831 -0.556
46 | assign wn_re[ 7] = 16'h62F2; assign wn_im[ 7] = 16'hAECC; // 7 0.773 -0.634
47 | assign wn_re[ 8] = 16'h5A82; assign wn_im[ 8] = 16'hA57E; // 8 0.707 -0.707
48 | assign wn_re[ 9] = 16'h5134; assign wn_im[ 9] = 16'h9D0E; // 9 0.634 -0.773
49 | assign wn_re[10] = 16'h471D; assign wn_im[10] = 16'h9592; // 10 0.556 -0.831
50 | assign wn_re[11] = 16'h3C57; assign wn_im[11] = 16'h8F1D; // 11 0.471 -0.882
51 | assign wn_re[12] = 16'h30FC; assign wn_im[12] = 16'h89BE; // 12 0.383 -0.924
52 | assign wn_re[13] = 16'h2528; assign wn_im[13] = 16'h8583; // 13 0.290 -0.957
53 | assign wn_re[14] = 16'h18F9; assign wn_im[14] = 16'h8276; // 14 0.195 -0.981
54 | assign wn_re[15] = 16'h0C8C; assign wn_im[15] = 16'h809E; // 15 0.098 -0.995
55 | assign wn_re[16] = 16'h0000; assign wn_im[16] = 16'h8000; // 16 0.000 -1.000
56 | assign wn_re[17] = 16'hxxxx; assign wn_im[17] = 16'hxxxx; // 17 -0.098 -0.995
57 | assign wn_re[18] = 16'hE707; assign wn_im[18] = 16'h8276; // 18 -0.195 -0.981
58 | assign wn_re[19] = 16'hxxxx; assign wn_im[19] = 16'hxxxx; // 19 -0.290 -0.957
59 | assign wn_re[20] = 16'hCF04; assign wn_im[20] = 16'h89BE; // 20 -0.383 -0.924
60 | assign wn_re[21] = 16'hC3A9; assign wn_im[21] = 16'h8F1D; // 21 -0.471 -0.882
61 | assign wn_re[22] = 16'hB8E3; assign wn_im[22] = 16'h9592; // 22 -0.556 -0.831
62 | assign wn_re[23] = 16'hxxxx; assign wn_im[23] = 16'hxxxx; // 23 -0.634 -0.773
63 | assign wn_re[24] = 16'hA57E; assign wn_im[24] = 16'hA57E; // 24 -0.707 -0.707
64 | assign wn_re[25] = 16'hxxxx; assign wn_im[25] = 16'hxxxx; // 25 -0.773 -0.634
65 | assign wn_re[26] = 16'h9592; assign wn_im[26] = 16'hB8E3; // 26 -0.831 -0.556
66 | assign wn_re[27] = 16'h8F1D; assign wn_im[27] = 16'hC3A9; // 27 -0.882 -0.471
67 | assign wn_re[28] = 16'h89BE; assign wn_im[28] = 16'hCF04; // 28 -0.924 -0.383
68 | assign wn_re[29] = 16'hxxxx; assign wn_im[29] = 16'hxxxx; // 29 -0.957 -0.290
69 | assign wn_re[30] = 16'h8276; assign wn_im[30] = 16'hE707; // 30 -0.981 -0.195
70 | assign wn_re[31] = 16'hxxxx; assign wn_im[31] = 16'hxxxx; // 31 -0.995 -0.098
71 | assign wn_re[32] = 16'hxxxx; assign wn_im[32] = 16'hxxxx; // 32 -1.000 -0.000
72 | assign wn_re[33] = 16'h809E; assign wn_im[33] = 16'h0C8C; // 33 -0.995 0.098
73 | assign wn_re[34] = 16'hxxxx; assign wn_im[34] = 16'hxxxx; // 34 -0.981 0.195
74 | assign wn_re[35] = 16'hxxxx; assign wn_im[35] = 16'hxxxx; // 35 -0.957 0.290
75 | assign wn_re[36] = 16'h89BE; assign wn_im[36] = 16'h30FC; // 36 -0.924 0.383
76 | assign wn_re[37] = 16'hxxxx; assign wn_im[37] = 16'hxxxx; // 37 -0.882 0.471
77 | assign wn_re[38] = 16'hxxxx; assign wn_im[38] = 16'hxxxx; // 38 -0.831 0.556
78 | assign wn_re[39] = 16'h9D0E; assign wn_im[39] = 16'h5134; // 39 -0.773 0.634
79 | assign wn_re[40] = 16'hxxxx; assign wn_im[40] = 16'hxxxx; // 40 -0.707 0.707
80 | assign wn_re[41] = 16'hxxxx; assign wn_im[41] = 16'hxxxx; // 41 -0.634 0.773
81 | assign wn_re[42] = 16'hB8E3; assign wn_im[42] = 16'h6A6E; // 42 -0.556 0.831
82 | assign wn_re[43] = 16'hxxxx; assign wn_im[43] = 16'hxxxx; // 43 -0.471 0.882
83 | assign wn_re[44] = 16'hxxxx; assign wn_im[44] = 16'hxxxx; // 44 -0.383 0.924
84 | assign wn_re[45] = 16'hDAD8; assign wn_im[45] = 16'h7A7D; // 45 -0.290 0.957
85 | assign wn_re[46] = 16'hxxxx; assign wn_im[46] = 16'hxxxx; // 46 -0.195 0.981
86 | assign wn_re[47] = 16'hxxxx; assign wn_im[47] = 16'hxxxx; // 47 -0.098 0.995
87 | assign wn_re[48] = 16'hxxxx; assign wn_im[48] = 16'hxxxx; // 48 -0.000 1.000
88 | assign wn_re[49] = 16'hxxxx; assign wn_im[49] = 16'hxxxx; // 49 0.098 0.995
89 | assign wn_re[50] = 16'hxxxx; assign wn_im[50] = 16'hxxxx; // 50 0.195 0.981
90 | assign wn_re[51] = 16'hxxxx; assign wn_im[51] = 16'hxxxx; // 51 0.290 0.957
91 | assign wn_re[52] = 16'hxxxx; assign wn_im[52] = 16'hxxxx; // 52 0.383 0.924
92 | assign wn_re[53] = 16'hxxxx; assign wn_im[53] = 16'hxxxx; // 53 0.471 0.882
93 | assign wn_re[54] = 16'hxxxx; assign wn_im[54] = 16'hxxxx; // 54 0.556 0.831
94 | assign wn_re[55] = 16'hxxxx; assign wn_im[55] = 16'hxxxx; // 55 0.634 0.773
95 | assign wn_re[56] = 16'hxxxx; assign wn_im[56] = 16'hxxxx; // 56 0.707 0.707
96 | assign wn_re[57] = 16'hxxxx; assign wn_im[57] = 16'hxxxx; // 57 0.773 0.634
97 | assign wn_re[58] = 16'hxxxx; assign wn_im[58] = 16'hxxxx; // 58 0.831 0.556
98 | assign wn_re[59] = 16'hxxxx; assign wn_im[59] = 16'hxxxx; // 59 0.882 0.471
99 | assign wn_re[60] = 16'hxxxx; assign wn_im[60] = 16'hxxxx; // 60 0.924 0.383
100 | assign wn_re[61] = 16'hxxxx; assign wn_im[61] = 16'hxxxx; // 61 0.957 0.290
101 | assign wn_re[62] = 16'hxxxx; assign wn_im[62] = 16'hxxxx; // 62 0.981 0.195
102 | assign wn_re[63] = 16'hxxxx; assign wn_im[63] = 16'hxxxx; // 63 0.995 0.098
103 |
104 | endmodule
105 |
--------------------------------------------------------------------------------
/verilog/SdfUnit.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // SdfUnit: Radix-2^2 Single-Path Delay Feedback Unit for N-Point FFT
3 | //----------------------------------------------------------------------
4 | module SdfUnit #(
5 | parameter N = 64, // Number of FFT Point
6 | parameter M = 64, // Twiddle Resolution
7 | parameter WIDTH = 16 // Data Bit Length
8 | )(
9 | input clock, // Master Clock
10 | input reset, // Active High Asynchronous Reset
11 | input di_en, // Input Data Enable
12 | input [WIDTH-1:0] di_re, // Input Data (Real)
13 | input [WIDTH-1:0] di_im, // Input Data (Imag)
14 | output do_en, // Output Data Enable
15 | output [WIDTH-1:0] do_re, // Output Data (Real)
16 | output [WIDTH-1:0] do_im // Output Data (Imag)
17 | );
18 |
19 | // log2 constant function
20 | function integer log2;
21 | input integer x;
22 | integer value;
23 | begin
24 | value = x-1;
25 | for (log2=0; value>0; log2=log2+1)
26 | value = value>>1;
27 | end
28 | endfunction
29 |
30 | localparam LOG_N = log2(N); // Bit Length of N
31 | localparam LOG_M = log2(M); // Bit Length of M
32 |
33 | //----------------------------------------------------------------------
34 | // Internal Regs and Nets
35 | //----------------------------------------------------------------------
36 | // 1st Butterfly
37 | reg [LOG_N-1:0] di_count; // Input Data Count
38 | wire bf1_bf; // Butterfly Add/Sub Enable
39 | wire[WIDTH-1:0] bf1_x0_re; // Data #0 to Butterfly (Real)
40 | wire[WIDTH-1:0] bf1_x0_im; // Data #0 to Butterfly (Imag)
41 | wire[WIDTH-1:0] bf1_x1_re; // Data #1 to Butterfly (Real)
42 | wire[WIDTH-1:0] bf1_x1_im; // Data #1 to Butterfly (Imag)
43 | wire[WIDTH-1:0] bf1_y0_re; // Data #0 from Butterfly (Real)
44 | wire[WIDTH-1:0] bf1_y0_im; // Data #0 from Butterfly (Imag)
45 | wire[WIDTH-1:0] bf1_y1_re; // Data #1 from Butterfly (Real)
46 | wire[WIDTH-1:0] bf1_y1_im; // Data #1 from Butterfly (Imag)
47 | wire[WIDTH-1:0] db1_di_re; // Data to DelayBuffer (Real)
48 | wire[WIDTH-1:0] db1_di_im; // Data to DelayBuffer (Imag)
49 | wire[WIDTH-1:0] db1_do_re; // Data from DelayBuffer (Real)
50 | wire[WIDTH-1:0] db1_do_im; // Data from DelayBuffer (Imag)
51 | wire[WIDTH-1:0] bf1_sp_re; // Single-Path Data Output (Real)
52 | wire[WIDTH-1:0] bf1_sp_im; // Single-Path Data Output (Imag)
53 | reg bf1_sp_en; // Single-Path Data Enable
54 | reg [LOG_N-1:0] bf1_count; // Single-Path Data Count
55 | wire bf1_start; // Single-Path Output Trigger
56 | wire bf1_end; // End of Single-Path Data
57 | wire bf1_mj; // Twiddle (-j) Enable
58 | reg [WIDTH-1:0] bf1_do_re; // 1st Butterfly Output Data (Real)
59 | reg [WIDTH-1:0] bf1_do_im; // 1st Butterfly Output Data (Imag)
60 |
61 | // 2nd Butterfly
62 | reg bf2_bf; // Butterfly Add/Sub Enable
63 | wire[WIDTH-1:0] bf2_x0_re; // Data #0 to Butterfly (Real)
64 | wire[WIDTH-1:0] bf2_x0_im; // Data #0 to Butterfly (Imag)
65 | wire[WIDTH-1:0] bf2_x1_re; // Data #1 to Butterfly (Real)
66 | wire[WIDTH-1:0] bf2_x1_im; // Data #1 to Butterfly (Imag)
67 | wire[WIDTH-1:0] bf2_y0_re; // Data #0 from Butterfly (Real)
68 | wire[WIDTH-1:0] bf2_y0_im; // Data #0 from Butterfly (Imag)
69 | wire[WIDTH-1:0] bf2_y1_re; // Data #1 from Butterfly (Real)
70 | wire[WIDTH-1:0] bf2_y1_im; // Data #1 from Butterfly (Imag)
71 | wire[WIDTH-1:0] db2_di_re; // Data to DelayBuffer (Real)
72 | wire[WIDTH-1:0] db2_di_im; // Data to DelayBuffer (Imag)
73 | wire[WIDTH-1:0] db2_do_re; // Data from DelayBuffer (Real)
74 | wire[WIDTH-1:0] db2_do_im; // Data from DelayBuffer (Imag)
75 | wire[WIDTH-1:0] bf2_sp_re; // Single-Path Data Output (Real)
76 | wire[WIDTH-1:0] bf2_sp_im; // Single-Path Data Output (Imag)
77 | reg bf2_sp_en; // Single-Path Data Enable
78 | reg [LOG_N-1:0] bf2_count; // Single-Path Data Count
79 | reg bf2_start; // Single-Path Output Trigger
80 | wire bf2_end; // End of Single-Path Data
81 | reg [WIDTH-1:0] bf2_do_re; // 2nd Butterfly Output Data (Real)
82 | reg [WIDTH-1:0] bf2_do_im; // 2nd Butterfly Output Data (Imag)
83 | reg bf2_do_en; // 2nd Butterfly Output Data Enable
84 |
85 | // Multiplication
86 | wire[1:0] tw_sel; // Twiddle Select (2n/n/3n)
87 | wire[LOG_N-3:0] tw_num; // Twiddle Number (n)
88 | wire[LOG_N-1:0] tw_addr; // Twiddle Table Address
89 | wire[WIDTH-1:0] tw_re; // Twiddle Factor (Real)
90 | wire[WIDTH-1:0] tw_im; // Twiddle Factor (Imag)
91 | reg mu_en; // Multiplication Enable
92 | wire[WIDTH-1:0] mu_a_re; // Multiplier Input (Real)
93 | wire[WIDTH-1:0] mu_a_im; // Multiplier Input (Imag)
94 | wire[WIDTH-1:0] mu_m_re; // Multiplier Output (Real)
95 | wire[WIDTH-1:0] mu_m_im; // Multiplier Output (Imag)
96 | reg [WIDTH-1:0] mu_do_re; // Multiplication Output Data (Real)
97 | reg [WIDTH-1:0] mu_do_im; // Multiplication Output Data (Imag)
98 | reg mu_do_en; // Multiplication Output Data Enable
99 |
100 | //----------------------------------------------------------------------
101 | // 1st Butterfly
102 | //----------------------------------------------------------------------
103 | always @(posedge clock or posedge reset) begin
104 | if (reset) begin
105 | di_count <= {LOG_N{1'b0}};
106 | end else begin
107 | di_count <= di_en ? (di_count + 1'b1) : {LOG_N{1'b0}};
108 | end
109 | end
110 | assign bf1_bf = di_count[LOG_M-1];
111 |
112 | // Set unknown value x for verification
113 | assign bf1_x0_re = bf1_bf ? db1_do_re : {WIDTH{1'bx}};
114 | assign bf1_x0_im = bf1_bf ? db1_do_im : {WIDTH{1'bx}};
115 | assign bf1_x1_re = bf1_bf ? di_re : {WIDTH{1'bx}};
116 | assign bf1_x1_im = bf1_bf ? di_im : {WIDTH{1'bx}};
117 |
118 | Butterfly #(.WIDTH(WIDTH),.RH(0)) BF1 (
119 | .x0_re (bf1_x0_re ), // i
120 | .x0_im (bf1_x0_im ), // i
121 | .x1_re (bf1_x1_re ), // i
122 | .x1_im (bf1_x1_im ), // i
123 | .y0_re (bf1_y0_re ), // o
124 | .y0_im (bf1_y0_im ), // o
125 | .y1_re (bf1_y1_re ), // o
126 | .y1_im (bf1_y1_im ) // o
127 | );
128 |
129 | DelayBuffer #(.DEPTH(2**(LOG_M-1)),.WIDTH(WIDTH)) DB1 (
130 | .clock (clock ), // i
131 | .di_re (db1_di_re ), // i
132 | .di_im (db1_di_im ), // i
133 | .do_re (db1_do_re ), // o
134 | .do_im (db1_do_im ) // o
135 | );
136 |
137 | assign db1_di_re = bf1_bf ? bf1_y1_re : di_re;
138 | assign db1_di_im = bf1_bf ? bf1_y1_im : di_im;
139 | assign bf1_sp_re = bf1_bf ? bf1_y0_re : bf1_mj ? db1_do_im : db1_do_re;
140 | assign bf1_sp_im = bf1_bf ? bf1_y0_im : bf1_mj ? -db1_do_re : db1_do_im;
141 |
142 | always @(posedge clock or posedge reset) begin
143 | if (reset) begin
144 | bf1_sp_en <= 1'b0;
145 | bf1_count <= {LOG_N{1'b0}};
146 | end else begin
147 | bf1_sp_en <= bf1_start ? 1'b1 : bf1_end ? 1'b0 : bf1_sp_en;
148 | bf1_count <= bf1_sp_en ? (bf1_count + 1'b1) : {LOG_N{1'b0}};
149 | end
150 | end
151 | assign bf1_start = (di_count == (2**(LOG_M-1)-1));
152 | assign bf1_end = (bf1_count == (2**LOG_N-1));
153 | assign bf1_mj = (bf1_count[LOG_M-1:LOG_M-2] == 2'd3);
154 |
155 | always @(posedge clock) begin
156 | bf1_do_re <= bf1_sp_re;
157 | bf1_do_im <= bf1_sp_im;
158 | end
159 |
160 | //----------------------------------------------------------------------
161 | // 2nd Butterfly
162 | //----------------------------------------------------------------------
163 | always @(posedge clock) begin
164 | bf2_bf <= bf1_count[LOG_M-2];
165 | end
166 |
167 | // Set unknown value x for verification
168 | assign bf2_x0_re = bf2_bf ? db2_do_re : {WIDTH{1'bx}};
169 | assign bf2_x0_im = bf2_bf ? db2_do_im : {WIDTH{1'bx}};
170 | assign bf2_x1_re = bf2_bf ? bf1_do_re : {WIDTH{1'bx}};
171 | assign bf2_x1_im = bf2_bf ? bf1_do_im : {WIDTH{1'bx}};
172 |
173 | // Negative bias occurs when RH=0 and positive bias occurs when RH=1.
174 | // Using both alternately reduces the overall rounding error.
175 | Butterfly #(.WIDTH(WIDTH),.RH(1)) BF2 (
176 | .x0_re (bf2_x0_re ), // i
177 | .x0_im (bf2_x0_im ), // i
178 | .x1_re (bf2_x1_re ), // i
179 | .x1_im (bf2_x1_im ), // i
180 | .y0_re (bf2_y0_re ), // o
181 | .y0_im (bf2_y0_im ), // o
182 | .y1_re (bf2_y1_re ), // o
183 | .y1_im (bf2_y1_im ) // o
184 | );
185 |
186 | DelayBuffer #(.DEPTH(2**(LOG_M-2)),.WIDTH(WIDTH)) DB2 (
187 | .clock (clock ), // i
188 | .di_re (db2_di_re ), // i
189 | .di_im (db2_di_im ), // i
190 | .do_re (db2_do_re ), // o
191 | .do_im (db2_do_im ) // o
192 | );
193 |
194 | assign db2_di_re = bf2_bf ? bf2_y1_re : bf1_do_re;
195 | assign db2_di_im = bf2_bf ? bf2_y1_im : bf1_do_im;
196 | assign bf2_sp_re = bf2_bf ? bf2_y0_re : db2_do_re;
197 | assign bf2_sp_im = bf2_bf ? bf2_y0_im : db2_do_im;
198 |
199 | always @(posedge clock or posedge reset) begin
200 | if (reset) begin
201 | bf2_sp_en <= 1'b0;
202 | bf2_count <= {LOG_N{1'b0}};
203 | end else begin
204 | bf2_sp_en <= bf2_start ? 1'b1 : bf2_end ? 1'b0 : bf2_sp_en;
205 | bf2_count <= bf2_sp_en ? (bf2_count + 1'b1) : {LOG_N{1'b0}};
206 | end
207 | end
208 |
209 | always @(posedge clock) begin
210 | bf2_start <= (bf1_count == (2**(LOG_M-2)-1)) & bf1_sp_en;
211 | end
212 | assign bf2_end = (bf2_count == (2**LOG_N-1));
213 |
214 | always @(posedge clock) begin
215 | bf2_do_re <= bf2_sp_re;
216 | bf2_do_im <= bf2_sp_im;
217 | end
218 |
219 | always @(posedge clock or posedge reset) begin
220 | if (reset) begin
221 | bf2_do_en <= 1'b0;
222 | end else begin
223 | bf2_do_en <= bf2_sp_en;
224 | end
225 | end
226 |
227 | //----------------------------------------------------------------------
228 | // Multiplication
229 | //----------------------------------------------------------------------
230 | assign tw_sel[1] = bf2_count[LOG_M-2];
231 | assign tw_sel[0] = bf2_count[LOG_M-1];
232 | assign tw_num = bf2_count << (LOG_N-LOG_M);
233 | assign tw_addr = tw_num * tw_sel;
234 |
235 | Twiddle TW (
236 | .clock (clock ), // i
237 | .addr (tw_addr), // i
238 | .tw_re (tw_re ), // o
239 | .tw_im (tw_im ) // o
240 | );
241 |
242 | // Multiplication is bypassed when twiddle address is 0.
243 | always @(posedge clock) begin
244 | mu_en <= (tw_addr != {LOG_N{1'b0}});
245 | end
246 | // Set unknown value x for verification
247 | assign mu_a_re = mu_en ? bf2_do_re : {WIDTH{1'bx}};
248 | assign mu_a_im = mu_en ? bf2_do_im : {WIDTH{1'bx}};
249 |
250 | Multiply #(.WIDTH(WIDTH)) MU (
251 | .a_re (mu_a_re), // i
252 | .a_im (mu_a_im), // i
253 | .b_re (tw_re ), // i
254 | .b_im (tw_im ), // i
255 | .m_re (mu_m_re), // o
256 | .m_im (mu_m_im) // o
257 | );
258 |
259 | always @(posedge clock) begin
260 | mu_do_re <= mu_en ? mu_m_re : bf2_do_re;
261 | mu_do_im <= mu_en ? mu_m_im : bf2_do_im;
262 | end
263 |
264 | always @(posedge clock or posedge reset) begin
265 | if (reset) begin
266 | mu_do_en <= 1'b0;
267 | end else begin
268 | mu_do_en <= bf2_do_en;
269 | end
270 | end
271 |
272 | // No multiplication required at final stage
273 | assign do_en = (LOG_M == 2) ? bf2_do_en : mu_do_en;
274 | assign do_re = (LOG_M == 2) ? bf2_do_re : mu_do_re;
275 | assign do_im = (LOG_M == 2) ? bf2_do_im : mu_do_im;
276 |
277 | endmodule
278 |
--------------------------------------------------------------------------------
/verilog/Twiddle128.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // Twiddle: 128-Point Twiddle Table for Radix-2^2 Butterfly
3 | //----------------------------------------------------------------------
4 | module Twiddle #(
5 | parameter TW_FF = 1 // Use Output Register
6 | )(
7 | input clock, // Master Clock
8 | input [6:0] addr, // Twiddle Factor Number
9 | output [15:0] tw_re, // Twiddle Factor (Real)
10 | output [15:0] tw_im // Twiddle Factor (Imag)
11 | );
12 |
13 | wire[15:0] wn_re[0:127]; // Twiddle Table (Real)
14 | wire[15:0] wn_im[0:127]; // Twiddle Table (Imag)
15 | wire[15:0] mx_re; // Multiplexer output (Real)
16 | wire[15:0] mx_im; // Multiplexer output (Imag)
17 | reg [15:0] ff_re; // Register output (Real)
18 | reg [15:0] ff_im; // Register output (Imag)
19 |
20 | assign mx_re = wn_re[addr];
21 | assign mx_im = wn_im[addr];
22 |
23 | always @(posedge clock) begin
24 | ff_re <= mx_re;
25 | ff_im <= mx_im;
26 | end
27 |
28 | assign tw_re = TW_FF ? ff_re : mx_re;
29 | assign tw_im = TW_FF ? ff_im : mx_im;
30 |
31 | //----------------------------------------------------------------------
32 | // Twiddle Factor Value
33 | //----------------------------------------------------------------------
34 | // Multiplication is bypassed when twiddle address is 0.
35 | // Setting wn_re[0] = 0 and wn_im[0] = 0 makes it easier to check the waveform.
36 | // It may also reduce power consumption slightly.
37 | //
38 | // wn_re = cos(-2pi*n/128) wn_im = sin(-2pi*n/128)
39 | assign wn_re[ 0] = 16'h0000; assign wn_im[ 0] = 16'h0000; // 0 1.000 -0.000
40 | assign wn_re[ 1] = 16'h7FD9; assign wn_im[ 1] = 16'hF9B8; // 1 0.999 -0.049
41 | assign wn_re[ 2] = 16'h7F62; assign wn_im[ 2] = 16'hF374; // 2 0.995 -0.098
42 | assign wn_re[ 3] = 16'h7E9D; assign wn_im[ 3] = 16'hED38; // 3 0.989 -0.147
43 | assign wn_re[ 4] = 16'h7D8A; assign wn_im[ 4] = 16'hE707; // 4 0.981 -0.195
44 | assign wn_re[ 5] = 16'h7C2A; assign wn_im[ 5] = 16'hE0E6; // 5 0.970 -0.243
45 | assign wn_re[ 6] = 16'h7A7D; assign wn_im[ 6] = 16'hDAD8; // 6 0.957 -0.290
46 | assign wn_re[ 7] = 16'h7885; assign wn_im[ 7] = 16'hD4E1; // 7 0.942 -0.337
47 | assign wn_re[ 8] = 16'h7642; assign wn_im[ 8] = 16'hCF04; // 8 0.924 -0.383
48 | assign wn_re[ 9] = 16'h73B6; assign wn_im[ 9] = 16'hC946; // 9 0.904 -0.428
49 | assign wn_re[10] = 16'h70E3; assign wn_im[10] = 16'hC3A9; // 10 0.882 -0.471
50 | assign wn_re[11] = 16'h6DCA; assign wn_im[11] = 16'hBE32; // 11 0.858 -0.514
51 | assign wn_re[12] = 16'h6A6E; assign wn_im[12] = 16'hB8E3; // 12 0.831 -0.556
52 | assign wn_re[13] = 16'h66D0; assign wn_im[13] = 16'hB3C0; // 13 0.803 -0.596
53 | assign wn_re[14] = 16'h62F2; assign wn_im[14] = 16'hAECC; // 14 0.773 -0.634
54 | assign wn_re[15] = 16'h5ED7; assign wn_im[15] = 16'hAA0A; // 15 0.741 -0.672
55 | assign wn_re[16] = 16'h5A82; assign wn_im[16] = 16'hA57E; // 16 0.707 -0.707
56 | assign wn_re[17] = 16'h55F6; assign wn_im[17] = 16'hA129; // 17 0.672 -0.741
57 | assign wn_re[18] = 16'h5134; assign wn_im[18] = 16'h9D0E; // 18 0.634 -0.773
58 | assign wn_re[19] = 16'h4C40; assign wn_im[19] = 16'h9930; // 19 0.596 -0.803
59 | assign wn_re[20] = 16'h471D; assign wn_im[20] = 16'h9592; // 20 0.556 -0.831
60 | assign wn_re[21] = 16'h41CE; assign wn_im[21] = 16'h9236; // 21 0.514 -0.858
61 | assign wn_re[22] = 16'h3C57; assign wn_im[22] = 16'h8F1D; // 22 0.471 -0.882
62 | assign wn_re[23] = 16'h36BA; assign wn_im[23] = 16'h8C4A; // 23 0.428 -0.904
63 | assign wn_re[24] = 16'h30FC; assign wn_im[24] = 16'h89BE; // 24 0.383 -0.924
64 | assign wn_re[25] = 16'h2B1F; assign wn_im[25] = 16'h877B; // 25 0.337 -0.942
65 | assign wn_re[26] = 16'h2528; assign wn_im[26] = 16'h8583; // 26 0.290 -0.957
66 | assign wn_re[27] = 16'h1F1A; assign wn_im[27] = 16'h83D6; // 27 0.243 -0.970
67 | assign wn_re[28] = 16'h18F9; assign wn_im[28] = 16'h8276; // 28 0.195 -0.981
68 | assign wn_re[29] = 16'h12C8; assign wn_im[29] = 16'h8163; // 29 0.147 -0.989
69 | assign wn_re[30] = 16'h0C8C; assign wn_im[30] = 16'h809E; // 30 0.098 -0.995
70 | assign wn_re[31] = 16'h0648; assign wn_im[31] = 16'h8027; // 31 0.049 -0.999
71 | assign wn_re[32] = 16'h0000; assign wn_im[32] = 16'h8000; // 32 0.000 -1.000
72 | assign wn_re[33] = 16'hF9B8; assign wn_im[33] = 16'h8027; // 33 -0.049 -0.999
73 | assign wn_re[34] = 16'hF374; assign wn_im[34] = 16'h809E; // 34 -0.098 -0.995
74 | assign wn_re[35] = 16'hxxxx; assign wn_im[35] = 16'hxxxx; // 35 -0.147 -0.989
75 | assign wn_re[36] = 16'hE707; assign wn_im[36] = 16'h8276; // 36 -0.195 -0.981
76 | assign wn_re[37] = 16'hxxxx; assign wn_im[37] = 16'hxxxx; // 37 -0.243 -0.970
77 | assign wn_re[38] = 16'hDAD8; assign wn_im[38] = 16'h8583; // 38 -0.290 -0.957
78 | assign wn_re[39] = 16'hD4E1; assign wn_im[39] = 16'h877B; // 39 -0.337 -0.942
79 | assign wn_re[40] = 16'hCF04; assign wn_im[40] = 16'h89BE; // 40 -0.383 -0.924
80 | assign wn_re[41] = 16'hxxxx; assign wn_im[41] = 16'hxxxx; // 41 -0.428 -0.904
81 | assign wn_re[42] = 16'hC3A9; assign wn_im[42] = 16'h8F1D; // 42 -0.471 -0.882
82 | assign wn_re[43] = 16'hxxxx; assign wn_im[43] = 16'hxxxx; // 43 -0.514 -0.858
83 | assign wn_re[44] = 16'hB8E3; assign wn_im[44] = 16'h9592; // 44 -0.556 -0.831
84 | assign wn_re[45] = 16'hB3C0; assign wn_im[45] = 16'h9930; // 45 -0.596 -0.803
85 | assign wn_re[46] = 16'hAECC; assign wn_im[46] = 16'h9D0E; // 46 -0.634 -0.773
86 | assign wn_re[47] = 16'hxxxx; assign wn_im[47] = 16'hxxxx; // 47 -0.672 -0.741
87 | assign wn_re[48] = 16'hA57E; assign wn_im[48] = 16'hA57E; // 48 -0.707 -0.707
88 | assign wn_re[49] = 16'hxxxx; assign wn_im[49] = 16'hxxxx; // 49 -0.741 -0.672
89 | assign wn_re[50] = 16'h9D0E; assign wn_im[50] = 16'hAECC; // 50 -0.773 -0.634
90 | assign wn_re[51] = 16'h9930; assign wn_im[51] = 16'hB3C0; // 51 -0.803 -0.596
91 | assign wn_re[52] = 16'h9592; assign wn_im[52] = 16'hB8E3; // 52 -0.831 -0.556
92 | assign wn_re[53] = 16'hxxxx; assign wn_im[53] = 16'hxxxx; // 53 -0.858 -0.514
93 | assign wn_re[54] = 16'h8F1D; assign wn_im[54] = 16'hC3A9; // 54 -0.882 -0.471
94 | assign wn_re[55] = 16'hxxxx; assign wn_im[55] = 16'hxxxx; // 55 -0.904 -0.428
95 | assign wn_re[56] = 16'h89BE; assign wn_im[56] = 16'hCF04; // 56 -0.924 -0.383
96 | assign wn_re[57] = 16'h877B; assign wn_im[57] = 16'hD4E1; // 57 -0.942 -0.337
97 | assign wn_re[58] = 16'h8583; assign wn_im[58] = 16'hDAD8; // 58 -0.957 -0.290
98 | assign wn_re[59] = 16'hxxxx; assign wn_im[59] = 16'hxxxx; // 59 -0.970 -0.243
99 | assign wn_re[60] = 16'h8276; assign wn_im[60] = 16'hE707; // 60 -0.981 -0.195
100 | assign wn_re[61] = 16'hxxxx; assign wn_im[61] = 16'hxxxx; // 61 -0.989 -0.147
101 | assign wn_re[62] = 16'h809E; assign wn_im[62] = 16'hF374; // 62 -0.995 -0.098
102 | assign wn_re[63] = 16'h8027; assign wn_im[63] = 16'hF9B8; // 63 -0.999 -0.049
103 | assign wn_re[64] = 16'hxxxx; assign wn_im[64] = 16'hxxxx; // 64 -1.000 -0.000
104 | assign wn_re[65] = 16'hxxxx; assign wn_im[65] = 16'hxxxx; // 65 -0.999 0.049
105 | assign wn_re[66] = 16'h809E; assign wn_im[66] = 16'h0C8C; // 66 -0.995 0.098
106 | assign wn_re[67] = 16'hxxxx; assign wn_im[67] = 16'hxxxx; // 67 -0.989 0.147
107 | assign wn_re[68] = 16'hxxxx; assign wn_im[68] = 16'hxxxx; // 68 -0.981 0.195
108 | assign wn_re[69] = 16'h83D6; assign wn_im[69] = 16'h1F1A; // 69 -0.970 0.243
109 | assign wn_re[70] = 16'hxxxx; assign wn_im[70] = 16'hxxxx; // 70 -0.957 0.290
110 | assign wn_re[71] = 16'hxxxx; assign wn_im[71] = 16'hxxxx; // 71 -0.942 0.337
111 | assign wn_re[72] = 16'h89BE; assign wn_im[72] = 16'h30FC; // 72 -0.924 0.383
112 | assign wn_re[73] = 16'hxxxx; assign wn_im[73] = 16'hxxxx; // 73 -0.904 0.428
113 | assign wn_re[74] = 16'hxxxx; assign wn_im[74] = 16'hxxxx; // 74 -0.882 0.471
114 | assign wn_re[75] = 16'h9236; assign wn_im[75] = 16'h41CE; // 75 -0.858 0.514
115 | assign wn_re[76] = 16'hxxxx; assign wn_im[76] = 16'hxxxx; // 76 -0.831 0.556
116 | assign wn_re[77] = 16'hxxxx; assign wn_im[77] = 16'hxxxx; // 77 -0.803 0.596
117 | assign wn_re[78] = 16'h9D0E; assign wn_im[78] = 16'h5134; // 78 -0.773 0.634
118 | assign wn_re[79] = 16'hxxxx; assign wn_im[79] = 16'hxxxx; // 79 -0.741 0.672
119 | assign wn_re[80] = 16'hxxxx; assign wn_im[80] = 16'hxxxx; // 80 -0.707 0.707
120 | assign wn_re[81] = 16'hAA0A; assign wn_im[81] = 16'h5ED7; // 81 -0.672 0.741
121 | assign wn_re[82] = 16'hxxxx; assign wn_im[82] = 16'hxxxx; // 82 -0.634 0.773
122 | assign wn_re[83] = 16'hxxxx; assign wn_im[83] = 16'hxxxx; // 83 -0.596 0.803
123 | assign wn_re[84] = 16'hB8E3; assign wn_im[84] = 16'h6A6E; // 84 -0.556 0.831
124 | assign wn_re[85] = 16'hxxxx; assign wn_im[85] = 16'hxxxx; // 85 -0.514 0.858
125 | assign wn_re[86] = 16'hxxxx; assign wn_im[86] = 16'hxxxx; // 86 -0.471 0.882
126 | assign wn_re[87] = 16'hC946; assign wn_im[87] = 16'h73B6; // 87 -0.428 0.904
127 | assign wn_re[88] = 16'hxxxx; assign wn_im[88] = 16'hxxxx; // 88 -0.383 0.924
128 | assign wn_re[89] = 16'hxxxx; assign wn_im[89] = 16'hxxxx; // 89 -0.337 0.942
129 | assign wn_re[90] = 16'hDAD8; assign wn_im[90] = 16'h7A7D; // 90 -0.290 0.957
130 | assign wn_re[91] = 16'hxxxx; assign wn_im[91] = 16'hxxxx; // 91 -0.243 0.970
131 | assign wn_re[92] = 16'hxxxx; assign wn_im[92] = 16'hxxxx; // 92 -0.195 0.981
132 | assign wn_re[93] = 16'hED38; assign wn_im[93] = 16'h7E9D; // 93 -0.147 0.989
133 | assign wn_re[94] = 16'hxxxx; assign wn_im[94] = 16'hxxxx; // 94 -0.098 0.995
134 | assign wn_re[95] = 16'hxxxx; assign wn_im[95] = 16'hxxxx; // 95 -0.049 0.999
135 | assign wn_re[96] = 16'hxxxx; assign wn_im[96] = 16'hxxxx; // 96 -0.000 1.000
136 | assign wn_re[97] = 16'hxxxx; assign wn_im[97] = 16'hxxxx; // 97 0.049 0.999
137 | assign wn_re[98] = 16'hxxxx; assign wn_im[98] = 16'hxxxx; // 98 0.098 0.995
138 | assign wn_re[99] = 16'hxxxx; assign wn_im[99] = 16'hxxxx; // 99 0.147 0.989
139 | assign wn_re[100] = 16'hxxxx; assign wn_im[100] = 16'hxxxx; // 100 0.195 0.981
140 | assign wn_re[101] = 16'hxxxx; assign wn_im[101] = 16'hxxxx; // 101 0.243 0.970
141 | assign wn_re[102] = 16'hxxxx; assign wn_im[102] = 16'hxxxx; // 102 0.290 0.957
142 | assign wn_re[103] = 16'hxxxx; assign wn_im[103] = 16'hxxxx; // 103 0.337 0.942
143 | assign wn_re[104] = 16'hxxxx; assign wn_im[104] = 16'hxxxx; // 104 0.383 0.924
144 | assign wn_re[105] = 16'hxxxx; assign wn_im[105] = 16'hxxxx; // 105 0.428 0.904
145 | assign wn_re[106] = 16'hxxxx; assign wn_im[106] = 16'hxxxx; // 106 0.471 0.882
146 | assign wn_re[107] = 16'hxxxx; assign wn_im[107] = 16'hxxxx; // 107 0.514 0.858
147 | assign wn_re[108] = 16'hxxxx; assign wn_im[108] = 16'hxxxx; // 108 0.556 0.831
148 | assign wn_re[109] = 16'hxxxx; assign wn_im[109] = 16'hxxxx; // 109 0.596 0.803
149 | assign wn_re[110] = 16'hxxxx; assign wn_im[110] = 16'hxxxx; // 110 0.634 0.773
150 | assign wn_re[111] = 16'hxxxx; assign wn_im[111] = 16'hxxxx; // 111 0.672 0.741
151 | assign wn_re[112] = 16'hxxxx; assign wn_im[112] = 16'hxxxx; // 112 0.707 0.707
152 | assign wn_re[113] = 16'hxxxx; assign wn_im[113] = 16'hxxxx; // 113 0.741 0.672
153 | assign wn_re[114] = 16'hxxxx; assign wn_im[114] = 16'hxxxx; // 114 0.773 0.634
154 | assign wn_re[115] = 16'hxxxx; assign wn_im[115] = 16'hxxxx; // 115 0.803 0.596
155 | assign wn_re[116] = 16'hxxxx; assign wn_im[116] = 16'hxxxx; // 116 0.831 0.556
156 | assign wn_re[117] = 16'hxxxx; assign wn_im[117] = 16'hxxxx; // 117 0.858 0.514
157 | assign wn_re[118] = 16'hxxxx; assign wn_im[118] = 16'hxxxx; // 118 0.882 0.471
158 | assign wn_re[119] = 16'hxxxx; assign wn_im[119] = 16'hxxxx; // 119 0.904 0.428
159 | assign wn_re[120] = 16'hxxxx; assign wn_im[120] = 16'hxxxx; // 120 0.924 0.383
160 | assign wn_re[121] = 16'hxxxx; assign wn_im[121] = 16'hxxxx; // 121 0.942 0.337
161 | assign wn_re[122] = 16'hxxxx; assign wn_im[122] = 16'hxxxx; // 122 0.957 0.290
162 | assign wn_re[123] = 16'hxxxx; assign wn_im[123] = 16'hxxxx; // 123 0.970 0.243
163 | assign wn_re[124] = 16'hxxxx; assign wn_im[124] = 16'hxxxx; // 124 0.981 0.195
164 | assign wn_re[125] = 16'hxxxx; assign wn_im[125] = 16'hxxxx; // 125 0.989 0.147
165 | assign wn_re[126] = 16'hxxxx; assign wn_im[126] = 16'hxxxx; // 126 0.995 0.098
166 | assign wn_re[127] = 16'hxxxx; assign wn_im[127] = 16'hxxxx; // 127 0.999 0.049
167 |
168 | endmodule
169 |
--------------------------------------------------------------------------------
/sim/fft_64/modelsim.mpf:
--------------------------------------------------------------------------------
1 | ; Copyright 1991-2009 Mentor Graphics Corporation
2 | ;
3 | ; All Rights Reserved.
4 | ;
5 | ; THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION WHICH IS THE PROPERTY OF
6 | ; MENTOR GRAPHICS CORPORATION OR ITS LICENSORS AND IS SUBJECT TO LICENSE TERMS.
7 | ;
8 |
9 | [Library]
10 | std = $MODEL_TECH/../std
11 | ieee = $MODEL_TECH/../ieee
12 | verilog = $MODEL_TECH/../verilog
13 | vital2000 = $MODEL_TECH/../vital2000
14 | std_developerskit = $MODEL_TECH/../std_developerskit
15 | synopsys = $MODEL_TECH/../synopsys
16 | modelsim_lib = $MODEL_TECH/../modelsim_lib
17 | sv_std = $MODEL_TECH/../sv_std
18 |
19 | [vcom]
20 | ; VHDL93 variable selects language version as the default.
21 | ; Default is VHDL-2002.
22 | ; Value of 0 or 1987 for VHDL-1987.
23 | ; Value of 1 or 1993 for VHDL-1993.
24 | ; Default or value of 2 or 2002 for VHDL-2002.
25 | ; Default or value of 3 or 2008 for VHDL-2008.
26 | VHDL93 = 2002
27 |
28 | ; Show source line containing error. Default is off.
29 | ; Show_source = 1
30 |
31 | ; Turn off unbound-component warnings. Default is on.
32 | ; Show_Warning1 = 0
33 |
34 | ; Turn off process-without-a-wait-statement warnings. Default is on.
35 | ; Show_Warning2 = 0
36 |
37 | ; Turn off null-range warnings. Default is on.
38 | ; Show_Warning3 = 0
39 |
40 | ; Turn off no-space-in-time-literal warnings. Default is on.
41 | ; Show_Warning4 = 0
42 |
43 | ; Turn off multiple-drivers-on-unresolved-signal warnings. Default is on.
44 | ; Show_Warning5 = 0
45 |
46 | ; Turn off optimization for IEEE std_logic_1164 package. Default is on.
47 | ; Optimize_1164 = 0
48 |
49 | ; Turn on resolving of ambiguous function overloading in favor of the
50 | ; "explicit" function declaration (not the one automatically created by
51 | ; the compiler for each type declaration). Default is off.
52 | ; The .ini file has Explicit enabled so that std_logic_signed/unsigned
53 | ; will match the behavior of synthesis tools.
54 | Explicit = 1
55 |
56 | ; Turn off acceleration of the VITAL packages. Default is to accelerate.
57 | ; NoVital = 1
58 |
59 | ; Turn off VITAL compliance checking. Default is checking on.
60 | ; NoVitalCheck = 1
61 |
62 | ; Ignore VITAL compliance checking errors. Default is to not ignore.
63 | ; IgnoreVitalErrors = 1
64 |
65 | ; Turn off VITAL compliance checking warnings. Default is to show warnings.
66 | ; Show_VitalChecksWarnings = 0
67 |
68 | ; Keep silent about case statement static warnings.
69 | ; Default is to give a warning.
70 | ; NoCaseStaticError = 1
71 |
72 | ; Keep silent about warnings caused by aggregates that are not locally static.
73 | ; Default is to give a warning.
74 | ; NoOthersStaticError = 1
75 |
76 | ; Turn off inclusion of debugging info within design units.
77 | ; Default is to include debugging info.
78 | ; NoDebug = 1
79 |
80 | ; Turn off "Loading..." messages. Default is messages on.
81 | ; Quiet = 1
82 |
83 | ; Turn on some limited synthesis rule compliance checking. Checks only:
84 | ; -- signals used (read) by a process must be in the sensitivity list
85 | ; CheckSynthesis = 1
86 |
87 | ; Activate optimizations on expressions that do not involve signals,
88 | ; waits, or function/procedure/task invocations. Default is off.
89 | ; ScalarOpts = 1
90 |
91 | ; Require the user to specify a configuration for all bindings,
92 | ; and do not generate a compile time default binding for the
93 | ; component. This will result in an elaboration error of
94 | ; 'component not bound' if the user fails to do so. Avoids the rare
95 | ; issue of a false dependency upon the unused default binding.
96 | ; RequireConfigForAllDefaultBinding = 1
97 |
98 | ; Inhibit range checking on subscripts of arrays. Range checking on
99 | ; scalars defined with subtypes is inhibited by default.
100 | ; NoIndexCheck = 1
101 |
102 | ; Inhibit range checks on all (implicit and explicit) assignments to
103 | ; scalar objects defined with subtypes.
104 | ; NoRangeCheck = 1
105 |
106 | [vlog]
107 |
108 | ; Turn off inclusion of debugging info within design units.
109 | ; Default is to include debugging info.
110 | ; NoDebug = 1
111 |
112 | ; Turn off "loading..." messages. Default is messages on.
113 | ; Quiet = 1
114 |
115 | ; Turn on Verilog hazard checking (order-dependent accessing of global vars).
116 | ; Default is off.
117 | ; Hazard = 1
118 |
119 | ; Turn on converting regular Verilog identifiers to uppercase. Allows case
120 | ; insensitivity for module names. Default is no conversion.
121 | ; UpCase = 1
122 |
123 | ; Turn on incremental compilation of modules. Default is off.
124 | ; Incremental = 1
125 |
126 | ; Turns on lint-style checking.
127 | ; Show_Lint = 1
128 |
129 | [vsim]
130 | ; Simulator resolution
131 | ; Set to fs, ps, ns, us, ms, or sec with optional prefix of 1, 10, or 100.
132 | Resolution = ps
133 |
134 | ; User time unit for run commands
135 | ; Set to default, fs, ps, ns, us, ms, or sec. The default is to use the
136 | ; unit specified for Resolution. For example, if Resolution is 100ps,
137 | ; then UserTimeUnit defaults to ps.
138 | ; Should generally be set to default.
139 | UserTimeUnit = default
140 |
141 | ; Default run length
142 | RunLength = 100 ps
143 |
144 | ; Maximum iterations that can be run without advancing simulation time
145 | IterationLimit = 5000
146 |
147 | ; Directive to license manager:
148 | ; vhdl Immediately reserve a VHDL license
149 | ; vlog Immediately reserve a Verilog license
150 | ; plus Immediately reserve a VHDL and Verilog license
151 | ; nomgc Do not look for Mentor Graphics Licenses
152 | ; nomti Do not look for Model Technology Licenses
153 | ; noqueue Do not wait in the license queue when a license isn't available
154 | ; viewsim Try for viewer license but accept simulator license(s) instead
155 | ; of queuing for viewer license
156 | ; License = plus
157 |
158 | ; Stop the simulator after a VHDL/Verilog assertion message
159 | ; 0 = Note 1 = Warning 2 = Error 3 = Failure 4 = Fatal
160 | BreakOnAssertion = 3
161 |
162 | ; Assertion Message Format
163 | ; %S - Severity Level
164 | ; %R - Report Message
165 | ; %T - Time of assertion
166 | ; %D - Delta
167 | ; %I - Instance or Region pathname (if available)
168 | ; %% - print '%' character
169 | ; AssertionFormat = "** %S: %R\n Time: %T Iteration: %D%I\n"
170 |
171 | ; Assertion File - alternate file for storing VHDL/Verilog assertion messages
172 | ; AssertFile = assert.log
173 |
174 | ; Default radix for all windows and commands...
175 | ; Set to symbolic, ascii, binary, octal, decimal, hex, unsigned
176 | ; DefaultRadix = symbolic
177 | DefaultRadix = hexadecimal
178 |
179 | ; VSIM Startup command
180 | ; Startup = do startup.do
181 |
182 | ; File for saving command transcript
183 | TranscriptFile = transcript
184 |
185 | ; File for saving command history
186 | ; CommandHistory = cmdhist.log
187 |
188 | ; Specify whether paths in simulator commands should be described
189 | ; in VHDL or Verilog format.
190 | ; For VHDL, PathSeparator = /
191 | ; For Verilog, PathSeparator = .
192 | ; Must not be the same character as DatasetSeparator.
193 | PathSeparator = /
194 |
195 | ; Specify the dataset separator for fully rooted contexts.
196 | ; The default is ':'. For example, sim:/top
197 | ; Must not be the same character as PathSeparator.
198 | DatasetSeparator = :
199 |
200 | ; Disable VHDL assertion messages
201 | ; IgnoreNote = 1
202 | ; IgnoreWarning = 1
203 | ; IgnoreError = 1
204 | ; IgnoreFailure = 1
205 |
206 | ; Default force kind. May be freeze, drive, deposit, or default
207 | ; or in other terms, fixed, wired, or charged.
208 | ; A value of "default" will use the signal kind to determine the
209 | ; force kind, drive for resolved signals, freeze for unresolved signals
210 | ; DefaultForceKind = freeze
211 |
212 | ; If zero, open files when elaborated; otherwise, open files on
213 | ; first read or write. Default is 0.
214 | ; DelayFileOpen = 1
215 |
216 | ; Control VHDL files opened for write.
217 | ; 0 = Buffered, 1 = Unbuffered
218 | UnbufferedOutput = 0
219 |
220 | ; Control the number of VHDL files open concurrently.
221 | ; This number should always be less than the current ulimit
222 | ; setting for max file descriptors.
223 | ; 0 = unlimited
224 | ConcurrentFileLimit = 40
225 |
226 | ; Control the number of hierarchical regions displayed as
227 | ; part of a signal name shown in the Wave window.
228 | ; A value of zero tells VSIM to display the full name.
229 | ; The default is 0.
230 | ; WaveSignalNameWidth = 0
231 |
232 | ; Turn off warnings from the std_logic_arith, std_logic_unsigned
233 | ; and std_logic_signed packages.
234 | StdArithNoWarnings = 1
235 |
236 | ; Turn off warnings from the IEEE numeric_std and numeric_bit packages.
237 | NumericStdNoWarnings = 1
238 |
239 | ; Control the format of the (VHDL) FOR generate statement label
240 | ; for each iteration. Do not quote it.
241 | ; The format string here must contain the conversion codes %s and %d,
242 | ; in that order, and no other conversion codes. The %s represents
243 | ; the generate_label; the %d represents the generate parameter value
244 | ; at a particular generate iteration (this is the position number if
245 | ; the generate parameter is of an enumeration type). Embedded whitespace
246 | ; is allowed (but discouraged); leading and trailing whitespace is ignored.
247 | ; Application of the format must result in a unique scope name over all
248 | ; such names in the design so that name lookup can function properly.
249 | ; GenerateFormat = %s__%d
250 |
251 | ; Specify whether checkpoint files should be compressed.
252 | ; The default is 1 (compressed).
253 | ; CheckpointCompressMode = 0
254 |
255 | ; List of dynamically loaded objects for Verilog PLI applications
256 | ; Veriuser = veriuser.sl
257 |
258 | ; Specify default options for the restart command. Options can be one
259 | ; or more of: -force -nobreakpoint -nolist -nolog -nowave
260 | ; DefaultRestartOptions = -force
261 |
262 | ; HP-UX 10.20 ONLY - Enable memory locking to speed up large designs
263 | ; (> 500 megabyte memory footprint). Default is disabled.
264 | ; Specify number of megabytes to lock.
265 | ; LockedMemory = 1000
266 |
267 | ; Turn on (1) or off (0) WLF file compression.
268 | ; The default is 1 (compress WLF file).
269 | ; WLFCompress = 0
270 |
271 | ; Specify whether to save all design hierarchy (1) in the WLF file
272 | ; or only regions containing logged signals (0).
273 | ; The default is 0 (save only regions with logged signals).
274 | ; WLFSaveAllRegions = 1
275 |
276 | ; WLF file time limit. Limit WLF file by time, as closely as possible,
277 | ; to the specified amount of simulation time. When the limit is exceeded
278 | ; the earliest times get truncated from the file.
279 | ; If both time and size limits are specified the most restrictive is used.
280 | ; UserTimeUnits are used if time units are not specified.
281 | ; The default is 0 (no limit). Example: WLFTimeLimit = {100 ms}
282 | ; WLFTimeLimit = 0
283 |
284 | ; WLF file size limit. Limit WLF file size, as closely as possible,
285 | ; to the specified number of megabytes. If both time and size limits
286 | ; are specified then the most restrictive is used.
287 | ; The default is 0 (no limit).
288 | ; WLFSizeLimit = 1000
289 |
290 | ; Specify whether or not a WLF file should be deleted when the
291 | ; simulation ends. A value of 1 will cause the WLF file to be deleted.
292 | ; The default is 0 (do not delete WLF file when simulation ends).
293 | ; WLFDeleteOnQuit = 1
294 |
295 | ; Automatic SDF compilation
296 | ; Disables automatic compilation of SDF files in flows that support it.
297 | ; Default is on, uncomment to turn off.
298 | ; NoAutoSDFCompile = 1
299 |
300 | [lmc]
301 |
302 | [msg_system]
303 | ; Change a message severity or suppress a message.
304 | ; The format is: = [,...]
305 | ; Examples:
306 | ; note = 3009
307 | ; warning = 3033
308 | ; error = 3010,3016
309 | ; fatal = 3016,3033
310 | ; suppress = 3009,3016,3043
311 | ; The command verror can be used to get the complete
312 | ; description of a message.
313 |
314 | ; Control transcripting of elaboration/runtime messages.
315 | ; The default is to have messages appear in the transcript and
316 | ; recorded in the wlf file (messages that are recorded in the
317 | ; wlf file can be viewed in the MsgViewer). The other settings
318 | ; are to send messages only to the transcript or only to the
319 | ; wlf file. The valid values are
320 | ; both {default}
321 | ; tran {transcript only}
322 | ; wlf {wlf file only}
323 | ; msgmode = both
324 | [Project]
325 | ; Warning -- Do not edit the project properties directly.
326 | ; Property names are dynamic in nature and property
327 | ; values have special syntax. Changing property data directly
328 | ; can result in a corrupt MPF file. All project properties
329 | ; can be modified through project window dialogs.
330 | Project_Version = 6
331 | Project_DefaultLib = work
332 | Project_SortMethod = unused
333 | Project_Files_Count = 0
334 | Project_Sim_Count = 0
335 | Project_Folder_Count = 0
336 | Echo_Compile_Output = 0
337 | Save_Compile_Report = 0
338 | Project_Opt_Count = 0
339 | ForceSoftPaths = 0
340 | ProjectStatusDelay = 5000
341 | VERILOG_DoubleClick = Edit
342 | VERILOG_CustomDoubleClick =
343 | SYSTEMVERILOG_DoubleClick = Edit
344 | SYSTEMVERILOG_CustomDoubleClick =
345 | VHDL_DoubleClick = Edit
346 | VHDL_CustomDoubleClick =
347 | PSL_DoubleClick = Edit
348 | PSL_CustomDoubleClick =
349 | TEXT_DoubleClick = Edit
350 | TEXT_CustomDoubleClick =
351 | SYSTEMC_DoubleClick = Edit
352 | SYSTEMC_CustomDoubleClick =
353 | TCL_DoubleClick = Edit
354 | TCL_CustomDoubleClick =
355 | MACRO_DoubleClick = Edit
356 | MACRO_CustomDoubleClick =
357 | VCD_DoubleClick = Edit
358 | VCD_CustomDoubleClick =
359 | SDF_DoubleClick = Edit
360 | SDF_CustomDoubleClick =
361 | XML_DoubleClick = Edit
362 | XML_CustomDoubleClick =
363 | LOGFILE_DoubleClick = Edit
364 | LOGFILE_CustomDoubleClick =
365 | UCDB_DoubleClick = Edit
366 | UCDB_CustomDoubleClick =
367 | UPF_DoubleClick = Edit
368 | UPF_CustomDoubleClick =
369 | PCF_DoubleClick = Edit
370 | PCF_CustomDoubleClick =
371 | PROJECT_DoubleClick = Edit
372 | PROJECT_CustomDoubleClick =
373 | VRM_DoubleClick = Edit
374 | VRM_CustomDoubleClick =
375 | DEBUGDATABASE_DoubleClick = Edit
376 | DEBUGDATABASE_CustomDoubleClick =
377 | DEBUGARCHIVE_DoubleClick = Edit
378 | DEBUGARCHIVE_CustomDoubleClick =
379 | Project_Major_Version = 10
380 | Project_Minor_Version = 1
381 |
--------------------------------------------------------------------------------
/sim/fft_128_tc/modelsim.mpf:
--------------------------------------------------------------------------------
1 | ; Copyright 1991-2009 Mentor Graphics Corporation
2 | ;
3 | ; All Rights Reserved.
4 | ;
5 | ; THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION WHICH IS THE PROPERTY OF
6 | ; MENTOR GRAPHICS CORPORATION OR ITS LICENSORS AND IS SUBJECT TO LICENSE TERMS.
7 | ;
8 |
9 | [Library]
10 | std = $MODEL_TECH/../std
11 | ieee = $MODEL_TECH/../ieee
12 | verilog = $MODEL_TECH/../verilog
13 | vital2000 = $MODEL_TECH/../vital2000
14 | std_developerskit = $MODEL_TECH/../std_developerskit
15 | synopsys = $MODEL_TECH/../synopsys
16 | modelsim_lib = $MODEL_TECH/../modelsim_lib
17 | sv_std = $MODEL_TECH/../sv_std
18 |
19 | [vcom]
20 | ; VHDL93 variable selects language version as the default.
21 | ; Default is VHDL-2002.
22 | ; Value of 0 or 1987 for VHDL-1987.
23 | ; Value of 1 or 1993 for VHDL-1993.
24 | ; Default or value of 2 or 2002 for VHDL-2002.
25 | ; Default or value of 3 or 2008 for VHDL-2008.
26 | VHDL93 = 2002
27 |
28 | ; Show source line containing error. Default is off.
29 | ; Show_source = 1
30 |
31 | ; Turn off unbound-component warnings. Default is on.
32 | ; Show_Warning1 = 0
33 |
34 | ; Turn off process-without-a-wait-statement warnings. Default is on.
35 | ; Show_Warning2 = 0
36 |
37 | ; Turn off null-range warnings. Default is on.
38 | ; Show_Warning3 = 0
39 |
40 | ; Turn off no-space-in-time-literal warnings. Default is on.
41 | ; Show_Warning4 = 0
42 |
43 | ; Turn off multiple-drivers-on-unresolved-signal warnings. Default is on.
44 | ; Show_Warning5 = 0
45 |
46 | ; Turn off optimization for IEEE std_logic_1164 package. Default is on.
47 | ; Optimize_1164 = 0
48 |
49 | ; Turn on resolving of ambiguous function overloading in favor of the
50 | ; "explicit" function declaration (not the one automatically created by
51 | ; the compiler for each type declaration). Default is off.
52 | ; The .ini file has Explicit enabled so that std_logic_signed/unsigned
53 | ; will match the behavior of synthesis tools.
54 | Explicit = 1
55 |
56 | ; Turn off acceleration of the VITAL packages. Default is to accelerate.
57 | ; NoVital = 1
58 |
59 | ; Turn off VITAL compliance checking. Default is checking on.
60 | ; NoVitalCheck = 1
61 |
62 | ; Ignore VITAL compliance checking errors. Default is to not ignore.
63 | ; IgnoreVitalErrors = 1
64 |
65 | ; Turn off VITAL compliance checking warnings. Default is to show warnings.
66 | ; Show_VitalChecksWarnings = 0
67 |
68 | ; Keep silent about case statement static warnings.
69 | ; Default is to give a warning.
70 | ; NoCaseStaticError = 1
71 |
72 | ; Keep silent about warnings caused by aggregates that are not locally static.
73 | ; Default is to give a warning.
74 | ; NoOthersStaticError = 1
75 |
76 | ; Turn off inclusion of debugging info within design units.
77 | ; Default is to include debugging info.
78 | ; NoDebug = 1
79 |
80 | ; Turn off "Loading..." messages. Default is messages on.
81 | ; Quiet = 1
82 |
83 | ; Turn on some limited synthesis rule compliance checking. Checks only:
84 | ; -- signals used (read) by a process must be in the sensitivity list
85 | ; CheckSynthesis = 1
86 |
87 | ; Activate optimizations on expressions that do not involve signals,
88 | ; waits, or function/procedure/task invocations. Default is off.
89 | ; ScalarOpts = 1
90 |
91 | ; Require the user to specify a configuration for all bindings,
92 | ; and do not generate a compile time default binding for the
93 | ; component. This will result in an elaboration error of
94 | ; 'component not bound' if the user fails to do so. Avoids the rare
95 | ; issue of a false dependency upon the unused default binding.
96 | ; RequireConfigForAllDefaultBinding = 1
97 |
98 | ; Inhibit range checking on subscripts of arrays. Range checking on
99 | ; scalars defined with subtypes is inhibited by default.
100 | ; NoIndexCheck = 1
101 |
102 | ; Inhibit range checks on all (implicit and explicit) assignments to
103 | ; scalar objects defined with subtypes.
104 | ; NoRangeCheck = 1
105 |
106 | [vlog]
107 |
108 | ; Turn off inclusion of debugging info within design units.
109 | ; Default is to include debugging info.
110 | ; NoDebug = 1
111 |
112 | ; Turn off "loading..." messages. Default is messages on.
113 | ; Quiet = 1
114 |
115 | ; Turn on Verilog hazard checking (order-dependent accessing of global vars).
116 | ; Default is off.
117 | ; Hazard = 1
118 |
119 | ; Turn on converting regular Verilog identifiers to uppercase. Allows case
120 | ; insensitivity for module names. Default is no conversion.
121 | ; UpCase = 1
122 |
123 | ; Turn on incremental compilation of modules. Default is off.
124 | ; Incremental = 1
125 |
126 | ; Turns on lint-style checking.
127 | ; Show_Lint = 1
128 |
129 | [vsim]
130 | ; Simulator resolution
131 | ; Set to fs, ps, ns, us, ms, or sec with optional prefix of 1, 10, or 100.
132 | Resolution = ps
133 |
134 | ; User time unit for run commands
135 | ; Set to default, fs, ps, ns, us, ms, or sec. The default is to use the
136 | ; unit specified for Resolution. For example, if Resolution is 100ps,
137 | ; then UserTimeUnit defaults to ps.
138 | ; Should generally be set to default.
139 | UserTimeUnit = default
140 |
141 | ; Default run length
142 | RunLength = 100 ps
143 |
144 | ; Maximum iterations that can be run without advancing simulation time
145 | IterationLimit = 5000
146 |
147 | ; Directive to license manager:
148 | ; vhdl Immediately reserve a VHDL license
149 | ; vlog Immediately reserve a Verilog license
150 | ; plus Immediately reserve a VHDL and Verilog license
151 | ; nomgc Do not look for Mentor Graphics Licenses
152 | ; nomti Do not look for Model Technology Licenses
153 | ; noqueue Do not wait in the license queue when a license isn't available
154 | ; viewsim Try for viewer license but accept simulator license(s) instead
155 | ; of queuing for viewer license
156 | ; License = plus
157 |
158 | ; Stop the simulator after a VHDL/Verilog assertion message
159 | ; 0 = Note 1 = Warning 2 = Error 3 = Failure 4 = Fatal
160 | BreakOnAssertion = 3
161 |
162 | ; Assertion Message Format
163 | ; %S - Severity Level
164 | ; %R - Report Message
165 | ; %T - Time of assertion
166 | ; %D - Delta
167 | ; %I - Instance or Region pathname (if available)
168 | ; %% - print '%' character
169 | ; AssertionFormat = "** %S: %R\n Time: %T Iteration: %D%I\n"
170 |
171 | ; Assertion File - alternate file for storing VHDL/Verilog assertion messages
172 | ; AssertFile = assert.log
173 |
174 | ; Default radix for all windows and commands...
175 | ; Set to symbolic, ascii, binary, octal, decimal, hex, unsigned
176 | ; DefaultRadix = symbolic
177 | DefaultRadix = hexadecimal
178 |
179 | ; VSIM Startup command
180 | ; Startup = do startup.do
181 |
182 | ; File for saving command transcript
183 | TranscriptFile = transcript
184 |
185 | ; File for saving command history
186 | ; CommandHistory = cmdhist.log
187 |
188 | ; Specify whether paths in simulator commands should be described
189 | ; in VHDL or Verilog format.
190 | ; For VHDL, PathSeparator = /
191 | ; For Verilog, PathSeparator = .
192 | ; Must not be the same character as DatasetSeparator.
193 | PathSeparator = /
194 |
195 | ; Specify the dataset separator for fully rooted contexts.
196 | ; The default is ':'. For example, sim:/top
197 | ; Must not be the same character as PathSeparator.
198 | DatasetSeparator = :
199 |
200 | ; Disable VHDL assertion messages
201 | ; IgnoreNote = 1
202 | ; IgnoreWarning = 1
203 | ; IgnoreError = 1
204 | ; IgnoreFailure = 1
205 |
206 | ; Default force kind. May be freeze, drive, deposit, or default
207 | ; or in other terms, fixed, wired, or charged.
208 | ; A value of "default" will use the signal kind to determine the
209 | ; force kind, drive for resolved signals, freeze for unresolved signals
210 | ; DefaultForceKind = freeze
211 |
212 | ; If zero, open files when elaborated; otherwise, open files on
213 | ; first read or write. Default is 0.
214 | ; DelayFileOpen = 1
215 |
216 | ; Control VHDL files opened for write.
217 | ; 0 = Buffered, 1 = Unbuffered
218 | UnbufferedOutput = 0
219 |
220 | ; Control the number of VHDL files open concurrently.
221 | ; This number should always be less than the current ulimit
222 | ; setting for max file descriptors.
223 | ; 0 = unlimited
224 | ConcurrentFileLimit = 40
225 |
226 | ; Control the number of hierarchical regions displayed as
227 | ; part of a signal name shown in the Wave window.
228 | ; A value of zero tells VSIM to display the full name.
229 | ; The default is 0.
230 | ; WaveSignalNameWidth = 0
231 |
232 | ; Turn off warnings from the std_logic_arith, std_logic_unsigned
233 | ; and std_logic_signed packages.
234 | StdArithNoWarnings = 1
235 |
236 | ; Turn off warnings from the IEEE numeric_std and numeric_bit packages.
237 | NumericStdNoWarnings = 1
238 |
239 | ; Control the format of the (VHDL) FOR generate statement label
240 | ; for each iteration. Do not quote it.
241 | ; The format string here must contain the conversion codes %s and %d,
242 | ; in that order, and no other conversion codes. The %s represents
243 | ; the generate_label; the %d represents the generate parameter value
244 | ; at a particular generate iteration (this is the position number if
245 | ; the generate parameter is of an enumeration type). Embedded whitespace
246 | ; is allowed (but discouraged); leading and trailing whitespace is ignored.
247 | ; Application of the format must result in a unique scope name over all
248 | ; such names in the design so that name lookup can function properly.
249 | ; GenerateFormat = %s__%d
250 |
251 | ; Specify whether checkpoint files should be compressed.
252 | ; The default is 1 (compressed).
253 | ; CheckpointCompressMode = 0
254 |
255 | ; List of dynamically loaded objects for Verilog PLI applications
256 | ; Veriuser = veriuser.sl
257 |
258 | ; Specify default options for the restart command. Options can be one
259 | ; or more of: -force -nobreakpoint -nolist -nolog -nowave
260 | ; DefaultRestartOptions = -force
261 |
262 | ; HP-UX 10.20 ONLY - Enable memory locking to speed up large designs
263 | ; (> 500 megabyte memory footprint). Default is disabled.
264 | ; Specify number of megabytes to lock.
265 | ; LockedMemory = 1000
266 |
267 | ; Turn on (1) or off (0) WLF file compression.
268 | ; The default is 1 (compress WLF file).
269 | ; WLFCompress = 0
270 |
271 | ; Specify whether to save all design hierarchy (1) in the WLF file
272 | ; or only regions containing logged signals (0).
273 | ; The default is 0 (save only regions with logged signals).
274 | ; WLFSaveAllRegions = 1
275 |
276 | ; WLF file time limit. Limit WLF file by time, as closely as possible,
277 | ; to the specified amount of simulation time. When the limit is exceeded
278 | ; the earliest times get truncated from the file.
279 | ; If both time and size limits are specified the most restrictive is used.
280 | ; UserTimeUnits are used if time units are not specified.
281 | ; The default is 0 (no limit). Example: WLFTimeLimit = {100 ms}
282 | ; WLFTimeLimit = 0
283 |
284 | ; WLF file size limit. Limit WLF file size, as closely as possible,
285 | ; to the specified number of megabytes. If both time and size limits
286 | ; are specified then the most restrictive is used.
287 | ; The default is 0 (no limit).
288 | ; WLFSizeLimit = 1000
289 |
290 | ; Specify whether or not a WLF file should be deleted when the
291 | ; simulation ends. A value of 1 will cause the WLF file to be deleted.
292 | ; The default is 0 (do not delete WLF file when simulation ends).
293 | ; WLFDeleteOnQuit = 1
294 |
295 | ; Automatic SDF compilation
296 | ; Disables automatic compilation of SDF files in flows that support it.
297 | ; Default is on, uncomment to turn off.
298 | ; NoAutoSDFCompile = 1
299 |
300 | [lmc]
301 |
302 | [msg_system]
303 | ; Change a message severity or suppress a message.
304 | ; The format is: = [,...]
305 | ; Examples:
306 | ; note = 3009
307 | ; warning = 3033
308 | ; error = 3010,3016
309 | ; fatal = 3016,3033
310 | ; suppress = 3009,3016,3043
311 | ; The command verror can be used to get the complete
312 | ; description of a message.
313 |
314 | ; Control transcripting of elaboration/runtime messages.
315 | ; The default is to have messages appear in the transcript and
316 | ; recorded in the wlf file (messages that are recorded in the
317 | ; wlf file can be viewed in the MsgViewer). The other settings
318 | ; are to send messages only to the transcript or only to the
319 | ; wlf file. The valid values are
320 | ; both {default}
321 | ; tran {transcript only}
322 | ; wlf {wlf file only}
323 | ; msgmode = both
324 | [Project]
325 | ; Warning -- Do not edit the project properties directly.
326 | ; Property names are dynamic in nature and property
327 | ; values have special syntax. Changing property data directly
328 | ; can result in a corrupt MPF file. All project properties
329 | ; can be modified through project window dialogs.
330 | Project_Version = 6
331 | Project_DefaultLib = work
332 | Project_SortMethod = unused
333 | Project_Files_Count = 0
334 | Project_Sim_Count = 0
335 | Project_Folder_Count = 0
336 | Echo_Compile_Output = 0
337 | Save_Compile_Report = 0
338 | Project_Opt_Count = 0
339 | ForceSoftPaths = 0
340 | ProjectStatusDelay = 5000
341 | VERILOG_DoubleClick = Edit
342 | VERILOG_CustomDoubleClick =
343 | SYSTEMVERILOG_DoubleClick = Edit
344 | SYSTEMVERILOG_CustomDoubleClick =
345 | VHDL_DoubleClick = Edit
346 | VHDL_CustomDoubleClick =
347 | PSL_DoubleClick = Edit
348 | PSL_CustomDoubleClick =
349 | TEXT_DoubleClick = Edit
350 | TEXT_CustomDoubleClick =
351 | SYSTEMC_DoubleClick = Edit
352 | SYSTEMC_CustomDoubleClick =
353 | TCL_DoubleClick = Edit
354 | TCL_CustomDoubleClick =
355 | MACRO_DoubleClick = Edit
356 | MACRO_CustomDoubleClick =
357 | VCD_DoubleClick = Edit
358 | VCD_CustomDoubleClick =
359 | SDF_DoubleClick = Edit
360 | SDF_CustomDoubleClick =
361 | XML_DoubleClick = Edit
362 | XML_CustomDoubleClick =
363 | LOGFILE_DoubleClick = Edit
364 | LOGFILE_CustomDoubleClick =
365 | UCDB_DoubleClick = Edit
366 | UCDB_CustomDoubleClick =
367 | UPF_DoubleClick = Edit
368 | UPF_CustomDoubleClick =
369 | PCF_DoubleClick = Edit
370 | PCF_CustomDoubleClick =
371 | PROJECT_DoubleClick = Edit
372 | PROJECT_CustomDoubleClick =
373 | VRM_DoubleClick = Edit
374 | VRM_CustomDoubleClick =
375 | DEBUGDATABASE_DoubleClick = Edit
376 | DEBUGDATABASE_CustomDoubleClick =
377 | DEBUGARCHIVE_DoubleClick = Edit
378 | DEBUGARCHIVE_CustomDoubleClick =
379 | Project_Major_Version = 10
380 | Project_Minor_Version = 1
381 |
--------------------------------------------------------------------------------
/verilog/SdfUnit_TC.v:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------
2 | // SdfUnit: Radix-2^2 SDF Unit with Twiddle Conversion
3 | //----------------------------------------------------------------------
4 | module SdfUnit #(
5 | parameter N = 64, // Number of FFT Point
6 | parameter M = 64, // Twiddle Resolution
7 | parameter WIDTH = 16, // Data Bit Length
8 | parameter T4_EN = 0, // Use TwiddleConvert4
9 | parameter T8_EN = 1, // Use TwiddleConvert8
10 | parameter TW_FF = 1, // Use Twiddle Output Register
11 | parameter TC_FF = 1, // Use TwiddleConvert Output Register
12 | parameter B1_RH = 0, // 1st Butterfly Round Half Up
13 | parameter B2_RH = 1, // 2nd Butterfly Round Half Up
14 | parameter LP = 0 // Power Saving
15 | )(
16 | input clock, // Master Clock
17 | input reset, // Active High Asynchronous Reset
18 | input di_en, // Input Data Enable
19 | input [WIDTH-1:0] di_re, // Input Data (Real)
20 | input [WIDTH-1:0] di_im, // Input Data (Imag)
21 | output do_en, // Output Data Enable
22 | output [WIDTH-1:0] do_re, // Output Data (Real)
23 | output [WIDTH-1:0] do_im // Output Data (Imag)
24 | );
25 |
26 | // log2 constant function
27 | function integer log2;
28 | input integer x;
29 | integer value;
30 | begin
31 | value = x-1;
32 | for (log2=0; value>0; log2=log2+1)
33 | value = value>>1;
34 | end
35 | endfunction
36 |
37 | localparam LOG_N = log2(N); // Bit Length of N
38 | localparam LOG_M = log2(M); // Bit Length of M
39 |
40 | // When using Twiddle Conversion, start counting 1T earlier
41 | localparam TC_EN = T4_EN | T8_EN;
42 | localparam EARLY = TC_EN & TW_FF & TC_FF;
43 |
44 | //----------------------------------------------------------------------
45 | // Internal Regs and Nets
46 | //----------------------------------------------------------------------
47 | // 1st Butterfly
48 | reg [LOG_N-1:0] di_count; // Input Data Count
49 | wire bf1_bf; // Butterfly Add/Sub Enable
50 | wire[WIDTH-1:0] bf1_x0_re; // Data #0 to Butterfly (Real)
51 | wire[WIDTH-1:0] bf1_x0_im; // Data #0 to Butterfly (Imag)
52 | wire[WIDTH-1:0] bf1_x1_re; // Data #1 to Butterfly (Real)
53 | wire[WIDTH-1:0] bf1_x1_im; // Data #1 to Butterfly (Imag)
54 | wire[WIDTH-1:0] bf1_y0_re; // Data #0 from Butterfly (Real)
55 | wire[WIDTH-1:0] bf1_y0_im; // Data #0 from Butterfly (Imag)
56 | wire[WIDTH-1:0] bf1_y1_re; // Data #1 from Butterfly (Real)
57 | wire[WIDTH-1:0] bf1_y1_im; // Data #1 from Butterfly (Imag)
58 | wire[WIDTH-1:0] db1_di_re; // Data to DelayBuffer (Real)
59 | wire[WIDTH-1:0] db1_di_im; // Data to DelayBuffer (Imag)
60 | wire[WIDTH-1:0] db1_do_re; // Data from DelayBuffer (Real)
61 | wire[WIDTH-1:0] db1_do_im; // Data from DelayBuffer (Imag)
62 | wire[WIDTH-1:0] bf1_sp_re; // Single-Path Data Output (Real)
63 | wire[WIDTH-1:0] bf1_sp_im; // Single-Path Data Output (Imag)
64 | reg bf1_sp_en; // Single-Path Data Enable
65 | reg [LOG_N-1:0] bf1_count; // Single-Path Data Count
66 | wire bf1_start; // Single-Path Output Trigger
67 | wire bf1_end; // End of Single-Path Data
68 | wire bf1_mj; // Twiddle (-j) Enable
69 | reg [WIDTH-1:0] bf1_do_re; // 1st Butterfly Output Data (Real)
70 | reg [WIDTH-1:0] bf1_do_im; // 1st Butterfly Output Data (Imag)
71 |
72 | // 2nd Butterfly
73 | reg bf2_bf; // Butterfly Add/Sub Enable
74 | wire[WIDTH-1:0] bf2_x0_re; // Data #0 to Butterfly (Real)
75 | wire[WIDTH-1:0] bf2_x0_im; // Data #0 to Butterfly (Imag)
76 | wire[WIDTH-1:0] bf2_x1_re; // Data #1 to Butterfly (Real)
77 | wire[WIDTH-1:0] bf2_x1_im; // Data #1 to Butterfly (Imag)
78 | wire[WIDTH-1:0] bf2_y0_re; // Data #0 from Butterfly (Real)
79 | wire[WIDTH-1:0] bf2_y0_im; // Data #0 from Butterfly (Imag)
80 | wire[WIDTH-1:0] bf2_y1_re; // Data #1 from Butterfly (Real)
81 | wire[WIDTH-1:0] bf2_y1_im; // Data #1 from Butterfly (Imag)
82 | wire[WIDTH-1:0] db2_di_re; // Data to DelayBuffer (Real)
83 | wire[WIDTH-1:0] db2_di_im; // Data to DelayBuffer (Imag)
84 | wire[WIDTH-1:0] db2_do_re; // Data from DelayBuffer (Real)
85 | wire[WIDTH-1:0] db2_do_im; // Data from DelayBuffer (Imag)
86 | wire[WIDTH-1:0] bf2_sp_re; // Single-Path Data Output (Real)
87 | wire[WIDTH-1:0] bf2_sp_im; // Single-Path Data Output (Imag)
88 | reg bf2_ct_en; // Single-Path Data Count Enable
89 | reg [LOG_N-1:0] bf2_count; // Single-Path Data Count
90 | wire bf2_start_0t;// Single-Path Output Trigger
91 | reg bf2_start_1t;// Single-Path Output Trigger
92 | wire bf2_start; // Single-Path Output Trigger
93 | wire bf2_end; // End of Single-Path Data
94 | reg bf2_ct_en_1d;// Single-Path Data Enable When Using TC
95 | wire bf2_sp_en; // Single-Path Data Enable
96 | reg [WIDTH-1:0] bf2_do_re; // 2nd Butterfly Output Data (Real)
97 | reg [WIDTH-1:0] bf2_do_im; // 2nd Butterfly Output Data (Imag)
98 | reg bf2_do_en; // 2nd Butterfly Output Data Enable
99 |
100 | // Multiplication
101 | wire[1:0] tw_sel; // Twiddle Select (2n/n/3n)
102 | wire[LOG_N-3:0] tw_num; // Twiddle Number (n)
103 | wire[LOG_N-1:0] tw_addr; // Twiddle Table Address
104 | wire[LOG_N-1:0] tc_addr; // Twiddle Address from TwiddleConvert
105 | wire[LOG_N-1:0] tw_addr_tc; // Twiddle Address after TC_EN Switch
106 | wire[WIDTH-1:0] tw_re; // Twiddle Data from Table (Real)
107 | wire[WIDTH-1:0] tw_im; // Twiddle Data from Table (Imag)
108 | wire[WIDTH-1:0] tc_re; // Twiddle Data from TwiddleConvert (Real)
109 | wire[WIDTH-1:0] tc_im; // Twiddle Data from TwiddleConvert (Imag)
110 | reg tw_nz; // Multiplication Enable
111 | reg tw_nz_1d; // Multiplication Enable
112 | wire mu_en; // Multiplication Enable
113 | wire[WIDTH-1:0] mu_a_re; // Multiplier Input (Real)
114 | wire[WIDTH-1:0] mu_a_im; // Multiplier Input (Imag)
115 | wire[WIDTH-1:0] mu_b_re; // Twiddle Data to Multiplier (Real)
116 | wire[WIDTH-1:0] mu_b_im; // Twiddle Data to Multiplier (Imag)
117 | wire[WIDTH-1:0] mu_m_re; // Multiplier Output (Real)
118 | wire[WIDTH-1:0] mu_m_im; // Multiplier Output (Imag)
119 | reg [WIDTH-1:0] mu_do_re; // Multiplication Output Data (Real)
120 | reg [WIDTH-1:0] mu_do_im; // Multiplication Output Data (Imag)
121 | reg mu_do_en; // Multiplication Output Data Enable
122 |
123 | //----------------------------------------------------------------------
124 | // 1st Butterfly
125 | //----------------------------------------------------------------------
126 | always @(posedge clock or posedge reset) begin
127 | if (reset) begin
128 | di_count <= {LOG_N{1'b0}};
129 | end else begin
130 | di_count <= di_en ? (di_count + 1'b1) : {LOG_N{1'b0}};
131 | end
132 | end
133 | assign bf1_bf = di_count[LOG_M-1];
134 |
135 | // Reducing signal changes may reduce power consumption
136 | // Set unknown value x for verification
137 | assign bf1_x0_re = bf1_bf ? db1_do_re : LP ? {WIDTH{1'b0}} : {WIDTH{1'bx}};
138 | assign bf1_x0_im = bf1_bf ? db1_do_im : LP ? {WIDTH{1'b0}} : {WIDTH{1'bx}};
139 | assign bf1_x1_re = bf1_bf ? di_re : LP ? {WIDTH{1'b0}} : {WIDTH{1'bx}};
140 | assign bf1_x1_im = bf1_bf ? di_im : LP ? {WIDTH{1'b0}} : {WIDTH{1'bx}};
141 |
142 | Butterfly #(.WIDTH(WIDTH),.RH(B1_RH)) BF1 (
143 | .x0_re (bf1_x0_re ), // i
144 | .x0_im (bf1_x0_im ), // i
145 | .x1_re (bf1_x1_re ), // i
146 | .x1_im (bf1_x1_im ), // i
147 | .y0_re (bf1_y0_re ), // o
148 | .y0_im (bf1_y0_im ), // o
149 | .y1_re (bf1_y1_re ), // o
150 | .y1_im (bf1_y1_im ) // o
151 | );
152 |
153 | DelayBuffer #(.DEPTH(2**(LOG_M-1)),.WIDTH(WIDTH)) DB1 (
154 | .clock (clock ), // i
155 | .di_re (db1_di_re ), // i
156 | .di_im (db1_di_im ), // i
157 | .do_re (db1_do_re ), // o
158 | .do_im (db1_do_im ) // o
159 | );
160 |
161 | assign db1_di_re = bf1_bf ? bf1_y1_re : di_re;
162 | assign db1_di_im = bf1_bf ? bf1_y1_im : di_im;
163 | assign bf1_sp_re = bf1_bf ? bf1_y0_re : bf1_mj ? db1_do_im : db1_do_re;
164 | assign bf1_sp_im = bf1_bf ? bf1_y0_im : bf1_mj ? -db1_do_re : db1_do_im;
165 |
166 | always @(posedge clock or posedge reset) begin
167 | if (reset) begin
168 | bf1_sp_en <= 1'b0;
169 | bf1_count <= {LOG_N{1'b0}};
170 | end else begin
171 | bf1_sp_en <= bf1_start ? 1'b1 : bf1_end ? 1'b0 : bf1_sp_en;
172 | bf1_count <= bf1_sp_en ? (bf1_count + 1'b1) : {LOG_N{1'b0}};
173 | end
174 | end
175 | assign bf1_start = (di_count == (2**(LOG_M-1)-1));
176 | assign bf1_end = (bf1_count == (2**LOG_N-1));
177 | assign bf1_mj = (bf1_count[LOG_M-1:LOG_M-2] == 2'd3);
178 |
179 | always @(posedge clock) begin
180 | bf1_do_re <= bf1_sp_re;
181 | bf1_do_im <= bf1_sp_im;
182 | end
183 |
184 | //----------------------------------------------------------------------
185 | // 2nd Butterfly
186 | //----------------------------------------------------------------------
187 | always @(posedge clock) begin
188 | bf2_bf <= bf1_count[LOG_M-2];
189 | end
190 |
191 | // Reducing signal changes may reduce power consumption
192 | // Set unknown value x for verification
193 | assign bf2_x0_re = bf2_bf ? db2_do_re : LP ? {WIDTH{1'b0}} : {WIDTH{1'bx}};
194 | assign bf2_x0_im = bf2_bf ? db2_do_im : LP ? {WIDTH{1'b0}} : {WIDTH{1'bx}};
195 | assign bf2_x1_re = bf2_bf ? bf1_do_re : LP ? {WIDTH{1'b0}} : {WIDTH{1'bx}};
196 | assign bf2_x1_im = bf2_bf ? bf1_do_im : LP ? {WIDTH{1'b0}} : {WIDTH{1'bx}};
197 |
198 | // Negative bias occurs when RH=0 and positive bias occurs when RH=1.
199 | // Using both alternately reduces the overall rounding error.
200 | Butterfly #(.WIDTH(WIDTH),.RH(B2_RH)) BF2 (
201 | .x0_re (bf2_x0_re ), // i
202 | .x0_im (bf2_x0_im ), // i
203 | .x1_re (bf2_x1_re ), // i
204 | .x1_im (bf2_x1_im ), // i
205 | .y0_re (bf2_y0_re ), // o
206 | .y0_im (bf2_y0_im ), // o
207 | .y1_re (bf2_y1_re ), // o
208 | .y1_im (bf2_y1_im ) // o
209 | );
210 |
211 | DelayBuffer #(.DEPTH(2**(LOG_M-2)),.WIDTH(WIDTH)) DB2 (
212 | .clock (clock ), // i
213 | .di_re (db2_di_re ), // i
214 | .di_im (db2_di_im ), // i
215 | .do_re (db2_do_re ), // o
216 | .do_im (db2_do_im ) // o
217 | );
218 |
219 | assign db2_di_re = bf2_bf ? bf2_y1_re : bf1_do_re;
220 | assign db2_di_im = bf2_bf ? bf2_y1_im : bf1_do_im;
221 | assign bf2_sp_re = bf2_bf ? bf2_y0_re : db2_do_re;
222 | assign bf2_sp_im = bf2_bf ? bf2_y0_im : db2_do_im;
223 |
224 | always @(posedge clock or posedge reset) begin
225 | if (reset) begin
226 | bf2_ct_en <= 1'b0;
227 | bf2_count <= {LOG_N{1'b0}};
228 | end else begin
229 | bf2_ct_en <= bf2_start ? 1'b1 : bf2_end ? 1'b0 : bf2_ct_en;
230 | bf2_count <= bf2_ct_en ? (bf2_count + 1'b1) : {LOG_N{1'b0}};
231 | end
232 | end
233 |
234 | // When using Twiddle Conversion, start counting 1T earlier
235 | assign bf2_start_0t = (bf1_count == (2**(LOG_M-2)-1)) & bf1_sp_en;
236 | always @(posedge clock) begin
237 | bf2_start_1t <= bf2_start_0t;
238 | end
239 | assign bf2_start = EARLY ? bf2_start_0t : bf2_start_1t;
240 | assign bf2_end = (bf2_count == (2**LOG_N-1));
241 |
242 | always @(posedge clock) begin
243 | bf2_ct_en_1d <= bf2_ct_en;
244 | end
245 | assign bf2_sp_en = EARLY ? bf2_ct_en_1d : bf2_ct_en;
246 |
247 | always @(posedge clock) begin
248 | bf2_do_re <= bf2_sp_re;
249 | bf2_do_im <= bf2_sp_im;
250 | end
251 |
252 | always @(posedge clock or posedge reset) begin
253 | if (reset) begin
254 | bf2_do_en <= 1'b0;
255 | end else begin
256 | bf2_do_en <= bf2_sp_en;
257 | end
258 | end
259 |
260 | //----------------------------------------------------------------------
261 | // Multiplication
262 | //----------------------------------------------------------------------
263 | assign tw_sel[1] = bf2_count[LOG_M-2];
264 | assign tw_sel[0] = bf2_count[LOG_M-1];
265 | assign tw_num = bf2_count << (LOG_N-LOG_M);
266 | assign tw_addr = tw_num * tw_sel;
267 |
268 | Twiddle #(.TW_FF(TW_FF)) TW (
269 | .clock (clock ), // i
270 | .addr (tw_addr_tc ), // i
271 | .tw_re (tw_re ), // o
272 | .tw_im (tw_im ) // o
273 | );
274 |
275 | generate if (T4_EN) begin
276 | TwiddleConvert4 #(.LOG_N(LOG_N),.WIDTH(WIDTH),.TW_FF(TW_FF),.TC_FF(TC_FF)) TC (
277 | .clock (clock ), // i
278 | .tw_addr (tw_addr), // i
279 | .tw_re (tw_re ), // i
280 | .tw_im (tw_im ), // i
281 | .tc_addr (tc_addr), // o
282 | .tc_re (tc_re ), // o
283 | .tc_im (tc_im ) // o
284 | );
285 | end else if (T8_EN) begin
286 | TwiddleConvert8 #(.LOG_N(LOG_N),.WIDTH(WIDTH),.TW_FF(TW_FF),.TC_FF(TC_FF)) TC (
287 | .clock (clock ), // i
288 | .tw_addr (tw_addr), // i
289 | .tw_re (tw_re ), // i
290 | .tw_im (tw_im ), // i
291 | .tc_addr (tc_addr), // o
292 | .tc_re (tc_re ), // o
293 | .tc_im (tc_im ) // o
294 | );
295 | end else begin
296 | assign tc_addr = {LOG_N{1'bx}};
297 | assign tc_re = {WIDTH{1'bx}};
298 | assign tc_im = {WIDTH{1'bx}};
299 | end endgenerate
300 |
301 | assign tw_addr_tc = TC_EN ? tc_addr : tw_addr;
302 | assign mu_b_re = TC_EN ? tc_re : tw_re;
303 | assign mu_b_im = TC_EN ? tc_im : tw_im;
304 |
305 | // Multiplication is bypassed when twiddle address is 0.
306 | always @(posedge clock) begin
307 | tw_nz <= (tw_addr != {LOG_N{1'b0}});
308 | tw_nz_1d <= tw_nz;
309 | end
310 | // When using Twiddle Conversion, address generated 1T Earlier
311 | assign mu_en = EARLY ? tw_nz_1d : tw_nz;
312 |
313 | // Set unknown value x for verification
314 | assign mu_a_re = mu_en ? bf2_do_re : {WIDTH{1'bx}};
315 | assign mu_a_im = mu_en ? bf2_do_im : {WIDTH{1'bx}};
316 |
317 | Multiply #(.WIDTH(WIDTH)) MU (
318 | .a_re (mu_a_re), // i
319 | .a_im (mu_a_im), // i
320 | .b_re (mu_b_re), // i
321 | .b_im (mu_b_im), // i
322 | .m_re (mu_m_re), // o
323 | .m_im (mu_m_im) // o
324 | );
325 |
326 | always @(posedge clock) begin
327 | mu_do_re <= mu_en ? mu_m_re : bf2_do_re;
328 | mu_do_im <= mu_en ? mu_m_im : bf2_do_im;
329 | end
330 |
331 | always @(posedge clock or posedge reset) begin
332 | if (reset) begin
333 | mu_do_en <= 1'b0;
334 | end else begin
335 | mu_do_en <= bf2_do_en;
336 | end
337 | end
338 |
339 | // No multiplication required at final stage
340 | assign do_en = (LOG_M == 2) ? bf2_do_en : mu_do_en;
341 | assign do_re = (LOG_M == 2) ? bf2_do_re : mu_do_re;
342 | assign do_im = (LOG_M == 2) ? bf2_do_im : mu_do_im;
343 |
344 | endmodule
345 |
--------------------------------------------------------------------------------