├── .gitignore
├── APR
├── .gitignore
├── README.md
├── innovus
│ ├── .gitignore
│ └── work
│ │ ├── .gitignore
│ │ ├── fft_multimode.globals
│ │ └── setup.tcl
└── 多模式FFT处理器Innovus后端流程.pdf
├── LICENSE
├── README.md
├── docs
└── README.md
├── figs
├── 128-point FFT output.png
├── 128-point iFFT output.png
├── 256-point FFT output.png
├── 256-point iFFT output.png
├── 512-point FFT output.png
├── 512-point iFFT output.png
├── 64-point FFT output.png
├── 64-point iFFT output.png
├── 64-point simulation wave.png
├── FFT processor arch.png
├── area report.png
├── layout.png
└── setup timing report of DC.png
├── lint
├── .gitignore
└── spyglass
│ ├── .gitignore
│ ├── Makefile
│ └── run_sg.tcl
├── rtl
├── .gitignore
├── sim
│ ├── common-sim-flags.mk
│ ├── lib
│ │ └── README.md
│ ├── tb_src
│ │ ├── fft_tb.v
│ │ └── reoder_tb.v
│ ├── test_vector
│ │ ├── fft128_input_im.txt
│ │ ├── fft128_input_re.txt
│ │ ├── fft256_input_im.txt
│ │ ├── fft256_input_re.txt
│ │ ├── fft512_input_im.txt
│ │ ├── fft512_input_re.txt
│ │ ├── fft64_input_im.txt
│ │ ├── fft64_input_re.txt
│ │ ├── fft_output_im.txt
│ │ ├── fft_output_re.txt
│ │ ├── ifft128_input_im.txt
│ │ ├── ifft128_input_re.txt
│ │ ├── ifft256_input_im.txt
│ │ ├── ifft256_input_re.txt
│ │ ├── ifft512_input_im.txt
│ │ ├── ifft512_input_re.txt
│ │ ├── ifft64_input_im.txt
│ │ └── ifft64_input_re.txt
│ ├── vcs
│ │ ├── .gitignore
│ │ ├── Makefile
│ │ └── vcs.mk
│ ├── verilator
│ │ └── Makefile
│ └── xcelium
│ │ ├── .gitignore
│ │ ├── Makefile
│ │ └── xcelium.mk
└── src
│ ├── bf_rdx2.v
│ ├── complex_mult.v
│ ├── fft16.v
│ ├── fft_multimode.v
│ ├── ifft_twiddle_rom.v
│ ├── include
│ └── .gitignore
│ ├── memory
│ ├── fft_reoder_sramsp16x256_maskoff.v
│ └── sramsp_maskoff.v
│ ├── reoder.v
│ ├── reserve_bits.v
│ ├── shiftreg.v
│ ├── switch.v
│ └── twiddle_rom.v
├── scripts
├── backup.sh
└── clean.sh
├── software
├── README.md
├── bit_reverse.m
├── fft_fixed.m
├── fft_fixed_run.m
├── fft_float.m
├── fft_run.m
├── ifft_fixed.m
├── ifft_fixed_run.m
├── ifft_input_gen.m
├── input_gen.m
├── wave.py
└── wn_gen.m
└── syn
├── syn_asic
├── .gitignore
├── Makefile
├── README.md
└── scripts
│ ├── .synopsys_dc.setup
│ ├── main.py
│ ├── sdc.tcl
│ └── synflow.tcl
└── syn_fpga
├── .gitignore
├── quartus
└── Makefile
└── vivado
├── Makefile
└── scripts
├── elaborate.tcl
├── impl.tcl
└── synth.tcl
/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !*/
3 | !.gitignore
4 | !*.md
5 | !LICENSE
6 | !*.[cSh]
7 | !*.v
8 | !*.sv
9 | !*.py
10 | !*.cc
11 | !*.cpp
12 | !*.m
13 | !/docs/*
14 | !/lint/*
15 | !/rtl/*
16 | !/scripts/*
17 | !/software/*
18 | !/syn/*
19 | !/APR/*
20 | !/figs/**
21 |
--------------------------------------------------------------------------------
/APR/.gitignore:
--------------------------------------------------------------------------------
1 | *.*
2 | *
3 | !*/
4 | !.gitignore
5 | !*.md
6 | !*.[cSh]
7 | !*.v
8 | !*.py
9 | !*.cc
10 | !*.cpp
11 | !Makefile
12 | !*.mk
13 | !*.pdf
14 | !/innovus/*
15 | !*.txt
16 |
--------------------------------------------------------------------------------
/APR/README.md:
--------------------------------------------------------------------------------
1 | Currently, only the Innovus process is available, and there may be errors in both the process and results. Please be aware of this!!!!
2 |
3 |
4 |
5 | TODO:
6 |
7 | - [ ] Add Foundry SRAM
8 |
9 | - [ ] Auto FloorPlan Script
10 |
11 | - [ ] ICC2 Flow
12 |
13 | ...
14 |
--------------------------------------------------------------------------------
/APR/innovus/.gitignore:
--------------------------------------------------------------------------------
1 | *.*
2 | *
3 | !*/
4 | !.gitignore
5 | !*.md
6 | !Makefile
7 | !*.mk
8 | !/work/*
9 |
--------------------------------------------------------------------------------
/APR/innovus/work/.gitignore:
--------------------------------------------------------------------------------
1 | *.*
2 | *
3 | !.gitignore
4 | !setup.tcl
5 | !fft_multimode.globals
6 |
--------------------------------------------------------------------------------
/APR/innovus/work/fft_multimode.globals:
--------------------------------------------------------------------------------
1 | set defHierChar {/}
2 | set locv_inter_clock_use_worst_derate false
3 | set init_oa_search_lib {}
4 | set lsgOCPGainMult 1.000000
5 | set init_verilog {../fft_multimode.v}
6 | set init_pwr_net {VDD}
7 | set init_lef_file {/tools/PDK/tsmc28nm/tn28clpr002e1_1_5a/N28_PRTF_Cad_v1d5a/PR_tech/Cadence/LefHeader/HVH/tsmcn28_10lm7X2RRDL.tlef /tools/PDK/tsmc28nm/TSMCHOME/digital/Back_End/lef/tcbn28hpcplusbwp40p140_110a/lef/tcbn28hpcplusbwp40p140.lef}
8 | set init_top_cell {fft_multimode}
9 | set fpIsMaxIoHeight 0
10 | set init_gnd_net {VSS}
11 | set timing_case_analysis_for_icg_propagation false
12 |
13 |
--------------------------------------------------------------------------------
/APR/innovus/work/setup.tcl:
--------------------------------------------------------------------------------
1 | # By BriMonzZY
2 |
3 |
4 | set design_name fft_multimode
5 | set vars(design) $design_name
6 | set vars(rtl_design) $vars(design)
7 | set init_verilog "../fft_multimode.v"
8 | set vars(fp_file) "fft_multimode.fp"
9 |
10 | set init_lef_file "/tools/PDK/tsmc28nm/tn28clpr002e1_1_5a/N28_PRTF_Cad_v1d5a/PR_tech/Cadence/LefHeader/HVH/tsmcn28_10lm7X2ZRDL.tlef"
11 | set vars(lef_files) "/tools/PDK/tsmc28nm/tn28clpr002e1_1_5a/N28_PRTF_Cad_v1d5a/PR_tech/Cadence/LefHeader/HVH/tsmcn28_10lm7X2ZRDL.tlef \
12 | /tools/PDK/tsmc28nm/TSMCHOME/digital/Back_End/lef/tcbn28hpcplusbwp40p140_110a/lef/tcbn28hpcplusbwp40p140.lef"
13 | set init_top_cell $vars(design)
14 | set init_gnd_net VSS
15 | set init_pwr_net VDD
16 | set vars(cts_cells) clk
17 |
18 | set vars(local_cpus) 8
19 | set vars(process) 28;# e.g. 16, 28
20 |
21 | set vars(rc_corners) "cworst_m40c cbest_125c ctyp_85c cworst_125c"
22 | set vars(delay_corners) "dc_slow_corner_cworst_m40c dc_typ_corner_ctyp_85c dc_fast_corner_cbest_125c"
23 | set vars(constraint_modes) "merged" ;# set vars(constraint_modes) "merged merged_1g"
24 |
25 | set slow_corner ssgnp_0p90v_m40c ;# e.g. ssgnp_0p72v_0c
26 | set typ_corner tt_1p00v_85c ;# e.g. tt_0p80v_85c
27 | set fast_corner ffgnp_1p05v_125c ;# e.g. ffgnp_0p88v_125c
28 |
29 | set vars(merged_slow_corner_cworst_m40c,delay_corner) [lindex $vars(delay_corners) 0]
30 | set vars(merged_fast_corner_cbest_125c,delay_corner) [lindex $vars(delay_corners) 2]
31 | set vars(merged_slow_corner_cworst_m40c,constraint_mode) [lindex $vars(constraint_modes) 0]
32 | set vars(merged_fast_corner_cbest_125c,constraint_mode) [lindex $vars(constraint_modes) 0]
33 | set vars(dc_fast_corner_cbest_125c,rc_corner) [lindex $vars(rc_corners) 1]
34 | set vars(dc_typ_corner_ctyp_85c,rc_corner) [lindex $vars(rc_corners) 2]
35 | set vars(dc_fast_corner_cbest_125c,library_set) $fast_corner
36 | set vars(dc_typ_corner_ctyp_85c,library_set) $typ_corner
37 | set vars(dc_slow_corner_cworst_m40c,library_set) $slow_corner
38 | set vars(dc_slow_corner_cworst_m40c,rc_corner) [lindex $vars(rc_corners) 0]
39 |
40 | set vars(setup_analysis_views) "merged_slow_corner_cworst_m40c"
41 | set vars(hold_analysis_views) "merged_fast_corner_cbest_125c"
42 | set vars(setup_analysis_views) "merged_slow_corner_cworst_m40c"
43 | set vars(hold_analysis_views) "merged_fast_corner_cbest_125c"
44 |
45 | set vars(default_setup_view) [lindex $vars(setup_analysis_views) 0]
46 | set vars(default_hold_view) [lindex $vars(hold_analysis_views) 0]
47 | set vars(active_setup_views) $vars(setup_analysis_views)
48 | set vars(active_hold_views) $vars(hold_analysis_views)
49 |
50 | set qrc_file(cworst) "/tools/PDK/tsmc28nm/RC_QRC_cln28hpc+_1p10m_5x2y2z_ut-alrdl_9corners_1.3a/RC_QRC_cln28hpc+_1p10m+ut-alrdl_5x2y2z_cworst_T/qrcTechFile"
51 | set qrc_file(cbest) "/tools/PDK/tsmc28nm/RC_QRC_cln28hpc+_1p10m_5x2y2z_ut-alrdl_9corners_1.3a/RC_QRC_cln28hpc+_1p10m+ut-alrdl_5x2y2z_cbest/qrcTechFile"
52 | set qrc_file(rcworst) "/tools/PDK/tsmc28nm/RC_QRC_cln28hpc+_1p10m_5x2y2z_ut-alrdl_9corners_1.3a/RC_QRC_cln28hpc+_1p10m+ut-alrdl_5x2y2z_rcworst_T/qrcTechFile"
53 | set qrc_file(rcbest) "/tools/PDK/tsmc28nm/RC_QRC_cln28hpc+_1p10m_5x2y2z_ut-alrdl_9corners_1.3a/RC_QRC_cln28hpc+_1p10m+ut-alrdl_5x2y2z_rcbest/qrcTechFile"
54 | set qrc_file(typical) "/tools/PDK/tsmc28nm/RC_QRC_cln28hpc+_1p10m_5x2y2z_ut-alrdl_9corners_1.3a/RC_QRC_cln28hpc+_1p10m+ut-alrdl_5x2y2z_typical/qrcTechFile"
55 | set vars(cworst_m40c,qx_tech_file) $qrc_file(cworst)
56 | set vars(cbest_125c,qx_tech_file) $qrc_file(cbest)
57 | set vars(ctyp_85c,qx_tech_file) $qrc_file(typical)
58 | set vars(cworst_125c,qx_tech_file) $qrc_file(cworst)
59 |
60 | set stdcell_library($fast_corner) "/tools/PDK/tsmc28nm/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tcbn28hpcplusbwp40p140_180a/tcbn28hpcplusbwp40p140ffg0p88v0c.lib"
61 | set stdcell_library($slow_corner) "/tools/PDK/tsmc28nm/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tcbn28hpcplusbwp40p140_180a/tcbn28hpcplusbwp40p140ffg0p88v0c.lib"
62 | set stdcell_library($typ_corner) "/tools/PDK/tsmc28nm/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tcbn28hpcplusbwp40p140_180a/tcbn28hpcplusbwp40p140ffg0p88v0c.lib"
63 |
64 | set macro_ctl_list [list ]
65 | set macro(lef) [list ]
66 | set macro_library($slow_corner) [list ]
67 | set macro_library($typ_corner) [list ]
68 | set macro_library($fast_corner) [list ]
69 | set vars(library_sets) [list $slow_corner $typ_corner $fast_corner]
70 | set vars($slow_corner,timing) [concat $stdcell_library($slow_corner) $macro_library($slow_corner)]
71 | set vars($typ_corner,timing) [concat $stdcell_library($typ_corner) $macro_library($typ_corner)]
72 | set vars($fast_corner,timing) [concat $stdcell_library($fast_corner) $macro_library($fast_corner)]
73 |
74 | set vars(merged,pre_cts_sdc) "../fft_multimode.sdc"
75 |
--------------------------------------------------------------------------------
/APR/多模式FFT处理器Innovus后端流程.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/APR/多模式FFT处理器Innovus后端流程.pdf
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 BriMonzZY
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # multi-mode FFT processor
2 |
3 | Author: BriMonzZY
4 |
5 |
6 |
7 | *FOR STUDY ONLY*
8 |
9 | *I cannot guarantee that this design is correct, it is for reference only!*
10 |
11 |
12 |
13 | ## Introduction
14 |
15 | This repo is a configurable **Simple R2MDC DIF-FFT Processor** implementation from algorithm to GDSII, supporting 64/128/256/512-point Fast Fourier Transform (FFT) and Inverse FFT (IFFT) computations. The design features a complete implementation flow including RTL verification and ASIC synthesis.
16 |
17 |
18 |
19 |
20 | File hierarchy:
21 |
22 | ```txt
23 | .
24 | ├── README.md
25 | ├── software # algorithm and data gen
26 | ├── rtl
27 | | ├── src # design files
28 | | └── sim
29 | | ├── tb_src # testbench files
30 | | ├── vcs # run VCS simulation
31 | | ├── xcelium # run xcelium simulation
32 | | └── verilator # TODO
33 | ├── syn # Synthesis
34 | | ├── syn_asic
35 | | | └── scripts # ASIC synthesize scripts
36 | | └── syn_fpga # TODO
37 | ├── APR # Auto Placement & Router
38 | | └── innovus # run PnR flow with innovus
39 | ├── scripts # clean or backup scripts
40 | └── (backup)
41 |
42 | ```
43 |
44 |
45 |
46 | ## Architecture
47 |
48 | Radix-2 MDC DIF-FFT:
49 |
50 |
51 |
52 |
53 |
54 | ## Quick Start
55 |
56 | Input and output ports of the FFT processor:
57 |
58 | | **name** | **in/out** | **width** | **description** |
59 | | --------- | ---------- | --------- | ------------------------------------------------------------ |
60 | | clk | I | 1 | system clock |
61 | | rst_n | I | 1 | System asynchronous reset, low level effective |
62 | | inv | I | 1 | Mode control, 0 represents FFT operation, 1 represents IFFT operation |
63 | | np | I | 2 | FFT/IFFT points: 0 represents 64 points, 1 represents 128 points, 2 represents 256 points, and 3 represents 512 points |
64 | | stb | I | 1 | Input data valid indication |
65 | | sop_in | I | 1 | The first valid data indicator for each set of input data (64 numbers) indicates that the high level is valid |
66 | | x_re | I | 16 | Input data real part, binary complement fixed-point format |
67 | | x_im | I | 16 | Input data imaginary part, binary complement fixed-point format |
68 | | valid_out | O | 1 | Effective indication of output data |
69 | | sop_out | O | 1 | The first valid data indicator for each set of output data (64 numbers) |
70 | | y_re | O | 16 | Output data real part, binary complement fixed-point format |
71 | | y_im | O | 16 | Output data imaginary part, binary complement fixed-point format |
72 |
73 |
74 |
75 | Edit `rtl/sim/test_vector/fft*_input_re.txt` to change the real part of FFT input data.
76 |
77 | Edit `rtl/sim/test_vector/fft*_input_im.txt` to change the imag part of FFT input data.
78 |
79 | Edit `rtl/sim/test_vector/ifft*_input_re.txt` to change the real part of IFFT input data.
80 |
81 | Edit `rtl/sim/test_vector/ifft*_input_im.txt` to change the imag part of IFFT input data.
82 |
83 | Edit the line (5 23 24 64 65) of file `rtl/sim/tb_src/fft_tb.v` to Change the input or the mode of processor.
84 |
85 | The simulation output will generated in `fft_output_re.txt `and `fft_output_im.txt` , you can draw a waveform of the output by using `python software/wave.py`.
86 |
87 | you can change the macro in file `fft_reoder_sramsp16x256_maskoff.v` to use Foundry SRAM or not.
88 |
89 |
90 |
91 |
92 | ### Simulation
93 |
94 | run simulation with Synopsys VCS:
95 | ```bash
96 | cd rtl/sim/vcs
97 | # make help
98 | make run
99 | ```
100 |
101 | run simulation with Cadence XCELIUM:
102 | ```bash
103 | cd rtl/sim/xcelium
104 | # make help
105 | make simx
106 | ```
107 |
108 | debug with Synopsys Verdi:
109 | ```bash
110 | cd rtl/sim/vcs
111 | make debug
112 | make rundebug
113 | make wave # show waveform using verdi
114 | ```
115 |
116 |
117 |
118 | ### Synthesis
119 |
120 | run synthesis with Design Compiler:
121 |
122 | ```bash
123 | cd syn/syn_asic
124 | # make help
125 | make syn
126 | ```
127 |
128 |
129 |
130 | ### APR
131 |
132 | run PnR with INNOVUS:
133 |
134 | see `APR/innovus/README.md`.
135 |
136 |
137 |
138 | ## Result of simulation
139 |
140 | Simulation waveform of 64-point FFT mode of our FFT processor:
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 | ### FFT
149 |
150 | We use 0.005*sin(t) for real input ( Q15 format ) and imag input to calculate FFT output.
151 |
152 | The following is the output of the FFT processor:
153 |
154 |
155 |
156 | 64-point FFT output:
157 |
158 |
159 |
160 | The maximum error output from the Matlab fixed-point model is 13 ( Q15 format ).
161 |
162 |
163 |
164 | 128-point FFT output:
165 |
166 |
167 |
168 | The maximum error output from the Matlab fixed-point model is 28 ( Q15 format ).
169 |
170 |
171 |
172 | 256-point FFT output:
173 |
174 |
175 |
176 | The maximum error output from the Matlab fixed-point model is 61 ( Q15 format ).
177 |
178 |
179 |
180 | 512-point FFT output:
181 |
182 |
183 |
184 | The maximum error output from the Matlab fixed-point model is 120 ( Q15 format ).
185 |
186 |
187 |
188 | ### iFFT
189 |
190 | We use n, n-1,n-2,..., 0 as raw input to calculate FFT as input of iFFT.
191 |
192 | The following is the output of the iFFT model of FFT processor:
193 |
194 |
195 |
196 | 64-point iFFT output:
197 |
198 |
199 |
200 | The maximum error output from the Matlab fixed-point model is 1 ( Q15 format ).
201 |
202 |
203 |
204 | 128-point iFFT output:
205 |
206 |
207 |
208 | The maximum error output from the Matlab fixed-point model is 1 ( Q15 format ).
209 |
210 |
211 |
212 | 256-point iFFT output:
213 |
214 |
215 |
216 | The maximum error output from the Matlab fixed-point model is 1 ( Q15 format ).
217 |
218 |
219 |
220 | 512-point iFFT output
221 |
222 |
223 |
224 | The output is **incorrect** due to the overflow of intermediate result bits within our current implementation.
225 |
226 |
227 |
228 | ## Result of Synthesis
229 |
230 | The FFT processor can run at **701.7 MHz** at TSMC N28, since we haven't optimized timing yet.
231 |
232 |
233 |
234 | setup timing report generated by Design Compiler:
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 | ## Result of PnR
243 |
244 |
245 |
246 | We use TSMC N28 to impl this project
247 |
248 | Area: 455x455=0.207mm^2
249 |
250 | Layout of FFT processor:
251 |
252 |
253 |
254 |
255 |
256 | ## Future Work
257 |
258 | 1. Using a larger bit width for intermediate calculations to reduce accuracy loss.
259 | 1. Multi-parallel MDC architecture.
260 | 2. Optimize timing and SRAM load/stroe.
261 | 3. Use Foundry ROM.
262 | 3. Add ICC2 flow.
263 | 4. Add STA and signoff flow.
264 |
265 |
266 |
267 | The design space for FFT hardware accelerators is still relatively large, and there are SDF MDF、SDC、MDC、SC、MSC、SFF、 There are even circuit architectures such as Radix-2 Combined SDC-SDF (R2CSS) and others; In terms of storage architecture, optimization can be achieved from aspects such as storage space and storage organizational structure There are also different combinations of Radix, choices of DIT and DIF, and so on. Different fields and applications require different characteristics and architectures. How FFT acceleration architecture performs Trade off is also a part that needs to be studied.
268 |
269 | In short, the current FFT processor design cannot be considered a future work. The current work is only a reproduction of the basic circuit structure that is easy to understand.
270 |
271 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/docs/README.md
--------------------------------------------------------------------------------
/figs/128-point FFT output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/figs/128-point FFT output.png
--------------------------------------------------------------------------------
/figs/128-point iFFT output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/figs/128-point iFFT output.png
--------------------------------------------------------------------------------
/figs/256-point FFT output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/figs/256-point FFT output.png
--------------------------------------------------------------------------------
/figs/256-point iFFT output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/figs/256-point iFFT output.png
--------------------------------------------------------------------------------
/figs/512-point FFT output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/figs/512-point FFT output.png
--------------------------------------------------------------------------------
/figs/512-point iFFT output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/figs/512-point iFFT output.png
--------------------------------------------------------------------------------
/figs/64-point FFT output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/figs/64-point FFT output.png
--------------------------------------------------------------------------------
/figs/64-point iFFT output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/figs/64-point iFFT output.png
--------------------------------------------------------------------------------
/figs/64-point simulation wave.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/figs/64-point simulation wave.png
--------------------------------------------------------------------------------
/figs/FFT processor arch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/figs/FFT processor arch.png
--------------------------------------------------------------------------------
/figs/area report.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/figs/area report.png
--------------------------------------------------------------------------------
/figs/layout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/figs/layout.png
--------------------------------------------------------------------------------
/figs/setup timing report of DC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/figs/setup timing report of DC.png
--------------------------------------------------------------------------------
/lint/.gitignore:
--------------------------------------------------------------------------------
1 | *.*
2 | *
3 | !*/
4 | !.gitignore
5 | !*.md
6 | !Makefile
7 | !*.tcl
8 | !/spyglass/*
9 |
--------------------------------------------------------------------------------
/lint/spyglass/.gitignore:
--------------------------------------------------------------------------------
1 | *.*
2 | *
3 | !*/
4 | !.gitignore
5 | !*.md
6 | !Makefile
7 | !*.tcl
8 | spyglass-1/
9 |
--------------------------------------------------------------------------------
/lint/spyglass/Makefile:
--------------------------------------------------------------------------------
1 |
2 | sg:
3 | sg_shell -tcl sg_lint.tcl
4 |
5 | help:
6 | sg_shell -help
7 |
8 | clean:
9 | rm -rf sg_shell_command.log spyglass-1
10 |
--------------------------------------------------------------------------------
/lint/spyglass/run_sg.tcl:
--------------------------------------------------------------------------------
1 | set design_name "example"
2 |
3 | # read in files
4 | read_file -type sourcelist ./sim_common_files.f
5 | # read_file -type gateslib ../../lib/
6 | # read_file -type sgdc ../../src/sdc/${design_name}.sgdc
7 |
8 | # setup
9 | set_option top ${design_name}
10 | # set_option sdc2sgdc yes
11 | current_goal Design_Read -top ${design_name}
12 | link_design -force
13 |
14 | # run lint
15 | current_goal lint/lint_rtl -top ${design_name}
16 | run_goal
17 |
18 | # save project
19 | save_project -force
20 |
--------------------------------------------------------------------------------
/rtl/.gitignore:
--------------------------------------------------------------------------------
1 | *.*
2 | *
3 | !*/
4 | !.gitignore
5 | !*.md
6 | !*.[cSh]
7 | !*.v
8 | !*.py
9 | !*.cc
10 | !*.cpp
11 | !Makefile
12 | !*.mk
13 | !/sim/*
14 | !/src/*
15 | !*.txt
16 |
--------------------------------------------------------------------------------
/rtl/sim/common-sim-flags.mk:
--------------------------------------------------------------------------------
1 | ## Refer to Chipyard
2 |
3 | #----------------------------------------------------------------------------------------
4 | # common gcc configuration/optimization
5 | #----------------------------------------------------------------------------------------
6 |
7 | SIM_OPT_CXXFLAGS := -O3
8 | MAX_CPU := $(shell nproc)
9 |
10 |
11 | MODEL_NAME ?= fft_tb
12 |
13 | TB = $(MODEL_NAME)
14 | long_name = $(MODEL_NAME)
15 |
16 |
17 | SIM_CXXFLAGS = \
18 | $(SIM_OPT_CXXFLAGS) \
19 | -std=c++17
20 |
21 | CLOCK_PERIOD ?= 1.0
22 | RESET_DELAY ?= 777.7
23 |
24 | SIM_PREPROC_DEFINES = \
25 | +define+CLOCK_PERIOD=$(CLOCK_PERIOD) \
26 | +define+RESET_DELAY=$(RESET_DELAY)
27 |
28 |
29 | # rtl
30 | base_dir=$(abspath ../..)
31 | # rtl/sim/vcs
32 | sim_dir=$(abspath .)
33 |
34 | generated_src_name ?= generated-src
35 | gen_dir =$(sim_dir)/$(generated_src_name)
36 | build_dir =$(gen_dir)/$(long_name)
37 | output_dir=$(sim_dir)/output/$(long_name)
38 |
39 | ALL_MODS_FILELIST ?= $(build_dir)/top.all.f
40 | sim_files ?= $(build_dir)/sim_files.f
41 | sim_common_files ?= $(build_dir)/sim_common_files.f
42 |
43 |
44 |
45 | $(build_dir):
46 | mkdir -p $@
47 |
48 | $(output_dir):
49 | mkdir -p $@
50 |
51 | $(sim_files): | $(build_dir)
52 | touch $@ && find $(base_dir)/sim/tb_src -name "*.v" >> $@
53 |
54 | $(ALL_MODS_FILELIST): | $(build_dir)
55 | touch $@ && find $(base_dir)/src -name "*.v" -o -name "*.h" -o -name "*.vh" -o -name "*.svh" >> $@
56 |
57 | $(sim_common_files): $(sim_files) $(ALL_MODS_FILELIST)
58 | sort -u $(sim_files) $(ALL_MODS_FILELIST) | grep -v '.*\.\(svh\|h\)$$' >> $@
59 |
--------------------------------------------------------------------------------
/rtl/sim/lib/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/rtl/sim/lib/README.md
--------------------------------------------------------------------------------
/rtl/sim/tb_src/fft_tb.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 |
3 | module fft_tb();
4 |
5 | parameter N = 512;
6 | localparam CLK_PERIOD = 10;
7 |
8 | reg clk, rst_n;
9 | reg [15:0] x_re;
10 | reg [15:0] x_im;
11 | reg inv;
12 | reg [1:0] np;
13 | reg stb;
14 | reg sop_in;
15 | wire valid_out;
16 | wire sop_out;
17 | wire [15:0] y_re;
18 | wire [15:0] y_im;
19 |
20 | reg [15:0] fft_input_re [0:N-1];
21 | reg [15:0] fft_input_im [0:N-1];
22 | initial begin
23 | $readmemh("../../../test_vector/fft512_input_re.txt", fft_input_re);
24 | $readmemh("../../../test_vector/fft512_input_im.txt", fft_input_im);
25 | end
26 |
27 | integer fft_output_re;
28 | integer fft_output_im;
29 | initial begin
30 | fft_output_re = $fopen("../../../test_vector/fft_output_re.txt", "w");
31 | fft_output_im = $fopen("../../../test_vector/fft_output_im.txt", "w");
32 | forever begin
33 | @(posedge clk);
34 | if(valid_out) begin
35 | if(y_re[15])
36 | $fwrite(fft_output_re, "0x%h ", -$signed(y_re));
37 | else
38 | $fwrite(fft_output_re, "0x%h ", y_re);
39 | if(y_im[15])
40 | $fwrite(fft_output_im, "0x%h ", -$signed(y_im));
41 | else
42 | $fwrite(fft_output_im, "0x%h ", y_im);
43 | end
44 | end
45 | end
46 |
47 | initial begin
48 | clk = 1'b0;
49 | forever #(CLK_PERIOD/2) clk = ~clk;
50 | end
51 |
52 | integer i;
53 | initial begin
54 | `ifdef DEBUG
55 | `ifdef FSDB
56 | $fsdbDumpfile("fft_tb.fsdb");
57 | $fsdbDumpvars(0, fft_tb);
58 | $fsdbDumpMDA(0, fft_tb);
59 | `endif
60 | `endif
61 |
62 | // reset and clk
63 | rst_n <= 1'b0;
64 | inv <= 1'b0;
65 | np <= 2'b11;
66 | stb <= 1'b0;
67 | sop_in <= 1'b0;
68 | x_re <= 16'h0;
69 | x_im <= 16'h0;
70 |
71 | repeat (2) @(posedge clk);
72 | rst_n <= 1;
73 | repeat (3) @(posedge clk);
74 |
75 | stb <= 1'b1;
76 | sop_in <= 1'b1;
77 | x_re <= fft_input_re[0];
78 | x_im <= fft_input_im[0];
79 | @(posedge clk);
80 | sop_in <= 1'b0;
81 | for(i=1; i
5 | ## make run MODEL_NAME=
6 | ## make debug MODEL_NAME=
7 | ## make rundebug MODEL_NAME=
8 | ## make wave
9 | ## make clean
10 | ##
11 |
12 | help:
13 | @echo " - make simv MODEL_NAME="
14 | @echo " - make run MODEL_NAME="
15 | @echo " - make debug MODEL_NAME="
16 | @echo " - make rundebug MODEL_NAME="
17 | @echo " - make wave MODEL_NAME="
18 |
19 | #########################################################################################
20 | # vcs makefile
21 | #########################################################################################
22 | # rtl
23 | base_dir=$(abspath ../..)
24 | # rtl/sim/vcs
25 | sim_dir=$(abspath .)
26 |
27 | #########################################################################################
28 | # name of simulator (used to generate *.f arguments file)
29 | #########################################################################################
30 | sim_name = vcs
31 |
32 | #########################################################################################
33 | # vcs simulator types and rules
34 | #########################################################################################
35 | sim_prefix = simv
36 |
37 | sim = $(sim_dir)/$(sim_prefix)-$(long_name)
38 | sim_debug = $(sim_dir)/$(sim_prefix)-$(long_name)-debug
39 |
40 | include $(sim_dir)/vcs.mk
41 |
42 | .PHONY: simv debug
43 | simv: $(sim)
44 | debug: $(sim_debug)
45 |
46 | #########################################################################################
47 | # vcs binary and arguments
48 | #########################################################################################
49 | VCS := vcs -full64
50 |
51 | VCS_OPTS = $(VCS_CC_OPTS) $(VCS_NONCC_OPTS) $(SIM_PREPROC_DEFINES) $(VCS_PREPROC_DEFINES)
52 |
53 | #########################################################################################
54 | # vcs build paths
55 | #########################################################################################
56 | model_dir = $(build_dir)/$(long_name)
57 | model_dir_debug = $(build_dir)/$(long_name).debug
58 |
59 | #########################################################################################
60 | # vcs simulator rules
61 | #########################################################################################
62 |
63 | $(sim): $(sim_common_files) $(output_dir)
64 | rm -rf $(model_dir)
65 | $(VCS) $(VCS_OPTS) -o $@ -Mdir=$(model_dir)
66 | cp $(sim_prefix)-$(long_name) $(output_dir) && rm -rf $(sim_prefix)-$(long_name)
67 | cp -r $(sim_prefix)-$(long_name).daidir $(output_dir) && rm -rf $(sim_prefix)-$(long_name).daidir
68 |
69 | $(sim_debug): $(sim_common_files) $(output_dir)
70 | rm -rf $(model_dir_debug)
71 | $(VCS) $(VCS_OPTS) -o $@ -Mdir=$(model_dir_debug) \
72 | +define+DEBUG -debug_access+all -kdb -lca
73 | cp $(sim_prefix)-$(long_name)-debug $(output_dir) && rm -rf $(sim_prefix)-$(long_name)-debug
74 | cp -r $(sim_prefix)-$(long_name)-debug.daidir $(output_dir) && rm -rf $(sim_prefix)-$(long_name)-debug.daidir
75 |
76 | run: $(sim)
77 | cd $(output_dir) && ./$(sim_prefix)-$(long_name)
78 |
79 | rundebug: $(sim_debug)
80 | cd $(output_dir) && ./$(sim_prefix)-$(long_name)-debug
81 |
82 | wave: $(sim_common_files)
83 | cd $(output_dir) && ./$(sim_prefix)-$(long_name)-debug && verdi +v2k -sv -f $(sim_common_files) -nologo -ssf $(TB).fsdb
84 |
85 | #########################################################################################
86 | # general cleanup rules
87 | #########################################################################################
88 | .PHONY: clean clean-sim clean-sim-debug
89 |
90 | clean:
91 | rm -rf $(gen_dir) $(sim_prefix)-* output ucli.key verdi_config_file
92 |
93 | clean-sim:
94 | rm -rf $(model_dir) $(build_dir)/vc_hdrs.h $(sim) $(sim).daidir output ucli.key
95 |
96 | clean-sim-debug:
97 | rm -rf $(model_dir_debug) $(build_dir)/vc_hdrs.h $(sim_debug) $(sim_debug).daidir output ucli.key
98 |
--------------------------------------------------------------------------------
/rtl/sim/vcs/vcs.mk:
--------------------------------------------------------------------------------
1 |
2 | ifndef USE_VPD
3 | get_waveform_flag=+fsdbfile=$(1).fsdb
4 | else
5 | get_waveform_flag=+vcdplusfile=$(1).vpd
6 | endif
7 |
8 | CLOCK_PERIOD ?= 1.0
9 | RESET_DELAY ?= 777.7
10 |
11 | PLATFORM := linux64
12 | NOVAS_PATH := ${NOVAS_HOME}/share/PLI/VCS/$(PLATFORM)
13 |
14 | #----------------------------------------------------------------------------------------
15 | # gcc configuration/optimization
16 | #----------------------------------------------------------------------------------------
17 | include $(base_dir)/sim/common-sim-flags.mk
18 |
19 | VCS_CXXFLAGS = $(SIM_CXXFLAGS)
20 |
21 | VCS_CC_OPTS = \
22 | -CFLAGS "$(VCS_CXXFLAGS)"
23 |
24 | VCS_NONCC_OPTS = \
25 | -notice \
26 | -line \
27 | +lint=all,noVCDE,noONGS,noUI \
28 | -error=PCWM-L \
29 | -error=noZMMCM \
30 | -timescale=1ns/10ps \
31 | -quiet \
32 | -q \
33 | +rad \
34 | +vcs+lic+wait \
35 | +vc+list \
36 | -f $(sim_common_files) \
37 | -sverilog +systemverilogext+.sv+.svi+.svh+.svt -assert svaext +libext+.sv \
38 | +v2k +verilog2001ext+.v95+.vt+.vp +libext+.v \
39 | -debug_pp \
40 | -top $(TB) \
41 | +incdir+$(base_dir)/src/include
42 | # -P $(NOVAS_PATH)/novas.tab $(NOVAS_PATH)/pli.a \
43 |
44 |
45 | VCS_PREPROC_DEFINES = \
46 | +define+VCS
47 |
48 | ifndef USE_VPD
49 | VCS_PREPROC_DEFINES += +define+FSDB
50 | endif
51 |
52 |
53 | ## For TSMC28 SRAM verilog Model
54 | VCS_PREPROC_DEFINES += +define+UNIT_DELAY
55 | VCS_PREPROC_DEFINES += +define+no_warning
56 | VCS_PREPROC_DEFINES += +define+TSMC_INITIALIZE_MEM
57 |
--------------------------------------------------------------------------------
/rtl/sim/verilator/Makefile:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/rtl/sim/verilator/Makefile
--------------------------------------------------------------------------------
/rtl/sim/xcelium/.gitignore:
--------------------------------------------------------------------------------
1 | *.*
2 | *
3 | !*/
4 | !.gitignore
5 | !*.md
6 | !*.[cSh]
7 | !*.v
8 | !*.py
9 | !*.cc
10 | !*.cpp
11 | !Makefile
12 | !*.mk
13 | !*.txt
14 | /generated-src/**
15 | /output/**
16 |
--------------------------------------------------------------------------------
/rtl/sim/xcelium/Makefile:
--------------------------------------------------------------------------------
1 | ## Refer to Chipyard
2 |
3 | ## by BriMon
4 | ## Email: zzybr@qq.com
5 | ##
6 | ## make simx MODEL_NAME=
7 | ## make run MODEL_NAME=
8 | ## make debug MODEL_NAME=
9 | ## make rundebug MODEL_NAME=
10 | ## make wave
11 | ## make clean
12 | ##
13 |
14 | help:
15 | @echo " - make simx MODEL_NAME="
16 | @echo " - make debug MODEL_NAME="
17 | @echo " - make indago MODEL_NAME="
18 | @echo " - make vdebug MODEL_NAME="
19 |
20 |
21 | #########################################################################################
22 | # xcelium makefile
23 | #########################################################################################
24 | # rtl
25 | base_dir=$(abspath ../..)
26 | # rtl/sim/vcs
27 | sim_dir=$(abspath .)
28 |
29 | sim_name = xrun
30 |
31 | #########################################################################################
32 | # xcelium simulator types and rules
33 | #########################################################################################
34 | sim_prefix = simx
35 | sim_workdir = $(build_dir)/xcelium.d
36 | sim_run_tcl = $(build_dir)/xcelium_run.tcl
37 | sim_debug_run_tcl = $(build_dir)/xcelium_debug_run.tcl
38 |
39 | sim = $(sim_dir)/$(sim_prefix)-$(long_name)
40 | sim_debug = $(sim_dir)/$(sim_prefix)-$(long_name)-debug
41 |
42 | include $(sim_dir)/xcelium.mk
43 |
44 | .PHONY: simx debug
45 | simx: $(sim)
46 | debug: $(sim_debug)
47 |
48 |
49 | #########################################################################################
50 | # xcelium binary and arguments
51 | #########################################################################################
52 | XCELIUM = xrun
53 | XCELIUM_OPTS = $(XCELIUM_CC_OPTS) $(XCELIUM_NONCC_OPTS) $(PREPROC_DEFINES)
54 |
55 | #########################################################################################
56 | # xcelium build paths
57 | #########################################################################################
58 | model_dir = $(build_dir)/$(long_name)
59 | model_dir_debug = $(build_dir)/$(long_name).debug
60 |
61 | #########################################################################################
62 | # xcelium simulator rules
63 | #########################################################################################
64 |
65 | $(sim_workdir): $(sim_common_files) $(output_dir)
66 | rm -rf $(model_dir)
67 | $(XCELIUM) -elaborate $(XCELIUM_OPTS) $(XCELIUM_COMMON_ARGS)
68 |
69 | $(sim_run_tcl): $(sim_workdir)
70 | echo "run" >> $@
71 | echo "exit" >> $@
72 |
73 | $(sim): $(sim_workdir) $(sim_run_tcl)
74 | echo "#!/usr/bin/env bash" > $@
75 | echo "$(XCELIUM) +permissive -R -input $(sim_run_tcl) $(XCELIUM_COMMON_ARGS) +permissive-off \$$INPUT_ARGS" >> $@
76 | chmod +x $@
77 | cp $(sim_prefix)-$(long_name) $(output_dir) && rm -rf $(sim_prefix)-$(long_name)
78 | cd $(output_dir) && ./$(sim_prefix)-$(long_name)
79 |
80 |
81 | $(sim_debug_run_tcl): $(sim_workdir)
82 | echo "ida_database -open -name=\"ida.db\"" >> $@
83 | echo "ida_probe -log -sv_flow -uvm_reg -log_objects -sv_modules -wave -wave_probe_args= \"tb -depth all -all -memories -variables -packed 10000000 -unpacked 10000000 -dynamic\" -wave_glitch_recording" >> $@
84 | echo "run" >> $@
85 | echo "exit" >> $@
86 |
87 | $(sim_debug): $(sim_workdir) $(sim_debug_run_tcl)
88 | echo "#!/usr/bin/env bash" > $@
89 | echo "$(XCELIUM) +permissive -R -input $(sim_debug_run_tcl) $(XCELIUM_COMMON_ARGS) +permissive-off \$$INPUT_ARGS" >> $@
90 | chmod +x $@
91 | cp $(sim_prefix)-$(long_name)-debug $(output_dir) && rm -rf $(sim_prefix)-$(long_name)-debug
92 | cd $(output_dir) && ./$(sim_prefix)-$(long_name)-debug
93 |
94 | indago:
95 | cd $(output_dir) && indago
96 |
97 | vdebug:
98 | cd $(output_dir) && verisium_debug
99 |
100 | #########################################################################################
101 | # create vcd rules
102 | #########################################################################################
103 | .PRECIOUS: $(output_dir)/%.vcd %.vcd
104 | $(output_dir)/%.vcd: $(output_dir)/% $(sim_debug)
105 | (set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) +vcdplusfile=$@ $(PERMISSIVE_OFF) $< >(spike-dasm > $<.out) | tee $<.log)
106 |
107 | #########################################################################################
108 | # general cleanup rules
109 | #########################################################################################
110 | .PHONY: clean clean-sim clean-sim-debug
111 | clean:
112 | rm -rf $(CLASSPATH_CACHE) output $(gen_dir) $(sim_prefix)-*
113 |
114 | clean-sim:
115 | rm -rf $(model_dir) $(sim) $(sim_workdir) $(sim_run_tcl) ucli.key bpad_*.err sigusrdump.out dramsim*.log
116 |
117 | clean-sim-debug:
118 | rm -rf $(model_dir_debug) $(sim_debug) $(sim_workdir) $(sim_debug_run_tcl) ucli.key bpad_*.err sigusrdump.out dramsim*.log
119 |
--------------------------------------------------------------------------------
/rtl/sim/xcelium/xcelium.mk:
--------------------------------------------------------------------------------
1 | ## Refer to Chipyard
2 |
3 | # If ntb_random_seed unspecified, xcelium uses 1 as constant seed.
4 | # Set ntb_random_seed_automatic to actually get a random seed
5 | ifdef RANDOM_SEED
6 | SEED_FLAG=+ntb_random_seed=$(RANDOM_SEED)
7 | else
8 | SEED_FLAG=+ntb_random_seed_automatic
9 | endif
10 |
11 | CLOCK_PERIOD ?= 1.0
12 | RESET_DELAY ?= 777.7
13 |
14 | #----------------------------------------------------------------------------------------
15 | # gcc configuration/optimization
16 | #----------------------------------------------------------------------------------------
17 | include $(base_dir)/sim/common-sim-flags.mk
18 |
19 |
20 | XC_CXX_PREFIX=-Wcxx,
21 | XC_LD_PREFIX=-Wld,
22 |
23 | REMOVE_RPATH=-Wl,-rpath%
24 |
25 | XCELIUM_CXXFLAGS = $(addprefix $(XC_CXX_PREFIX), $(SIM_CXXFLAGS))
26 | XCELIUM_LDFLAGS = $(addprefix $(XC_LD_PREFIX), $(filter-out $(REMOVE_RPATH), $(SIM_LDFLAGS)))
27 |
28 | XCELIUM_COMMON_ARGS = \
29 | -64bit \
30 | -xmlibdirname $(sim_workdir) \
31 | -l /dev/null \
32 | -log_xmsc_run /dev/null
33 |
34 | XCELIUM_CC_OPTS = \
35 | $(XCELIUM_CXXFLAGS) \
36 | $(XCELIUM_LDFLAGS) \
37 | -enable_rpath
38 |
39 | XCELIUM_NONCC_OPTS = \
40 | -fast_recompilation \
41 | -top $(TB) \
42 | -sv \
43 | -ALLOWREDEFINITION \
44 | -timescale 1ns/10ps \
45 | -define INTCNOPWR \
46 | -define INTC_NO_PWR_PINS \
47 | -define INTC_EMULATION \
48 | -f $(sim_common_files) \
49 | -glsperf \
50 | -notimingchecks \
51 | -delay_mode zero
52 |
53 | PREPROC_DEFINES = \
54 | -define XCELIUM \
55 | -define CLOCK_PERIOD=$(CLOCK_PERIOD) \
56 | -define RESET_DELAY=$(RESET_DELAY) \
57 | -define PRINTF_COND=$(TB).printf_cond \
58 | -define STOP_COND=!$(TB).reset \
59 | -define MODEL=$(MODEL) \
60 | -define RANDOMIZE_MEM_INIT \
61 | -define RANDOMIZE_REG_INIT \
62 | -define RANDOMIZE_GARBAGE_ASSIGN \
63 | -define RANDOMIZE_INVALID_ASSIGN
64 |
65 |
66 | PREPROC_DEFINES += +define+FSDB
67 |
68 |
--------------------------------------------------------------------------------
/rtl/src/bf_rdx2.v:
--------------------------------------------------------------------------------
1 | // Author: brimonzzy
2 | // Create Date: 2025/2/13
3 | // Description: Gentleman-Sande algorithm Radix-2 Butterfly unit
4 | // module bf_rdx2 and module bf_rdx2_noW
5 |
6 | module bf_rdx2 (
7 | input signed [15:0] x0_re,
8 | input signed [15:0] x0_im,
9 | input signed [15:0] x1_re,
10 | input signed [15:0] x1_im,
11 | input signed [15:0] w_re,
12 | input signed [15:0] w_im,
13 | output signed [15:0] y0_re,
14 | output signed [15:0] y0_im,
15 | output signed [15:0] y1_re,
16 | output signed [15:0] y1_im
17 | );
18 |
19 | wire [15:0] add1_re, add1_im, sub2_re, sub2_im, mul2_re, mul2_im;
20 |
21 | complex_add add1_u (
22 | .x0_re(x0_re),
23 | .x0_im(x0_im),
24 | .x1_re(x1_re),
25 | .x1_im(x1_im),
26 | .res_re(add1_re),
27 | .res_im(add1_im)
28 | );
29 |
30 | complex_sub sub2_u (
31 | .x0_re(x0_re),
32 | .x0_im(x0_im),
33 | .x1_re(x1_re),
34 | .x1_im(x1_im),
35 | .res_re(sub2_re),
36 | .res_im(sub2_im)
37 | );
38 |
39 | complex_mult mul2_u (
40 | .x0_re(sub2_re),
41 | .x0_im(sub2_im),
42 | .x1_re(w_re),
43 | .x1_im(w_im),
44 | .res_re(mul2_re),
45 | .res_im(mul2_im)
46 | );
47 |
48 | assign y0_re = add1_re;
49 | assign y0_im = add1_im;
50 | assign y1_re = mul2_re;
51 | assign y1_im = mul2_im;
52 |
53 | endmodule
54 |
55 |
56 | module bf_rdx2_noW (
57 | input signed [15:0] x0_re,
58 | input signed [15:0] x0_im,
59 | input signed [15:0] x1_re,
60 | input signed [15:0] x1_im,
61 | output signed [15:0] y0_re,
62 | output signed [15:0] y0_im,
63 | output signed [15:0] y1_re,
64 | output signed [15:0] y1_im
65 | );
66 |
67 | wire [15:0] add1_re, add1_im, sub2_re, sub2_im;
68 |
69 | complex_add add1_u (
70 | .x0_re(x0_re),
71 | .x0_im(x0_im),
72 | .x1_re(x1_re),
73 | .x1_im(x1_im),
74 | .res_re(add1_re),
75 | .res_im(add1_im)
76 | );
77 |
78 | complex_sub sub2_u (
79 | .x0_re(x0_re),
80 | .x0_im(x0_im),
81 | .x1_re(x1_re),
82 | .x1_im(x1_im),
83 | .res_re(sub2_re),
84 | .res_im(sub2_im)
85 | );
86 |
87 | assign y0_re = add1_re;
88 | assign y0_im = add1_im;
89 | assign y1_re = sub2_re;
90 | assign y1_im = sub2_im;
91 |
92 | endmodule
93 |
--------------------------------------------------------------------------------
/rtl/src/complex_mult.v:
--------------------------------------------------------------------------------
1 | // Author: brimonzzy
2 | // Create Date: 2025/2/13
3 | // Description: Complex multiplier
4 | // Complex Adder
5 | // Complex Subtractor
6 |
7 | module complex_mult #(
8 | parameter useGauss = 0
9 | )(
10 | input signed [15:0] x0_re,
11 | input signed [15:0] x0_im,
12 | input signed [15:0] x1_re,
13 | input signed [15:0] x1_im,
14 | output signed [15:0] res_re,
15 | output signed [15:0] res_im
16 | );
17 |
18 | function signed [15:0] saturate(input signed [18:0] value);
19 | begin
20 | if (value > 32767) saturate = 16'h7FFF;
21 | else if (value < -32768) saturate = 16'h8000;
22 | else saturate = value[15:0];
23 | end
24 | endfunction
25 |
26 | generate
27 | if(useGauss) begin
28 | // k1 = x1_re * (x0_re + x0_im);
29 | // k2 = x0_re * (x1_im - x1_re);
30 | // k3 = x0_im * (x1_re + x1_im);
31 | // res_re = k1 - k3;
32 | // res_im = k1 + k2;
33 | // Intermediate sums and differences (17-bit to handle overflow)
34 | wire signed [16:0] sum_x0 = x0_re + x0_im;
35 | wire signed [16:0] diff_x0 = x0_re - x0_im;
36 | wire signed [16:0] sum_x1 = x1_re + x1_im;
37 | wire signed [16:0] diff_x1 = x1_re - x1_im;
38 |
39 | // Extend to 32 bits for multiplication
40 | wire signed [31:0] k1 = sum_x0 * x1_re; // Q15 * Q15 = Q30
41 | wire signed [31:0] k2 = diff_x0 * x1_im; // Q15 * Q15 = Q30
42 | wire signed [31:0] k3 = x0_im * sum_x1; // Q15 * Q15 = Q30
43 |
44 | // Adjust back to Q15 format
45 | assign res_re = (k1 - k3) >>> 15;
46 | assign res_im = (k1 + k2) >>> 15;
47 |
48 | end else begin
49 | // res_re = x0_re * x1_re - x0_im * x1_im;
50 | // res_im = x0_re * x1_im + x0_im * x1_re;
51 | // Multiply components (results are in Q30 format)
52 | wire signed [31:0] mul_re_re = x0_re * x1_re;
53 | wire signed [31:0] mul_im_im = x0_im * x1_im;
54 | wire signed [31:0] mul_re_im = x0_re * x1_im;
55 | wire signed [31:0] mul_im_re = x0_im * x1_re;
56 |
57 | wire signed [32:0] sub_re = {mul_re_re[31], mul_re_re} - {mul_im_im[31], mul_im_im};
58 | wire signed [32:0] add_im = {mul_re_im[31], mul_re_im} + {mul_im_re[31], mul_im_re};
59 |
60 | // Adjust back to Q15 format
61 | assign res_re = saturate(sub_re >>> 15);
62 | assign res_im = saturate(add_im >>> 15);
63 |
64 | end
65 | endgenerate
66 |
67 | endmodule
68 |
69 | module complex_add (
70 | input signed [15:0] x0_re,
71 | input signed [15:0] x0_im,
72 | input signed [15:0] x1_re,
73 | input signed [15:0] x1_im,
74 | output signed [15:0] res_re,
75 | output signed [15:0] res_im
76 | );
77 |
78 | assign res_re = x0_re + x1_re;
79 | assign res_im = x0_im + x1_im;
80 |
81 | endmodule
82 |
83 | module complex_sub (
84 | input signed [15:0] x0_re,
85 | input signed [15:0] x0_im,
86 | input signed [15:0] x1_re,
87 | input signed [15:0] x1_im,
88 | output signed [15:0] res_re,
89 | output signed [15:0] res_im
90 | );
91 |
92 | assign res_re = x0_re - x1_re;
93 | assign res_im = x0_im - x1_im;
94 |
95 | endmodule
96 |
97 |
--------------------------------------------------------------------------------
/rtl/src/fft16.v:
--------------------------------------------------------------------------------
1 | // 16-points R2MDC DIF-FFT
2 |
3 | module fft16 (
4 | input clk,
5 | input rst_n,
6 | input stb, // Input data valid (active high)
7 | input sop_in, // The first valid data in the input stream
8 | input [15:0] x_re, // Input real part
9 | input [15:0] x_im, // Input imaginary part
10 | output valid_out, // Output data valid (active high)
11 | output sop_out, // The first valid data in the output stream
12 | output [15:0] y_re, // Output real part
13 | output [15:0] y_im // Output imaginary part
14 | );
15 |
16 | wire [15:0] bf_0_x0_re;
17 | wire [15:0] bf_0_x0_im;
18 | wire [15:0] bf_0_x1_re;
19 | wire [15:0] bf_0_x1_im;
20 | wire [15:0] bf_0_w_re;
21 | wire [15:0] bf_0_w_im;
22 | wire [15:0] bf_0_y0_re;
23 | wire [15:0] bf_0_y0_im;
24 | wire [15:0] bf_0_y1_re;
25 | wire [15:0] bf_0_y1_im;
26 | wire switch_0_sel;
27 | wire [15:0] switch_0_x0_re;
28 | wire [15:0] switch_0_x0_im;
29 | wire [15:0] switch_0_x1_re;
30 | wire [15:0] switch_0_x1_im;
31 | wire [15:0] switch_0_y0_re;
32 | wire [15:0] switch_0_y0_im;
33 | wire [15:0] switch_0_y1_re;
34 | wire [15:0] switch_0_y1_im;
35 | wire [15:0] bf_1_x0_re;
36 | wire [15:0] bf_1_x0_im;
37 | wire [15:0] bf_1_x1_re;
38 | wire [15:0] bf_1_x1_im;
39 | wire [15:0] bf_1_w_re;
40 | wire [15:0] bf_1_w_im;
41 | wire [15:0] bf_1_y0_re;
42 | wire [15:0] bf_1_y0_im;
43 | wire [15:0] bf_1_y1_re;
44 | wire [15:0] bf_1_y1_im;
45 | wire switch_1_sel;
46 | wire [15:0] switch_1_x0_re;
47 | wire [15:0] switch_1_x0_im;
48 | wire [15:0] switch_1_x1_re;
49 | wire [15:0] switch_1_x1_im;
50 | wire [15:0] switch_1_y0_re;
51 | wire [15:0] switch_1_y0_im;
52 | wire [15:0] switch_1_y1_re;
53 | wire [15:0] switch_1_y1_im;
54 | wire [15:0] bf_2_x0_re;
55 | wire [15:0] bf_2_x0_im;
56 | wire [15:0] bf_2_x1_re;
57 | wire [15:0] bf_2_x1_im;
58 | wire [15:0] bf_2_w_re;
59 | wire [15:0] bf_2_w_im;
60 | wire [15:0] bf_2_y0_re;
61 | wire [15:0] bf_2_y0_im;
62 | wire [15:0] bf_2_y1_re;
63 | wire [15:0] bf_2_y1_im;
64 | wire switch_2_sel;
65 | wire [15:0] switch_2_x0_re;
66 | wire [15:0] switch_2_x0_im;
67 | wire [15:0] switch_2_x1_re;
68 | wire [15:0] switch_2_x1_im;
69 | wire [15:0] switch_2_y0_re;
70 | wire [15:0] switch_2_y0_im;
71 | wire [15:0] switch_2_y1_re;
72 | wire [15:0] switch_2_y1_im;
73 | wire [15:0] bf_3_x0_re;
74 | wire [15:0] bf_3_x0_im;
75 | wire [15:0] bf_3_x1_re;
76 | wire [15:0] bf_3_x1_im;
77 | wire [15:0] bf_3_y0_re;
78 | wire [15:0] bf_3_y0_im;
79 | wire [15:0] bf_3_y1_re;
80 | wire [15:0] bf_3_y1_im;
81 |
82 | wire busy;
83 | reg [15:0] cnt; // wide:stage+1
84 |
85 | assign busy = cnt != 10'd0;
86 | always @(posedge clk or negedge rst_n) begin
87 | if(!rst_n) begin
88 | cnt <= 10'd0;
89 | end
90 | else if(sop_in)
91 | cnt <= 10'd1;
92 | else begin
93 | if(stb || busy) begin
94 | if(cnt == 10'd23) // TODO: cnt==FFTlen * 3 / 2 - 1
95 | cnt <= 10'd0;
96 | else
97 | cnt <= cnt + 1'b1;
98 | end
99 | end
100 | end
101 |
102 |
103 | bf_rdx2 bf_0 (
104 | .x0_re(bf_0_x0_re),
105 | .x0_im(bf_0_x0_im),
106 | .x1_re(bf_0_x1_re),
107 | .x1_im(bf_0_x1_im),
108 | .w_re(bf_0_w_re),
109 | .w_im(bf_0_w_im),
110 | .y0_re(bf_0_y0_re),
111 | .y0_im(bf_0_y0_im),
112 | .y1_re(bf_0_y1_re),
113 | .y1_im(bf_0_y1_im)
114 | );
115 | switch switch_0 (
116 | .sel(switch_0_sel),
117 | .x0_re(switch_0_x0_re),
118 | .x0_im(switch_0_x0_im),
119 | .x1_re(switch_0_x1_re),
120 | .x1_im(switch_0_x1_im),
121 | .y0_re(switch_0_y0_re),
122 | .y0_im(switch_0_y0_im),
123 | .y1_re(switch_0_y1_re),
124 | .y1_im(switch_0_y1_im)
125 | );
126 | bf_rdx2 bf_1 (
127 | .x0_re(bf_1_x0_re),
128 | .x0_im(bf_1_x0_im),
129 | .x1_re(bf_1_x1_re),
130 | .x1_im(bf_1_x1_im),
131 | .w_re(bf_1_w_re),
132 | .w_im(bf_1_w_im),
133 | .y0_re(bf_1_y0_re),
134 | .y0_im(bf_1_y0_im),
135 | .y1_re(bf_1_y1_re),
136 | .y1_im(bf_1_y1_im)
137 | );
138 | switch switch_1 (
139 | .sel(switch_1_sel),
140 | .x0_re(switch_1_x0_re),
141 | .x0_im(switch_1_x0_im),
142 | .x1_re(switch_1_x1_re),
143 | .x1_im(switch_1_x1_im),
144 | .y0_re(switch_1_y0_re),
145 | .y0_im(switch_1_y0_im),
146 | .y1_re(switch_1_y1_re),
147 | .y1_im(switch_1_y1_im)
148 | );
149 | bf_rdx2 bf_2 (
150 | .x0_re(bf_2_x0_re),
151 | .x0_im(bf_2_x0_im),
152 | .x1_re(bf_2_x1_re),
153 | .x1_im(bf_2_x1_im),
154 | .w_re(bf_2_w_re),
155 | .w_im(bf_2_w_im),
156 | .y0_re(bf_2_y0_re),
157 | .y0_im(bf_2_y0_im),
158 | .y1_re(bf_2_y1_re),
159 | .y1_im(bf_2_y1_im)
160 | );
161 | switch switch_2 (
162 | .sel(switch_2_sel),
163 | .x0_re(switch_2_x0_re),
164 | .x0_im(switch_2_x0_im),
165 | .x1_re(switch_2_x1_re),
166 | .x1_im(switch_2_x1_im),
167 | .y0_re(switch_2_y0_re),
168 | .y0_im(switch_2_y0_im),
169 | .y1_re(switch_2_y1_re),
170 | .y1_im(switch_2_y1_im)
171 | );
172 | bf_rdx2_noW bf_noW_1 (
173 | .x0_re(bf_3_x0_re),
174 | .x0_im(bf_3_x0_im),
175 | .x1_re(bf_3_x1_re),
176 | .x1_im(bf_3_x1_im),
177 | .y0_re(bf_3_y0_re),
178 | .y0_im(bf_3_y0_im),
179 | .y1_re(bf_3_y1_re),
180 | .y1_im(bf_3_y1_im)
181 | );
182 |
183 | twiddle_rom twiddle_rom_0 (
184 | .addr0(cnt[4-2-0:0]), // TODO: stage-2-i
185 | .addr1({cnt[4-2-1:0], 1'b0}),
186 | .addr2({cnt[4-2-2:0], 2'b0}),
187 | .data0_re(bf_0_w_re),
188 | .data0_im(bf_0_w_im),
189 | .data1_re(bf_1_w_re),
190 | .data1_im(bf_1_w_im),
191 | .data2_re(bf_2_w_re),
192 | .data2_im(bf_2_w_im)
193 | );
194 |
195 | assign bf_0_x1_re = x_re;
196 | assign bf_0_x1_im = x_im;
197 | assign switch_0_x0_re = bf_0_y0_re;
198 | assign switch_0_x0_im = bf_0_y0_im;
199 | assign switch_0_sel = cnt[4-2-0]; // TODO: stage-2-i
200 | assign bf_1_x1_re = switch_0_y1_re;
201 | assign bf_1_x1_im = switch_0_y1_im;
202 | assign switch_1_x0_re = bf_1_y0_re;
203 | assign switch_1_x0_im = bf_1_y0_im;
204 | assign switch_1_sel = cnt[4-2-1];
205 | assign bf_2_x1_re = switch_1_y1_re;
206 | assign bf_2_x1_im = switch_1_y1_im;
207 | assign switch_2_x0_re = bf_2_y0_re;
208 | assign switch_2_x0_im = bf_2_y0_im;
209 | assign switch_2_sel = cnt[4-2-2];
210 | assign bf_3_x1_re = switch_2_y1_re;
211 | assign bf_3_x1_im = switch_2_y1_im;
212 |
213 | shiftreg #(16, 8) shiftreg_0 (
214 | .clk(clk),
215 | .rst_n(rst_n),
216 | .d_in(x_re),
217 | .d_out(bf_0_x0_re)
218 | );
219 | shiftreg #(16, 8) shiftreg_1 (
220 | .clk(clk),
221 | .rst_n(rst_n),
222 | .d_in(x_im),
223 | .d_out(bf_0_x0_im)
224 | );
225 |
226 | shiftreg #(16, 4) shiftreg_2 (
227 | .clk(clk),
228 | .rst_n(rst_n),
229 | .d_in(bf_0_y1_re),
230 | .d_out(switch_0_x1_re)
231 | );
232 | shiftreg #(16, 4) shiftreg_3 (
233 | .clk(clk),
234 | .rst_n(rst_n),
235 | .d_in(bf_0_y1_im),
236 | .d_out(switch_0_x1_im)
237 | );
238 |
239 | shiftreg #(16, 4) shiftreg_4 (
240 | .clk(clk),
241 | .rst_n(rst_n),
242 | .d_in(switch_0_y0_re),
243 | .d_out(bf_1_x0_re)
244 | );
245 | shiftreg #(16, 4) shiftreg_5 (
246 | .clk(clk),
247 | .rst_n(rst_n),
248 | .d_in(switch_0_y0_im),
249 | .d_out(bf_1_x0_im)
250 | );
251 |
252 | shiftreg #(16, 2) shiftreg_6 (
253 | .clk(clk),
254 | .rst_n(rst_n),
255 | .d_in(bf_1_y1_re),
256 | .d_out(switch_1_x1_re)
257 | );
258 | shiftreg #(16, 2) shiftreg_7 (
259 | .clk(clk),
260 | .rst_n(rst_n),
261 | .d_in(bf_1_y1_im),
262 | .d_out(switch_1_x1_im)
263 | );
264 |
265 | shiftreg #(16, 2) shiftreg_8 (
266 | .clk(clk),
267 | .rst_n(rst_n),
268 | .d_in(switch_1_y0_re),
269 | .d_out(bf_2_x0_re)
270 | );
271 | shiftreg #(16, 2) shiftreg_9 (
272 | .clk(clk),
273 | .rst_n(rst_n),
274 | .d_in(switch_1_y0_im),
275 | .d_out(bf_2_x0_im)
276 | );
277 |
278 | shiftreg #(16, 1) shiftreg_10 (
279 | .clk(clk),
280 | .rst_n(rst_n),
281 | .d_in(bf_2_y1_re),
282 | .d_out(switch_2_x1_re)
283 | );
284 | shiftreg #(16, 1) shiftreg_11 (
285 | .clk(clk),
286 | .rst_n(rst_n),
287 | .d_in(bf_2_y1_im),
288 | .d_out(switch_2_x1_im)
289 | );
290 |
291 | shiftreg #(16, 1) shiftreg_12 (
292 | .clk(clk),
293 | .rst_n(rst_n),
294 | .d_in(switch_2_y0_re),
295 | .d_out(bf_3_x0_re)
296 | );
297 | shiftreg #(16, 1) shiftreg_13 (
298 | .clk(clk),
299 | .rst_n(rst_n),
300 | .d_in(switch_2_y0_im),
301 | .d_out(bf_3_x0_im)
302 | );
303 |
304 | wire fft_out_valid = cnt >= 16'd15 && cnt < 16'd23; // TODO: FFTlen-1 cnt==FFTlen * 3 / 2 - 1
305 |
306 | reorder #(16, 16) reorder_0 (
307 | .clk(clk),
308 | .rst_n(rst_n),
309 | .in1_re(bf_3_y0_re),
310 | .in1_im(bf_3_y0_im),
311 | .in2_re(bf_3_y1_re),
312 | .in2_im(bf_3_y1_im),
313 | .in_valid(fft_out_valid),
314 | .out_re(y_re),
315 | .out_im(y_im),
316 | .out_valid(valid_out)
317 | );
318 |
319 | assign sop_out = cnt == 16'd23; // TODO: cnt==FFTlen * 3 / 2 - 1
320 |
321 | endmodule
322 |
--------------------------------------------------------------------------------
/rtl/src/fft_multimode.v:
--------------------------------------------------------------------------------
1 | // Author: brimonzzy
2 | // Create Date: 2025/2/13
3 | // Description: Multi-mode FFT accelerator top module
4 |
5 | module fft_multimode (
6 | input clk,
7 | input rst_n,
8 | input inv, // 0: fft, 1: ifft
9 | input [1:0] np, // FFT/IFFT point number 0:64, 1:128, 2:256, 3:512
10 | input stb, // Input data valid (active high)
11 | input sop_in, // The first valid data in the input stream
12 | input [15:0] x_re, // Input real part
13 | input [15:0] x_im, // Input imaginary part
14 | output valid_out, // Output data valid (active high)
15 | output reg sop_out, // The first valid data in the output stream
16 | output [15:0] y_re, // Output real part
17 | output [15:0] y_im // Output imaginary part
18 | );
19 |
20 | parameter N = 512;
21 | parameter stage = $clog2(N);
22 |
23 | reg [9:0] point;
24 | reg [3:0] log2point;
25 | always @(*) begin
26 | case(np)
27 | 2'b00: begin point = 10'd64; log2point = 4'd6; end
28 | 2'b01: begin point = 10'd128; log2point = 4'd7; end
29 | 2'b10: begin point = 10'd256; log2point = 4'd8; end
30 | 2'b11: begin point = 10'd512; log2point = 4'd9; end
31 | endcase
32 | end
33 |
34 | wire [15:0] bf_x0_re [0:stage-2];
35 | wire [15:0] bf_x0_im [0:stage-2];
36 | wire [15:0] bf_x1_re [0:stage-2];
37 | wire [15:0] bf_x1_im [0:stage-2];
38 | wire [15:0] bf_w_re [0:stage-2];
39 | wire [15:0] bf_w_im [0:stage-2];
40 | wire [15:0] bf_y0_re [0:stage-2];
41 | wire [15:0] bf_y0_im [0:stage-2];
42 | wire [15:0] bf_y1_re [0:stage-2];
43 | wire [15:0] bf_y1_im [0:stage-2];
44 | wire [15:0] switch_x0_re [0:stage-2];
45 | wire [15:0] switch_x0_im [0:stage-2];
46 | wire [15:0] switch_x1_re [0:stage-2];
47 | wire [15:0] switch_x1_im [0:stage-2];
48 | wire [15:0] switch_y0_re [0:stage-2];
49 | wire [15:0] switch_y0_im [0:stage-2];
50 | wire [15:0] switch_y1_re [0:stage-2];
51 | wire [15:0] switch_y1_im [0:stage-2];
52 | wire switch_sel [0:stage-2];
53 | wire [15:0] bf_noW_x0_re;
54 | wire [15:0] bf_noW_x0_im;
55 | wire [15:0] bf_noW_x1_re;
56 | wire [15:0] bf_noW_x1_im;
57 | wire [15:0] bf_noW_y0_re;
58 | wire [15:0] bf_noW_y0_im;
59 | wire [15:0] bf_noW_y1_re;
60 | wire [15:0] bf_noW_y1_im;
61 |
62 | wire busy;
63 | reg [$clog2(N):0] cnt; // wide:stage+1
64 |
65 | assign busy = cnt != 10'd0;
66 | always @(posedge clk or negedge rst_n) begin
67 | if(!rst_n) begin
68 | cnt <= {($clog2(N)+1){1'b0}};
69 | end
70 | else if(sop_in)
71 | cnt <= 1;
72 | else begin
73 | if(stb || busy) begin
74 | if(cnt == (point*3/2-1)) // cnt==FFTlen * 3 / 2 - 1
75 | cnt <= {($clog2(N)+1){1'b0}};
76 | else
77 | cnt <= cnt + 1'b1;
78 | end
79 | end
80 | end
81 |
82 | genvar i;
83 | generate
84 | for(i=0; i= (point-1) && cnt < (point*3/2-1); // FFTlen-1 cnt==FFTlen * 3 / 2 - 1
318 |
319 | wire [15:0] reorder_out_re, reorder_out_im;
320 | reorder #(16, N) output_reorder_u (
321 | .clk(clk),
322 | .rst_n(rst_n),
323 | .in1_re(bf_noW_y0_re),
324 | .in1_im(bf_noW_y0_im),
325 | .in2_re(bf_noW_y1_re),
326 | .in2_im(bf_noW_y1_im),
327 | .in_valid(fft_out_valid),
328 | .np(np),
329 | .out_re(reorder_out_re),
330 | .out_im(reorder_out_im),
331 | .out_valid(valid_out)
332 | );
333 | assign y_re = inv ? reorder_out_re >> log2point : reorder_out_re;
334 | assign y_im = inv ? reorder_out_im >> log2point : reorder_out_im;
335 |
336 |
337 | wire sop_out_t = cnt == (point*3/2-1);
338 | reg sop_out_t1;
339 | always @(posedge clk or negedge rst_n) begin
340 | if(!rst_n) begin
341 | sop_out_t1 <= 1'b0;
342 | sop_out <= 1'b0;
343 | end
344 | else begin
345 | sop_out_t1 <= sop_out_t;
346 | sop_out <= sop_out_t1;
347 | end
348 | end
349 |
350 | endmodule
351 |
--------------------------------------------------------------------------------
/rtl/src/ifft_twiddle_rom.v:
--------------------------------------------------------------------------------
1 | // For 512-point IFFT
2 | // 8 read ports
3 |
4 | module ifft_twiddle_rom (
5 | input [7:0] addr0,
6 | input [7:0] addr1,
7 | input [7:0] addr2,
8 | input [7:0] addr3,
9 | input [7:0] addr4,
10 | input [7:0] addr5,
11 | input [7:0] addr6,
12 | input [7:0] addr7,
13 | output [15:0] data0_re,
14 | output [15:0] data0_im,
15 | output [15:0] data1_re,
16 | output [15:0] data1_im,
17 | output [15:0] data2_re,
18 | output [15:0] data2_im,
19 | output [15:0] data3_re,
20 | output [15:0] data3_im,
21 | output [15:0] data4_re,
22 | output [15:0] data4_im,
23 | output [15:0] data5_re,
24 | output [15:0] data5_im,
25 | output [15:0] data6_re,
26 | output [15:0] data6_im,
27 | output [15:0] data7_re,
28 | output [15:0] data7_im
29 | );
30 | // For N=512
31 | wire signed [15:0] wn_re [0:255];
32 | wire signed [15:0] wn_im [0:255];
33 |
34 | assign wn_re[0] = $signed(16'sh7FFF);
35 | assign wn_re[1] = $signed(16'sh7FFE);
36 | assign wn_re[2] = $signed(16'sh7FF6);
37 | assign wn_re[3] = $signed(16'sh7FEA);
38 | assign wn_re[4] = $signed(16'sh7FD9);
39 | assign wn_re[5] = $signed(16'sh7FC2);
40 | assign wn_re[6] = $signed(16'sh7FA7);
41 | assign wn_re[7] = $signed(16'sh7F87);
42 | assign wn_re[8] = $signed(16'sh7F62);
43 | assign wn_re[9] = $signed(16'sh7F38);
44 | assign wn_re[10] = $signed(16'sh7F0A);
45 | assign wn_re[11] = $signed(16'sh7ED6);
46 | assign wn_re[12] = $signed(16'sh7E9D);
47 | assign wn_re[13] = $signed(16'sh7E60);
48 | assign wn_re[14] = $signed(16'sh7E1E);
49 | assign wn_re[15] = $signed(16'sh7DD6);
50 | assign wn_re[16] = $signed(16'sh7D8A);
51 | assign wn_re[17] = $signed(16'sh7D3A);
52 | assign wn_re[18] = $signed(16'sh7CE4);
53 | assign wn_re[19] = $signed(16'sh7C89);
54 | assign wn_re[20] = $signed(16'sh7C2A);
55 | assign wn_re[21] = $signed(16'sh7BC6);
56 | assign wn_re[22] = $signed(16'sh7B5D);
57 | assign wn_re[23] = $signed(16'sh7AEF);
58 | assign wn_re[24] = $signed(16'sh7A7D);
59 | assign wn_re[25] = $signed(16'sh7A06);
60 | assign wn_re[26] = $signed(16'sh798A);
61 | assign wn_re[27] = $signed(16'sh790A);
62 | assign wn_re[28] = $signed(16'sh7885);
63 | assign wn_re[29] = $signed(16'sh77FB);
64 | assign wn_re[30] = $signed(16'sh776C);
65 | assign wn_re[31] = $signed(16'sh76D9);
66 | assign wn_re[32] = $signed(16'sh7642);
67 | assign wn_re[33] = $signed(16'sh75A6);
68 | assign wn_re[34] = $signed(16'sh7505);
69 | assign wn_re[35] = $signed(16'sh7460);
70 | assign wn_re[36] = $signed(16'sh73B6);
71 | assign wn_re[37] = $signed(16'sh7308);
72 | assign wn_re[38] = $signed(16'sh7255);
73 | assign wn_re[39] = $signed(16'sh719E);
74 | assign wn_re[40] = $signed(16'sh70E3);
75 | assign wn_re[41] = $signed(16'sh7023);
76 | assign wn_re[42] = $signed(16'sh6F5F);
77 | assign wn_re[43] = $signed(16'sh6E97);
78 | assign wn_re[44] = $signed(16'sh6DCA);
79 | assign wn_re[45] = $signed(16'sh6CF9);
80 | assign wn_re[46] = $signed(16'sh6C24);
81 | assign wn_re[47] = $signed(16'sh6B4B);
82 | assign wn_re[48] = $signed(16'sh6A6E);
83 | assign wn_re[49] = $signed(16'sh698C);
84 | assign wn_re[50] = $signed(16'sh68A7);
85 | assign wn_re[51] = $signed(16'sh67BD);
86 | assign wn_re[52] = $signed(16'sh66D0);
87 | assign wn_re[53] = $signed(16'sh65DE);
88 | assign wn_re[54] = $signed(16'sh64E9);
89 | assign wn_re[55] = $signed(16'sh63EF);
90 | assign wn_re[56] = $signed(16'sh62F2);
91 | assign wn_re[57] = $signed(16'sh61F1);
92 | assign wn_re[58] = $signed(16'sh60EC);
93 | assign wn_re[59] = $signed(16'sh5FE4);
94 | assign wn_re[60] = $signed(16'sh5ED7);
95 | assign wn_re[61] = $signed(16'sh5DC8);
96 | assign wn_re[62] = $signed(16'sh5CB4);
97 | assign wn_re[63] = $signed(16'sh5B9D);
98 | assign wn_re[64] = $signed(16'sh5A82);
99 | assign wn_re[65] = $signed(16'sh5964);
100 | assign wn_re[66] = $signed(16'sh5843);
101 | assign wn_re[67] = $signed(16'sh571E);
102 | assign wn_re[68] = $signed(16'sh55F6);
103 | assign wn_re[69] = $signed(16'sh54CA);
104 | assign wn_re[70] = $signed(16'sh539B);
105 | assign wn_re[71] = $signed(16'sh5269);
106 | assign wn_re[72] = $signed(16'sh5134);
107 | assign wn_re[73] = $signed(16'sh4FFB);
108 | assign wn_re[74] = $signed(16'sh4EC0);
109 | assign wn_re[75] = $signed(16'sh4D81);
110 | assign wn_re[76] = $signed(16'sh4C40);
111 | assign wn_re[77] = $signed(16'sh4AFB);
112 | assign wn_re[78] = $signed(16'sh49B4);
113 | assign wn_re[79] = $signed(16'sh486A);
114 | assign wn_re[80] = $signed(16'sh471D);
115 | assign wn_re[81] = $signed(16'sh45CD);
116 | assign wn_re[82] = $signed(16'sh447B);
117 | assign wn_re[83] = $signed(16'sh4326);
118 | assign wn_re[84] = $signed(16'sh41CE);
119 | assign wn_re[85] = $signed(16'sh4074);
120 | assign wn_re[86] = $signed(16'sh3F17);
121 | assign wn_re[87] = $signed(16'sh3DB8);
122 | assign wn_re[88] = $signed(16'sh3C57);
123 | assign wn_re[89] = $signed(16'sh3AF3);
124 | assign wn_re[90] = $signed(16'sh398D);
125 | assign wn_re[91] = $signed(16'sh3825);
126 | assign wn_re[92] = $signed(16'sh36BA);
127 | assign wn_re[93] = $signed(16'sh354E);
128 | assign wn_re[94] = $signed(16'sh33DF);
129 | assign wn_re[95] = $signed(16'sh326E);
130 | assign wn_re[96] = $signed(16'sh30FC);
131 | assign wn_re[97] = $signed(16'sh2F87);
132 | assign wn_re[98] = $signed(16'sh2E11);
133 | assign wn_re[99] = $signed(16'sh2C99);
134 | assign wn_re[100] = $signed(16'sh2B1F);
135 | assign wn_re[101] = $signed(16'sh29A4);
136 | assign wn_re[102] = $signed(16'sh2827);
137 | assign wn_re[103] = $signed(16'sh26A8);
138 | assign wn_re[104] = $signed(16'sh2528);
139 | assign wn_re[105] = $signed(16'sh23A7);
140 | assign wn_re[106] = $signed(16'sh2224);
141 | assign wn_re[107] = $signed(16'sh209F);
142 | assign wn_re[108] = $signed(16'sh1F1A);
143 | assign wn_re[109] = $signed(16'sh1D93);
144 | assign wn_re[110] = $signed(16'sh1C0C);
145 | assign wn_re[111] = $signed(16'sh1A83);
146 | assign wn_re[112] = $signed(16'sh18F9);
147 | assign wn_re[113] = $signed(16'sh176E);
148 | assign wn_re[114] = $signed(16'sh15E2);
149 | assign wn_re[115] = $signed(16'sh1455);
150 | assign wn_re[116] = $signed(16'sh12C8);
151 | assign wn_re[117] = $signed(16'sh113A);
152 | assign wn_re[118] = $signed(16'sh0FAB);
153 | assign wn_re[119] = $signed(16'sh0E1C);
154 | assign wn_re[120] = $signed(16'sh0C8C);
155 | assign wn_re[121] = $signed(16'sh0AFB);
156 | assign wn_re[122] = $signed(16'sh096B);
157 | assign wn_re[123] = $signed(16'sh07D9);
158 | assign wn_re[124] = $signed(16'sh0648);
159 | assign wn_re[125] = $signed(16'sh04B6);
160 | assign wn_re[126] = $signed(16'sh0324);
161 | assign wn_re[127] = $signed(16'sh0192);
162 | assign wn_re[128] = $signed(16'sh0000);
163 | assign wn_re[129] = $signed(-16'sh0192);
164 | assign wn_re[130] = $signed(-16'sh0324);
165 | assign wn_re[131] = $signed(-16'sh04B6);
166 | assign wn_re[132] = $signed(-16'sh0648);
167 | assign wn_re[133] = $signed(-16'sh07D9);
168 | assign wn_re[134] = $signed(-16'sh096B);
169 | assign wn_re[135] = $signed(-16'sh0AFB);
170 | assign wn_re[136] = $signed(-16'sh0C8C);
171 | assign wn_re[137] = $signed(-16'sh0E1C);
172 | assign wn_re[138] = $signed(-16'sh0FAB);
173 | assign wn_re[139] = $signed(-16'sh113A);
174 | assign wn_re[140] = $signed(-16'sh12C8);
175 | assign wn_re[141] = $signed(-16'sh1455);
176 | assign wn_re[142] = $signed(-16'sh15E2);
177 | assign wn_re[143] = $signed(-16'sh176E);
178 | assign wn_re[144] = $signed(-16'sh18F9);
179 | assign wn_re[145] = $signed(-16'sh1A83);
180 | assign wn_re[146] = $signed(-16'sh1C0C);
181 | assign wn_re[147] = $signed(-16'sh1D93);
182 | assign wn_re[148] = $signed(-16'sh1F1A);
183 | assign wn_re[149] = $signed(-16'sh209F);
184 | assign wn_re[150] = $signed(-16'sh2224);
185 | assign wn_re[151] = $signed(-16'sh23A7);
186 | assign wn_re[152] = $signed(-16'sh2528);
187 | assign wn_re[153] = $signed(-16'sh26A8);
188 | assign wn_re[154] = $signed(-16'sh2827);
189 | assign wn_re[155] = $signed(-16'sh29A4);
190 | assign wn_re[156] = $signed(-16'sh2B1F);
191 | assign wn_re[157] = $signed(-16'sh2C99);
192 | assign wn_re[158] = $signed(-16'sh2E11);
193 | assign wn_re[159] = $signed(-16'sh2F87);
194 | assign wn_re[160] = $signed(-16'sh30FC);
195 | assign wn_re[161] = $signed(-16'sh326E);
196 | assign wn_re[162] = $signed(-16'sh33DF);
197 | assign wn_re[163] = $signed(-16'sh354E);
198 | assign wn_re[164] = $signed(-16'sh36BA);
199 | assign wn_re[165] = $signed(-16'sh3825);
200 | assign wn_re[166] = $signed(-16'sh398D);
201 | assign wn_re[167] = $signed(-16'sh3AF3);
202 | assign wn_re[168] = $signed(-16'sh3C57);
203 | assign wn_re[169] = $signed(-16'sh3DB8);
204 | assign wn_re[170] = $signed(-16'sh3F17);
205 | assign wn_re[171] = $signed(-16'sh4074);
206 | assign wn_re[172] = $signed(-16'sh41CE);
207 | assign wn_re[173] = $signed(-16'sh4326);
208 | assign wn_re[174] = $signed(-16'sh447B);
209 | assign wn_re[175] = $signed(-16'sh45CD);
210 | assign wn_re[176] = $signed(-16'sh471D);
211 | assign wn_re[177] = $signed(-16'sh486A);
212 | assign wn_re[178] = $signed(-16'sh49B4);
213 | assign wn_re[179] = $signed(-16'sh4AFB);
214 | assign wn_re[180] = $signed(-16'sh4C40);
215 | assign wn_re[181] = $signed(-16'sh4D81);
216 | assign wn_re[182] = $signed(-16'sh4EC0);
217 | assign wn_re[183] = $signed(-16'sh4FFB);
218 | assign wn_re[184] = $signed(-16'sh5134);
219 | assign wn_re[185] = $signed(-16'sh5269);
220 | assign wn_re[186] = $signed(-16'sh539B);
221 | assign wn_re[187] = $signed(-16'sh54CA);
222 | assign wn_re[188] = $signed(-16'sh55F6);
223 | assign wn_re[189] = $signed(-16'sh571E);
224 | assign wn_re[190] = $signed(-16'sh5843);
225 | assign wn_re[191] = $signed(-16'sh5964);
226 | assign wn_re[192] = $signed(-16'sh5A82);
227 | assign wn_re[193] = $signed(-16'sh5B9D);
228 | assign wn_re[194] = $signed(-16'sh5CB4);
229 | assign wn_re[195] = $signed(-16'sh5DC8);
230 | assign wn_re[196] = $signed(-16'sh5ED7);
231 | assign wn_re[197] = $signed(-16'sh5FE4);
232 | assign wn_re[198] = $signed(-16'sh60EC);
233 | assign wn_re[199] = $signed(-16'sh61F1);
234 | assign wn_re[200] = $signed(-16'sh62F2);
235 | assign wn_re[201] = $signed(-16'sh63EF);
236 | assign wn_re[202] = $signed(-16'sh64E9);
237 | assign wn_re[203] = $signed(-16'sh65DE);
238 | assign wn_re[204] = $signed(-16'sh66D0);
239 | assign wn_re[205] = $signed(-16'sh67BD);
240 | assign wn_re[206] = $signed(-16'sh68A7);
241 | assign wn_re[207] = $signed(-16'sh698C);
242 | assign wn_re[208] = $signed(-16'sh6A6E);
243 | assign wn_re[209] = $signed(-16'sh6B4B);
244 | assign wn_re[210] = $signed(-16'sh6C24);
245 | assign wn_re[211] = $signed(-16'sh6CF9);
246 | assign wn_re[212] = $signed(-16'sh6DCA);
247 | assign wn_re[213] = $signed(-16'sh6E97);
248 | assign wn_re[214] = $signed(-16'sh6F5F);
249 | assign wn_re[215] = $signed(-16'sh7023);
250 | assign wn_re[216] = $signed(-16'sh70E3);
251 | assign wn_re[217] = $signed(-16'sh719E);
252 | assign wn_re[218] = $signed(-16'sh7255);
253 | assign wn_re[219] = $signed(-16'sh7308);
254 | assign wn_re[220] = $signed(-16'sh73B6);
255 | assign wn_re[221] = $signed(-16'sh7460);
256 | assign wn_re[222] = $signed(-16'sh7505);
257 | assign wn_re[223] = $signed(-16'sh75A6);
258 | assign wn_re[224] = $signed(-16'sh7642);
259 | assign wn_re[225] = $signed(-16'sh76D9);
260 | assign wn_re[226] = $signed(-16'sh776C);
261 | assign wn_re[227] = $signed(-16'sh77FB);
262 | assign wn_re[228] = $signed(-16'sh7885);
263 | assign wn_re[229] = $signed(-16'sh790A);
264 | assign wn_re[230] = $signed(-16'sh798A);
265 | assign wn_re[231] = $signed(-16'sh7A06);
266 | assign wn_re[232] = $signed(-16'sh7A7D);
267 | assign wn_re[233] = $signed(-16'sh7AEF);
268 | assign wn_re[234] = $signed(-16'sh7B5D);
269 | assign wn_re[235] = $signed(-16'sh7BC6);
270 | assign wn_re[236] = $signed(-16'sh7C2A);
271 | assign wn_re[237] = $signed(-16'sh7C89);
272 | assign wn_re[238] = $signed(-16'sh7CE4);
273 | assign wn_re[239] = $signed(-16'sh7D3A);
274 | assign wn_re[240] = $signed(-16'sh7D8A);
275 | assign wn_re[241] = $signed(-16'sh7DD6);
276 | assign wn_re[242] = $signed(-16'sh7E1E);
277 | assign wn_re[243] = $signed(-16'sh7E60);
278 | assign wn_re[244] = $signed(-16'sh7E9D);
279 | assign wn_re[245] = $signed(-16'sh7ED6);
280 | assign wn_re[246] = $signed(-16'sh7F0A);
281 | assign wn_re[247] = $signed(-16'sh7F38);
282 | assign wn_re[248] = $signed(-16'sh7F62);
283 | assign wn_re[249] = $signed(-16'sh7F87);
284 | assign wn_re[250] = $signed(-16'sh7FA7);
285 | assign wn_re[251] = $signed(-16'sh7FC2);
286 | assign wn_re[252] = $signed(-16'sh7FD9);
287 | assign wn_re[253] = $signed(-16'sh7FEA);
288 | assign wn_re[254] = $signed(-16'sh7FF6);
289 | assign wn_re[255] = $signed(-16'sh7FFE);
290 | assign wn_im[0] = $signed(16'sh0000);
291 | assign wn_im[1] = $signed(16'sh0192);
292 | assign wn_im[2] = $signed(16'sh0324);
293 | assign wn_im[3] = $signed(16'sh04B6);
294 | assign wn_im[4] = $signed(16'sh0648);
295 | assign wn_im[5] = $signed(16'sh07D9);
296 | assign wn_im[6] = $signed(16'sh096B);
297 | assign wn_im[7] = $signed(16'sh0AFB);
298 | assign wn_im[8] = $signed(16'sh0C8C);
299 | assign wn_im[9] = $signed(16'sh0E1C);
300 | assign wn_im[10] = $signed(16'sh0FAB);
301 | assign wn_im[11] = $signed(16'sh113A);
302 | assign wn_im[12] = $signed(16'sh12C8);
303 | assign wn_im[13] = $signed(16'sh1455);
304 | assign wn_im[14] = $signed(16'sh15E2);
305 | assign wn_im[15] = $signed(16'sh176E);
306 | assign wn_im[16] = $signed(16'sh18F9);
307 | assign wn_im[17] = $signed(16'sh1A83);
308 | assign wn_im[18] = $signed(16'sh1C0C);
309 | assign wn_im[19] = $signed(16'sh1D93);
310 | assign wn_im[20] = $signed(16'sh1F1A);
311 | assign wn_im[21] = $signed(16'sh209F);
312 | assign wn_im[22] = $signed(16'sh2224);
313 | assign wn_im[23] = $signed(16'sh23A7);
314 | assign wn_im[24] = $signed(16'sh2528);
315 | assign wn_im[25] = $signed(16'sh26A8);
316 | assign wn_im[26] = $signed(16'sh2827);
317 | assign wn_im[27] = $signed(16'sh29A4);
318 | assign wn_im[28] = $signed(16'sh2B1F);
319 | assign wn_im[29] = $signed(16'sh2C99);
320 | assign wn_im[30] = $signed(16'sh2E11);
321 | assign wn_im[31] = $signed(16'sh2F87);
322 | assign wn_im[32] = $signed(16'sh30FC);
323 | assign wn_im[33] = $signed(16'sh326E);
324 | assign wn_im[34] = $signed(16'sh33DF);
325 | assign wn_im[35] = $signed(16'sh354E);
326 | assign wn_im[36] = $signed(16'sh36BA);
327 | assign wn_im[37] = $signed(16'sh3825);
328 | assign wn_im[38] = $signed(16'sh398D);
329 | assign wn_im[39] = $signed(16'sh3AF3);
330 | assign wn_im[40] = $signed(16'sh3C57);
331 | assign wn_im[41] = $signed(16'sh3DB8);
332 | assign wn_im[42] = $signed(16'sh3F17);
333 | assign wn_im[43] = $signed(16'sh4074);
334 | assign wn_im[44] = $signed(16'sh41CE);
335 | assign wn_im[45] = $signed(16'sh4326);
336 | assign wn_im[46] = $signed(16'sh447B);
337 | assign wn_im[47] = $signed(16'sh45CD);
338 | assign wn_im[48] = $signed(16'sh471D);
339 | assign wn_im[49] = $signed(16'sh486A);
340 | assign wn_im[50] = $signed(16'sh49B4);
341 | assign wn_im[51] = $signed(16'sh4AFB);
342 | assign wn_im[52] = $signed(16'sh4C40);
343 | assign wn_im[53] = $signed(16'sh4D81);
344 | assign wn_im[54] = $signed(16'sh4EC0);
345 | assign wn_im[55] = $signed(16'sh4FFB);
346 | assign wn_im[56] = $signed(16'sh5134);
347 | assign wn_im[57] = $signed(16'sh5269);
348 | assign wn_im[58] = $signed(16'sh539B);
349 | assign wn_im[59] = $signed(16'sh54CA);
350 | assign wn_im[60] = $signed(16'sh55F6);
351 | assign wn_im[61] = $signed(16'sh571E);
352 | assign wn_im[62] = $signed(16'sh5843);
353 | assign wn_im[63] = $signed(16'sh5964);
354 | assign wn_im[64] = $signed(16'sh5A82);
355 | assign wn_im[65] = $signed(16'sh5B9D);
356 | assign wn_im[66] = $signed(16'sh5CB4);
357 | assign wn_im[67] = $signed(16'sh5DC8);
358 | assign wn_im[68] = $signed(16'sh5ED7);
359 | assign wn_im[69] = $signed(16'sh5FE4);
360 | assign wn_im[70] = $signed(16'sh60EC);
361 | assign wn_im[71] = $signed(16'sh61F1);
362 | assign wn_im[72] = $signed(16'sh62F2);
363 | assign wn_im[73] = $signed(16'sh63EF);
364 | assign wn_im[74] = $signed(16'sh64E9);
365 | assign wn_im[75] = $signed(16'sh65DE);
366 | assign wn_im[76] = $signed(16'sh66D0);
367 | assign wn_im[77] = $signed(16'sh67BD);
368 | assign wn_im[78] = $signed(16'sh68A7);
369 | assign wn_im[79] = $signed(16'sh698C);
370 | assign wn_im[80] = $signed(16'sh6A6E);
371 | assign wn_im[81] = $signed(16'sh6B4B);
372 | assign wn_im[82] = $signed(16'sh6C24);
373 | assign wn_im[83] = $signed(16'sh6CF9);
374 | assign wn_im[84] = $signed(16'sh6DCA);
375 | assign wn_im[85] = $signed(16'sh6E97);
376 | assign wn_im[86] = $signed(16'sh6F5F);
377 | assign wn_im[87] = $signed(16'sh7023);
378 | assign wn_im[88] = $signed(16'sh70E3);
379 | assign wn_im[89] = $signed(16'sh719E);
380 | assign wn_im[90] = $signed(16'sh7255);
381 | assign wn_im[91] = $signed(16'sh7308);
382 | assign wn_im[92] = $signed(16'sh73B6);
383 | assign wn_im[93] = $signed(16'sh7460);
384 | assign wn_im[94] = $signed(16'sh7505);
385 | assign wn_im[95] = $signed(16'sh75A6);
386 | assign wn_im[96] = $signed(16'sh7642);
387 | assign wn_im[97] = $signed(16'sh76D9);
388 | assign wn_im[98] = $signed(16'sh776C);
389 | assign wn_im[99] = $signed(16'sh77FB);
390 | assign wn_im[100] = $signed(16'sh7885);
391 | assign wn_im[101] = $signed(16'sh790A);
392 | assign wn_im[102] = $signed(16'sh798A);
393 | assign wn_im[103] = $signed(16'sh7A06);
394 | assign wn_im[104] = $signed(16'sh7A7D);
395 | assign wn_im[105] = $signed(16'sh7AEF);
396 | assign wn_im[106] = $signed(16'sh7B5D);
397 | assign wn_im[107] = $signed(16'sh7BC6);
398 | assign wn_im[108] = $signed(16'sh7C2A);
399 | assign wn_im[109] = $signed(16'sh7C89);
400 | assign wn_im[110] = $signed(16'sh7CE4);
401 | assign wn_im[111] = $signed(16'sh7D3A);
402 | assign wn_im[112] = $signed(16'sh7D8A);
403 | assign wn_im[113] = $signed(16'sh7DD6);
404 | assign wn_im[114] = $signed(16'sh7E1E);
405 | assign wn_im[115] = $signed(16'sh7E60);
406 | assign wn_im[116] = $signed(16'sh7E9D);
407 | assign wn_im[117] = $signed(16'sh7ED6);
408 | assign wn_im[118] = $signed(16'sh7F0A);
409 | assign wn_im[119] = $signed(16'sh7F38);
410 | assign wn_im[120] = $signed(16'sh7F62);
411 | assign wn_im[121] = $signed(16'sh7F87);
412 | assign wn_im[122] = $signed(16'sh7FA7);
413 | assign wn_im[123] = $signed(16'sh7FC2);
414 | assign wn_im[124] = $signed(16'sh7FD9);
415 | assign wn_im[125] = $signed(16'sh7FEA);
416 | assign wn_im[126] = $signed(16'sh7FF6);
417 | assign wn_im[127] = $signed(16'sh7FFE);
418 | assign wn_im[128] = $signed(16'sh7FFF);
419 | assign wn_im[129] = $signed(16'sh7FFE);
420 | assign wn_im[130] = $signed(16'sh7FF6);
421 | assign wn_im[131] = $signed(16'sh7FEA);
422 | assign wn_im[132] = $signed(16'sh7FD9);
423 | assign wn_im[133] = $signed(16'sh7FC2);
424 | assign wn_im[134] = $signed(16'sh7FA7);
425 | assign wn_im[135] = $signed(16'sh7F87);
426 | assign wn_im[136] = $signed(16'sh7F62);
427 | assign wn_im[137] = $signed(16'sh7F38);
428 | assign wn_im[138] = $signed(16'sh7F0A);
429 | assign wn_im[139] = $signed(16'sh7ED6);
430 | assign wn_im[140] = $signed(16'sh7E9D);
431 | assign wn_im[141] = $signed(16'sh7E60);
432 | assign wn_im[142] = $signed(16'sh7E1E);
433 | assign wn_im[143] = $signed(16'sh7DD6);
434 | assign wn_im[144] = $signed(16'sh7D8A);
435 | assign wn_im[145] = $signed(16'sh7D3A);
436 | assign wn_im[146] = $signed(16'sh7CE4);
437 | assign wn_im[147] = $signed(16'sh7C89);
438 | assign wn_im[148] = $signed(16'sh7C2A);
439 | assign wn_im[149] = $signed(16'sh7BC6);
440 | assign wn_im[150] = $signed(16'sh7B5D);
441 | assign wn_im[151] = $signed(16'sh7AEF);
442 | assign wn_im[152] = $signed(16'sh7A7D);
443 | assign wn_im[153] = $signed(16'sh7A06);
444 | assign wn_im[154] = $signed(16'sh798A);
445 | assign wn_im[155] = $signed(16'sh790A);
446 | assign wn_im[156] = $signed(16'sh7885);
447 | assign wn_im[157] = $signed(16'sh77FB);
448 | assign wn_im[158] = $signed(16'sh776C);
449 | assign wn_im[159] = $signed(16'sh76D9);
450 | assign wn_im[160] = $signed(16'sh7642);
451 | assign wn_im[161] = $signed(16'sh75A6);
452 | assign wn_im[162] = $signed(16'sh7505);
453 | assign wn_im[163] = $signed(16'sh7460);
454 | assign wn_im[164] = $signed(16'sh73B6);
455 | assign wn_im[165] = $signed(16'sh7308);
456 | assign wn_im[166] = $signed(16'sh7255);
457 | assign wn_im[167] = $signed(16'sh719E);
458 | assign wn_im[168] = $signed(16'sh70E3);
459 | assign wn_im[169] = $signed(16'sh7023);
460 | assign wn_im[170] = $signed(16'sh6F5F);
461 | assign wn_im[171] = $signed(16'sh6E97);
462 | assign wn_im[172] = $signed(16'sh6DCA);
463 | assign wn_im[173] = $signed(16'sh6CF9);
464 | assign wn_im[174] = $signed(16'sh6C24);
465 | assign wn_im[175] = $signed(16'sh6B4B);
466 | assign wn_im[176] = $signed(16'sh6A6E);
467 | assign wn_im[177] = $signed(16'sh698C);
468 | assign wn_im[178] = $signed(16'sh68A7);
469 | assign wn_im[179] = $signed(16'sh67BD);
470 | assign wn_im[180] = $signed(16'sh66D0);
471 | assign wn_im[181] = $signed(16'sh65DE);
472 | assign wn_im[182] = $signed(16'sh64E9);
473 | assign wn_im[183] = $signed(16'sh63EF);
474 | assign wn_im[184] = $signed(16'sh62F2);
475 | assign wn_im[185] = $signed(16'sh61F1);
476 | assign wn_im[186] = $signed(16'sh60EC);
477 | assign wn_im[187] = $signed(16'sh5FE4);
478 | assign wn_im[188] = $signed(16'sh5ED7);
479 | assign wn_im[189] = $signed(16'sh5DC8);
480 | assign wn_im[190] = $signed(16'sh5CB4);
481 | assign wn_im[191] = $signed(16'sh5B9D);
482 | assign wn_im[192] = $signed(16'sh5A82);
483 | assign wn_im[193] = $signed(16'sh5964);
484 | assign wn_im[194] = $signed(16'sh5843);
485 | assign wn_im[195] = $signed(16'sh571E);
486 | assign wn_im[196] = $signed(16'sh55F6);
487 | assign wn_im[197] = $signed(16'sh54CA);
488 | assign wn_im[198] = $signed(16'sh539B);
489 | assign wn_im[199] = $signed(16'sh5269);
490 | assign wn_im[200] = $signed(16'sh5134);
491 | assign wn_im[201] = $signed(16'sh4FFB);
492 | assign wn_im[202] = $signed(16'sh4EC0);
493 | assign wn_im[203] = $signed(16'sh4D81);
494 | assign wn_im[204] = $signed(16'sh4C40);
495 | assign wn_im[205] = $signed(16'sh4AFB);
496 | assign wn_im[206] = $signed(16'sh49B4);
497 | assign wn_im[207] = $signed(16'sh486A);
498 | assign wn_im[208] = $signed(16'sh471D);
499 | assign wn_im[209] = $signed(16'sh45CD);
500 | assign wn_im[210] = $signed(16'sh447B);
501 | assign wn_im[211] = $signed(16'sh4326);
502 | assign wn_im[212] = $signed(16'sh41CE);
503 | assign wn_im[213] = $signed(16'sh4074);
504 | assign wn_im[214] = $signed(16'sh3F17);
505 | assign wn_im[215] = $signed(16'sh3DB8);
506 | assign wn_im[216] = $signed(16'sh3C57);
507 | assign wn_im[217] = $signed(16'sh3AF3);
508 | assign wn_im[218] = $signed(16'sh398D);
509 | assign wn_im[219] = $signed(16'sh3825);
510 | assign wn_im[220] = $signed(16'sh36BA);
511 | assign wn_im[221] = $signed(16'sh354E);
512 | assign wn_im[222] = $signed(16'sh33DF);
513 | assign wn_im[223] = $signed(16'sh326E);
514 | assign wn_im[224] = $signed(16'sh30FC);
515 | assign wn_im[225] = $signed(16'sh2F87);
516 | assign wn_im[226] = $signed(16'sh2E11);
517 | assign wn_im[227] = $signed(16'sh2C99);
518 | assign wn_im[228] = $signed(16'sh2B1F);
519 | assign wn_im[229] = $signed(16'sh29A4);
520 | assign wn_im[230] = $signed(16'sh2827);
521 | assign wn_im[231] = $signed(16'sh26A8);
522 | assign wn_im[232] = $signed(16'sh2528);
523 | assign wn_im[233] = $signed(16'sh23A7);
524 | assign wn_im[234] = $signed(16'sh2224);
525 | assign wn_im[235] = $signed(16'sh209F);
526 | assign wn_im[236] = $signed(16'sh1F1A);
527 | assign wn_im[237] = $signed(16'sh1D93);
528 | assign wn_im[238] = $signed(16'sh1C0C);
529 | assign wn_im[239] = $signed(16'sh1A83);
530 | assign wn_im[240] = $signed(16'sh18F9);
531 | assign wn_im[241] = $signed(16'sh176E);
532 | assign wn_im[242] = $signed(16'sh15E2);
533 | assign wn_im[243] = $signed(16'sh1455);
534 | assign wn_im[244] = $signed(16'sh12C8);
535 | assign wn_im[245] = $signed(16'sh113A);
536 | assign wn_im[246] = $signed(16'sh0FAB);
537 | assign wn_im[247] = $signed(16'sh0E1C);
538 | assign wn_im[248] = $signed(16'sh0C8C);
539 | assign wn_im[249] = $signed(16'sh0AFB);
540 | assign wn_im[250] = $signed(16'sh096B);
541 | assign wn_im[251] = $signed(16'sh07D9);
542 | assign wn_im[252] = $signed(16'sh0648);
543 | assign wn_im[253] = $signed(16'sh04B6);
544 | assign wn_im[254] = $signed(16'sh0324);
545 | assign wn_im[255] = $signed(16'sh0192);
546 |
547 | assign data0_re = wn_re[addr0];
548 | assign data0_im = wn_im[addr0];
549 | assign data1_re = wn_re[addr1];
550 | assign data1_im = wn_im[addr1];
551 | assign data2_re = wn_re[addr2];
552 | assign data2_im = wn_im[addr2];
553 | assign data3_re = wn_re[addr3];
554 | assign data3_im = wn_im[addr3];
555 | assign data4_re = wn_re[addr4];
556 | assign data4_im = wn_im[addr4];
557 | assign data5_re = wn_re[addr5];
558 | assign data5_im = wn_im[addr5];
559 | assign data6_re = wn_re[addr6];
560 | assign data6_im = wn_im[addr6];
561 | assign data7_re = wn_re[addr7];
562 | assign data7_im = wn_im[addr7];
563 |
564 | endmodule
--------------------------------------------------------------------------------
/rtl/src/include/.gitignore:
--------------------------------------------------------------------------------
1 | *.*
2 | *
3 | !*/
4 | !.gitignore
5 | !*.md
6 | !*.[cSh]
7 | !*.v
8 | !*.vh
9 |
--------------------------------------------------------------------------------
/rtl/src/memory/fft_reoder_sramsp16x256_maskoff.v:
--------------------------------------------------------------------------------
1 |
2 | // use tsmc n28 hpc
3 | `define TSMC_N28HPC
4 |
5 | module fft_reoder_sramsp16x256_maskoff (
6 | input clk,
7 | input ce,
8 | input rw,
9 | input [7:0] addr,
10 | input [15:0] din,
11 | output reg [15:0] dout
12 | );
13 |
14 | `ifdef TSMC_N28HPC
15 |
16 | sramsp16x256_tsmc28hpc sramsp16x256_maskoff (
17 | .CLK (clk ),
18 | .CEB (~ce ),
19 | .WEB (~rw ),
20 | .A (addr ),
21 | .D (din ),
22 | .Q (dout )
23 | );
24 |
25 | `else
26 |
27 | sramsp_maskoff #(
28 | .DATA_WIDTH(16),
29 | .ADDR_WIDTH(8)
30 | ) sramsp16x256_maskoff (
31 | .CLK (clk ),
32 | .GWEN (~rw ),
33 | .CEN (~ce ),
34 | .A (addr),
35 | .D (din ),
36 | .Q (dout)
37 | );
38 |
39 | `endif
40 |
41 | endmodule
42 |
--------------------------------------------------------------------------------
/rtl/src/memory/sramsp_maskoff.v:
--------------------------------------------------------------------------------
1 | module sramsp_maskoff #(
2 | parameter DATA_WIDTH = 16,
3 | parameter ADDR_WIDTH = 8
4 | ) (
5 | input CLK,
6 | input GWEN,
7 | input CEN,
8 | input [ADDR_WIDTH-1:0] A,
9 | input [DATA_WIDTH-1:0] D,
10 | output reg [DATA_WIDTH-1:0] Q
11 | );
12 |
13 | reg [DATA_WIDTH-1:0] mem [0:(1 << ADDR_WIDTH)-1];
14 |
15 | always @(posedge CLK) begin
16 | if ((! CEN) && (! GWEN )) begin
17 | mem[A] <= D;
18 | end
19 | end
20 | always @(posedge CLK) begin
21 | if ((! CEN) && GWEN) begin
22 | Q <= mem[A];
23 | end
24 | else begin
25 | Q <= {DATA_WIDTH{1'bx}};
26 | end
27 | end
28 |
29 | endmodule
30 |
--------------------------------------------------------------------------------
/rtl/src/reoder.v:
--------------------------------------------------------------------------------
1 | module reorder #(
2 | parameter DATA_WIDTH = 16,
3 | parameter FFT_LENGTH = 64
4 | ) (
5 | input clk,
6 | input rst_n,
7 | input [DATA_WIDTH-1:0] in1_re,
8 | input [DATA_WIDTH-1:0] in1_im,
9 | input [DATA_WIDTH-1:0] in2_re,
10 | input [DATA_WIDTH-1:0] in2_im,
11 | input in_valid,
12 | input [1:0] np,
13 | output [DATA_WIDTH-1:0] out_re,
14 | output [DATA_WIDTH-1:0] out_im,
15 | output reg out_valid
16 | );
17 |
18 | localparam TIMES = $clog2(FFT_LENGTH/2);
19 |
20 | reg [TIMES:0] index1;
21 | reg [TIMES:0] index2;
22 |
23 | reg [TIMES-1:0] in_counter; // receive 2 data per cycle
24 | reg [TIMES:0] out_counter, out_counter_reg1, out_counter_reg2; // output 1 data per cycle
25 |
26 | always @(posedge clk or negedge rst_n) begin
27 | if(!rst_n) begin
28 | out_counter_reg1 <= {(TIMES+1){1'b0}};
29 | out_counter_reg2 <= {(TIMES+1){1'b0}};
30 | end
31 | else begin
32 | out_counter_reg1 <= out_counter;
33 | out_counter_reg2 <= out_counter_reg1;
34 | end
35 | end
36 |
37 | wire out_valid_t;
38 |
39 | reg [9:0] point;
40 | always @(*) begin
41 | case(np)
42 | 2'b00: point = 10'd64;
43 | 2'b01: point = 10'd128;
44 | 2'b10: point = 10'd256;
45 | 2'b11: point = 10'd512;
46 | endcase
47 | end
48 |
49 | reg w_en;
50 | reg [TIMES-1:0] addr0, addr1;
51 | reg [DATA_WIDTH-1:0] din0, din1, din2, din3;
52 | wire [DATA_WIDTH-1:0] dout0, dout1, dout2, dout3;
53 |
54 | // rambank0_re
55 | fft_reoder_sramsp16x256_maskoff sram16x256_0 (
56 | .clk(clk),
57 | .ce(1'b1),
58 | .rw(w_en),
59 | .addr(addr0),
60 | .din(din0),
61 | .dout(dout0)
62 | );
63 | // rambank0_im
64 | fft_reoder_sramsp16x256_maskoff sram16x256_1 (
65 | .clk(clk),
66 | .ce(1'b1),
67 | .rw(w_en),
68 | .addr(addr0),
69 | .din(din1),
70 | .dout(dout1)
71 | );
72 | // rambank1_re
73 | fft_reoder_sramsp16x256_maskoff sram16x256_2 (
74 | .clk(clk),
75 | .ce(1'b1),
76 | .rw(w_en),
77 | .addr(addr1),
78 | .din(din2),
79 | .dout(dout2)
80 | );
81 | // rambank1_im
82 | fft_reoder_sramsp16x256_maskoff sram16x256_3 (
83 | .clk(clk),
84 | .ce(1'b1),
85 | .rw(w_en),
86 | .addr(addr1),
87 | .din(din3),
88 | .dout(dout3)
89 | );
90 |
91 |
92 | wire [TIMES:0] index1_0, index1_1, index1_2, index1_3;
93 | wire [TIMES:0] index2_0, index2_1, index2_2, index2_3;
94 | // 512
95 | reverse_bits #(TIMES+1) reverse_bits_00 (
96 | .in({in_counter, 1'b0}),
97 | .out(index1_0)
98 | );
99 | reverse_bits #(TIMES+1) reverse_bits_01 (
100 | .in({in_counter, 1'b1}),
101 | .out(index2_0)
102 | );
103 | // 256
104 | reverse_bits #(TIMES) reverse_bits_10 (
105 | .in({in_counter[6:0], 1'b0}),
106 | .out(index1_1[7:0])
107 | );
108 | reverse_bits #(TIMES) reverse_bits_11 (
109 | .in({in_counter[6:0], 1'b1}),
110 | .out(index2_1[7:0])
111 | );
112 | // 128
113 | reverse_bits #(TIMES-1) reverse_bits_20 (
114 | .in({in_counter[5:0], 1'b0}),
115 | .out(index1_2[6:0])
116 | );
117 | reverse_bits #(TIMES-1) reverse_bits_21 (
118 | .in({in_counter[5:0], 1'b1}),
119 | .out(index2_2[6:0])
120 | );
121 | // 64
122 | reverse_bits #(TIMES-2) reverse_bits_30 (
123 | .in({in_counter[4:0], 1'b0}),
124 | .out(index1_3[5:0])
125 | );
126 | reverse_bits #(TIMES-2) reverse_bits_31 (
127 | .in({in_counter[4:0], 1'b1}),
128 | .out(index2_3[5:0])
129 | );
130 |
131 | always @(*) begin
132 | case(np)
133 | 2'b00: begin //64
134 | index1 = {3'b0, index1_3[5:0]};
135 | index2 = {3'b0, index2_3[5:0]};
136 | end
137 | 2'b01: begin //128
138 | index1 = {2'b0, index1_2[6:0]};
139 | index2 = {2'b0, index2_2[6:0]};
140 | end
141 | 2'b10: begin //256
142 | index1 = {1'b0, index1_1[7:0]};
143 | index2 = {1'b0, index2_1[7:0]};
144 | end
145 | 2'b11: begin //512
146 | index1 = index1_0;
147 | index2 = index2_0;
148 | end
149 | endcase
150 | end
151 |
152 |
153 | always @(posedge clk or negedge rst_n) begin
154 | if (!rst_n) begin
155 | in_counter <= {TIMES{1'b0}};
156 | addr0 <= {TIMES{1'b0}};
157 | addr1 <= {TIMES{1'b0}};
158 | end
159 | else if ((in_valid || in_counter != {TIMES{1'b0}}) && (in_counter < (point>>1))) begin
160 | in_counter <= in_counter + 1'b1;
161 | w_en <= 1'b1;
162 | addr0 <= index1;
163 | addr1 <= index2-(point>>1);
164 | din0 <= in1_re;
165 | din1 <= in1_im;
166 | din2 <= in2_re;
167 | din3 <= in2_im;
168 | end
169 | else begin
170 | in_counter <= {TIMES{1'b0}};
171 | w_en <= 1'b0;
172 |
173 | if(out_counter < (point>>1)) begin
174 | addr0 <= out_counter;
175 | addr1 <= out_counter;
176 | end
177 | else begin
178 | addr0 <= out_counter-(point>>1);
179 | addr1 <= out_counter-(point>>1);
180 | end
181 | end
182 | end
183 |
184 | always @(posedge clk or negedge rst_n) begin
185 | if (!rst_n) begin
186 | out_counter <= {(TIMES+1){1'b0}};
187 | end
188 | else if (out_valid_t && out_counter < point-1) begin
189 | out_counter <= out_counter + 1;
190 | end
191 | else begin
192 | out_counter <= {(TIMES+1){1'b0}};
193 | end
194 | end
195 |
196 | reg [TIMES-1:0] in_counter_reg;
197 | always @(posedge clk or negedge rst_n) begin
198 | if (!rst_n)
199 | in_counter_reg <= {TIMES{1'b0}};
200 | else
201 | in_counter_reg <= in_counter;
202 | end
203 |
204 | assign out_re = (out_counter_reg2 < ((point>>1))) ? dout0 : dout2;
205 | assign out_im = (out_counter_reg2 < ((point>>1))) ? dout1 : dout3;
206 |
207 | assign out_valid_t = (in_counter_reg == ((point>>1) - 1)) || (out_counter != 0);
208 |
209 | reg out_valid_t1;
210 | always @(posedge clk or negedge rst_n) begin
211 | if(!rst_n) begin
212 | out_valid_t1 <= 1'b0;
213 | out_valid <= 1'b0;
214 | end
215 | else begin
216 | out_valid_t1 <= out_valid_t;
217 | out_valid <= out_valid_t1;
218 | end
219 | end
220 |
221 | endmodule
222 |
--------------------------------------------------------------------------------
/rtl/src/reserve_bits.v:
--------------------------------------------------------------------------------
1 | module reverse_bits #(
2 | parameter WIDTH = 16
3 | )(
4 | input [WIDTH-1:0] in,
5 | output [WIDTH-1:0] out
6 | );
7 |
8 | genvar i;
9 | generate
10 | for(i = 0; i < WIDTH; i = i + 1) begin : bit_reverse
11 | assign out[i] = in[WIDTH-1 - i];
12 | end
13 | endgenerate
14 |
15 | endmodule
16 |
--------------------------------------------------------------------------------
/rtl/src/shiftreg.v:
--------------------------------------------------------------------------------
1 | // Author: brimonzzy
2 | // Create Date: 2025/2/13
3 | // Description: N-stage shift register with width W
4 |
5 | module shiftreg #(
6 | parameter W = 16,
7 | parameter N = 8
8 | )(
9 | input clk,
10 | input rst_n,
11 | input [W-1:0] d_in,
12 | output [W-1:0] d_out
13 | );
14 |
15 | reg [W-1:0] shift_reg [N-1:0];
16 | integer i;
17 |
18 | always @(posedge clk or negedge rst_n) begin
19 | if (!rst_n) begin
20 | for (i = 0; i < N; i = i + 1) begin
21 | shift_reg[i] <= {W{1'b0}};
22 | end
23 | end
24 | else begin
25 | shift_reg[0] <= d_in;
26 | for (i = 1; i < N; i = i + 1) begin
27 | shift_reg[i] <= shift_reg[i-1];
28 | end
29 | end
30 | end
31 |
32 | assign d_out = shift_reg[N-1];
33 |
34 | endmodule
35 |
--------------------------------------------------------------------------------
/rtl/src/switch.v:
--------------------------------------------------------------------------------
1 | // Author: brimonzzy
2 | // Create Date: 2025/2/13
3 | // Description: Complex switch module
4 |
5 | module switch (
6 | input sel,
7 | input signed [15:0] x0_re,
8 | input signed [15:0] x0_im,
9 | input signed [15:0] x1_re,
10 | input signed [15:0] x1_im,
11 | output signed [15:0] y0_re,
12 | output signed [15:0] y0_im,
13 | output signed [15:0] y1_re,
14 | output signed [15:0] y1_im
15 | );
16 |
17 | assign y0_re = sel ? x1_re : x0_re;
18 | assign y0_im = sel ? x1_im : x0_im;
19 | assign y1_re = sel ? x0_re : x1_re;
20 | assign y1_im = sel ? x0_im : x1_im;
21 |
22 | endmodule
23 |
--------------------------------------------------------------------------------
/rtl/src/twiddle_rom.v:
--------------------------------------------------------------------------------
1 | // For 512-point FFT
2 | // 8 read ports
3 |
4 | module twiddle_rom (
5 | input [7:0] addr0,
6 | input [7:0] addr1,
7 | input [7:0] addr2,
8 | input [7:0] addr3,
9 | input [7:0] addr4,
10 | input [7:0] addr5,
11 | input [7:0] addr6,
12 | input [7:0] addr7,
13 | output [15:0] data0_re,
14 | output [15:0] data0_im,
15 | output [15:0] data1_re,
16 | output [15:0] data1_im,
17 | output [15:0] data2_re,
18 | output [15:0] data2_im,
19 | output [15:0] data3_re,
20 | output [15:0] data3_im,
21 | output [15:0] data4_re,
22 | output [15:0] data4_im,
23 | output [15:0] data5_re,
24 | output [15:0] data5_im,
25 | output [15:0] data6_re,
26 | output [15:0] data6_im,
27 | output [15:0] data7_re,
28 | output [15:0] data7_im
29 | );
30 | // For N=512
31 | wire signed [15:0] wn_re [0:255];
32 | wire signed [15:0] wn_im [0:255];
33 |
34 | assign wn_re[0] = $signed(16'sh7FFF);
35 | assign wn_re[1] = $signed(16'sh7FFE);
36 | assign wn_re[2] = $signed(16'sh7FF6);
37 | assign wn_re[3] = $signed(16'sh7FEA);
38 | assign wn_re[4] = $signed(16'sh7FD9);
39 | assign wn_re[5] = $signed(16'sh7FC2);
40 | assign wn_re[6] = $signed(16'sh7FA7);
41 | assign wn_re[7] = $signed(16'sh7F87);
42 | assign wn_re[8] = $signed(16'sh7F62);
43 | assign wn_re[9] = $signed(16'sh7F38);
44 | assign wn_re[10] = $signed(16'sh7F0A);
45 | assign wn_re[11] = $signed(16'sh7ED6);
46 | assign wn_re[12] = $signed(16'sh7E9D);
47 | assign wn_re[13] = $signed(16'sh7E60);
48 | assign wn_re[14] = $signed(16'sh7E1E);
49 | assign wn_re[15] = $signed(16'sh7DD6);
50 | assign wn_re[16] = $signed(16'sh7D8A);
51 | assign wn_re[17] = $signed(16'sh7D3A);
52 | assign wn_re[18] = $signed(16'sh7CE4);
53 | assign wn_re[19] = $signed(16'sh7C89);
54 | assign wn_re[20] = $signed(16'sh7C2A);
55 | assign wn_re[21] = $signed(16'sh7BC6);
56 | assign wn_re[22] = $signed(16'sh7B5D);
57 | assign wn_re[23] = $signed(16'sh7AEF);
58 | assign wn_re[24] = $signed(16'sh7A7D);
59 | assign wn_re[25] = $signed(16'sh7A06);
60 | assign wn_re[26] = $signed(16'sh798A);
61 | assign wn_re[27] = $signed(16'sh790A);
62 | assign wn_re[28] = $signed(16'sh7885);
63 | assign wn_re[29] = $signed(16'sh77FB);
64 | assign wn_re[30] = $signed(16'sh776C);
65 | assign wn_re[31] = $signed(16'sh76D9);
66 | assign wn_re[32] = $signed(16'sh7642);
67 | assign wn_re[33] = $signed(16'sh75A6);
68 | assign wn_re[34] = $signed(16'sh7505);
69 | assign wn_re[35] = $signed(16'sh7460);
70 | assign wn_re[36] = $signed(16'sh73B6);
71 | assign wn_re[37] = $signed(16'sh7308);
72 | assign wn_re[38] = $signed(16'sh7255);
73 | assign wn_re[39] = $signed(16'sh719E);
74 | assign wn_re[40] = $signed(16'sh70E3);
75 | assign wn_re[41] = $signed(16'sh7023);
76 | assign wn_re[42] = $signed(16'sh6F5F);
77 | assign wn_re[43] = $signed(16'sh6E97);
78 | assign wn_re[44] = $signed(16'sh6DCA);
79 | assign wn_re[45] = $signed(16'sh6CF9);
80 | assign wn_re[46] = $signed(16'sh6C24);
81 | assign wn_re[47] = $signed(16'sh6B4B);
82 | assign wn_re[48] = $signed(16'sh6A6E);
83 | assign wn_re[49] = $signed(16'sh698C);
84 | assign wn_re[50] = $signed(16'sh68A7);
85 | assign wn_re[51] = $signed(16'sh67BD);
86 | assign wn_re[52] = $signed(16'sh66D0);
87 | assign wn_re[53] = $signed(16'sh65DE);
88 | assign wn_re[54] = $signed(16'sh64E9);
89 | assign wn_re[55] = $signed(16'sh63EF);
90 | assign wn_re[56] = $signed(16'sh62F2);
91 | assign wn_re[57] = $signed(16'sh61F1);
92 | assign wn_re[58] = $signed(16'sh60EC);
93 | assign wn_re[59] = $signed(16'sh5FE4);
94 | assign wn_re[60] = $signed(16'sh5ED7);
95 | assign wn_re[61] = $signed(16'sh5DC8);
96 | assign wn_re[62] = $signed(16'sh5CB4);
97 | assign wn_re[63] = $signed(16'sh5B9D);
98 | assign wn_re[64] = $signed(16'sh5A82);
99 | assign wn_re[65] = $signed(16'sh5964);
100 | assign wn_re[66] = $signed(16'sh5843);
101 | assign wn_re[67] = $signed(16'sh571E);
102 | assign wn_re[68] = $signed(16'sh55F6);
103 | assign wn_re[69] = $signed(16'sh54CA);
104 | assign wn_re[70] = $signed(16'sh539B);
105 | assign wn_re[71] = $signed(16'sh5269);
106 | assign wn_re[72] = $signed(16'sh5134);
107 | assign wn_re[73] = $signed(16'sh4FFB);
108 | assign wn_re[74] = $signed(16'sh4EC0);
109 | assign wn_re[75] = $signed(16'sh4D81);
110 | assign wn_re[76] = $signed(16'sh4C40);
111 | assign wn_re[77] = $signed(16'sh4AFB);
112 | assign wn_re[78] = $signed(16'sh49B4);
113 | assign wn_re[79] = $signed(16'sh486A);
114 | assign wn_re[80] = $signed(16'sh471D);
115 | assign wn_re[81] = $signed(16'sh45CD);
116 | assign wn_re[82] = $signed(16'sh447B);
117 | assign wn_re[83] = $signed(16'sh4326);
118 | assign wn_re[84] = $signed(16'sh41CE);
119 | assign wn_re[85] = $signed(16'sh4074);
120 | assign wn_re[86] = $signed(16'sh3F17);
121 | assign wn_re[87] = $signed(16'sh3DB8);
122 | assign wn_re[88] = $signed(16'sh3C57);
123 | assign wn_re[89] = $signed(16'sh3AF3);
124 | assign wn_re[90] = $signed(16'sh398D);
125 | assign wn_re[91] = $signed(16'sh3825);
126 | assign wn_re[92] = $signed(16'sh36BA);
127 | assign wn_re[93] = $signed(16'sh354E);
128 | assign wn_re[94] = $signed(16'sh33DF);
129 | assign wn_re[95] = $signed(16'sh326E);
130 | assign wn_re[96] = $signed(16'sh30FC);
131 | assign wn_re[97] = $signed(16'sh2F87);
132 | assign wn_re[98] = $signed(16'sh2E11);
133 | assign wn_re[99] = $signed(16'sh2C99);
134 | assign wn_re[100] = $signed(16'sh2B1F);
135 | assign wn_re[101] = $signed(16'sh29A4);
136 | assign wn_re[102] = $signed(16'sh2827);
137 | assign wn_re[103] = $signed(16'sh26A8);
138 | assign wn_re[104] = $signed(16'sh2528);
139 | assign wn_re[105] = $signed(16'sh23A7);
140 | assign wn_re[106] = $signed(16'sh2224);
141 | assign wn_re[107] = $signed(16'sh209F);
142 | assign wn_re[108] = $signed(16'sh1F1A);
143 | assign wn_re[109] = $signed(16'sh1D93);
144 | assign wn_re[110] = $signed(16'sh1C0C);
145 | assign wn_re[111] = $signed(16'sh1A83);
146 | assign wn_re[112] = $signed(16'sh18F9);
147 | assign wn_re[113] = $signed(16'sh176E);
148 | assign wn_re[114] = $signed(16'sh15E2);
149 | assign wn_re[115] = $signed(16'sh1455);
150 | assign wn_re[116] = $signed(16'sh12C8);
151 | assign wn_re[117] = $signed(16'sh113A);
152 | assign wn_re[118] = $signed(16'sh0FAB);
153 | assign wn_re[119] = $signed(16'sh0E1C);
154 | assign wn_re[120] = $signed(16'sh0C8C);
155 | assign wn_re[121] = $signed(16'sh0AFB);
156 | assign wn_re[122] = $signed(16'sh096B);
157 | assign wn_re[123] = $signed(16'sh07D9);
158 | assign wn_re[124] = $signed(16'sh0648);
159 | assign wn_re[125] = $signed(16'sh04B6);
160 | assign wn_re[126] = $signed(16'sh0324);
161 | assign wn_re[127] = $signed(16'sh0192);
162 | assign wn_re[128] = $signed(16'sh0000);
163 | assign wn_re[129] = $signed(-16'sh0192);
164 | assign wn_re[130] = $signed(-16'sh0324);
165 | assign wn_re[131] = $signed(-16'sh04B6);
166 | assign wn_re[132] = $signed(-16'sh0648);
167 | assign wn_re[133] = $signed(-16'sh07D9);
168 | assign wn_re[134] = $signed(-16'sh096B);
169 | assign wn_re[135] = $signed(-16'sh0AFB);
170 | assign wn_re[136] = $signed(-16'sh0C8C);
171 | assign wn_re[137] = $signed(-16'sh0E1C);
172 | assign wn_re[138] = $signed(-16'sh0FAB);
173 | assign wn_re[139] = $signed(-16'sh113A);
174 | assign wn_re[140] = $signed(-16'sh12C8);
175 | assign wn_re[141] = $signed(-16'sh1455);
176 | assign wn_re[142] = $signed(-16'sh15E2);
177 | assign wn_re[143] = $signed(-16'sh176E);
178 | assign wn_re[144] = $signed(-16'sh18F9);
179 | assign wn_re[145] = $signed(-16'sh1A83);
180 | assign wn_re[146] = $signed(-16'sh1C0C);
181 | assign wn_re[147] = $signed(-16'sh1D93);
182 | assign wn_re[148] = $signed(-16'sh1F1A);
183 | assign wn_re[149] = $signed(-16'sh209F);
184 | assign wn_re[150] = $signed(-16'sh2224);
185 | assign wn_re[151] = $signed(-16'sh23A7);
186 | assign wn_re[152] = $signed(-16'sh2528);
187 | assign wn_re[153] = $signed(-16'sh26A8);
188 | assign wn_re[154] = $signed(-16'sh2827);
189 | assign wn_re[155] = $signed(-16'sh29A4);
190 | assign wn_re[156] = $signed(-16'sh2B1F);
191 | assign wn_re[157] = $signed(-16'sh2C99);
192 | assign wn_re[158] = $signed(-16'sh2E11);
193 | assign wn_re[159] = $signed(-16'sh2F87);
194 | assign wn_re[160] = $signed(-16'sh30FC);
195 | assign wn_re[161] = $signed(-16'sh326E);
196 | assign wn_re[162] = $signed(-16'sh33DF);
197 | assign wn_re[163] = $signed(-16'sh354E);
198 | assign wn_re[164] = $signed(-16'sh36BA);
199 | assign wn_re[165] = $signed(-16'sh3825);
200 | assign wn_re[166] = $signed(-16'sh398D);
201 | assign wn_re[167] = $signed(-16'sh3AF3);
202 | assign wn_re[168] = $signed(-16'sh3C57);
203 | assign wn_re[169] = $signed(-16'sh3DB8);
204 | assign wn_re[170] = $signed(-16'sh3F17);
205 | assign wn_re[171] = $signed(-16'sh4074);
206 | assign wn_re[172] = $signed(-16'sh41CE);
207 | assign wn_re[173] = $signed(-16'sh4326);
208 | assign wn_re[174] = $signed(-16'sh447B);
209 | assign wn_re[175] = $signed(-16'sh45CD);
210 | assign wn_re[176] = $signed(-16'sh471D);
211 | assign wn_re[177] = $signed(-16'sh486A);
212 | assign wn_re[178] = $signed(-16'sh49B4);
213 | assign wn_re[179] = $signed(-16'sh4AFB);
214 | assign wn_re[180] = $signed(-16'sh4C40);
215 | assign wn_re[181] = $signed(-16'sh4D81);
216 | assign wn_re[182] = $signed(-16'sh4EC0);
217 | assign wn_re[183] = $signed(-16'sh4FFB);
218 | assign wn_re[184] = $signed(-16'sh5134);
219 | assign wn_re[185] = $signed(-16'sh5269);
220 | assign wn_re[186] = $signed(-16'sh539B);
221 | assign wn_re[187] = $signed(-16'sh54CA);
222 | assign wn_re[188] = $signed(-16'sh55F6);
223 | assign wn_re[189] = $signed(-16'sh571E);
224 | assign wn_re[190] = $signed(-16'sh5843);
225 | assign wn_re[191] = $signed(-16'sh5964);
226 | assign wn_re[192] = $signed(-16'sh5A82);
227 | assign wn_re[193] = $signed(-16'sh5B9D);
228 | assign wn_re[194] = $signed(-16'sh5CB4);
229 | assign wn_re[195] = $signed(-16'sh5DC8);
230 | assign wn_re[196] = $signed(-16'sh5ED7);
231 | assign wn_re[197] = $signed(-16'sh5FE4);
232 | assign wn_re[198] = $signed(-16'sh60EC);
233 | assign wn_re[199] = $signed(-16'sh61F1);
234 | assign wn_re[200] = $signed(-16'sh62F2);
235 | assign wn_re[201] = $signed(-16'sh63EF);
236 | assign wn_re[202] = $signed(-16'sh64E9);
237 | assign wn_re[203] = $signed(-16'sh65DE);
238 | assign wn_re[204] = $signed(-16'sh66D0);
239 | assign wn_re[205] = $signed(-16'sh67BD);
240 | assign wn_re[206] = $signed(-16'sh68A7);
241 | assign wn_re[207] = $signed(-16'sh698C);
242 | assign wn_re[208] = $signed(-16'sh6A6E);
243 | assign wn_re[209] = $signed(-16'sh6B4B);
244 | assign wn_re[210] = $signed(-16'sh6C24);
245 | assign wn_re[211] = $signed(-16'sh6CF9);
246 | assign wn_re[212] = $signed(-16'sh6DCA);
247 | assign wn_re[213] = $signed(-16'sh6E97);
248 | assign wn_re[214] = $signed(-16'sh6F5F);
249 | assign wn_re[215] = $signed(-16'sh7023);
250 | assign wn_re[216] = $signed(-16'sh70E3);
251 | assign wn_re[217] = $signed(-16'sh719E);
252 | assign wn_re[218] = $signed(-16'sh7255);
253 | assign wn_re[219] = $signed(-16'sh7308);
254 | assign wn_re[220] = $signed(-16'sh73B6);
255 | assign wn_re[221] = $signed(-16'sh7460);
256 | assign wn_re[222] = $signed(-16'sh7505);
257 | assign wn_re[223] = $signed(-16'sh75A6);
258 | assign wn_re[224] = $signed(-16'sh7642);
259 | assign wn_re[225] = $signed(-16'sh76D9);
260 | assign wn_re[226] = $signed(-16'sh776C);
261 | assign wn_re[227] = $signed(-16'sh77FB);
262 | assign wn_re[228] = $signed(-16'sh7885);
263 | assign wn_re[229] = $signed(-16'sh790A);
264 | assign wn_re[230] = $signed(-16'sh798A);
265 | assign wn_re[231] = $signed(-16'sh7A06);
266 | assign wn_re[232] = $signed(-16'sh7A7D);
267 | assign wn_re[233] = $signed(-16'sh7AEF);
268 | assign wn_re[234] = $signed(-16'sh7B5D);
269 | assign wn_re[235] = $signed(-16'sh7BC6);
270 | assign wn_re[236] = $signed(-16'sh7C2A);
271 | assign wn_re[237] = $signed(-16'sh7C89);
272 | assign wn_re[238] = $signed(-16'sh7CE4);
273 | assign wn_re[239] = $signed(-16'sh7D3A);
274 | assign wn_re[240] = $signed(-16'sh7D8A);
275 | assign wn_re[241] = $signed(-16'sh7DD6);
276 | assign wn_re[242] = $signed(-16'sh7E1E);
277 | assign wn_re[243] = $signed(-16'sh7E60);
278 | assign wn_re[244] = $signed(-16'sh7E9D);
279 | assign wn_re[245] = $signed(-16'sh7ED6);
280 | assign wn_re[246] = $signed(-16'sh7F0A);
281 | assign wn_re[247] = $signed(-16'sh7F38);
282 | assign wn_re[248] = $signed(-16'sh7F62);
283 | assign wn_re[249] = $signed(-16'sh7F87);
284 | assign wn_re[250] = $signed(-16'sh7FA7);
285 | assign wn_re[251] = $signed(-16'sh7FC2);
286 | assign wn_re[252] = $signed(-16'sh7FD9);
287 | assign wn_re[253] = $signed(-16'sh7FEA);
288 | assign wn_re[254] = $signed(-16'sh7FF6);
289 | assign wn_re[255] = $signed(-16'sh7FFE);
290 | assign wn_im[0] = $signed(16'sh0000);
291 | assign wn_im[1] = $signed(-16'sh0192);
292 | assign wn_im[2] = $signed(-16'sh0324);
293 | assign wn_im[3] = $signed(-16'sh04B6);
294 | assign wn_im[4] = $signed(-16'sh0648);
295 | assign wn_im[5] = $signed(-16'sh07D9);
296 | assign wn_im[6] = $signed(-16'sh096B);
297 | assign wn_im[7] = $signed(-16'sh0AFB);
298 | assign wn_im[8] = $signed(-16'sh0C8C);
299 | assign wn_im[9] = $signed(-16'sh0E1C);
300 | assign wn_im[10] = $signed(-16'sh0FAB);
301 | assign wn_im[11] = $signed(-16'sh113A);
302 | assign wn_im[12] = $signed(-16'sh12C8);
303 | assign wn_im[13] = $signed(-16'sh1455);
304 | assign wn_im[14] = $signed(-16'sh15E2);
305 | assign wn_im[15] = $signed(-16'sh176E);
306 | assign wn_im[16] = $signed(-16'sh18F9);
307 | assign wn_im[17] = $signed(-16'sh1A83);
308 | assign wn_im[18] = $signed(-16'sh1C0C);
309 | assign wn_im[19] = $signed(-16'sh1D93);
310 | assign wn_im[20] = $signed(-16'sh1F1A);
311 | assign wn_im[21] = $signed(-16'sh209F);
312 | assign wn_im[22] = $signed(-16'sh2224);
313 | assign wn_im[23] = $signed(-16'sh23A7);
314 | assign wn_im[24] = $signed(-16'sh2528);
315 | assign wn_im[25] = $signed(-16'sh26A8);
316 | assign wn_im[26] = $signed(-16'sh2827);
317 | assign wn_im[27] = $signed(-16'sh29A4);
318 | assign wn_im[28] = $signed(-16'sh2B1F);
319 | assign wn_im[29] = $signed(-16'sh2C99);
320 | assign wn_im[30] = $signed(-16'sh2E11);
321 | assign wn_im[31] = $signed(-16'sh2F87);
322 | assign wn_im[32] = $signed(-16'sh30FC);
323 | assign wn_im[33] = $signed(-16'sh326E);
324 | assign wn_im[34] = $signed(-16'sh33DF);
325 | assign wn_im[35] = $signed(-16'sh354E);
326 | assign wn_im[36] = $signed(-16'sh36BA);
327 | assign wn_im[37] = $signed(-16'sh3825);
328 | assign wn_im[38] = $signed(-16'sh398D);
329 | assign wn_im[39] = $signed(-16'sh3AF3);
330 | assign wn_im[40] = $signed(-16'sh3C57);
331 | assign wn_im[41] = $signed(-16'sh3DB8);
332 | assign wn_im[42] = $signed(-16'sh3F17);
333 | assign wn_im[43] = $signed(-16'sh4074);
334 | assign wn_im[44] = $signed(-16'sh41CE);
335 | assign wn_im[45] = $signed(-16'sh4326);
336 | assign wn_im[46] = $signed(-16'sh447B);
337 | assign wn_im[47] = $signed(-16'sh45CD);
338 | assign wn_im[48] = $signed(-16'sh471D);
339 | assign wn_im[49] = $signed(-16'sh486A);
340 | assign wn_im[50] = $signed(-16'sh49B4);
341 | assign wn_im[51] = $signed(-16'sh4AFB);
342 | assign wn_im[52] = $signed(-16'sh4C40);
343 | assign wn_im[53] = $signed(-16'sh4D81);
344 | assign wn_im[54] = $signed(-16'sh4EC0);
345 | assign wn_im[55] = $signed(-16'sh4FFB);
346 | assign wn_im[56] = $signed(-16'sh5134);
347 | assign wn_im[57] = $signed(-16'sh5269);
348 | assign wn_im[58] = $signed(-16'sh539B);
349 | assign wn_im[59] = $signed(-16'sh54CA);
350 | assign wn_im[60] = $signed(-16'sh55F6);
351 | assign wn_im[61] = $signed(-16'sh571E);
352 | assign wn_im[62] = $signed(-16'sh5843);
353 | assign wn_im[63] = $signed(-16'sh5964);
354 | assign wn_im[64] = $signed(-16'sh5A82);
355 | assign wn_im[65] = $signed(-16'sh5B9D);
356 | assign wn_im[66] = $signed(-16'sh5CB4);
357 | assign wn_im[67] = $signed(-16'sh5DC8);
358 | assign wn_im[68] = $signed(-16'sh5ED7);
359 | assign wn_im[69] = $signed(-16'sh5FE4);
360 | assign wn_im[70] = $signed(-16'sh60EC);
361 | assign wn_im[71] = $signed(-16'sh61F1);
362 | assign wn_im[72] = $signed(-16'sh62F2);
363 | assign wn_im[73] = $signed(-16'sh63EF);
364 | assign wn_im[74] = $signed(-16'sh64E9);
365 | assign wn_im[75] = $signed(-16'sh65DE);
366 | assign wn_im[76] = $signed(-16'sh66D0);
367 | assign wn_im[77] = $signed(-16'sh67BD);
368 | assign wn_im[78] = $signed(-16'sh68A7);
369 | assign wn_im[79] = $signed(-16'sh698C);
370 | assign wn_im[80] = $signed(-16'sh6A6E);
371 | assign wn_im[81] = $signed(-16'sh6B4B);
372 | assign wn_im[82] = $signed(-16'sh6C24);
373 | assign wn_im[83] = $signed(-16'sh6CF9);
374 | assign wn_im[84] = $signed(-16'sh6DCA);
375 | assign wn_im[85] = $signed(-16'sh6E97);
376 | assign wn_im[86] = $signed(-16'sh6F5F);
377 | assign wn_im[87] = $signed(-16'sh7023);
378 | assign wn_im[88] = $signed(-16'sh70E3);
379 | assign wn_im[89] = $signed(-16'sh719E);
380 | assign wn_im[90] = $signed(-16'sh7255);
381 | assign wn_im[91] = $signed(-16'sh7308);
382 | assign wn_im[92] = $signed(-16'sh73B6);
383 | assign wn_im[93] = $signed(-16'sh7460);
384 | assign wn_im[94] = $signed(-16'sh7505);
385 | assign wn_im[95] = $signed(-16'sh75A6);
386 | assign wn_im[96] = $signed(-16'sh7642);
387 | assign wn_im[97] = $signed(-16'sh76D9);
388 | assign wn_im[98] = $signed(-16'sh776C);
389 | assign wn_im[99] = $signed(-16'sh77FB);
390 | assign wn_im[100] = $signed(-16'sh7885);
391 | assign wn_im[101] = $signed(-16'sh790A);
392 | assign wn_im[102] = $signed(-16'sh798A);
393 | assign wn_im[103] = $signed(-16'sh7A06);
394 | assign wn_im[104] = $signed(-16'sh7A7D);
395 | assign wn_im[105] = $signed(-16'sh7AEF);
396 | assign wn_im[106] = $signed(-16'sh7B5D);
397 | assign wn_im[107] = $signed(-16'sh7BC6);
398 | assign wn_im[108] = $signed(-16'sh7C2A);
399 | assign wn_im[109] = $signed(-16'sh7C89);
400 | assign wn_im[110] = $signed(-16'sh7CE4);
401 | assign wn_im[111] = $signed(-16'sh7D3A);
402 | assign wn_im[112] = $signed(-16'sh7D8A);
403 | assign wn_im[113] = $signed(-16'sh7DD6);
404 | assign wn_im[114] = $signed(-16'sh7E1E);
405 | assign wn_im[115] = $signed(-16'sh7E60);
406 | assign wn_im[116] = $signed(-16'sh7E9D);
407 | assign wn_im[117] = $signed(-16'sh7ED6);
408 | assign wn_im[118] = $signed(-16'sh7F0A);
409 | assign wn_im[119] = $signed(-16'sh7F38);
410 | assign wn_im[120] = $signed(-16'sh7F62);
411 | assign wn_im[121] = $signed(-16'sh7F87);
412 | assign wn_im[122] = $signed(-16'sh7FA7);
413 | assign wn_im[123] = $signed(-16'sh7FC2);
414 | assign wn_im[124] = $signed(-16'sh7FD9);
415 | assign wn_im[125] = $signed(-16'sh7FEA);
416 | assign wn_im[126] = $signed(-16'sh7FF6);
417 | assign wn_im[127] = $signed(-16'sh7FFE);
418 | assign wn_im[128] = $signed(-16'sh7FFF);
419 | assign wn_im[129] = $signed(-16'sh7FFE);
420 | assign wn_im[130] = $signed(-16'sh7FF6);
421 | assign wn_im[131] = $signed(-16'sh7FEA);
422 | assign wn_im[132] = $signed(-16'sh7FD9);
423 | assign wn_im[133] = $signed(-16'sh7FC2);
424 | assign wn_im[134] = $signed(-16'sh7FA7);
425 | assign wn_im[135] = $signed(-16'sh7F87);
426 | assign wn_im[136] = $signed(-16'sh7F62);
427 | assign wn_im[137] = $signed(-16'sh7F38);
428 | assign wn_im[138] = $signed(-16'sh7F0A);
429 | assign wn_im[139] = $signed(-16'sh7ED6);
430 | assign wn_im[140] = $signed(-16'sh7E9D);
431 | assign wn_im[141] = $signed(-16'sh7E60);
432 | assign wn_im[142] = $signed(-16'sh7E1E);
433 | assign wn_im[143] = $signed(-16'sh7DD6);
434 | assign wn_im[144] = $signed(-16'sh7D8A);
435 | assign wn_im[145] = $signed(-16'sh7D3A);
436 | assign wn_im[146] = $signed(-16'sh7CE4);
437 | assign wn_im[147] = $signed(-16'sh7C89);
438 | assign wn_im[148] = $signed(-16'sh7C2A);
439 | assign wn_im[149] = $signed(-16'sh7BC6);
440 | assign wn_im[150] = $signed(-16'sh7B5D);
441 | assign wn_im[151] = $signed(-16'sh7AEF);
442 | assign wn_im[152] = $signed(-16'sh7A7D);
443 | assign wn_im[153] = $signed(-16'sh7A06);
444 | assign wn_im[154] = $signed(-16'sh798A);
445 | assign wn_im[155] = $signed(-16'sh790A);
446 | assign wn_im[156] = $signed(-16'sh7885);
447 | assign wn_im[157] = $signed(-16'sh77FB);
448 | assign wn_im[158] = $signed(-16'sh776C);
449 | assign wn_im[159] = $signed(-16'sh76D9);
450 | assign wn_im[160] = $signed(-16'sh7642);
451 | assign wn_im[161] = $signed(-16'sh75A6);
452 | assign wn_im[162] = $signed(-16'sh7505);
453 | assign wn_im[163] = $signed(-16'sh7460);
454 | assign wn_im[164] = $signed(-16'sh73B6);
455 | assign wn_im[165] = $signed(-16'sh7308);
456 | assign wn_im[166] = $signed(-16'sh7255);
457 | assign wn_im[167] = $signed(-16'sh719E);
458 | assign wn_im[168] = $signed(-16'sh70E3);
459 | assign wn_im[169] = $signed(-16'sh7023);
460 | assign wn_im[170] = $signed(-16'sh6F5F);
461 | assign wn_im[171] = $signed(-16'sh6E97);
462 | assign wn_im[172] = $signed(-16'sh6DCA);
463 | assign wn_im[173] = $signed(-16'sh6CF9);
464 | assign wn_im[174] = $signed(-16'sh6C24);
465 | assign wn_im[175] = $signed(-16'sh6B4B);
466 | assign wn_im[176] = $signed(-16'sh6A6E);
467 | assign wn_im[177] = $signed(-16'sh698C);
468 | assign wn_im[178] = $signed(-16'sh68A7);
469 | assign wn_im[179] = $signed(-16'sh67BD);
470 | assign wn_im[180] = $signed(-16'sh66D0);
471 | assign wn_im[181] = $signed(-16'sh65DE);
472 | assign wn_im[182] = $signed(-16'sh64E9);
473 | assign wn_im[183] = $signed(-16'sh63EF);
474 | assign wn_im[184] = $signed(-16'sh62F2);
475 | assign wn_im[185] = $signed(-16'sh61F1);
476 | assign wn_im[186] = $signed(-16'sh60EC);
477 | assign wn_im[187] = $signed(-16'sh5FE4);
478 | assign wn_im[188] = $signed(-16'sh5ED7);
479 | assign wn_im[189] = $signed(-16'sh5DC8);
480 | assign wn_im[190] = $signed(-16'sh5CB4);
481 | assign wn_im[191] = $signed(-16'sh5B9D);
482 | assign wn_im[192] = $signed(-16'sh5A82);
483 | assign wn_im[193] = $signed(-16'sh5964);
484 | assign wn_im[194] = $signed(-16'sh5843);
485 | assign wn_im[195] = $signed(-16'sh571E);
486 | assign wn_im[196] = $signed(-16'sh55F6);
487 | assign wn_im[197] = $signed(-16'sh54CA);
488 | assign wn_im[198] = $signed(-16'sh539B);
489 | assign wn_im[199] = $signed(-16'sh5269);
490 | assign wn_im[200] = $signed(-16'sh5134);
491 | assign wn_im[201] = $signed(-16'sh4FFB);
492 | assign wn_im[202] = $signed(-16'sh4EC0);
493 | assign wn_im[203] = $signed(-16'sh4D81);
494 | assign wn_im[204] = $signed(-16'sh4C40);
495 | assign wn_im[205] = $signed(-16'sh4AFB);
496 | assign wn_im[206] = $signed(-16'sh49B4);
497 | assign wn_im[207] = $signed(-16'sh486A);
498 | assign wn_im[208] = $signed(-16'sh471D);
499 | assign wn_im[209] = $signed(-16'sh45CD);
500 | assign wn_im[210] = $signed(-16'sh447B);
501 | assign wn_im[211] = $signed(-16'sh4326);
502 | assign wn_im[212] = $signed(-16'sh41CE);
503 | assign wn_im[213] = $signed(-16'sh4074);
504 | assign wn_im[214] = $signed(-16'sh3F17);
505 | assign wn_im[215] = $signed(-16'sh3DB8);
506 | assign wn_im[216] = $signed(-16'sh3C57);
507 | assign wn_im[217] = $signed(-16'sh3AF3);
508 | assign wn_im[218] = $signed(-16'sh398D);
509 | assign wn_im[219] = $signed(-16'sh3825);
510 | assign wn_im[220] = $signed(-16'sh36BA);
511 | assign wn_im[221] = $signed(-16'sh354E);
512 | assign wn_im[222] = $signed(-16'sh33DF);
513 | assign wn_im[223] = $signed(-16'sh326E);
514 | assign wn_im[224] = $signed(-16'sh30FC);
515 | assign wn_im[225] = $signed(-16'sh2F87);
516 | assign wn_im[226] = $signed(-16'sh2E11);
517 | assign wn_im[227] = $signed(-16'sh2C99);
518 | assign wn_im[228] = $signed(-16'sh2B1F);
519 | assign wn_im[229] = $signed(-16'sh29A4);
520 | assign wn_im[230] = $signed(-16'sh2827);
521 | assign wn_im[231] = $signed(-16'sh26A8);
522 | assign wn_im[232] = $signed(-16'sh2528);
523 | assign wn_im[233] = $signed(-16'sh23A7);
524 | assign wn_im[234] = $signed(-16'sh2224);
525 | assign wn_im[235] = $signed(-16'sh209F);
526 | assign wn_im[236] = $signed(-16'sh1F1A);
527 | assign wn_im[237] = $signed(-16'sh1D93);
528 | assign wn_im[238] = $signed(-16'sh1C0C);
529 | assign wn_im[239] = $signed(-16'sh1A83);
530 | assign wn_im[240] = $signed(-16'sh18F9);
531 | assign wn_im[241] = $signed(-16'sh176E);
532 | assign wn_im[242] = $signed(-16'sh15E2);
533 | assign wn_im[243] = $signed(-16'sh1455);
534 | assign wn_im[244] = $signed(-16'sh12C8);
535 | assign wn_im[245] = $signed(-16'sh113A);
536 | assign wn_im[246] = $signed(-16'sh0FAB);
537 | assign wn_im[247] = $signed(-16'sh0E1C);
538 | assign wn_im[248] = $signed(-16'sh0C8C);
539 | assign wn_im[249] = $signed(-16'sh0AFB);
540 | assign wn_im[250] = $signed(-16'sh096B);
541 | assign wn_im[251] = $signed(-16'sh07D9);
542 | assign wn_im[252] = $signed(-16'sh0648);
543 | assign wn_im[253] = $signed(-16'sh04B6);
544 | assign wn_im[254] = $signed(-16'sh0324);
545 | assign wn_im[255] = $signed(-16'sh0192);
546 |
547 | assign data0_re = wn_re[addr0];
548 | assign data0_im = wn_im[addr0];
549 | assign data1_re = wn_re[addr1];
550 | assign data1_im = wn_im[addr1];
551 | assign data2_re = wn_re[addr2];
552 | assign data2_im = wn_im[addr2];
553 | assign data3_re = wn_re[addr3];
554 | assign data3_im = wn_im[addr3];
555 | assign data4_re = wn_re[addr4];
556 | assign data4_im = wn_im[addr4];
557 | assign data5_re = wn_re[addr5];
558 | assign data5_im = wn_im[addr5];
559 | assign data6_re = wn_re[addr6];
560 | assign data6_im = wn_im[addr6];
561 | assign data7_re = wn_re[addr7];
562 | assign data7_im = wn_im[addr7];
563 |
564 | endmodule
565 |
--------------------------------------------------------------------------------
/scripts/backup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ## Use to backup the whole project
3 | ##
4 | ## By brimonzzy
5 | ## Email: zzzy218@foxmail.com
6 | ##
7 |
8 | cd ..
9 |
10 | mkdir -p backup
11 |
12 | cur_date=$(date +%Y-%m-%d-%H-%M)
13 | echo $cur_date
14 | prj_folder=$(basename "$PWD")
15 |
16 | ## check pigz command
17 | if command -v pigz > /dev/null 2>&1; then
18 | echo "$(pigz -V)"
19 | else
20 | echo "*** 'pigz' no found, please install 'pigz' ***"
21 | exit 1
22 | fi
23 |
24 | cd ..
25 |
26 | tar -cvf - --exclude=backup --exclude=*.fsdb --exclude=*.tar.gz $prj_folder | pigz --best -k > ${prj_folder}-${cur_date}.tar.gz
27 | mv ${prj_folder}-${cur_date}.tar.gz $prj_folder/backup
28 |
--------------------------------------------------------------------------------
/scripts/clean.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ## clean temp files in project
3 | ##
4 | ## By brimonzzy
5 | ## Email: zzzy218@foxmail.com
6 | ##
7 |
8 | cd ..
9 | prj_path=$(pwd)
10 | echo "project path: $prj_path"
11 |
12 | read -p "是否执行该操作?(y/n): " choice
13 | # 判断用户输入
14 | case "$choice" in
15 | y|Y )
16 | ;;
17 | n|N )
18 | exit 1
19 | ;;
20 | * )
21 | echo "无效的输入,请输入 'y' 或 'n'。"
22 | exit 1
23 | ;;
24 | esac
25 |
26 | rm -rf $prj_path/sim/vcs/generated-src
27 | rm -rf $prj_path/sim/vcs/output
28 | rm -rf $prj_path/sim/vcs/verdi_config_file
29 |
30 | rm -rf $prj_path/syn/syn_asic/output
31 | rm -rf $prj_path/syn/syn_asic/syn
32 |
--------------------------------------------------------------------------------
/software/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/software/README.md
--------------------------------------------------------------------------------
/software/bit_reverse.m:
--------------------------------------------------------------------------------
1 | function x_reversed = bit_reverse(x, n_bits)
2 | % Bit-reverse the input vector
3 | % x: input vector
4 | % n_bits: number of bits (log2(N))
5 | % Example:
6 | % x=[0 1 2 3 4 5 6 7]
7 | % n_bits=3
8 | % x_reversed=[0 4 2 6 1 5 3 7]
9 |
10 | N = length(x);
11 | reversed_indices = zeros(1, N);
12 |
13 | for i = 0:N-1
14 | reversed = 0;
15 | for bit_pos = 1:n_bits
16 | reversed = bitshift(reversed, 1);
17 | reversed = reversed + bitget(i, bit_pos);
18 | end
19 | reversed_indices(i + 1) = reversed;
20 | end
21 |
22 | x_reversed = x(reversed_indices + 1); % 转换为Matlab的1-based索引
23 |
24 | end
25 |
--------------------------------------------------------------------------------
/software/fft_fixed.m:
--------------------------------------------------------------------------------
1 | function [X_re, X_im] = fft_fixed(x_re, x_im, N)
2 | % N-point fixed FFT
3 | % Input:
4 | % x_re: real part of input signal (int16)
5 | % x_im: image part of input signal (int16)
6 | % Output:
7 | % X_re: real part of FFT result
8 | % X_im: image part of FFT result
9 |
10 | real = x_re;
11 | imag = x_im;
12 |
13 | % 生成旋转因子
14 | rotation_factors = cell(log2(N), 1);
15 | for stage = 1:log2(N)
16 | m = 2^(log2(N) - stage + 1);
17 | factors = int16(zeros(m/2, 2));
18 | for k = 0:(m/2 - 1)
19 | theta = 2 * pi * k / m;
20 | W_real = cos(theta);
21 | W_imag = -sin(theta);
22 | factors(k+1, 1) = int16(round(W_real * 2^15));
23 | factors(k+1, 2) = int16(round(W_imag * 2^15));
24 | end
25 | rotation_factors{stage} = factors;
26 | end
27 | % W=rotation_factors{1}
28 |
29 | for stage = 1:log2(N)
30 | m = 2^(log2(N) - stage + 1);
31 | half_m = m / 2;
32 | factors = rotation_factors{stage};
33 | for k = 0:(N/m - 1)
34 | for j = 0:(half_m - 1)
35 | idx1 = k * m + j + 1;
36 | idx2 = idx1 + half_m;
37 |
38 | % 提取 x(idx1) 和 x(idx2)
39 | a_re = real(idx1);
40 | a_im = imag(idx1);
41 | b_re = real(idx2);
42 | b_im = imag(idx2);
43 |
44 | % 蝶形运算
45 | temp_re = int16(a_re - b_re);
46 | temp_im = int16(a_im - b_im);
47 | real(idx1) = int16(a_re + b_re);
48 | imag(idx1) = int16(a_im + b_im);
49 |
50 | % 获取旋转因子
51 | W_real = factors(j+1, 1);
52 | W_imag = factors(j+1, 2);
53 |
54 | t_re = int32(temp_re) * int32(W_real) - int32(temp_im) * int32(W_imag);
55 | t_im = int32(temp_re) * int32(W_imag) + int32(temp_im) * int32(W_real);
56 |
57 | % 右移15位并四舍五入
58 | % 逐级处理蝶形运算,每次乘法后右移15位进行四舍五入,加减法后右移1位防止溢出。
59 | t_re = int16(bitshift(t_re + 16384, -15));
60 | t_im = int16(bitshift(t_im + 16384, -15));
61 |
62 | real(idx2) = t_re;
63 | imag(idx2) = t_im;
64 | end
65 | end
66 |
67 | fprintf('Stage%d re0 output:\n', stage);
68 | for ii = 1:N/2
69 | hex_value = dec2hex(typecast(abs(real(ii)), 'uint16'), 4);
70 | fprintf('%s\n', hex_value);
71 | end
72 | fprintf('\n');
73 | fprintf('Stage%d re1 output:\n', stage);
74 | for ii = 1:N/2
75 | hex_value = dec2hex(typecast(abs(real(ii+half_m)), 'uint16'), 4);
76 | fprintf('%s\n', hex_value);
77 | end
78 | fprintf('\n\n\n\n');
79 |
80 | end
81 |
82 | X_re = bit_reverse(real, log2(N));
83 | X_im = bit_reverse(imag, log2(N));
84 |
85 | end
86 |
--------------------------------------------------------------------------------
/software/fft_fixed_run.m:
--------------------------------------------------------------------------------
1 | clc;clear;
2 |
3 | % 设置FFT点数
4 | N = 512;
5 |
6 | % 处理输入数据
7 | t = 0:N-1;
8 | % x_re = 0.0001*flip(1:N);
9 | % x_im = 0.0001*flip(1:N);
10 | x_re = 0.005*sin(t);
11 | x_im = 0.005*sin(t);
12 |
13 | % 输入定点化
14 | % x_re_fixed = int16(x_re);
15 | % x_im_fixed = int16(x_im);
16 | x_re_fixed=int16(round(x_re * 2^15)); % Q15
17 | x_im_fixed=int16(round(x_im * 2^15));
18 |
19 | x_fixed = complex(x_re_fixed, x_im_fixed);
20 |
21 |
22 | % 计算FFT
23 | [X_re,X_im] = fft_fixed(x_re_fixed, x_im_fixed, N);
24 | X_matlab = fft(x_fixed, N);
25 |
26 | X_matlab_fixed_re = int16(real(X_matlab));
27 | X_matlab_fixed_im = int16(imag(X_matlab));
28 |
29 | fprintf('Output:\n');
30 | for ii = 1:N
31 | hex_value = dec2hex(typecast(abs(X_re(ii)), 'uint16'), 4);
32 | fprintf('%d:%s\n', ii-1, hex_value);
33 | end
34 |
35 | % 比较结果
36 | subplot(2,2,1);
37 | plot(abs(X_re));
38 | title('My FFT re');
39 | subplot(2,2,2);
40 | plot(abs(X_matlab_fixed_re));
41 | title('Matlab FFT re');
42 | subplot(2,2,3);
43 | plot(abs(X_im));
44 | title('My FFT im');
45 | subplot(2,2,4);
46 | plot(abs(X_matlab_fixed_im));
47 | title('Matlab FFT im');
48 |
49 | % 计算最大误差
50 | max_error = max(abs(X_re - X_matlab_fixed_re));
51 | fprintf('实部最大误差: %e\n', max_error);
52 | max_error = max(abs(X_im - X_matlab_fixed_im));
53 | fprintf('虚部最大误差: %e\n', max_error);
54 |
--------------------------------------------------------------------------------
/software/fft_float.m:
--------------------------------------------------------------------------------
1 | function X = fft_float(x, N)
2 | % N-point FFT implementation using floating-point model
3 | % Input:
4 | % x: input signal (N points)
5 | % Output:
6 | % X: FFT result
7 |
8 | % Bit-reverse the input
9 | x = bit_reverse(x, log2(N));
10 |
11 | % Process each stage (log2N stages)
12 | for stage = 0:(log2(N)-1)
13 | num_blocks = N / (2^(stage + 1)); % 每一级有多少组
14 | butterflies_per_block = 2^stage; % 每一组有多少个
15 | step = 2^stage;
16 |
17 | % Calculate twiddle factors for this stage
18 | k = 0 : butterflies_per_block - 1;
19 | W = exp(-1j * 2 * pi * k / (2^(stage + 1)));
20 |
21 | for block = 0 : num_blocks - 1
22 | base = block * 2^(stage + 1);
23 |
24 | for b = 0 : butterflies_per_block - 1
25 | idx1 = base + b + 1; % Matlab索引从1开始
26 | idx2 = idx1 + step;
27 |
28 | % 获取旋转因子
29 | w = W(b + 1);
30 |
31 | % 蝶形运算
32 | a = x(idx1);
33 | b_val = x(idx2) * w;
34 |
35 | x(idx1) = a + b_val;
36 | x(idx2) = a - b_val;
37 | end
38 | end
39 | end
40 |
41 | X = x;
42 |
43 | end
44 |
--------------------------------------------------------------------------------
/software/fft_run.m:
--------------------------------------------------------------------------------
1 | clc;clear;
2 |
3 | % FFT点数
4 | N = 64;
5 |
6 | t = 0:N-1;
7 | f = 10;
8 | % x_re = cos(2*pi*f*t/N);
9 | % x_im = sin(2*pi*f*t/N);
10 | % x_re = flip(1:N);
11 | % x_im = flip(1:N);
12 | x_re = cos(1/3*pi*t);
13 | x_im = zeros(1,N);
14 | x = complex(x_re, x_im);
15 |
16 | % 计算FFT
17 | X_my = fft_float(x, N);
18 | X_matlab = fft(x, N);
19 |
20 | % 比较结果
21 | subplot(2,1,1);
22 | plot(abs(X_my));
23 | title('My FFT');
24 | subplot(2,1,2);
25 | plot(abs(X_matlab));
26 | title('Matlab FFT');
27 |
28 | % 计算最大误差
29 | max_error = max(abs(X_my - X_matlab));
30 | fprintf('最大误差: %e\n', max_error);
31 |
--------------------------------------------------------------------------------
/software/ifft_fixed.m:
--------------------------------------------------------------------------------
1 | function [X_re, X_im] = ifft_fixed(x_re, x_im, N)
2 | % N-point fixed FFT
3 | % Input:
4 | % x_re: real part of input signal (int16)
5 | % x_im: image part of input signal (int16)
6 | % Output:
7 | % X_re: real part of FFT result
8 | % X_im: image part of FFT result
9 |
10 | real = x_re;
11 | imag = x_im;
12 |
13 | % 生成旋转因子
14 | rotation_factors = cell(log2(N), 1);
15 | for stage = 1:log2(N)
16 | m = 2^(log2(N) - stage + 1);
17 | factors = int16(zeros(m/2, 2));
18 | for k = 0:(m/2 - 1)
19 | theta = 2 * pi * k / m;
20 | W_real = cos(theta);
21 | W_imag = sin(theta);
22 | factors(k+1, 1) = int16(round(W_real * 2^15));
23 | factors(k+1, 2) = int16(round(W_imag * 2^15));
24 | end
25 | rotation_factors{stage} = factors;
26 | end
27 | W=rotation_factors{1}
28 |
29 | for stage = 1:log2(N)
30 | m = 2^(log2(N) - stage + 1);
31 | half_m = m / 2;
32 | factors = rotation_factors{stage};
33 | for k = 0:(N/m - 1)
34 | for j = 0:(half_m - 1)
35 | idx1 = k * m + j + 1;
36 | idx2 = idx1 + half_m;
37 |
38 | % 提取 x(idx1) 和 x(idx2)
39 | a_re = real(idx1);
40 | a_im = imag(idx1);
41 | b_re = real(idx2);
42 | b_im = imag(idx2);
43 |
44 | % 蝶形运算
45 | temp_re = int16(a_re - b_re);
46 | temp_im = int16(a_im - b_im);
47 | real(idx1) = int16(a_re + b_re);
48 | imag(idx1) = int16(a_im + b_im);
49 |
50 | % 获取旋转因子
51 | W_real = factors(j+1, 1);
52 | W_imag = factors(j+1, 2);
53 |
54 | t_re = int32(temp_re) * int32(W_real) - int32(temp_im) * int32(W_imag);
55 | t_im = int32(temp_re) * int32(W_imag) + int32(temp_im) * int32(W_real);
56 |
57 | % 右移15位并四舍五入
58 | % 逐级处理蝶形运算,每次乘法后右移15位进行四舍五入,加减法后右移1位防止溢出。
59 | t_re = int16(bitshift(t_re + 16384, -15));
60 | t_im = int16(bitshift(t_im + 16384, -15));
61 |
62 | real(idx2) = t_re;
63 | imag(idx2) = t_im;
64 | end
65 | end
66 |
67 | fprintf('Stage%d re0 output:\n', stage);
68 | for ii = 1:N/2
69 | hex_value = dec2hex(typecast(abs(real(ii)), 'uint16'), 4);
70 | fprintf('%s\n', hex_value);
71 | end
72 | fprintf('\n');
73 | fprintf('Stage%d re1 output:\n', stage);
74 | for ii = 1:N/2
75 | hex_value = dec2hex(typecast(abs(real(ii+half_m)), 'uint16'), 4);
76 | fprintf('%s\n', hex_value);
77 | end
78 | fprintf('\n\n\n\n');
79 |
80 | end
81 |
82 | X_re = bit_reverse(real, log2(N));
83 | X_im = bit_reverse(imag, log2(N));
84 |
85 | shift = log2(N);
86 | for i = 1:N
87 | X_re(i) = int16(bitshift(X_re(i), -shift));
88 | X_im(i) = int16(bitshift(X_im(i), -shift));
89 | end
90 |
91 | end
92 |
--------------------------------------------------------------------------------
/software/ifft_fixed_run.m:
--------------------------------------------------------------------------------
1 | clc;clear;
2 |
3 | % 设置FFT点数
4 | N = 256;
5 |
6 | % 处理原输入数据
7 | t = 0:N-1;
8 | x_re = 0.00003*flip(1:N);
9 | x_im = 0.00003*flip(1:N);
10 |
11 | % 原输入定点化
12 | x_re_fixed=int16(round(x_re * 2^15)); % Q15
13 | x_im_fixed=int16(round(x_im * 2^15));
14 | x_fixed = complex(x_re_fixed, x_im_fixed);
15 |
16 | % 计算FFT
17 | X_matlab = fft(x_fixed, N);
18 | X_matlab_fixed_re = int16(real(X_matlab));
19 | X_matlab_fixed_im = int16(imag(X_matlab));
20 | X_matlab_fixed = complex(X_matlab_fixed_re, X_matlab_fixed_im);
21 |
22 | % 计算IFFT
23 | X_matlab_ifft = ifft(X_matlab_fixed, N);
24 | [X_ifft_re, X_ifft_im] = ifft_fixed(X_matlab_fixed_re, X_matlab_fixed_im, N);
25 |
26 | X_matlab_ifft_fixed_re = int16(real(X_matlab_ifft));
27 | X_matlab_ifft_fixed_im = int16(imag(X_matlab_ifft));
28 |
29 |
30 | % fprintf('Output:\n');
31 | % for ii = 1:N
32 | % hex_value = dec2hex(typecast(abs(X_re(ii)), 'uint16'), 4);
33 | % fprintf('%d:%s\n', ii-1, hex_value);
34 | % end
35 |
36 | % 比较结果
37 | subplot(2,2,1);
38 | plot(abs(X_ifft_re));
39 | title('My IFFT re');
40 | subplot(2,2,2);
41 | plot(abs(X_matlab_ifft_fixed_re));
42 | title('Matlab IFFT re');
43 | subplot(2,2,3);
44 | plot(abs(X_ifft_im));
45 | title('My IFFT im');
46 | subplot(2,2,4);
47 | plot(abs(X_matlab_ifft_fixed_im));
48 | title('Matlab IFFT im');
49 |
50 | % 计算最大误差
51 | max_error = max(abs(X_ifft_re - X_matlab_ifft_fixed_re));
52 | fprintf('实部最大误差: %e\n', max_error);
53 | max_error = max(abs(X_ifft_im - X_matlab_ifft_fixed_im));
54 | fprintf('虚部最大误差: %e\n', max_error);
55 |
--------------------------------------------------------------------------------
/software/ifft_input_gen.m:
--------------------------------------------------------------------------------
1 | function ifft_input_gen(N)
2 | % 生成激励的verilog代码
3 |
4 | % 处理原输入数据
5 | x_re = 0.00003*flip(1:N);
6 | x_im = 0.00003*flip(1:N);
7 |
8 | % 原输入定点化
9 | x_re_fixed=int16(round(x_re * 2^15)); % Q15
10 | x_im_fixed=int16(round(x_im * 2^15));
11 | x_fixed = complex(x_re_fixed, x_im_fixed);
12 |
13 | % 计算FFT
14 | X_matlab = fft(x_fixed, N);
15 | X_re = int16(real(X_matlab));
16 | X_im = int16(imag(X_matlab));
17 |
18 | for ii = 1:N
19 | hex_value = dec2hex(typecast(X_re(ii), 'uint16'), 4);
20 | fprintf('%s\n', hex_value);
21 | end
22 | fprintf("\n\n\n");
23 | for ii = 1:N
24 | hex_value = dec2hex(typecast(X_im(ii), 'uint16'), 4);
25 | fprintf('%s\n', hex_value);
26 | end
27 |
28 | end
29 |
--------------------------------------------------------------------------------
/software/input_gen.m:
--------------------------------------------------------------------------------
1 | function input_gen(N)
2 | % 生成激励的verilog代码
3 |
4 | n=0:N-1;
5 |
6 | % 输入激励
7 | in_re = 0.005*sin(n);
8 | in_im = 0.005*sin(n);
9 | % 定点化输入激励
10 | x_re=int16(round(in_re * 2^15)); % Q15
11 | x_im=int16(round(in_im * 2^15));
12 |
13 | fprintf('reg [15:0] x_re;\n');
14 | fprintf('reg [15:0] x_re;\n\n');
15 |
16 | for ii = 1:N
17 | hex_value = dec2hex(typecast(x_re(ii), 'uint16'), 4);
18 | fprintf('%s\n', hex_value);
19 | end
20 | fprintf("\n\n\n");
21 | for ii = 1:N
22 | hex_value = dec2hex(typecast(x_im(ii), 'uint16'), 4);
23 | fprintf('%s\n', hex_value);
24 | end
25 |
26 | end
27 |
--------------------------------------------------------------------------------
/software/wave.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 |
3 | def read_hex_data_from_file(file_name):
4 | with open(file_name, 'r') as file:
5 | data = file.read().split()
6 | return [int(value, 16) for value in data]
7 |
8 | def plot_re_im(re_data, im_data):
9 | print(len(re_data))
10 | plt.figure(figsize=(12, 5))
11 |
12 | plt.subplot(1, 2, 1)
13 | # plt.plot(range(len(re_data)), re_data, marker='o', color='blue', linestyle='-', label='Real Part')
14 | plt.plot(range(len(re_data)), re_data, color='blue', linestyle='-', label='Real Part')
15 | plt.xlabel('Index')
16 | plt.ylabel('Real')
17 | plt.title('FFT Real output')
18 | plt.grid(True)
19 | plt.legend()
20 |
21 | plt.subplot(1, 2, 2)
22 | # plt.plot(range(len(im_data)), im_data, marker='o', color='red', linestyle='-', label='Imaginary Part')
23 | plt.plot(range(len(im_data)), im_data, color='red', linestyle='-', label='Imaginary Part')
24 | plt.xlabel('Index')
25 | plt.ylabel('Imag')
26 | plt.title('FFT Imag output')
27 | plt.grid(True)
28 | plt.legend()
29 |
30 | plt.tight_layout()
31 | plt.show()
32 |
33 | re_data = read_hex_data_from_file('../rtl/sim/test_vector/fft_output_re.txt')
34 | im_data = read_hex_data_from_file('../rtl/sim/test_vector/fft_output_im.txt')
35 |
36 |
37 | plot_re_im(re_data, im_data)
38 |
--------------------------------------------------------------------------------
/software/wn_gen.m:
--------------------------------------------------------------------------------
1 | function wn_gen(N, IFFT)
2 | % 生成N点FFT的旋转因子ROM的verilog代码
3 |
4 | if IFFT
5 | n=0:(N/2-1);
6 | w_re=cos(2*pi*n/N);
7 | wn_re=int16(round(w_re * 2^15));
8 | w_im=sin(2*pi*n/N);
9 | wn_im=int16(round(w_im * 2^15));
10 | else
11 | n=0:(N/2-1);
12 | w_re=cos(2*pi*n/N);
13 | wn_re=int16(round(w_re * 2^15));
14 | w_im=-sin(2*pi*n/N);
15 | wn_im=int16(round(w_im * 2^15));
16 | end
17 |
18 | % 打印实部赋值
19 | for ii = 1:(N/2)
20 | if wn_re(ii) >= 0
21 | hex_value = dec2hex(typecast(wn_re(ii), 'uint16'), 4);
22 | fprintf('assign wn_re[%d] = $signed(16''sh%s);\n', ii-1, hex_value);
23 | else
24 | hex_value = dec2hex(typecast(abs(wn_re(ii)), 'uint16'), 4);
25 | fprintf('assign wn_re[%d] = $signed(-16''sh%s);\n', ii-1, hex_value);
26 | end
27 | end
28 |
29 | % 打印虚部赋值
30 | for ii = 1:(N/2)
31 | if wn_im(ii) >= 0
32 | hex_value = dec2hex(typecast(wn_im(ii), 'uint16'), 4);
33 | fprintf('assign wn_im[%d] = $signed(16''sh%s);\n', ii-1, hex_value);
34 | else
35 | hex_value = dec2hex(typecast(abs(wn_im(ii)), 'uint16'), 4);
36 | fprintf('assign wn_im[%d] = $signed(-16''sh%s);\n', ii-1, hex_value);
37 | end
38 | end
39 |
40 | end
41 |
--------------------------------------------------------------------------------
/syn/syn_asic/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !*/
3 | !.gitignore
4 | !Makefile
5 | !*.md
6 | !/scripts/*
7 |
8 |
--------------------------------------------------------------------------------
/syn/syn_asic/Makefile:
--------------------------------------------------------------------------------
1 | ## by BriMon
2 | ## Email: zzybr@qq.com
3 | ## DC synthesis flow
4 | ##
5 | ## make syn MODEL_NAME= CLK= RST=
6 | ## make clean
7 | ##
8 |
9 | ## parameter
10 | MODEL_NAME?=fft_multimode
11 | CLK?=clk
12 | RST?=rst_n
13 |
14 |
15 | DC:=dc_shell
16 |
17 | base_dir:=$(abspath .)
18 | db_dir:=$(base_dir)/db
19 | output_dir:=$(base_dir)/output
20 | syn_reslut_dir:=$(base_dir)/syn
21 | script_dir:=$(base_dir)/scripts
22 | rtl_src_dir:=$(base_dir)/../../rtl/src
23 |
24 | syn_files ?= $(syn_reslut_dir)/syn_files.f
25 |
26 | help:
27 | @echo " - make syn MODEL_NAME= RST= CLK="
28 | @echo " - make clean"
29 |
30 |
31 | .PHONY: syn clean
32 |
33 | syn: $(syn_files) update_synflow
34 | cd output && $(DC) -f $(script_dir)/synflow.tcl -output_log_file ./syn/log/syn.log
35 |
36 | update_synflow:
37 | sed -i 's/^set TOP_DESIGN .*/set TOP_DESIGN $(MODEL_NAME)/' $(script_dir)/synflow.tcl
38 | sed -i 's/^set RST_NAME .*/set RST_NAME $(RST)/' $(script_dir)/sdc.tcl
39 | sed -i 's/^set CLK_NAME .*/set CLK_NAME $(CLK)/' $(script_dir)/sdc.tcl
40 |
41 | $(output_dir):
42 | mkdir -p $@
43 |
44 | $(syn_reslut_dir):
45 | mkdir -p $@ && mkdir -p $(syn_reslut_dir)/mapped $(syn_reslut_dir)/report $(syn_reslut_dir)/unmapped $(syn_reslut_dir)/log
46 |
47 | $(syn_files): | $(syn_reslut_dir) $(output_dir)
48 | touch $@ && find $(rtl_src_dir) -name "*.v" -o -name "*.h" -o -name "*.vh" -o -name "*.svh" >> $@
49 |
50 | clean:
51 | rm -rf output syn
52 |
--------------------------------------------------------------------------------
/syn/syn_asic/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/syn/syn_asic/README.md
--------------------------------------------------------------------------------
/syn/syn_asic/scripts/.synopsys_dc.setup:
--------------------------------------------------------------------------------
1 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2 | # Library Setup
3 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
4 |
5 | #set search_path "$search_path ./db/tsmc90"
6 | #set target_library "typical.db"
7 | #set link_library "* typical.db"
8 | #set symbol_library "tsmc090.sdb"
9 |
10 | #echo "\n\nSettings:"
11 | #echo "search_path: $search_path"
12 | #echo "link_library: $link_library"
13 | #echo "target_library: $target_library"
14 | #echo "symbol_library: $symbol_library"
15 |
16 |
17 | #define_design_lib DEFAULT -path ./analyzed
18 |
19 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
20 | # History
21 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22 |
23 | history keep 200
24 |
25 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
26 | # Aliases
27 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
28 |
29 | alias h history
30 | alias rc "report_constraint -all_violators"
31 | alias rt report_timing
32 | alias ra report_area
33 | alias page_on {set sh_enable_page_mode true}
34 | alias page_off {set sh_enable_page_mode false}
35 | alias fr "remove_design -designs"
36 |
37 | echo "\n\nI am ready...\n"
38 |
--------------------------------------------------------------------------------
/syn/syn_asic/scripts/main.py:
--------------------------------------------------------------------------------
1 |
2 | import os
3 |
4 | script1_file_dir = "/home/yian/workspace/seq_detector/syn/syn_asic/scripts/synflow.tcl"
5 | script2_file_dir = "/home/yian/workspace/seq_detector/syn/syn_asic/scripts/sdc.tcl"
6 | design_file_dir = "/home/yian/workspace/seq_detector/rtl/src"
7 |
8 | def CopyScript():
9 | os.system('cp {} ../syn/script/'.format(script1_file_dir))
10 | os.system('cp {} ../syn/script/'.format(script2_file_dir))
11 |
12 |
13 | def create_SynFlow(design):
14 | text = """
15 | #--------------------------Specify Libraries--------------------------
16 | set search_path "$search_path /home/yian/workspace/seq_detector/syn/syn_asic/db/tsmc90"
17 | set target_library "fast.db"
18 | set link_library "* fast.db"
19 | set symbol_library "tsmc090.sdb"
20 |
21 | echo "\n\nSettings:"
22 | echo "search_path: $search_path"
23 | echo "link_library: $link_library"
24 | echo "target_library: $target_library"
25 | echo "\n\nI'm Ready!"
26 | #--------------------------Prepare Filelist---------------------------
27 | set FILE_LIST ""
28 | set f [open "../scripts/files_syn.fl" r]
29 | while {![eof $f]} {
30 | gets $f line
31 | append FILE_LIST "$line "
32 | }
33 | echo $FILE_LIST
34 | close $f
35 |
36 | #--------------------------Read Designs------------------------------
37 |
38 | # Reset all constraints
39 | # reset_design
40 |
41 | set TOP_DESIGN seq_detector
42 | analyze -format verilog $FILE_LIST
43 | elaborate $TOP_DESIGN
44 |
45 | #------------------------Set Current Design&&Link Designs--------------------------
46 | #current_design $TOP_DESIGN(auto)
47 | #link(auto)
48 |
49 | #-------------------------------SDC----------------------------------
50 | source ../syn/script/sdc.tcl
51 |
52 | #--------------------Map and Optimize the Design---------------------
53 | compile_ultra -no_autoungroup -incremental -no_boundary_optimization
54 | #----------------------Save Design Database--------------------------
55 | change_names -rules verilog -hierarchy
56 | set_fix_multiple_port_nets -all -buffer_constants
57 | #---------------Check the Synthesized Design for Consistency---------
58 | check_design -summary > ../syn/report/check_design.rpt
59 | check_timing > ../syn/report/check_timing.rpt
60 | #---------------------Report Timing and Area-------------------------
61 | report_qor > ../syn/report/$TOP_DESIGN.qor_rpt
62 | report_timing -max_paths 1000 > ../syn/report/$TOP_DESIGN.timing_rpt
63 | report_timing -path full > ../syn/report/$TOP_DESIGN.full_timing_rpt
64 | report_timing -delay max > ../syn/report/$TOP_DESIGN.setup_timing_rpt
65 | report_timing -delay min > ../syn/report/$TOP_DESIGN.hold_timing_rpt
66 | report_reference > ../syn/report/$TOP_DESIGN.ref_rpt
67 | report_area > ../syn/report/$TOP_DESIGN.area_rpt
68 | report_constraints > ../syn/report/$TOP_DESIGN.const_rpt
69 | report_constraint -all_violators > ../syn/report/$TOP_DESIGN.violators_rpt
70 | report_power > ../syn/report/$TOP_DESIGN.power_rpt
71 | check_timing > ../syn/log/last_check_timing.log
72 | #---------------------Generate Files -------------------------
73 | write -f verilog -hierarchy -output ../syn/mapped/$TOP_DESIGN.v
74 | write_sdc ../syn/mapped/$TOP_DESIGN.sdc
75 | write_sdf -context verilog ../syn/mapped/$TOP_DESIGN.sdf
76 |
77 | """
78 | return text
79 |
80 |
81 | def create_Sdc(design):
82 | text = """
83 | #==================================Env Vars===================================
84 | set RST_NAME rst_n
85 | set CLK_NAME clk
86 |
87 | set CLK_PERIOD_I 7
88 | set CLK_PERIOD [expr $CLK_PERIOD_I*0.95]
89 | set CLK_SKEW [expr $CLK_PERIOD*0.01]
90 | set CLK_SOURCE_LATENCY [expr $CLK_PERIOD*0.1]
91 | set CLK_NETWORK_LATENCY [expr $CLK_PERIOD*0.1]
92 | set CLK_TRAN [expr $CLK_PERIOD*0.01]
93 |
94 | set INPUT_DELAY_MAX [expr $CLK_PERIOD*0.4]
95 | set INPUT_DELAY_MIN 0
96 | set OUTPUT_DELAY_MAX [expr $CLK_PERIOD*0.4]
97 | set OUTPUT_DELAY_MIN 0
98 |
99 | set MAX_FANOUT 6
100 | set MAX_TRAN 5
101 | set MAX_CAP 1.5
102 |
103 | set ALL_INPUT_EX_CLK [remove_from_collection [all_inputs] [get_ports $CLK_NAME]]
104 | #==================================Define Design Environment=========================
105 | #GUIDANCE: use the default
106 | set_max_area 0
107 | #set_max_transition $MAX_TRAN [current_design]
108 | #set_max_fanout $MAX_FANOUT [current_design]
109 | #set_max_capacitance $MAX_CAP [current_design]
110 |
111 | #============================= Set Design Constraints=========================
112 | #--------------------------------Clock and Reset Definition----------------------------
113 | set_drive 0 [get_ports $CLK_NAME]
114 | create_clock -name $CLK_NAME -period $CLK_PERIOD [get_ports $CLK_NAME]
115 | set_dont_touch_network [get_ports $CLK_NAME]
116 |
117 | set_clock_uncertainty $CLK_SKEW [get_clocks $CLK_NAME]
118 | set_clock_transition $CLK_TRAN [all_clocks]
119 | set_clock_latency -source $CLK_SOURCE_LATENCY [get_clocks $CLK_NAME]
120 | set_clock_latency -max $CLK_NETWORK_LATENCY [get_clocks $CLK_NAME]
121 | #rst_ports
122 | set_drive 0 [get_ports $RST_NAME]
123 | set_dont_touch_network [get_ports $RST_NAME]
124 | set_false_path -from [get_ports $RST_NAME]
125 | set_ideal_network -no_propagate [get_ports $RST_NAME]
126 | set_ideal_network -no_propagate [get_ports $CLK_NAME]
127 |
128 |
129 | #--------------------------------I/O Constraint-----------------------------
130 | set_input_delay -max $INPUT_DELAY_MAX -clock $CLK_NAME $ALL_INPUT_EX_CLK
131 | set_input_delay -min $INPUT_DELAY_MIN -clock $CLK_NAME $ALL_INPUT_EX_CLK -add
132 | set_output_delay -max $OUTPUT_DELAY_MAX -clock $CLK_NAME [all_outputs]
133 | set_output_delay -min $OUTPUT_DELAY_MIN -clock $CLK_NAME [all_outputs] -add
134 | set_load 0.2 [all_outputs]
135 |
136 | """
137 | return text
138 |
139 |
140 | def createFile():
141 | prjname = "seq_detector"
142 | with open(f"../syn/script/synflow.tcl", "w") as f:
143 | synflow = create_SynFlow(prjname)
144 | f.write(synflow)
145 |
146 | with open(f"../syn/script/sdc.tcl", "w") as f:
147 | sdc = create_Sdc(prjname)
148 | f.write(sdc)
149 |
150 |
151 | if __name__ == "__main__":
152 | os.system('rm -rf ../syn ./files_syn.fl ../temp')
153 | os.system('mkdir -p ../syn/mapped ../syn/report ../syn/script ../syn/unmapped ../syn/log ../temp')
154 | createFile()
155 | os.system("find /home/yian/workspace/seq_detector/rtl/src/ -name \"*.v\" > files_syn.fl")
156 | # CopyScript()
157 | os.system("cp .synopsys_dc.setup ../temp") # copy dc setup file
158 | os.system('cd ../temp && dc_shell -f ../syn/script/synflow.tcl -output_log_file ../syn/log/syn.log')
159 |
160 |
--------------------------------------------------------------------------------
/syn/syn_asic/scripts/sdc.tcl:
--------------------------------------------------------------------------------
1 | #==================================Env Vars===================================
2 | set RST_NAME rst_n
3 | set CLK_NAME clk
4 |
5 | set CLK_PERIOD_I 1.5
6 | set CLK_PERIOD [expr $CLK_PERIOD_I*0.95]
7 | set CLK_SKEW [expr $CLK_PERIOD*0.005]
8 | set CLK_SOURCE_LATENCY [expr $CLK_PERIOD*0.01]
9 | set CLK_NETWORK_LATENCY [expr $CLK_PERIOD*0.005]
10 | set CLK_TRAN [expr $CLK_PERIOD*0.005]
11 |
12 | set INPUT_DELAY_MAX [expr $CLK_PERIOD*0.2]
13 | set INPUT_DELAY_MIN 0
14 | set OUTPUT_DELAY_MAX [expr $CLK_PERIOD*0.2]
15 | set OUTPUT_DELAY_MIN 0
16 |
17 | set MAX_FANOUT 6
18 | set MAX_TRAN 5
19 | set MAX_CAP 1.5
20 |
21 | set ALL_INPUT_EX_CLK [remove_from_collection [all_inputs] [get_ports $CLK_NAME]]
22 |
23 | #==================================Define Design Environment=========================
24 | set_max_area 0
25 | #set_max_transition $MAX_TRAN [current_design]
26 | #set_max_fanout $MAX_FANOUT [current_design]
27 | #set_max_capacitance $MAX_CAP [current_design]
28 |
29 | #============================= Set Design Constraints=========================
30 | #--------------------------------Clock and Reset Definition----------------------------
31 | set_drive 0 [get_ports $CLK_NAME]
32 | create_clock -name $CLK_NAME -period $CLK_PERIOD [get_ports $CLK_NAME]
33 | set_dont_touch_network [get_ports $CLK_NAME]
34 |
35 | set_clock_uncertainty $CLK_SKEW [get_clocks $CLK_NAME]
36 | set_clock_transition $CLK_TRAN [all_clocks]
37 | set_clock_latency -source $CLK_SOURCE_LATENCY [get_clocks $CLK_NAME]
38 | set_clock_latency -max $CLK_NETWORK_LATENCY [get_clocks $CLK_NAME]
39 | #rst_ports
40 | set_drive 0 [get_ports $RST_NAME]
41 | set_dont_touch_network [get_ports $RST_NAME]
42 | set_false_path -from [get_ports $RST_NAME]
43 |
44 | set_ideal_network -no_propagate [get_ports $RST_NAME]
45 | set_ideal_network -no_propagate [get_ports $CLK_NAME]
46 |
47 | #--------------------------------I/O Constraint-----------------------------
48 | set_input_delay -max $INPUT_DELAY_MAX -clock $CLK_NAME $ALL_INPUT_EX_CLK
49 | set_input_delay -min $INPUT_DELAY_MIN -clock $CLK_NAME $ALL_INPUT_EX_CLK -add
50 | set_output_delay -max $OUTPUT_DELAY_MAX -clock $CLK_NAME [all_outputs]
51 | set_output_delay -min $OUTPUT_DELAY_MIN -clock $CLK_NAME [all_outputs] -add
52 | set_load 0.2 [all_outputs]
53 |
--------------------------------------------------------------------------------
/syn/syn_asic/scripts/synflow.tcl:
--------------------------------------------------------------------------------
1 | #--------------------------Specify Libraries--------------------------
2 | set search_path "$search_path\
3 | /tools/PDK/tsmc28nm/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tcbn28hpcplusbwp40p140_180a\
4 | /tools/PDK/tsmc40nm/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tcbn40lpbwp_200a\
5 | /home/brimon/workspace/multi-mode-fft-processor/rtl/src/include"
6 |
7 | ## tsmc28
8 | set target_library "tcbn28hpcplusbwp40p140ffg0p88v0c.db\
9 | /home/brimon/workspace/multi-mode-fft-processor/syn/syn_asic/sram/sramsp16x256_tsmc28hpc_ffg0p99v0c.db"
10 | set link_library "* tcbn28hpcplusbwp40p140ffg0p88v0c.db"
11 |
12 | ## tsmc40
13 | # set target_library "tcbn40lpbwpbc.db\
14 | # "
15 | # set link_library "* tcbn40lpbwpbc.db"
16 |
17 | ## tsmc90
18 | # set target_library "fast.db"
19 | # set link_library "* fast.db"
20 | ## smic40
21 | # set target_library "scc40nll_hs_rvt_ff_v1p21_-40c_basic.db"
22 | # set link_library "* scc40nll_hs_rvt_ff_v1p21_-40c_basic.db"
23 |
24 | ## for DesignWare use
25 | # set synthetic_library "dw_foundation.sldb"
26 | # set link_library "* fast.db $synthetic_library"
27 |
28 | ## tsmc90
29 | # set symbol_library "tsmc090.sdb"
30 | ## smic40
31 | # set symbol_library "SCC40NLL_HS_RVT_V0p1.sdb"
32 |
33 |
34 |
35 | echo "\n\nSettings:"
36 | echo "search_path: $search_path"
37 | echo "link_library: $link_library"
38 | echo "target_library: $target_library"
39 | echo "\n\nI'm Ready!"
40 | #--------------------------Prepare Filelist---------------------------
41 | set FILE_LIST ""
42 | set f [open "../syn/syn_files.f" r]
43 | while {![eof $f]} {
44 | gets $f line
45 | append FILE_LIST "$line "
46 | }
47 | echo $FILE_LIST
48 | close $f
49 |
50 | #--------------------------Read Designs------------------------------
51 |
52 | # Reset all constraints
53 | # reset_design
54 | set TOP_DESIGN fft_multimode
55 |
56 | analyze -format verilog $FILE_LIST
57 | elaborate $TOP_DESIGN
58 |
59 | #------------------------Set Current Design&&Link Designs--------------------------
60 | current_design $TOP_DESIGN
61 | link
62 |
63 | #-------------------------------SDC----------------------------------
64 | source ../scripts/sdc.tcl
65 |
66 | #--------------------Map and Optimize the Design---------------------
67 | compile_ultra -no_autoungroup -incremental -no_boundary_optimization
68 | # compile_ultra
69 | #----------------------Save Design Database--------------------------
70 | change_names -rules verilog -hierarchy
71 | set_fix_multiple_port_nets -all -buffer_constants
72 | #---------------Check the Synthesized Design for Consistency---------
73 | check_design -summary > ../syn/report/check_design.rpt
74 | check_timing > ../syn/report/check_timing.rpt
75 | #---------------------Report Timing and Area-------------------------
76 | report_qor > ../syn/report/qor_$TOP_DESIGN.rpt
77 | report_timing -max_paths 1000 > ../syn/report/timing_$TOP_DESIGN.rpt
78 | report_timing -path full > ../syn/report/full_timing_$TOP_DESIGN.rpt
79 | report_timing -delay max > ../syn/report/setup_timing_$TOP_DESIGN.rpt
80 | report_timing -delay min > ../syn/report/hold_timing_$TOP_DESIGN.rpt
81 | report_reference > ../syn/report/ref_$TOP_DESIGN.rpt
82 | report_area > ../syn/report/area_$TOP_DESIGN.rpt
83 | report_constraints > ../syn/report/const_$TOP_DESIGN.rpt
84 | report_constraint -all_violators > ../syn/report/violators_$TOP_DESIGN.rpt
85 | report_power > ../syn/report/power_$TOP_DESIGN.rpt
86 | check_timing > ../syn/log/last_check_timing.log
87 |
88 | #---------------------Generate Files -------------------------
89 | write -f verilog -hierarchy -output ../syn/mapped/$TOP_DESIGN.v
90 | write_sdc ../syn/mapped/$TOP_DESIGN.sdc
91 | write_sdf -context verilog ../syn/mapped/$TOP_DESIGN.sdf
92 | write -hierarchy -format ddc -output ../syn/mapped/$TOP_DESIGN.ddc
93 |
--------------------------------------------------------------------------------
/syn/syn_fpga/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !*/
3 | !.gitignore
4 | !Makefile
5 | !*.md
6 | !*.tcl
7 | !*.setup
8 | !/quartus/*
9 | !/vivado/*
10 |
--------------------------------------------------------------------------------
/syn/syn_fpga/quartus/Makefile:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BriMonzZY/multi-mode-fft-processor/976bf9512f40cdac07363e99d41b312627e83921/syn/syn_fpga/quartus/Makefile
--------------------------------------------------------------------------------
/syn/syn_fpga/vivado/Makefile:
--------------------------------------------------------------------------------
1 | ## by BriMon
2 | ##
3 | ## Vivado
4 | ##
5 | ## make synth
6 | ## make impl
7 | ## make all
8 | ## make elaborate
9 | ##
10 |
11 |
12 | MAX_CPU := $(shell nproc)
13 | VIVADO ?= vivado
14 | VIVADO_OPTS ?= -nolog -nojournal -mode batch
15 |
16 |
17 | FPGA_PART ?= xc7z020clg400-1
18 | MODEL_NAME ?= fft_multimode
19 |
20 | RTL ?= v.........
21 | CONSTRAINTS ?= xdc..........
22 |
23 |
24 | base_dir := $(abspath .)
25 | SCRIPTS := $(base_dir)/scripts
26 |
27 |
28 |
29 | ## generate tcl file
30 | build/target.tcl: $(RTL) $(CONSTRAINTS)
31 | mkdir -p build
32 | truncate -s 0 $@
33 | echo "set ABS_TOP $(ABS_TOP)" >> $@
34 | echo "set TOP $(MODEL_NAME)" >> $@
35 | echo "set FPGA_PART $(FPGA_PART)" >> $@
36 | echo "set_param general.maxThreads $(MAX_CPU)" >> $@
37 | echo "set_param general.maxBackupLogs 0" >> $@
38 | echo -n "set RTL { " >> $@
39 | FLIST="$(RTL)"; for f in $$FLIST; do echo -n "$$f " ; done >> $@
40 | echo "}" >> $@
41 | echo -n "set CONSTRAINTS { " >> $@
42 | FLIST="$(CONSTRAINTS)"; for f in $$FLIST; do echo -n "$$f " ; done >> $@
43 | echo "}" >> $@
44 |
45 |
46 | setup: build/target.tcl
47 |
48 | elaborate: build/target.tcl $(SCRIPTS)/elaborate.tcl
49 | mkdir -p ./build
50 | cd ./build && $(VIVADO) $(VIVADO_OPTS) -source $(SCRIPTS)/elaborate.tcl |& tee elaborate.log
51 |
52 | build/synth/$(TOP).dcp: build/target.tcl $(SCRIPTS)/synth.tcl
53 | mkdir -p ./build/synth/
54 | cd ./build/synth/ && $(VIVADO) $(VIVADO_OPTS) -source $(SCRIPTS)/synth.tcl |& tee synth.log
55 |
56 | synth: build/synth/$(TOP).dcp
57 |
58 | build/impl/$(TOP).bit: build/synth/$(TOP).dcp $(SCRIPTS)/impl.tcl
59 | mkdir -p ./build/impl/
60 | cd ./build/impl && $(VIVADO) $(VIVADO_OPTS) -source $(SCRIPTS)/impl.tcl |& tee impl.log
61 |
62 | impl: build/impl/$(TOP).bit
63 | all: build/impl/$(TOP).bit
64 |
65 | vivado: build
66 | cd build && nohup $(VIVADO) /dev/null 2>&1 &
67 |
68 | sim_build/compile_simlib/synopsys_sim.setup:
69 | mkdir -p sim_build/compile_simlib
70 | cd build/sim_build/compile_simlib && $(VIVADO) $(VIVADO_OPTS) -source $(SCRIPTS)/compile_simlib.tcl
71 |
72 |
--------------------------------------------------------------------------------
/syn/syn_fpga/vivado/scripts/elaborate.tcl:
--------------------------------------------------------------------------------
1 | source ./target.tcl
2 |
3 | # Read Verilog source files
4 | if {[string trim ${RTL}] ne ""} {
5 | read_verilog -v ${RTL}
6 | }
7 |
8 | # Read user constraints
9 | if {[string trim ${CONSTRAINTS}] ne ""} {
10 | read_xdc ${CONSTRAINTS}
11 | }
12 |
13 | # Only elaborate RTL (don't synthesize to netlist)
14 | synth_design -top ${TOP} -part ${FPGA_PART} -rtl
15 |
16 | # write_checkpoint doesn't work:
17 | # Vivado% write_checkpoint -force z1top_post_elab.dcp
18 | # ERROR: [Common 17-69] Command failed: Checkpoints are not supported for RTL designs
19 |
20 | # Open the schematic visualization
21 | start_gui
22 |
--------------------------------------------------------------------------------
/syn/syn_fpga/vivado/scripts/impl.tcl:
--------------------------------------------------------------------------------
1 | source ../target.tcl
2 |
3 | open_checkpoint ${ABS_TOP}/build/synth/${TOP}.dcp
4 |
5 | if {[string trim ${CONSTRAINTS}] ne ""} {
6 | read_xdc ${CONSTRAINTS}
7 | }
8 |
9 | opt_design
10 | place_design
11 | write_checkpoint -force ${TOP}_placed.dcp
12 | report_utilization -file post_place_utilization.rpt
13 | phys_opt_design
14 | route_design
15 |
16 | write_checkpoint -force ${TOP}_routed.dcp
17 | write_verilog -force post_route.v
18 | write_xdc -force post_route.xdc
19 | report_drc -file post_route_drc.rpt
20 | report_timing_summary -warn_on_violation -file post_route_timing_summary.rpt
21 |
22 | write_bitstream -force ${TOP}.bit
23 |
--------------------------------------------------------------------------------
/syn/syn_fpga/vivado/scripts/synth.tcl:
--------------------------------------------------------------------------------
1 | source ../target.tcl
2 |
3 | # Read Verilog source files
4 | if {[string trim ${RTL}] ne ""} {
5 | read_verilog -v ${RTL}
6 | }
7 |
8 | # Read user constraints
9 | if {[string trim ${CONSTRAINTS}] ne ""} {
10 | read_xdc ${CONSTRAINTS}
11 | }
12 |
13 | synth_design -top ${TOP} -part ${FPGA_PART}
14 |
15 | write_checkpoint -force ${TOP}.dcp
16 | report_timing_summary -file post_synth_timing_summary.rpt
17 | report_drc -file post_synth_drc.rpt
18 | report_utilization -file post_synth_utilization.rpt
19 | write_verilog -force -file post_synth.v
20 | write_xdc -force -file post_synth.xdc
21 |
--------------------------------------------------------------------------------