├── 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 | ![64-point FFT timing diagram](img/fft64_wave.png) 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 | ![64-point FFT block diagram](img/fft64_block.png) 78 | 79 | ![SDF unit block diagram](img/sdfunit.png) 80 | 81 | ![Deriving radix-22 butterfly](img/butterfly.png) 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 | --------------------------------------------------------------------------------