├── .gitignore ├── FPGA ├── fft.srcs │ └── sources_1 │ │ └── ip │ │ └── clk_wiz_0 │ │ ├── clk_wiz_0.dcp │ │ ├── clk_wiz_0.v │ │ ├── clk_wiz_0.veo │ │ ├── clk_wiz_0.xci │ │ ├── clk_wiz_0.xdc │ │ ├── clk_wiz_0.xml │ │ ├── clk_wiz_0_board.xdc │ │ ├── clk_wiz_0_clk_wiz.v │ │ ├── clk_wiz_0_ooc.xdc │ │ ├── clk_wiz_0_sim_netlist.v │ │ ├── clk_wiz_0_sim_netlist.vhdl │ │ ├── clk_wiz_0_stub.v │ │ ├── clk_wiz_0_stub.vhdl │ │ ├── doc │ │ └── clk_wiz_v6_0_changelog.txt │ │ ├── mmcm_pll_drp_func_7s_mmcm.vh │ │ ├── mmcm_pll_drp_func_7s_pll.vh │ │ ├── mmcm_pll_drp_func_us_mmcm.vh │ │ ├── mmcm_pll_drp_func_us_pll.vh │ │ ├── mmcm_pll_drp_func_us_plus_mmcm.vh │ │ └── mmcm_pll_drp_func_us_plus_pll.vh └── src │ ├── FFT128.v │ ├── FFT256.v │ ├── FFT512.v │ ├── VC707_rev_2.0.ucf.xdc │ └── fft.tcl ├── README.md ├── build.sbt ├── project ├── build.properties └── plugins.sbt ├── scalastyle-config.xml ├── scalastyle-test-config.xml └── src ├── main └── scala │ ├── FFT │ ├── Butterfly.scala │ ├── Config.scala │ ├── FFT.scala │ ├── Reorder.scala │ ├── TOP.scala │ └── VerilogEmitter.scala │ └── gcd │ └── GCD.scala └── test └── scala ├── FFT └── FFTTest.scala └── gcd ├── GCDMain.scala └── GCDUnitTest.scala /.gitignore: -------------------------------------------------------------------------------- 1 | ### Project Specific stuff 2 | test_run_dir/* 3 | Verilog/ 4 | ### XilinxISE template 5 | # intermediate build files 6 | *.bgn 7 | *.bit 8 | *.bld 9 | *.cmd_log 10 | *.drc 11 | *.ll 12 | *.lso 13 | *.msd 14 | *.msk 15 | *.ncd 16 | *.ngc 17 | *.ngd 18 | *.ngr 19 | *.pad 20 | *.par 21 | *.pcf 22 | *.prj 23 | *.ptwx 24 | *.rbb 25 | *.rbd 26 | *.stx 27 | *.syr 28 | *.twr 29 | *.twx 30 | *.unroutes 31 | *.ut 32 | *.xpi 33 | *.xst 34 | *_bitgen.xwbt 35 | *_envsettings.html 36 | *_map.map 37 | *_map.mrp 38 | *_map.ngm 39 | *_map.xrpt 40 | *_ngdbuild.xrpt 41 | *_pad.csv 42 | *_pad.txt 43 | *_par.xrpt 44 | *_summary.html 45 | *_summary.xml 46 | *_usage.xml 47 | *_xst.xrpt 48 | 49 | # project-wide generated files 50 | *.gise 51 | par_usage_statistics.html 52 | usage_statistics_webtalk.html 53 | webtalk.log 54 | webtalk_pn.xml 55 | 56 | # generated folders 57 | iseconfig/ 58 | xlnx_auto_0_xdb/ 59 | xst/ 60 | _ngo/ 61 | _xmsgs/ 62 | ### Eclipse template 63 | *.pydevproject 64 | .metadata 65 | .gradle 66 | bin/ 67 | tmp/ 68 | *.tmp 69 | *.bak 70 | *.swp 71 | *~.nib 72 | local.properties 73 | .settings/ 74 | .loadpath 75 | 76 | # Eclipse Core 77 | .project 78 | 79 | # External tool builders 80 | .externalToolBuilders/ 81 | 82 | # Locally stored "Eclipse launch configurations" 83 | *.launch 84 | 85 | # CDT-specific 86 | .cproject 87 | 88 | # JDT-specific (Eclipse Java Development Tools) 89 | .classpath 90 | 91 | # Java annotation processor (APT) 92 | .factorypath 93 | 94 | # PDT-specific 95 | .buildpath 96 | 97 | # sbteclipse plugin 98 | .target 99 | 100 | # TeXlipse plugin 101 | .texlipse 102 | ### C template 103 | # Object files 104 | *.o 105 | *.ko 106 | *.obj 107 | *.elf 108 | 109 | # Precompiled Headers 110 | *.gch 111 | *.pch 112 | 113 | # Libraries 114 | *.lib 115 | *.a 116 | *.la 117 | *.lo 118 | 119 | # Shared objects (inc. Windows DLLs) 120 | *.dll 121 | *.so 122 | *.so.* 123 | *.dylib 124 | 125 | # Executables 126 | *.exe 127 | *.out 128 | *.app 129 | *.i*86 130 | *.x86_64 131 | *.hex 132 | 133 | # Debug files 134 | *.dSYM/ 135 | ### SBT template 136 | # Simple Build Tool 137 | # http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control 138 | 139 | target/ 140 | lib_managed/ 141 | src_managed/ 142 | project/boot/ 143 | .history 144 | .cache 145 | ### Emacs template 146 | # -*- mode: gitignore; -*- 147 | *~ 148 | \#*\# 149 | /.emacs.desktop 150 | /.emacs.desktop.lock 151 | *.elc 152 | auto-save-list 153 | tramp 154 | .\#* 155 | 156 | # Org-mode 157 | .org-id-locations 158 | *_archive 159 | 160 | # flymake-mode 161 | *_flymake.* 162 | 163 | # eshell files 164 | /eshell/history 165 | /eshell/lastdir 166 | 167 | # elpa packages 168 | /elpa/ 169 | 170 | # reftex files 171 | *.rel 172 | 173 | # AUCTeX auto folder 174 | /auto/ 175 | 176 | # cask packages 177 | .cask/ 178 | ### Vim template 179 | [._]*.s[a-w][a-z] 180 | [._]s[a-w][a-z] 181 | *.un~ 182 | Session.vim 183 | .netrwhist 184 | *~ 185 | ### JetBrains template 186 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio 187 | 188 | *.iml 189 | 190 | ## Directory-based project format: 191 | .idea/ 192 | # if you remove the above rule, at least ignore the following: 193 | 194 | # User-specific stuff: 195 | # .idea/workspace.xml 196 | # .idea/tasks.xml 197 | # .idea/dictionaries 198 | 199 | # Sensitive or high-churn files: 200 | # .idea/dataSources.ids 201 | # .idea/dataSources.xml 202 | # .idea/sqlDataSources.xml 203 | # .idea/dynamic.xml 204 | # .idea/uiDesigner.xml 205 | 206 | # Gradle: 207 | # .idea/gradle.xml 208 | # .idea/libraries 209 | 210 | # Mongo Explorer plugin: 211 | # .idea/mongoSettings.xml 212 | 213 | ## File-based project format: 214 | *.ipr 215 | *.iws 216 | 217 | ## Plugin-specific files: 218 | 219 | # IntelliJ 220 | /out/ 221 | 222 | # mpeltonen/sbt-idea plugin 223 | .idea_modules/ 224 | 225 | # JIRA plugin 226 | atlassian-ide-plugin.xml 227 | 228 | # Crashlytics plugin (for Android Studio and IntelliJ) 229 | com_crashlytics_export_strings.xml 230 | crashlytics.properties 231 | crashlytics-build.properties 232 | ### C++ template 233 | # Compiled Object files 234 | *.slo 235 | *.lo 236 | *.o 237 | *.obj 238 | 239 | # Precompiled Headers 240 | *.gch 241 | *.pch 242 | 243 | # Compiled Dynamic libraries 244 | *.so 245 | *.dylib 246 | *.dll 247 | 248 | # Fortran module files 249 | *.mod 250 | 251 | # Compiled Static libraries 252 | *.lai 253 | *.la 254 | *.a 255 | *.lib 256 | 257 | # Executables 258 | *.exe 259 | *.out 260 | *.app 261 | ### OSX template 262 | .DS_Store 263 | .AppleDouble 264 | .LSOverride 265 | 266 | # Icon must end with two \r 267 | Icon 268 | 269 | # Thumbnails 270 | ._* 271 | 272 | # Files that might appear in the root of a volume 273 | .DocumentRevisions-V100 274 | .fseventsd 275 | .Spotlight-V100 276 | .TemporaryItems 277 | .Trashes 278 | .VolumeIcon.icns 279 | 280 | # Directories potentially created on remote AFP share 281 | .AppleDB 282 | .AppleDesktop 283 | Network Trash Folder 284 | Temporary Items 285 | .apdisk 286 | ### Xcode template 287 | # Xcode 288 | # 289 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 290 | 291 | ## Build generated 292 | build/ 293 | DerivedData 294 | 295 | ## Various settings 296 | *.pbxuser 297 | !default.pbxuser 298 | *.mode1v3 299 | !default.mode1v3 300 | *.mode2v3 301 | !default.mode2v3 302 | *.perspectivev3 303 | !default.perspectivev3 304 | xcuserdata 305 | 306 | ## Other 307 | *.xccheckout 308 | *.moved-aside 309 | *.xcuserstate 310 | ### Scala template 311 | *.class 312 | *.log 313 | 314 | # sbt specific 315 | .cache 316 | .history 317 | .lib/ 318 | dist/* 319 | target/ 320 | lib_managed/ 321 | src_managed/ 322 | project/boot/ 323 | project/plugins/project/ 324 | 325 | # Scala-IDE specific 326 | .scala_dependencies 327 | .worksheet 328 | ### Java template 329 | *.class 330 | 331 | # Mobile Tools for Java (J2ME) 332 | .mtj.tmp/ 333 | 334 | # Package Files # 335 | *.jar 336 | *.war 337 | *.ear 338 | 339 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 340 | hs_err_pid* 341 | 342 | -------------------------------------------------------------------------------- /FPGA/fft.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0.dcp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IA-C-Lab-Fudan/Chisel-FFT-generator/65fc40ce8d34a54634c7206f03ab9002ece01c41/FPGA/fft.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0.dcp -------------------------------------------------------------------------------- /FPGA/fft.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0.v: -------------------------------------------------------------------------------- 1 | 2 | // file: clk_wiz_0.v 3 | // 4 | // (c) Copyright 2008 - 2013 Xilinx, Inc. All rights reserved. 5 | // 6 | // This file contains confidential and proprietary information 7 | // of Xilinx, Inc. and is protected under U.S. and 8 | // international copyright and other intellectual property 9 | // laws. 10 | // 11 | // DISCLAIMER 12 | // This disclaimer is not a license and does not grant any 13 | // rights to the materials distributed herewith. Except as 14 | // otherwise provided in a valid license issued to you by 15 | // Xilinx, and to the maximum extent permitted by applicable 16 | // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 17 | // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 18 | // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 19 | // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 20 | // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 21 | // (2) Xilinx shall not be liable (whether in contract or tort, 22 | // including negligence, or under any other theory of 23 | // liability) for any loss or damage of any kind or nature 24 | // related to, arising under or in connection with these 25 | // materials, including for any direct, or any indirect, 26 | // special, incidental, or consequential loss or damage 27 | // (including loss of data, profits, goodwill, or any type of 28 | // loss or damage suffered as a result of any action brought 29 | // by a third party) even if such damage or loss was 30 | // reasonably foreseeable or Xilinx had been advised of the 31 | // possibility of the same. 32 | // 33 | // CRITICAL APPLICATIONS 34 | // Xilinx products are not designed or intended to be fail- 35 | // safe, or for use in any application requiring fail-safe 36 | // performance, such as life-support or safety devices or 37 | // systems, Class III medical devices, nuclear facilities, 38 | // applications related to the deployment of airbags, or any 39 | // other applications that could lead to death, personal 40 | // injury, or severe property or environmental damage 41 | // (individually and collectively, "Critical 42 | // Applications"). Customer assumes the sole risk and 43 | // liability of any use of Xilinx products in Critical 44 | // Applications, subject only to applicable laws and 45 | // regulations governing limitations on product liability. 46 | // 47 | // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 48 | // PART OF THIS FILE AT ALL TIMES. 49 | // 50 | //---------------------------------------------------------------------------- 51 | // User entered comments 52 | //---------------------------------------------------------------------------- 53 | // None 54 | // 55 | //---------------------------------------------------------------------------- 56 | // Output Output Phase Duty Cycle Pk-to-Pk Phase 57 | // Clock Freq (MHz) (degrees) (%) Jitter (ps) Error (ps) 58 | //---------------------------------------------------------------------------- 59 | // clk_out1__70.00000______0.000______50.0______251.494____293.793 60 | // 61 | //---------------------------------------------------------------------------- 62 | // Input Clock Freq (MHz) Input Jitter (UI) 63 | //---------------------------------------------------------------------------- 64 | // __primary_________200.000____________0.010 65 | 66 | `timescale 1ps/1ps 67 | 68 | (* CORE_GENERATION_INFO = "clk_wiz_0,clk_wiz_v6_0_4_0_0,{component_name=clk_wiz_0,use_phase_alignment=false,use_min_o_jitter=false,use_max_i_jitter=false,use_dyn_phase_shift=false,use_inclk_switchover=false,use_dyn_reconfig=false,enable_axi=0,feedback_source=FDBK_AUTO,PRIMITIVE=MMCM,num_out_clk=1,clkin1_period=5.000,clkin2_period=10.0,use_power_down=false,use_reset=false,use_locked=false,use_inclk_stopped=false,feedback_type=SINGLE,CLOCK_MGR_TYPE=NA,manual_override=false}" *) 69 | 70 | module clk_wiz_0 71 | ( 72 | // Clock out ports 73 | output clk_out1, 74 | // Clock in ports 75 | input clk_in1_p, 76 | input clk_in1_n 77 | ); 78 | 79 | clk_wiz_0_clk_wiz inst 80 | ( 81 | // Clock out ports 82 | .clk_out1(clk_out1), 83 | // Clock in ports 84 | .clk_in1_p(clk_in1_p), 85 | .clk_in1_n(clk_in1_n) 86 | ); 87 | 88 | endmodule 89 | -------------------------------------------------------------------------------- /FPGA/fft.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0.veo: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // (c) Copyright 2008 - 2013 Xilinx, Inc. All rights reserved. 4 | // 5 | // This file contains confidential and proprietary information 6 | // of Xilinx, Inc. and is protected under U.S. and 7 | // international copyright and other intellectual property 8 | // laws. 9 | // 10 | // DISCLAIMER 11 | // This disclaimer is not a license and does not grant any 12 | // rights to the materials distributed herewith. Except as 13 | // otherwise provided in a valid license issued to you by 14 | // Xilinx, and to the maximum extent permitted by applicable 15 | // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 16 | // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 17 | // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 18 | // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 19 | // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 20 | // (2) Xilinx shall not be liable (whether in contract or tort, 21 | // including negligence, or under any other theory of 22 | // liability) for any loss or damage of any kind or nature 23 | // related to, arising under or in connection with these 24 | // materials, including for any direct, or any indirect, 25 | // special, incidental, or consequential loss or damage 26 | // (including loss of data, profits, goodwill, or any type of 27 | // loss or damage suffered as a result of any action brought 28 | // by a third party) even if such damage or loss was 29 | // reasonably foreseeable or Xilinx had been advised of the 30 | // possibility of the same. 31 | // 32 | // CRITICAL APPLICATIONS 33 | // Xilinx products are not designed or intended to be fail- 34 | // safe, or for use in any application requiring fail-safe 35 | // performance, such as life-support or safety devices or 36 | // systems, Class III medical devices, nuclear facilities, 37 | // applications related to the deployment of airbags, or any 38 | // other applications that could lead to death, personal 39 | // injury, or severe property or environmental damage 40 | // (individually and collectively, "Critical 41 | // Applications"). Customer assumes the sole risk and 42 | // liability of any use of Xilinx products in Critical 43 | // Applications, subject only to applicable laws and 44 | // regulations governing limitations on product liability. 45 | // 46 | // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 47 | // PART OF THIS FILE AT ALL TIMES. 48 | // 49 | //---------------------------------------------------------------------------- 50 | // User entered comments 51 | //---------------------------------------------------------------------------- 52 | // None 53 | // 54 | //---------------------------------------------------------------------------- 55 | // Output Output Phase Duty Cycle Pk-to-Pk Phase 56 | // Clock Freq (MHz) (degrees) (%) Jitter (ps) Error (ps) 57 | //---------------------------------------------------------------------------- 58 | // clk_out1__70.00000______0.000______50.0______251.494____293.793 59 | // 60 | //---------------------------------------------------------------------------- 61 | // Input Clock Freq (MHz) Input Jitter (UI) 62 | //---------------------------------------------------------------------------- 63 | // __primary_________200.000____________0.010 64 | 65 | // The following must be inserted into your Verilog file for this 66 | // core to be instantiated. Change the instance name and port connections 67 | // (in parentheses) to your own signal names. 68 | 69 | //----------- Begin Cut here for INSTANTIATION Template ---// INST_TAG 70 | 71 | clk_wiz_0 instance_name 72 | ( 73 | // Clock out ports 74 | .clk_out1(clk_out1), // output clk_out1 75 | // Clock in ports 76 | .clk_in1_p(clk_in1_p), // input clk_in1_p 77 | .clk_in1_n(clk_in1_n)); // input clk_in1_n 78 | // INST_TAG_END ------ End INSTANTIATION Template --------- 79 | -------------------------------------------------------------------------------- /FPGA/fft.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0.xdc: -------------------------------------------------------------------------------- 1 | 2 | # file: clk_wiz_0.xdc 3 | # 4 | # (c) Copyright 2008 - 2013 Xilinx, Inc. All rights reserved. 5 | # 6 | # This file contains confidential and proprietary information 7 | # of Xilinx, Inc. and is protected under U.S. and 8 | # international copyright and other intellectual property 9 | # laws. 10 | # 11 | # DISCLAIMER 12 | # This disclaimer is not a license and does not grant any 13 | # rights to the materials distributed herewith. Except as 14 | # otherwise provided in a valid license issued to you by 15 | # Xilinx, and to the maximum extent permitted by applicable 16 | # law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 17 | # WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 18 | # AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 19 | # BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 20 | # INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 21 | # (2) Xilinx shall not be liable (whether in contract or tort, 22 | # including negligence, or under any other theory of 23 | # liability) for any loss or damage of any kind or nature 24 | # related to, arising under or in connection with these 25 | # materials, including for any direct, or any indirect, 26 | # special, incidental, or consequential loss or damage 27 | # (including loss of data, profits, goodwill, or any type of 28 | # loss or damage suffered as a result of any action brought 29 | # by a third party) even if such damage or loss was 30 | # reasonably foreseeable or Xilinx had been advised of the 31 | # possibility of the same. 32 | # 33 | # CRITICAL APPLICATIONS 34 | # Xilinx products are not designed or intended to be fail- 35 | # safe, or for use in any application requiring fail-safe 36 | # performance, such as life-support or safety devices or 37 | # systems, Class III medical devices, nuclear facilities, 38 | # applications related to the deployment of airbags, or any 39 | # other applications that could lead to death, personal 40 | # injury, or severe property or environmental damage 41 | # (individually and collectively, "Critical 42 | # Applications"). Customer assumes the sole risk and 43 | # liability of any use of Xilinx products in Critical 44 | # Applications, subject only to applicable laws and 45 | # regulations governing limitations on product liability. 46 | # 47 | # THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 48 | # PART OF THIS FILE AT ALL TIMES. 49 | # 50 | 51 | # Input clock periods. These duplicate the values entered for the 52 | # input clocks. You can use these to time your system. If required 53 | # commented constraints can be used in the top level xdc 54 | #---------------------------------------------------------------- 55 | # Differential clock only needs one constraint 56 | create_clock -period 5.000 [get_ports clk_in1_p] 57 | set_input_jitter [get_clocks -of_objects [get_ports clk_in1_p]] 0.05 58 | 59 | 60 | set_property PHASESHIFT_MODE WAVEFORM [get_cells -hierarchical *adv*] 61 | -------------------------------------------------------------------------------- /FPGA/fft.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0_board.xdc: -------------------------------------------------------------------------------- 1 | #--------------------Physical Constraints----------------- 2 | 3 | -------------------------------------------------------------------------------- /FPGA/fft.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0_clk_wiz.v: -------------------------------------------------------------------------------- 1 | 2 | // file: clk_wiz_0.v 3 | // 4 | // (c) Copyright 2008 - 2013 Xilinx, Inc. All rights reserved. 5 | // 6 | // This file contains confidential and proprietary information 7 | // of Xilinx, Inc. and is protected under U.S. and 8 | // international copyright and other intellectual property 9 | // laws. 10 | // 11 | // DISCLAIMER 12 | // This disclaimer is not a license and does not grant any 13 | // rights to the materials distributed herewith. Except as 14 | // otherwise provided in a valid license issued to you by 15 | // Xilinx, and to the maximum extent permitted by applicable 16 | // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 17 | // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 18 | // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 19 | // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 20 | // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 21 | // (2) Xilinx shall not be liable (whether in contract or tort, 22 | // including negligence, or under any other theory of 23 | // liability) for any loss or damage of any kind or nature 24 | // related to, arising under or in connection with these 25 | // materials, including for any direct, or any indirect, 26 | // special, incidental, or consequential loss or damage 27 | // (including loss of data, profits, goodwill, or any type of 28 | // loss or damage suffered as a result of any action brought 29 | // by a third party) even if such damage or loss was 30 | // reasonably foreseeable or Xilinx had been advised of the 31 | // possibility of the same. 32 | // 33 | // CRITICAL APPLICATIONS 34 | // Xilinx products are not designed or intended to be fail- 35 | // safe, or for use in any application requiring fail-safe 36 | // performance, such as life-support or safety devices or 37 | // systems, Class III medical devices, nuclear facilities, 38 | // applications related to the deployment of airbags, or any 39 | // other applications that could lead to death, personal 40 | // injury, or severe property or environmental damage 41 | // (individually and collectively, "Critical 42 | // Applications"). Customer assumes the sole risk and 43 | // liability of any use of Xilinx products in Critical 44 | // Applications, subject only to applicable laws and 45 | // regulations governing limitations on product liability. 46 | // 47 | // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 48 | // PART OF THIS FILE AT ALL TIMES. 49 | // 50 | //---------------------------------------------------------------------------- 51 | // User entered comments 52 | //---------------------------------------------------------------------------- 53 | // None 54 | // 55 | //---------------------------------------------------------------------------- 56 | // Output Output Phase Duty Cycle Pk-to-Pk Phase 57 | // Clock Freq (MHz) (degrees) (%) Jitter (ps) Error (ps) 58 | //---------------------------------------------------------------------------- 59 | // clk_out1__70.00000______0.000______50.0______251.494____293.793 60 | // 61 | //---------------------------------------------------------------------------- 62 | // Input Clock Freq (MHz) Input Jitter (UI) 63 | //---------------------------------------------------------------------------- 64 | // __primary_________200.000____________0.010 65 | 66 | `timescale 1ps/1ps 67 | 68 | module clk_wiz_0_clk_wiz 69 | 70 | (// Clock in ports 71 | // Clock out ports 72 | output clk_out1, 73 | input clk_in1_p, 74 | input clk_in1_n 75 | ); 76 | // Input buffering 77 | //------------------------------------ 78 | wire clk_in1_clk_wiz_0; 79 | wire clk_in2_clk_wiz_0; 80 | IBUFDS clkin1_ibufgds 81 | (.O (clk_in1_clk_wiz_0), 82 | .I (clk_in1_p), 83 | .IB (clk_in1_n)); 84 | 85 | 86 | 87 | 88 | // Clocking PRIMITIVE 89 | //------------------------------------ 90 | 91 | // Instantiation of the MMCM PRIMITIVE 92 | // * Unused inputs are tied off 93 | // * Unused outputs are labeled unused 94 | 95 | wire clk_out1_clk_wiz_0; 96 | wire clk_out2_clk_wiz_0; 97 | wire clk_out3_clk_wiz_0; 98 | wire clk_out4_clk_wiz_0; 99 | wire clk_out5_clk_wiz_0; 100 | wire clk_out6_clk_wiz_0; 101 | wire clk_out7_clk_wiz_0; 102 | 103 | wire [15:0] do_unused; 104 | wire drdy_unused; 105 | wire psdone_unused; 106 | wire locked_int; 107 | wire clkfbout_clk_wiz_0; 108 | wire clkfboutb_unused; 109 | wire clkout0b_unused; 110 | wire clkout1_unused; 111 | wire clkout1b_unused; 112 | wire clkout2_unused; 113 | wire clkout2b_unused; 114 | wire clkout3_unused; 115 | wire clkout3b_unused; 116 | wire clkout4_unused; 117 | wire clkout5_unused; 118 | wire clkout6_unused; 119 | wire clkfbstopped_unused; 120 | wire clkinstopped_unused; 121 | 122 | MMCME2_ADV 123 | #(.BANDWIDTH ("OPTIMIZED"), 124 | .CLKOUT4_CASCADE ("FALSE"), 125 | .COMPENSATION ("ZHOLD"), 126 | .STARTUP_WAIT ("FALSE"), 127 | .DIVCLK_DIVIDE (10), 128 | .CLKFBOUT_MULT_F (49.875), 129 | .CLKFBOUT_PHASE (0.000), 130 | .CLKFBOUT_USE_FINE_PS ("FALSE"), 131 | .CLKOUT0_DIVIDE_F (14.250), 132 | .CLKOUT0_PHASE (0.000), 133 | .CLKOUT0_DUTY_CYCLE (0.500), 134 | .CLKOUT0_USE_FINE_PS ("FALSE"), 135 | .CLKIN1_PERIOD (5.000)) 136 | mmcm_adv_inst 137 | // Output clocks 138 | ( 139 | .CLKFBOUT (clkfbout_clk_wiz_0), 140 | .CLKFBOUTB (clkfboutb_unused), 141 | .CLKOUT0 (clk_out1_clk_wiz_0), 142 | .CLKOUT0B (clkout0b_unused), 143 | .CLKOUT1 (clkout1_unused), 144 | .CLKOUT1B (clkout1b_unused), 145 | .CLKOUT2 (clkout2_unused), 146 | .CLKOUT2B (clkout2b_unused), 147 | .CLKOUT3 (clkout3_unused), 148 | .CLKOUT3B (clkout3b_unused), 149 | .CLKOUT4 (clkout4_unused), 150 | .CLKOUT5 (clkout5_unused), 151 | .CLKOUT6 (clkout6_unused), 152 | // Input clock control 153 | .CLKFBIN (clkfbout_clk_wiz_0), 154 | .CLKIN1 (clk_in1_clk_wiz_0), 155 | .CLKIN2 (1'b0), 156 | // Tied to always select the primary input clock 157 | .CLKINSEL (1'b1), 158 | // Ports for dynamic reconfiguration 159 | .DADDR (7'h0), 160 | .DCLK (1'b0), 161 | .DEN (1'b0), 162 | .DI (16'h0), 163 | .DO (do_unused), 164 | .DRDY (drdy_unused), 165 | .DWE (1'b0), 166 | // Ports for dynamic phase shift 167 | .PSCLK (1'b0), 168 | .PSEN (1'b0), 169 | .PSINCDEC (1'b0), 170 | .PSDONE (psdone_unused), 171 | // Other control and status signals 172 | .LOCKED (locked_int), 173 | .CLKINSTOPPED (clkinstopped_unused), 174 | .CLKFBSTOPPED (clkfbstopped_unused), 175 | .PWRDWN (1'b0), 176 | .RST (1'b0)); 177 | 178 | // Clock Monitor clock assigning 179 | //-------------------------------------- 180 | // Output buffering 181 | //----------------------------------- 182 | 183 | 184 | 185 | 186 | 187 | 188 | BUFG clkout1_buf 189 | (.O (clk_out1), 190 | .I (clk_out1_clk_wiz_0)); 191 | 192 | 193 | 194 | 195 | endmodule 196 | -------------------------------------------------------------------------------- /FPGA/fft.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0_ooc.xdc: -------------------------------------------------------------------------------- 1 | 2 | # file: clk_wiz_0_ooc.xdc 3 | # 4 | # (c) Copyright 2008 - 2013 Xilinx, Inc. All rights reserved. 5 | # 6 | # This file contains confidential and proprietary information 7 | # of Xilinx, Inc. and is protected under U.S. and 8 | # international copyright and other intellectual property 9 | # laws. 10 | # 11 | # DISCLAIMER 12 | # This disclaimer is not a license and does not grant any 13 | # rights to the materials distributed herewith. Except as 14 | # otherwise provided in a valid license issued to you by 15 | # Xilinx, and to the maximum extent permitted by applicable 16 | # law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 17 | # WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 18 | # AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 19 | # BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 20 | # INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 21 | # (2) Xilinx shall not be liable (whether in contract or tort, 22 | # including negligence, or under any other theory of 23 | # liability) for any loss or damage of any kind or nature 24 | # related to, arising under or in connection with these 25 | # materials, including for any direct, or any indirect, 26 | # special, incidental, or consequential loss or damage 27 | # (including loss of data, profits, goodwill, or any type of 28 | # loss or damage suffered as a result of any action brought 29 | # by a third party) even if such damage or loss was 30 | # reasonably foreseeable or Xilinx had been advised of the 31 | # possibility of the same. 32 | # 33 | # CRITICAL APPLICATIONS 34 | # Xilinx products are not designed or intended to be fail- 35 | # safe, or for use in any application requiring fail-safe 36 | # performance, such as life-support or safety devices or 37 | # systems, Class III medical devices, nuclear facilities, 38 | # applications related to the deployment of airbags, or any 39 | # other applications that could lead to death, personal 40 | # injury, or severe property or environmental damage 41 | # (individually and collectively, "Critical 42 | # Applications"). Customer assumes the sole risk and 43 | # liability of any use of Xilinx products in Critical 44 | # Applications, subject only to applicable laws and 45 | # regulations governing limitations on product liability. 46 | # 47 | # THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 48 | # PART OF THIS FILE AT ALL TIMES. 49 | # 50 | 51 | ################# 52 | #DEFAULT CLOCK CONSTRAINTS 53 | 54 | ############################################################ 55 | # Clock Period Constraints # 56 | ############################################################ 57 | # Differential clock only needs one constraint 58 | #create_clock -period 5.000 [get_ports clk_in1_p] 59 | 60 | -------------------------------------------------------------------------------- /FPGA/fft.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0_sim_netlist.v: -------------------------------------------------------------------------------- 1 | // Copyright 1986-2019 Xilinx, Inc. All Rights Reserved. 2 | // -------------------------------------------------------------------------------- 3 | // Tool Version: Vivado v.2019.2 (win64) Build 2708876 Wed Nov 6 21:40:23 MST 2019 4 | // Date : Thu Apr 30 11:09:19 2020 5 | // Host : DESKTOP-2SF54E0 running 64-bit major release (build 9200) 6 | // Command : write_verilog -force -mode funcsim e:/xil_pj/fft/fft.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0_sim_netlist.v 7 | // Design : clk_wiz_0 8 | // Purpose : This verilog netlist is a functional simulation representation of the design and should not be modified 9 | // or synthesized. This netlist cannot be used for SDF annotated simulation. 10 | // Device : xc7vx485tffg1761-2 11 | // -------------------------------------------------------------------------------- 12 | `timescale 1 ps / 1 ps 13 | 14 | (* NotValidForBitStream *) 15 | module clk_wiz_0 16 | (clk_out1, 17 | clk_in1_p, 18 | clk_in1_n); 19 | output clk_out1; 20 | input clk_in1_p; 21 | input clk_in1_n; 22 | 23 | (* DIFF_TERM = 0 *) (* IBUF_LOW_PWR *) wire clk_in1_n; 24 | (* DIFF_TERM = 0 *) (* IBUF_LOW_PWR *) wire clk_in1_p; 25 | wire clk_out1; 26 | 27 | clk_wiz_0_clk_wiz_0_clk_wiz inst 28 | (.clk_in1_n(clk_in1_n), 29 | .clk_in1_p(clk_in1_p), 30 | .clk_out1(clk_out1)); 31 | endmodule 32 | 33 | (* ORIG_REF_NAME = "clk_wiz_0_clk_wiz" *) 34 | module clk_wiz_0_clk_wiz_0_clk_wiz 35 | (clk_out1, 36 | clk_in1_p, 37 | clk_in1_n); 38 | output clk_out1; 39 | input clk_in1_p; 40 | input clk_in1_n; 41 | 42 | wire clk_in1_clk_wiz_0; 43 | wire clk_in1_n; 44 | wire clk_in1_p; 45 | wire clk_out1; 46 | wire clk_out1_clk_wiz_0; 47 | wire clkfbout_clk_wiz_0; 48 | wire NLW_mmcm_adv_inst_CLKFBOUTB_UNCONNECTED; 49 | wire NLW_mmcm_adv_inst_CLKFBSTOPPED_UNCONNECTED; 50 | wire NLW_mmcm_adv_inst_CLKINSTOPPED_UNCONNECTED; 51 | wire NLW_mmcm_adv_inst_CLKOUT0B_UNCONNECTED; 52 | wire NLW_mmcm_adv_inst_CLKOUT1_UNCONNECTED; 53 | wire NLW_mmcm_adv_inst_CLKOUT1B_UNCONNECTED; 54 | wire NLW_mmcm_adv_inst_CLKOUT2_UNCONNECTED; 55 | wire NLW_mmcm_adv_inst_CLKOUT2B_UNCONNECTED; 56 | wire NLW_mmcm_adv_inst_CLKOUT3_UNCONNECTED; 57 | wire NLW_mmcm_adv_inst_CLKOUT3B_UNCONNECTED; 58 | wire NLW_mmcm_adv_inst_CLKOUT4_UNCONNECTED; 59 | wire NLW_mmcm_adv_inst_CLKOUT5_UNCONNECTED; 60 | wire NLW_mmcm_adv_inst_CLKOUT6_UNCONNECTED; 61 | wire NLW_mmcm_adv_inst_DRDY_UNCONNECTED; 62 | wire NLW_mmcm_adv_inst_LOCKED_UNCONNECTED; 63 | wire NLW_mmcm_adv_inst_PSDONE_UNCONNECTED; 64 | wire [15:0]NLW_mmcm_adv_inst_DO_UNCONNECTED; 65 | 66 | (* BOX_TYPE = "PRIMITIVE" *) 67 | (* CAPACITANCE = "DONT_CARE" *) 68 | (* IBUF_DELAY_VALUE = "0" *) 69 | (* IFD_DELAY_VALUE = "AUTO" *) 70 | IBUFDS #( 71 | .IOSTANDARD("DEFAULT")) 72 | clkin1_ibufgds 73 | (.I(clk_in1_p), 74 | .IB(clk_in1_n), 75 | .O(clk_in1_clk_wiz_0)); 76 | (* BOX_TYPE = "PRIMITIVE" *) 77 | BUFG clkout1_buf 78 | (.I(clk_out1_clk_wiz_0), 79 | .O(clk_out1)); 80 | (* BOX_TYPE = "PRIMITIVE" *) 81 | MMCME2_ADV #( 82 | .BANDWIDTH("OPTIMIZED"), 83 | .CLKFBOUT_MULT_F(49.875000), 84 | .CLKFBOUT_PHASE(0.000000), 85 | .CLKFBOUT_USE_FINE_PS("FALSE"), 86 | .CLKIN1_PERIOD(5.000000), 87 | .CLKIN2_PERIOD(0.000000), 88 | .CLKOUT0_DIVIDE_F(14.250000), 89 | .CLKOUT0_DUTY_CYCLE(0.500000), 90 | .CLKOUT0_PHASE(0.000000), 91 | .CLKOUT0_USE_FINE_PS("FALSE"), 92 | .CLKOUT1_DIVIDE(1), 93 | .CLKOUT1_DUTY_CYCLE(0.500000), 94 | .CLKOUT1_PHASE(0.000000), 95 | .CLKOUT1_USE_FINE_PS("FALSE"), 96 | .CLKOUT2_DIVIDE(1), 97 | .CLKOUT2_DUTY_CYCLE(0.500000), 98 | .CLKOUT2_PHASE(0.000000), 99 | .CLKOUT2_USE_FINE_PS("FALSE"), 100 | .CLKOUT3_DIVIDE(1), 101 | .CLKOUT3_DUTY_CYCLE(0.500000), 102 | .CLKOUT3_PHASE(0.000000), 103 | .CLKOUT3_USE_FINE_PS("FALSE"), 104 | .CLKOUT4_CASCADE("FALSE"), 105 | .CLKOUT4_DIVIDE(1), 106 | .CLKOUT4_DUTY_CYCLE(0.500000), 107 | .CLKOUT4_PHASE(0.000000), 108 | .CLKOUT4_USE_FINE_PS("FALSE"), 109 | .CLKOUT5_DIVIDE(1), 110 | .CLKOUT5_DUTY_CYCLE(0.500000), 111 | .CLKOUT5_PHASE(0.000000), 112 | .CLKOUT5_USE_FINE_PS("FALSE"), 113 | .CLKOUT6_DIVIDE(1), 114 | .CLKOUT6_DUTY_CYCLE(0.500000), 115 | .CLKOUT6_PHASE(0.000000), 116 | .CLKOUT6_USE_FINE_PS("FALSE"), 117 | .COMPENSATION("INTERNAL"), 118 | .DIVCLK_DIVIDE(10), 119 | .IS_CLKINSEL_INVERTED(1'b0), 120 | .IS_PSEN_INVERTED(1'b0), 121 | .IS_PSINCDEC_INVERTED(1'b0), 122 | .IS_PWRDWN_INVERTED(1'b0), 123 | .IS_RST_INVERTED(1'b0), 124 | .REF_JITTER1(0.010000), 125 | .REF_JITTER2(0.010000), 126 | .SS_EN("FALSE"), 127 | .SS_MODE("CENTER_HIGH"), 128 | .SS_MOD_PERIOD(10000), 129 | .STARTUP_WAIT("FALSE")) 130 | mmcm_adv_inst 131 | (.CLKFBIN(clkfbout_clk_wiz_0), 132 | .CLKFBOUT(clkfbout_clk_wiz_0), 133 | .CLKFBOUTB(NLW_mmcm_adv_inst_CLKFBOUTB_UNCONNECTED), 134 | .CLKFBSTOPPED(NLW_mmcm_adv_inst_CLKFBSTOPPED_UNCONNECTED), 135 | .CLKIN1(clk_in1_clk_wiz_0), 136 | .CLKIN2(1'b0), 137 | .CLKINSEL(1'b1), 138 | .CLKINSTOPPED(NLW_mmcm_adv_inst_CLKINSTOPPED_UNCONNECTED), 139 | .CLKOUT0(clk_out1_clk_wiz_0), 140 | .CLKOUT0B(NLW_mmcm_adv_inst_CLKOUT0B_UNCONNECTED), 141 | .CLKOUT1(NLW_mmcm_adv_inst_CLKOUT1_UNCONNECTED), 142 | .CLKOUT1B(NLW_mmcm_adv_inst_CLKOUT1B_UNCONNECTED), 143 | .CLKOUT2(NLW_mmcm_adv_inst_CLKOUT2_UNCONNECTED), 144 | .CLKOUT2B(NLW_mmcm_adv_inst_CLKOUT2B_UNCONNECTED), 145 | .CLKOUT3(NLW_mmcm_adv_inst_CLKOUT3_UNCONNECTED), 146 | .CLKOUT3B(NLW_mmcm_adv_inst_CLKOUT3B_UNCONNECTED), 147 | .CLKOUT4(NLW_mmcm_adv_inst_CLKOUT4_UNCONNECTED), 148 | .CLKOUT5(NLW_mmcm_adv_inst_CLKOUT5_UNCONNECTED), 149 | .CLKOUT6(NLW_mmcm_adv_inst_CLKOUT6_UNCONNECTED), 150 | .DADDR({1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}), 151 | .DCLK(1'b0), 152 | .DEN(1'b0), 153 | .DI({1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}), 154 | .DO(NLW_mmcm_adv_inst_DO_UNCONNECTED[15:0]), 155 | .DRDY(NLW_mmcm_adv_inst_DRDY_UNCONNECTED), 156 | .DWE(1'b0), 157 | .LOCKED(NLW_mmcm_adv_inst_LOCKED_UNCONNECTED), 158 | .PSCLK(1'b0), 159 | .PSDONE(NLW_mmcm_adv_inst_PSDONE_UNCONNECTED), 160 | .PSEN(1'b0), 161 | .PSINCDEC(1'b0), 162 | .PWRDWN(1'b0), 163 | .RST(1'b0)); 164 | endmodule 165 | `ifndef GLBL 166 | `define GLBL 167 | `timescale 1 ps / 1 ps 168 | 169 | module glbl (); 170 | 171 | parameter ROC_WIDTH = 100000; 172 | parameter TOC_WIDTH = 0; 173 | 174 | //-------- STARTUP Globals -------------- 175 | wire GSR; 176 | wire GTS; 177 | wire GWE; 178 | wire PRLD; 179 | tri1 p_up_tmp; 180 | tri (weak1, strong0) PLL_LOCKG = p_up_tmp; 181 | 182 | wire PROGB_GLBL; 183 | wire CCLKO_GLBL; 184 | wire FCSBO_GLBL; 185 | wire [3:0] DO_GLBL; 186 | wire [3:0] DI_GLBL; 187 | 188 | reg GSR_int; 189 | reg GTS_int; 190 | reg PRLD_int; 191 | 192 | //-------- JTAG Globals -------------- 193 | wire JTAG_TDO_GLBL; 194 | wire JTAG_TCK_GLBL; 195 | wire JTAG_TDI_GLBL; 196 | wire JTAG_TMS_GLBL; 197 | wire JTAG_TRST_GLBL; 198 | 199 | reg JTAG_CAPTURE_GLBL; 200 | reg JTAG_RESET_GLBL; 201 | reg JTAG_SHIFT_GLBL; 202 | reg JTAG_UPDATE_GLBL; 203 | reg JTAG_RUNTEST_GLBL; 204 | 205 | reg JTAG_SEL1_GLBL = 0; 206 | reg JTAG_SEL2_GLBL = 0 ; 207 | reg JTAG_SEL3_GLBL = 0; 208 | reg JTAG_SEL4_GLBL = 0; 209 | 210 | reg JTAG_USER_TDO1_GLBL = 1'bz; 211 | reg JTAG_USER_TDO2_GLBL = 1'bz; 212 | reg JTAG_USER_TDO3_GLBL = 1'bz; 213 | reg JTAG_USER_TDO4_GLBL = 1'bz; 214 | 215 | assign (strong1, weak0) GSR = GSR_int; 216 | assign (strong1, weak0) GTS = GTS_int; 217 | assign (weak1, weak0) PRLD = PRLD_int; 218 | 219 | initial begin 220 | GSR_int = 1'b1; 221 | PRLD_int = 1'b1; 222 | #(ROC_WIDTH) 223 | GSR_int = 1'b0; 224 | PRLD_int = 1'b0; 225 | end 226 | 227 | initial begin 228 | GTS_int = 1'b1; 229 | #(TOC_WIDTH) 230 | GTS_int = 1'b0; 231 | end 232 | 233 | endmodule 234 | `endif 235 | -------------------------------------------------------------------------------- /FPGA/fft.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0_sim_netlist.vhdl: -------------------------------------------------------------------------------- 1 | -- Copyright 1986-2019 Xilinx, Inc. All Rights Reserved. 2 | -- -------------------------------------------------------------------------------- 3 | -- Tool Version: Vivado v.2019.2 (win64) Build 2708876 Wed Nov 6 21:40:23 MST 2019 4 | -- Date : Thu Apr 30 11:09:19 2020 5 | -- Host : DESKTOP-2SF54E0 running 64-bit major release (build 9200) 6 | -- Command : write_vhdl -force -mode funcsim e:/xil_pj/fft/fft.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0_sim_netlist.vhdl 7 | -- Design : clk_wiz_0 8 | -- Purpose : This VHDL netlist is a functional simulation representation of the design and should not be modified or 9 | -- synthesized. This netlist cannot be used for SDF annotated simulation. 10 | -- Device : xc7vx485tffg1761-2 11 | -- -------------------------------------------------------------------------------- 12 | library IEEE; 13 | use IEEE.STD_LOGIC_1164.ALL; 14 | library UNISIM; 15 | use UNISIM.VCOMPONENTS.ALL; 16 | entity clk_wiz_0_clk_wiz_0_clk_wiz is 17 | port ( 18 | clk_out1 : out STD_LOGIC; 19 | clk_in1_p : in STD_LOGIC; 20 | clk_in1_n : in STD_LOGIC 21 | ); 22 | attribute ORIG_REF_NAME : string; 23 | attribute ORIG_REF_NAME of clk_wiz_0_clk_wiz_0_clk_wiz : entity is "clk_wiz_0_clk_wiz"; 24 | end clk_wiz_0_clk_wiz_0_clk_wiz; 25 | 26 | architecture STRUCTURE of clk_wiz_0_clk_wiz_0_clk_wiz is 27 | signal clk_in1_clk_wiz_0 : STD_LOGIC; 28 | signal clk_out1_clk_wiz_0 : STD_LOGIC; 29 | signal clkfbout_clk_wiz_0 : STD_LOGIC; 30 | signal NLW_mmcm_adv_inst_CLKFBOUTB_UNCONNECTED : STD_LOGIC; 31 | signal NLW_mmcm_adv_inst_CLKFBSTOPPED_UNCONNECTED : STD_LOGIC; 32 | signal NLW_mmcm_adv_inst_CLKINSTOPPED_UNCONNECTED : STD_LOGIC; 33 | signal NLW_mmcm_adv_inst_CLKOUT0B_UNCONNECTED : STD_LOGIC; 34 | signal NLW_mmcm_adv_inst_CLKOUT1_UNCONNECTED : STD_LOGIC; 35 | signal NLW_mmcm_adv_inst_CLKOUT1B_UNCONNECTED : STD_LOGIC; 36 | signal NLW_mmcm_adv_inst_CLKOUT2_UNCONNECTED : STD_LOGIC; 37 | signal NLW_mmcm_adv_inst_CLKOUT2B_UNCONNECTED : STD_LOGIC; 38 | signal NLW_mmcm_adv_inst_CLKOUT3_UNCONNECTED : STD_LOGIC; 39 | signal NLW_mmcm_adv_inst_CLKOUT3B_UNCONNECTED : STD_LOGIC; 40 | signal NLW_mmcm_adv_inst_CLKOUT4_UNCONNECTED : STD_LOGIC; 41 | signal NLW_mmcm_adv_inst_CLKOUT5_UNCONNECTED : STD_LOGIC; 42 | signal NLW_mmcm_adv_inst_CLKOUT6_UNCONNECTED : STD_LOGIC; 43 | signal NLW_mmcm_adv_inst_DRDY_UNCONNECTED : STD_LOGIC; 44 | signal NLW_mmcm_adv_inst_LOCKED_UNCONNECTED : STD_LOGIC; 45 | signal NLW_mmcm_adv_inst_PSDONE_UNCONNECTED : STD_LOGIC; 46 | signal NLW_mmcm_adv_inst_DO_UNCONNECTED : STD_LOGIC_VECTOR ( 15 downto 0 ); 47 | attribute BOX_TYPE : string; 48 | attribute BOX_TYPE of clkin1_ibufgds : label is "PRIMITIVE"; 49 | attribute CAPACITANCE : string; 50 | attribute CAPACITANCE of clkin1_ibufgds : label is "DONT_CARE"; 51 | attribute IBUF_DELAY_VALUE : string; 52 | attribute IBUF_DELAY_VALUE of clkin1_ibufgds : label is "0"; 53 | attribute IFD_DELAY_VALUE : string; 54 | attribute IFD_DELAY_VALUE of clkin1_ibufgds : label is "AUTO"; 55 | attribute BOX_TYPE of clkout1_buf : label is "PRIMITIVE"; 56 | attribute BOX_TYPE of mmcm_adv_inst : label is "PRIMITIVE"; 57 | begin 58 | clkin1_ibufgds: unisim.vcomponents.IBUFDS 59 | generic map( 60 | IOSTANDARD => "DEFAULT" 61 | ) 62 | port map ( 63 | I => clk_in1_p, 64 | IB => clk_in1_n, 65 | O => clk_in1_clk_wiz_0 66 | ); 67 | clkout1_buf: unisim.vcomponents.BUFG 68 | port map ( 69 | I => clk_out1_clk_wiz_0, 70 | O => clk_out1 71 | ); 72 | mmcm_adv_inst: unisim.vcomponents.MMCME2_ADV 73 | generic map( 74 | BANDWIDTH => "OPTIMIZED", 75 | CLKFBOUT_MULT_F => 49.875000, 76 | CLKFBOUT_PHASE => 0.000000, 77 | CLKFBOUT_USE_FINE_PS => false, 78 | CLKIN1_PERIOD => 5.000000, 79 | CLKIN2_PERIOD => 0.000000, 80 | CLKOUT0_DIVIDE_F => 14.250000, 81 | CLKOUT0_DUTY_CYCLE => 0.500000, 82 | CLKOUT0_PHASE => 0.000000, 83 | CLKOUT0_USE_FINE_PS => false, 84 | CLKOUT1_DIVIDE => 1, 85 | CLKOUT1_DUTY_CYCLE => 0.500000, 86 | CLKOUT1_PHASE => 0.000000, 87 | CLKOUT1_USE_FINE_PS => false, 88 | CLKOUT2_DIVIDE => 1, 89 | CLKOUT2_DUTY_CYCLE => 0.500000, 90 | CLKOUT2_PHASE => 0.000000, 91 | CLKOUT2_USE_FINE_PS => false, 92 | CLKOUT3_DIVIDE => 1, 93 | CLKOUT3_DUTY_CYCLE => 0.500000, 94 | CLKOUT3_PHASE => 0.000000, 95 | CLKOUT3_USE_FINE_PS => false, 96 | CLKOUT4_CASCADE => false, 97 | CLKOUT4_DIVIDE => 1, 98 | CLKOUT4_DUTY_CYCLE => 0.500000, 99 | CLKOUT4_PHASE => 0.000000, 100 | CLKOUT4_USE_FINE_PS => false, 101 | CLKOUT5_DIVIDE => 1, 102 | CLKOUT5_DUTY_CYCLE => 0.500000, 103 | CLKOUT5_PHASE => 0.000000, 104 | CLKOUT5_USE_FINE_PS => false, 105 | CLKOUT6_DIVIDE => 1, 106 | CLKOUT6_DUTY_CYCLE => 0.500000, 107 | CLKOUT6_PHASE => 0.000000, 108 | CLKOUT6_USE_FINE_PS => false, 109 | COMPENSATION => "INTERNAL", 110 | DIVCLK_DIVIDE => 10, 111 | IS_CLKINSEL_INVERTED => '0', 112 | IS_PSEN_INVERTED => '0', 113 | IS_PSINCDEC_INVERTED => '0', 114 | IS_PWRDWN_INVERTED => '0', 115 | IS_RST_INVERTED => '0', 116 | REF_JITTER1 => 0.010000, 117 | REF_JITTER2 => 0.010000, 118 | SS_EN => "FALSE", 119 | SS_MODE => "CENTER_HIGH", 120 | SS_MOD_PERIOD => 10000, 121 | STARTUP_WAIT => false 122 | ) 123 | port map ( 124 | CLKFBIN => clkfbout_clk_wiz_0, 125 | CLKFBOUT => clkfbout_clk_wiz_0, 126 | CLKFBOUTB => NLW_mmcm_adv_inst_CLKFBOUTB_UNCONNECTED, 127 | CLKFBSTOPPED => NLW_mmcm_adv_inst_CLKFBSTOPPED_UNCONNECTED, 128 | CLKIN1 => clk_in1_clk_wiz_0, 129 | CLKIN2 => '0', 130 | CLKINSEL => '1', 131 | CLKINSTOPPED => NLW_mmcm_adv_inst_CLKINSTOPPED_UNCONNECTED, 132 | CLKOUT0 => clk_out1_clk_wiz_0, 133 | CLKOUT0B => NLW_mmcm_adv_inst_CLKOUT0B_UNCONNECTED, 134 | CLKOUT1 => NLW_mmcm_adv_inst_CLKOUT1_UNCONNECTED, 135 | CLKOUT1B => NLW_mmcm_adv_inst_CLKOUT1B_UNCONNECTED, 136 | CLKOUT2 => NLW_mmcm_adv_inst_CLKOUT2_UNCONNECTED, 137 | CLKOUT2B => NLW_mmcm_adv_inst_CLKOUT2B_UNCONNECTED, 138 | CLKOUT3 => NLW_mmcm_adv_inst_CLKOUT3_UNCONNECTED, 139 | CLKOUT3B => NLW_mmcm_adv_inst_CLKOUT3B_UNCONNECTED, 140 | CLKOUT4 => NLW_mmcm_adv_inst_CLKOUT4_UNCONNECTED, 141 | CLKOUT5 => NLW_mmcm_adv_inst_CLKOUT5_UNCONNECTED, 142 | CLKOUT6 => NLW_mmcm_adv_inst_CLKOUT6_UNCONNECTED, 143 | DADDR(6 downto 0) => B"0000000", 144 | DCLK => '0', 145 | DEN => '0', 146 | DI(15 downto 0) => B"0000000000000000", 147 | DO(15 downto 0) => NLW_mmcm_adv_inst_DO_UNCONNECTED(15 downto 0), 148 | DRDY => NLW_mmcm_adv_inst_DRDY_UNCONNECTED, 149 | DWE => '0', 150 | LOCKED => NLW_mmcm_adv_inst_LOCKED_UNCONNECTED, 151 | PSCLK => '0', 152 | PSDONE => NLW_mmcm_adv_inst_PSDONE_UNCONNECTED, 153 | PSEN => '0', 154 | PSINCDEC => '0', 155 | PWRDWN => '0', 156 | RST => '0' 157 | ); 158 | end STRUCTURE; 159 | library IEEE; 160 | use IEEE.STD_LOGIC_1164.ALL; 161 | library UNISIM; 162 | use UNISIM.VCOMPONENTS.ALL; 163 | entity clk_wiz_0 is 164 | port ( 165 | clk_out1 : out STD_LOGIC; 166 | clk_in1_p : in STD_LOGIC; 167 | clk_in1_n : in STD_LOGIC 168 | ); 169 | attribute NotValidForBitStream : boolean; 170 | attribute NotValidForBitStream of clk_wiz_0 : entity is true; 171 | end clk_wiz_0; 172 | 173 | architecture STRUCTURE of clk_wiz_0 is 174 | begin 175 | inst: entity work.clk_wiz_0_clk_wiz_0_clk_wiz 176 | port map ( 177 | clk_in1_n => clk_in1_n, 178 | clk_in1_p => clk_in1_p, 179 | clk_out1 => clk_out1 180 | ); 181 | end STRUCTURE; 182 | -------------------------------------------------------------------------------- /FPGA/fft.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0_stub.v: -------------------------------------------------------------------------------- 1 | // Copyright 1986-2019 Xilinx, Inc. All Rights Reserved. 2 | // -------------------------------------------------------------------------------- 3 | // Tool Version: Vivado v.2019.2 (win64) Build 2708876 Wed Nov 6 21:40:23 MST 2019 4 | // Date : Thu Apr 30 11:09:19 2020 5 | // Host : DESKTOP-2SF54E0 running 64-bit major release (build 9200) 6 | // Command : write_verilog -force -mode synth_stub e:/xil_pj/fft/fft.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0_stub.v 7 | // Design : clk_wiz_0 8 | // Purpose : Stub declaration of top-level module interface 9 | // Device : xc7vx485tffg1761-2 10 | // -------------------------------------------------------------------------------- 11 | 12 | // This empty module with port declaration file causes synthesis tools to infer a black box for IP. 13 | // The synthesis directives are for Synopsys Synplify support to prevent IO buffer insertion. 14 | // Please paste the declaration into a Verilog source file or add the file as an additional source. 15 | module clk_wiz_0(clk_out1, clk_in1_p, clk_in1_n) 16 | /* synthesis syn_black_box black_box_pad_pin="clk_out1,clk_in1_p,clk_in1_n" */; 17 | output clk_out1; 18 | input clk_in1_p; 19 | input clk_in1_n; 20 | endmodule 21 | -------------------------------------------------------------------------------- /FPGA/fft.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0_stub.vhdl: -------------------------------------------------------------------------------- 1 | -- Copyright 1986-2019 Xilinx, Inc. All Rights Reserved. 2 | -- -------------------------------------------------------------------------------- 3 | -- Tool Version: Vivado v.2019.2 (win64) Build 2708876 Wed Nov 6 21:40:23 MST 2019 4 | -- Date : Thu Apr 30 11:09:19 2020 5 | -- Host : DESKTOP-2SF54E0 running 64-bit major release (build 9200) 6 | -- Command : write_vhdl -force -mode synth_stub e:/xil_pj/fft/fft.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0_stub.vhdl 7 | -- Design : clk_wiz_0 8 | -- Purpose : Stub declaration of top-level module interface 9 | -- Device : xc7vx485tffg1761-2 10 | -- -------------------------------------------------------------------------------- 11 | library IEEE; 12 | use IEEE.STD_LOGIC_1164.ALL; 13 | 14 | entity clk_wiz_0 is 15 | Port ( 16 | clk_out1 : out STD_LOGIC; 17 | clk_in1_p : in STD_LOGIC; 18 | clk_in1_n : in STD_LOGIC 19 | ); 20 | 21 | end clk_wiz_0; 22 | 23 | architecture stub of clk_wiz_0 is 24 | attribute syn_black_box : boolean; 25 | attribute black_box_pad_pin : string; 26 | attribute syn_black_box of stub : architecture is true; 27 | attribute black_box_pad_pin of stub : architecture is "clk_out1,clk_in1_p,clk_in1_n"; 28 | begin 29 | end; 30 | -------------------------------------------------------------------------------- /FPGA/fft.srcs/sources_1/ip/clk_wiz_0/doc/clk_wiz_v6_0_changelog.txt: -------------------------------------------------------------------------------- 1 | 2019.2: 2 | * Version 6.0 (Rev. 4) 3 | * Bug Fix: Internal GUI fixes 4 | * Other: CR Fixes 5 | 6 | 2019.1.3: 7 | * Version 6.0 (Rev. 3) 8 | * No changes 9 | 10 | 2019.1.2: 11 | * Version 6.0 (Rev. 3) 12 | * No changes 13 | 14 | 2019.1.1: 15 | * Version 6.0 (Rev. 3) 16 | * No changes 17 | 18 | 2019.1: 19 | * Version 6.0 (Rev. 3) 20 | * Bug Fix: Internal GUI fixes 21 | * Other: New family support added 22 | 23 | 2018.3.1: 24 | * Version 6.0 (Rev. 2) 25 | * No changes 26 | 27 | 2018.3: 28 | * Version 6.0 (Rev. 2) 29 | * Bug Fix: Made input source independent for primary and secondary clock 30 | * Other: New family support added 31 | 32 | 2018.2: 33 | * Version 6.0 (Rev. 1) 34 | * Bug Fix: Removed vco freq check when Primitive is None 35 | * Other: New family support added 36 | 37 | 2018.1: 38 | * Version 6.0 39 | * Bug Fix: Bug fixes in Dynamic Reconfiguration feature and Write DRP feature 40 | * Bug Fix: Bug fixes for connection issue for s_axi_aresetn pin in IPI 41 | * Feature Enhancement: The default value of USE_PHASE_ALIGMENT is updated to false for UltraScale and UltraScale+ devices. Phase Alignment feature uses extra clock routes in UltraScale and UltraScale+ designs when MMCMs are used. These routing resources are wasted when user do not understand when phase alignment is really needed. Now, implementation tools can use these extra clock routing resources for high fanout signals. 42 | * Feature Enhancement: A column "Max. freq of buffer" is added in the Output Clock table which shows the maximum frequency that the selected output buffer can support 43 | * Other: DRCs added for invalid input values in Override mode 44 | 45 | 2017.4: 46 | * Version 5.4 (Rev. 3) 47 | * Bug Fix: Internal GUI issues are fixed for COMPENSATION mode as INTERNAL 48 | * Bug Fix: Fixed issue in dynamic reconfiguration of fractional values of M in MMCME3, MMCME4 49 | 50 | 2017.3: 51 | * Version 5.4 (Rev. 2) 52 | * General: Internal GUI changes. No effect on the customer design. Added support for aspartan7 devices 53 | 54 | 2017.2: 55 | * Version 5.4 (Rev. 1) 56 | * General: Internal GUI changes. No effect on the customer design. 57 | 58 | 2017.1: 59 | * Version 5.4 60 | * Port Change: Minor version upgrade. CLR pins are added to the pin list when selected buffer is BUFGCEDIV for ultrascale and ultrascale plus devices. 61 | * Other: Added support for new zynq ultrascale plus devices. 62 | 63 | 2016.4: 64 | * Version 5.3 (Rev. 3) 65 | * Bug Fix: Internal GUI issues are fixed. 66 | 67 | 2016.3: 68 | * Version 5.3 (Rev. 2) 69 | * Feature Enhancement: Added new option "Auto" under PRIMITIVE selection for ultrascale and above devices. This option allows the Wizard to instantiate appropriate primitive for the user inputs. 70 | * Feature Enhancement: Added Matched Routing Option for better timing solutions. 71 | * Feature Enhancement: Options 'Buffer' and 'Buffer_with_CE' are added to the buffer selection list. 72 | * Other: Source HDL files are concatenated into a single file to speed up synthesis and simulation. No changes required by the user 73 | * Other: Added support for Spartan7 devices. 74 | 75 | 2016.2: 76 | * Version 5.3 (Rev. 1) 77 | * Internal register bit update, no effect on customer designs. 78 | 79 | 2016.1: 80 | * Version 5.3 81 | * Added Clock Monitor Feature as part of clocking wizard 82 | * DRP registers can be directly written through AXI without resource utilization 83 | * Changes to HDL library management to support Vivado IP simulation library 84 | 85 | 2015.4.2: 86 | * Version 5.2 (Rev. 1) 87 | * No changes 88 | 89 | 2015.4.1: 90 | * Version 5.2 (Rev. 1) 91 | * No changes 92 | 93 | 2015.4: 94 | * Version 5.2 (Rev. 1) 95 | * Internal device family change, no functional changes 96 | 97 | 2015.3: 98 | * Version 5.2 99 | * IP revision number added to HDL module, library, and include file names, to support designs with both locked and upgraded IP instances 100 | * Port Renaming tab is hidden in the GUI in IP Integrator as this feature is not supported 101 | * Phase alignment feature is removed for ultrascale PLL as primitve has limited capabilities of supporting this feature 102 | * When clocking wizard is targetted on a board part, the frequency values that gets propagated to primary and secondary clocks are displayed in floating number format 103 | * Example design and simulation files are delivered in verilog only 104 | 105 | 2015.2.1: 106 | * Version 5.1 (Rev. 6) 107 | * No changes 108 | 109 | 2015.2: 110 | * Version 5.1 (Rev. 6) 111 | * No changes 112 | 113 | 2015.1: 114 | * Version 5.1 (Rev. 6) 115 | * Updated mmcm_pll_filter_lookup and mmcm_pll_lock_lookup functions in the header file for 7-Series and UltraScale devices 116 | * Supported devices and production status are now determined automatically, to simplify support for future devices 117 | 118 | 2014.4.1: 119 | * Version 5.1 (Rev. 5) 120 | * No changes 121 | 122 | 2014.4: 123 | * Version 5.1 (Rev. 5) 124 | * Internal device family change, no functional changes 125 | * updates related to the source selection based on board interface for zed board 126 | 127 | 2014.3: 128 | * Version 5.1 (Rev. 4) 129 | * Option added to enable dynamic phase and duty cycle for resource optimization in AXI4-Lite interface 130 | 131 | 2014.2: 132 | * Version 5.1 (Rev. 3) 133 | * Updated for AXI4-Lite interface locked status register address and bit mapping to align with the pg065 134 | 135 | 2014.1: 136 | * Version 5.1 (Rev. 2) 137 | * Updated to use inverted output CLKOUTB 0-3 of Clocking Primitive based on requested 180 phase w.r.t. previous clock 138 | * Internal device family name change, no functional changes 139 | 140 | 2013.4: 141 | * Version 5.1 (Rev. 1) 142 | * Added support for Ultrascale devices 143 | * Updated Board Flow GUI to select the clock interfaces 144 | * Fixed issue with Stub file parameter error for BUFR output driver 145 | 146 | 2013.3: 147 | * Version 5.1 148 | * Added AXI4-Lite interface to dynamically reconfigure MMCM/PLL 149 | * Improved safe clock logic to remove glitches on clock outputs for odd multiples of input clock frequencies 150 | * Fixed precision issues between displayed and actual frequencies 151 | * Added tool tips to GUI 152 | * Added Jitter and Phase error values to IP properties 153 | * Added support for Cadence IES and Synopsys VCS simulators 154 | * Reduced warnings in synthesis and simulation 155 | * Enhanced support for IP Integrator 156 | 157 | 2013.2: 158 | * Version 5.0 (Rev. 1) 159 | * Fixed issue with clock constraints for multiple instances of clocking wizard 160 | * Updated Life-Cycle status of devices 161 | 162 | 2013.1: 163 | * Version 5.0 164 | * Lower case ports for Verilog 165 | * Added Safe Clock Startup and Clock Sequencing 166 | 167 | (c) Copyright 2008 - 2019 Xilinx, Inc. All rights reserved. 168 | 169 | This file contains confidential and proprietary information 170 | of Xilinx, Inc. and is protected under U.S. and 171 | international copyright and other intellectual property 172 | laws. 173 | 174 | DISCLAIMER 175 | This disclaimer is not a license and does not grant any 176 | rights to the materials distributed herewith. Except as 177 | otherwise provided in a valid license issued to you by 178 | Xilinx, and to the maximum extent permitted by applicable 179 | law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 180 | WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 181 | AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 182 | BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 183 | INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 184 | (2) Xilinx shall not be liable (whether in contract or tort, 185 | including negligence, or under any other theory of 186 | liability) for any loss or damage of any kind or nature 187 | related to, arising under or in connection with these 188 | materials, including for any direct, or any indirect, 189 | special, incidental, or consequential loss or damage 190 | (including loss of data, profits, goodwill, or any type of 191 | loss or damage suffered as a result of any action brought 192 | by a third party) even if such damage or loss was 193 | reasonably foreseeable or Xilinx had been advised of the 194 | possibility of the same. 195 | 196 | CRITICAL APPLICATIONS 197 | Xilinx products are not designed or intended to be fail- 198 | safe, or for use in any application requiring fail-safe 199 | performance, such as life-support or safety devices or 200 | systems, Class III medical devices, nuclear facilities, 201 | applications related to the deployment of airbags, or any 202 | other applications that could lead to death, personal 203 | injury, or severe property or environmental damage 204 | (individually and collectively, "Critical 205 | Applications"). Customer assumes the sole risk and 206 | liability of any use of Xilinx products in Critical 207 | Applications, subject only to applicable laws and 208 | regulations governing limitations on product liability. 209 | 210 | THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 211 | PART OF THIS FILE AT ALL TIMES. 212 | -------------------------------------------------------------------------------- /FPGA/fft.srcs/sources_1/ip/clk_wiz_0/mmcm_pll_drp_func_7s_mmcm.vh: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Company: Xilinx 4 | // Engineer: Jim Tatsukawa, Karl Kurbjun and Carl Ribbing 5 | // Date: 7/30/2014 6 | // Design Name: MMCME2 DRP 7 | // Module Name: mmcme2_drp_func.h 8 | // Version: 1.04 9 | // Target Devices: 7 Series || MMCM 10 | // Tool versions: 2014.3 11 | // Description: This header provides the functions necessary to 12 | // calculate the DRP register values for the V6 MMCM. 13 | // 14 | // Revision Notes: 3/12 - Updating lookup_low/lookup_high (CR) 15 | // 4/13 - Fractional divide function in mmcm_frac_count_calc function. CRS610807 16 | // 17 | // Disclaimer: XILINX IS PROVIDING THIS DESIGN, CODE, OR 18 | // INFORMATION "AS IS" SOLELY FOR USE IN DEVELOPING 19 | // PROGRAMS AND SOLUTIONS FOR XILINX DEVICES. BY 20 | // PROVIDING THIS DESIGN, CODE, OR INFORMATION AS 21 | // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, 22 | // APPLICATION OR STANDARD, XILINX IS MAKING NO 23 | // REPRESENTATION THAT THIS IMPLEMENTATION IS FREE 24 | // FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE 25 | // RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY 26 | // REQUIRE FOR YOUR IMPLEMENTATION. XILINX 27 | // EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH 28 | // RESPECT TO THE ADEQUACY OF THE IMPLEMENTATION, 29 | // INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR 30 | // REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE 31 | // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES 32 | // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 33 | // PURPOSE. 34 | // 35 | // (c) Copyright 2009-2010 Xilinx, Inc. 36 | // All rights reserved. 37 | // 38 | /////////////////////////////////////////////////////////////////////////////// 39 | 40 | // These are user functions that should not be modified. Changes to the defines 41 | // or code within the functions may alter the accuracy of the calculations. 42 | 43 | // Define debug to provide extra messages durring elaboration 44 | //`define DEBUG 1 45 | 46 | // FRAC_PRECISION describes the width of the fractional portion of the fixed 47 | // point numbers. These should not be modified, they are for development 48 | // only 49 | `define FRAC_PRECISION 10 50 | // FIXED_WIDTH describes the total size for fixed point calculations(int+frac). 51 | // Warning: L.50 and below will not calculate properly with FIXED_WIDTHs 52 | // greater than 32 53 | `define FIXED_WIDTH 32 54 | 55 | // This function takes a fixed point number and rounds it to the nearest 56 | // fractional precision bit. 57 | function [`FIXED_WIDTH:1] round_frac 58 | ( 59 | // Input is (FIXED_WIDTH-FRAC_PRECISION).FRAC_PRECISION fixed point number 60 | input [`FIXED_WIDTH:1] decimal, 61 | 62 | // This describes the precision of the fraction, for example a value 63 | // of 1 would modify the fractional so that instead of being a .16 64 | // fractional, it would be a .1 (rounded to the nearest 0.5 in turn) 65 | input [`FIXED_WIDTH:1] precision 66 | ); 67 | 68 | begin 69 | 70 | `ifdef DEBUG 71 | $display("round_frac - decimal: %h, precision: %h", decimal, precision); 72 | `endif 73 | // If the fractional precision bit is high then round up 74 | if( decimal[(`FRAC_PRECISION-precision)] == 1'b1) begin 75 | round_frac = decimal + (1'b1 << (`FRAC_PRECISION-precision)); 76 | end else begin 77 | round_frac = decimal; 78 | end 79 | `ifdef DEBUG 80 | $display("round_frac: %h", round_frac); 81 | `endif 82 | end 83 | endfunction 84 | 85 | // This function calculates high_time, low_time, w_edge, and no_count 86 | // of a non-fractional counter based on the divide and duty cycle 87 | // 88 | // NOTE: high_time and low_time are returned as integers between 0 and 63 89 | // inclusive. 64 should equal 6'b000000 (in other words it is okay to 90 | // ignore the overflow) 91 | function [13:0] mmcm_pll_divider 92 | ( 93 | input [7:0] divide, // Max divide is 128 94 | input [31:0] duty_cycle // Duty cycle is multiplied by 100,000 95 | ); 96 | 97 | reg [`FIXED_WIDTH:1] duty_cycle_fix; 98 | 99 | // High/Low time is initially calculated with a wider integer to prevent a 100 | // calculation error when it overflows to 64. 101 | reg [6:0] high_time; 102 | reg [6:0] low_time; 103 | reg w_edge; 104 | reg no_count; 105 | 106 | reg [`FIXED_WIDTH:1] temp; 107 | 108 | begin 109 | // Duty Cycle must be between 0 and 1,000 110 | if(duty_cycle <=0 || duty_cycle >= 100000) begin 111 | `ifndef SYNTHESIS 112 | $display("ERROR: duty_cycle: %d is invalid", duty_cycle); 113 | `endif 114 | $finish; 115 | end 116 | 117 | // Convert to FIXED_WIDTH-FRAC_PRECISION.FRAC_PRECISION fixed point 118 | duty_cycle_fix = (duty_cycle << `FRAC_PRECISION) / 100_000; 119 | 120 | `ifdef DEBUG 121 | $display("duty_cycle_fix: %h", duty_cycle_fix); 122 | `endif 123 | 124 | // If the divide is 1 nothing needs to be set except the no_count bit. 125 | // Other values are dummies 126 | if(divide == 7'h01) begin 127 | high_time = 7'h01; 128 | w_edge = 1'b0; 129 | low_time = 7'h01; 130 | no_count = 1'b1; 131 | end else begin 132 | temp = round_frac(duty_cycle_fix*divide, 1); 133 | 134 | // comes from above round_frac 135 | high_time = temp[`FRAC_PRECISION+7:`FRAC_PRECISION+1]; 136 | // If the duty cycle * divide rounded is .5 or greater then this bit 137 | // is set. 138 | w_edge = temp[`FRAC_PRECISION]; // comes from round_frac 139 | 140 | // If the high time comes out to 0, it needs to be set to at least 1 141 | // and w_edge set to 0 142 | if(high_time == 7'h00) begin 143 | high_time = 7'h01; 144 | w_edge = 1'b0; 145 | end 146 | 147 | if(high_time == divide) begin 148 | high_time = divide - 1; 149 | w_edge = 1'b1; 150 | end 151 | 152 | // Calculate low_time based on the divide setting and set no_count to 153 | // 0 as it is only used when divide is 1. 154 | low_time = divide - high_time; 155 | no_count = 1'b0; 156 | end 157 | 158 | // Set the return value. 159 | mmcm_pll_divider = {w_edge,no_count,high_time[5:0],low_time[5:0]}; 160 | end 161 | endfunction 162 | 163 | // This function calculates mx, delay_time, and phase_mux 164 | // of a non-fractional counter based on the divide and phase 165 | // 166 | // NOTE: The only valid value for the MX bits is 2'b00 to ensure the coarse mux 167 | // is used. 168 | function [10:0] mmcm_pll_phase 169 | ( 170 | // divide must be an integer (use fractional if not) 171 | // assumed that divide already checked to be valid 172 | input [7:0] divide, // Max divide is 128 173 | 174 | // Phase is given in degrees (-360,000 to 360,000) 175 | input signed [31:0] phase 176 | ); 177 | 178 | reg [`FIXED_WIDTH:1] phase_in_cycles; 179 | reg [`FIXED_WIDTH:1] phase_fixed; 180 | reg [1:0] mx; 181 | reg [5:0] delay_time; 182 | reg [2:0] phase_mux; 183 | 184 | reg [`FIXED_WIDTH:1] temp; 185 | 186 | begin 187 | `ifdef DEBUG 188 | $display("mmcm_pll_phase-divide:%d,phase:%d", 189 | divide, phase); 190 | `endif 191 | 192 | if ((phase < -360000) || (phase > 360000)) begin 193 | `ifndef SYNTHESIS 194 | $display("ERROR: phase of $phase is not between -360000 and 360000"); 195 | `endif 196 | $finish; 197 | end 198 | 199 | // If phase is less than 0, convert it to a positive phase shift 200 | // Convert to (FIXED_WIDTH-FRAC_PRECISION).FRAC_PRECISION fixed point 201 | if(phase < 0) begin 202 | phase_fixed = ( (phase + 360000) << `FRAC_PRECISION ) / 1000; 203 | end else begin 204 | phase_fixed = ( phase << `FRAC_PRECISION ) / 1000; 205 | end 206 | 207 | // Put phase in terms of decimal number of vco clock cycles 208 | phase_in_cycles = ( phase_fixed * divide ) / 360; 209 | 210 | `ifdef DEBUG 211 | $display("phase_in_cycles: %h", phase_in_cycles); 212 | `endif 213 | 214 | 215 | temp = round_frac(phase_in_cycles, 3); 216 | 217 | // set mx to 2'b00 that the phase mux from the VCO is enabled 218 | mx = 2'b00; 219 | phase_mux = temp[`FRAC_PRECISION:`FRAC_PRECISION-2]; 220 | delay_time = temp[`FRAC_PRECISION+6:`FRAC_PRECISION+1]; 221 | 222 | `ifdef DEBUG 223 | $display("temp: %h", temp); 224 | `endif 225 | 226 | // Setup the return value 227 | mmcm_pll_phase={mx, phase_mux, delay_time}; 228 | end 229 | endfunction 230 | 231 | // This function takes the divide value and outputs the necessary lock values 232 | function [39:0] mmcm_pll_lock_lookup 233 | ( 234 | input [6:0] divide // Max divide is 64 235 | ); 236 | 237 | reg [2559:0] lookup; 238 | 239 | begin 240 | lookup = { 241 | // This table is composed of: 242 | // LockRefDly_LockFBDly_LockCnt_LockSatHigh_UnlockCnt 243 | 40'b00110_00110_1111101000_1111101001_0000000001, 244 | 40'b00110_00110_1111101000_1111101001_0000000001, 245 | 40'b01000_01000_1111101000_1111101001_0000000001, 246 | 40'b01011_01011_1111101000_1111101001_0000000001, 247 | 40'b01110_01110_1111101000_1111101001_0000000001, 248 | 40'b10001_10001_1111101000_1111101001_0000000001, 249 | 40'b10011_10011_1111101000_1111101001_0000000001, 250 | 40'b10110_10110_1111101000_1111101001_0000000001, 251 | 40'b11001_11001_1111101000_1111101001_0000000001, 252 | 40'b11100_11100_1111101000_1111101001_0000000001, 253 | 40'b11111_11111_1110000100_1111101001_0000000001, 254 | 40'b11111_11111_1100111001_1111101001_0000000001, 255 | 40'b11111_11111_1011101110_1111101001_0000000001, 256 | 40'b11111_11111_1010111100_1111101001_0000000001, 257 | 40'b11111_11111_1010001010_1111101001_0000000001, 258 | 40'b11111_11111_1001110001_1111101001_0000000001, 259 | 40'b11111_11111_1000111111_1111101001_0000000001, 260 | 40'b11111_11111_1000100110_1111101001_0000000001, 261 | 40'b11111_11111_1000001101_1111101001_0000000001, 262 | 40'b11111_11111_0111110100_1111101001_0000000001, 263 | 40'b11111_11111_0111011011_1111101001_0000000001, 264 | 40'b11111_11111_0111000010_1111101001_0000000001, 265 | 40'b11111_11111_0110101001_1111101001_0000000001, 266 | 40'b11111_11111_0110010000_1111101001_0000000001, 267 | 40'b11111_11111_0110010000_1111101001_0000000001, 268 | 40'b11111_11111_0101110111_1111101001_0000000001, 269 | 40'b11111_11111_0101011110_1111101001_0000000001, 270 | 40'b11111_11111_0101011110_1111101001_0000000001, 271 | 40'b11111_11111_0101000101_1111101001_0000000001, 272 | 40'b11111_11111_0101000101_1111101001_0000000001, 273 | 40'b11111_11111_0100101100_1111101001_0000000001, 274 | 40'b11111_11111_0100101100_1111101001_0000000001, 275 | 40'b11111_11111_0100101100_1111101001_0000000001, 276 | 40'b11111_11111_0100010011_1111101001_0000000001, 277 | 40'b11111_11111_0100010011_1111101001_0000000001, 278 | 40'b11111_11111_0100010011_1111101001_0000000001, 279 | 40'b11111_11111_0011111010_1111101001_0000000001, 280 | 40'b11111_11111_0011111010_1111101001_0000000001, 281 | 40'b11111_11111_0011111010_1111101001_0000000001, 282 | 40'b11111_11111_0011111010_1111101001_0000000001, 283 | 40'b11111_11111_0011111010_1111101001_0000000001, 284 | 40'b11111_11111_0011111010_1111101001_0000000001, 285 | 40'b11111_11111_0011111010_1111101001_0000000001, 286 | 40'b11111_11111_0011111010_1111101001_0000000001, 287 | 40'b11111_11111_0011111010_1111101001_0000000001, 288 | 40'b11111_11111_0011111010_1111101001_0000000001, 289 | 40'b11111_11111_0011111010_1111101001_0000000001, 290 | 40'b11111_11111_0011111010_1111101001_0000000001, 291 | 40'b11111_11111_0011111010_1111101001_0000000001, 292 | 40'b11111_11111_0011111010_1111101001_0000000001, 293 | 40'b11111_11111_0011111010_1111101001_0000000001, 294 | 40'b11111_11111_0011111010_1111101001_0000000001, 295 | 40'b11111_11111_0011111010_1111101001_0000000001, 296 | 40'b11111_11111_0011111010_1111101001_0000000001, 297 | 40'b11111_11111_0011111010_1111101001_0000000001, 298 | 40'b11111_11111_0011111010_1111101001_0000000001, 299 | 40'b11111_11111_0011111010_1111101001_0000000001, 300 | 40'b11111_11111_0011111010_1111101001_0000000001, 301 | 40'b11111_11111_0011111010_1111101001_0000000001, 302 | 40'b11111_11111_0011111010_1111101001_0000000001, 303 | 40'b11111_11111_0011111010_1111101001_0000000001, 304 | 40'b11111_11111_0011111010_1111101001_0000000001, 305 | 40'b11111_11111_0011111010_1111101001_0000000001, 306 | 40'b11111_11111_0011111010_1111101001_0000000001 307 | }; 308 | 309 | // Set lookup_entry with the explicit bits from lookup with a part select 310 | mmcm_pll_lock_lookup = lookup[ ((64-divide)*40) +: 40]; 311 | `ifdef DEBUG 312 | $display("lock_lookup: %b", mmcm_pll_lock_lookup); 313 | `endif 314 | end 315 | endfunction 316 | 317 | // This function takes the divide value and the bandwidth setting of the MMCM 318 | // and outputs the digital filter settings necessary. 319 | function [9:0] mmcm_pll_filter_lookup 320 | ( 321 | input [6:0] divide, // Max divide is 64 322 | input [8*9:0] BANDWIDTH 323 | ); 324 | 325 | reg [639:0] lookup_low; 326 | reg [639:0] lookup_high; 327 | 328 | reg [9:0] lookup_entry; 329 | 330 | begin 331 | lookup_low = { 332 | // CP_RES_LFHF 333 | 10'b0010_1111_00, 334 | 10'b0010_1111_00, 335 | 10'b0010_1111_00, 336 | 10'b0010_1111_00, 337 | 10'b0010_0111_00, 338 | 10'b0010_1011_00, 339 | 10'b0010_1101_00, 340 | 10'b0010_0011_00, 341 | 10'b0010_0101_00, 342 | 10'b0010_0101_00, 343 | 10'b0010_1001_00, 344 | 10'b0010_1110_00, 345 | 10'b0010_1110_00, 346 | 10'b0010_1110_00, 347 | 10'b0010_1110_00, 348 | 10'b0010_0001_00, 349 | 10'b0010_0001_00, 350 | 10'b0010_0001_00, 351 | 10'b0010_0110_00, 352 | 10'b0010_0110_00, 353 | 10'b0010_0110_00, 354 | 10'b0010_0110_00, 355 | 10'b0010_0110_00, 356 | 10'b0010_0110_00, 357 | 10'b0010_0110_00, 358 | 10'b0010_1010_00, 359 | 10'b0010_1010_00, 360 | 10'b0010_1010_00, 361 | 10'b0010_1010_00, 362 | 10'b0010_1010_00, 363 | 10'b0010_1100_00, 364 | 10'b0010_1100_00, 365 | 10'b0010_1100_00, 366 | 10'b0010_1100_00, 367 | 10'b0010_1100_00, 368 | 10'b0010_1100_00, 369 | 10'b0010_1100_00, 370 | 10'b0010_1100_00, 371 | 10'b0010_1100_00, 372 | 10'b0010_1100_00, 373 | 10'b0010_1100_00, 374 | 10'b0010_1100_00, 375 | 10'b0010_1100_00, 376 | 10'b0010_1100_00, 377 | 10'b0010_1100_00, 378 | 10'b0010_1100_00, 379 | 10'b0010_1100_00, 380 | 10'b0010_0010_00, 381 | 10'b0010_0010_00, 382 | 10'b0010_0010_00, 383 | 10'b0010_0010_00, 384 | 10'b0010_0010_00, 385 | 10'b0010_0010_00, 386 | 10'b0010_0010_00, 387 | 10'b0010_0010_00, 388 | 10'b0010_0010_00, 389 | 10'b0010_0010_00, 390 | 10'b0010_0010_00, 391 | 10'b0010_0010_00, 392 | 10'b0010_0010_00, 393 | 10'b0010_0010_00, 394 | 10'b0010_0010_00, 395 | 10'b0010_0010_00, 396 | 10'b0010_0010_00 397 | }; 398 | 399 | lookup_high = { 400 | // CP_RES_LFHF 401 | 10'b0010_1111_00, 402 | 10'b0100_1111_00, 403 | 10'b0101_1011_00, 404 | 10'b0111_0111_00, 405 | 10'b1101_0111_00, 406 | 10'b1110_1011_00, 407 | 10'b1110_1101_00, 408 | 10'b1111_0011_00, 409 | 10'b1110_0101_00, 410 | 10'b1111_0101_00, 411 | 10'b1111_1001_00, 412 | 10'b1101_0001_00, 413 | 10'b1111_1001_00, 414 | 10'b1111_1001_00, 415 | 10'b1111_1001_00, 416 | 10'b1111_1001_00, 417 | 10'b1111_0101_00, 418 | 10'b1111_0101_00, 419 | 10'b1100_0001_00, 420 | 10'b1100_0001_00, 421 | 10'b1100_0001_00, 422 | 10'b0101_1100_00, 423 | 10'b0101_1100_00, 424 | 10'b0101_1100_00, 425 | 10'b0101_1100_00, 426 | 10'b0011_0100_00, 427 | 10'b0011_0100_00, 428 | 10'b0011_0100_00, 429 | 10'b0011_0100_00, 430 | 10'b0011_0100_00, 431 | 10'b0011_0100_00, 432 | 10'b0011_0100_00, 433 | 10'b0011_0100_00, 434 | 10'b0011_0100_00, 435 | 10'b0011_0100_00, 436 | 10'b0011_0100_00, 437 | 10'b0011_0100_00, 438 | 10'b0011_0100_00, 439 | 10'b0011_0100_00, 440 | 10'b0011_0100_00, 441 | 10'b0011_0100_00, 442 | 10'b0010_1000_00, 443 | 10'b0010_1000_00, 444 | 10'b0010_1000_00, 445 | 10'b0010_1000_00, 446 | 10'b0010_1000_00, 447 | 10'b0111_0001_00, 448 | 10'b0111_0001_00, 449 | 10'b0100_1100_00, 450 | 10'b0100_1100_00, 451 | 10'b0100_1100_00, 452 | 10'b0100_1100_00, 453 | 10'b0110_0001_00, 454 | 10'b0110_0001_00, 455 | 10'b0101_0110_00, 456 | 10'b0101_0110_00, 457 | 10'b0101_0110_00, 458 | 10'b0010_0100_00, 459 | 10'b0010_0100_00, 460 | 10'b0010_0100_00, 461 | 10'b0010_0100_00, 462 | 10'b0100_1010_00, 463 | 10'b0011_1100_00, 464 | 10'b0011_1100_00 465 | }; 466 | 467 | // Set lookup_entry with the explicit bits from lookup with a part select 468 | if(BANDWIDTH == "LOW") begin 469 | // Low Bandwidth 470 | mmcm_pll_filter_lookup = lookup_low[ ((64-divide)*10) +: 10]; 471 | end else begin 472 | // High or optimized bandwidth 473 | mmcm_pll_filter_lookup = lookup_high[ ((64-divide)*10) +: 10]; 474 | end 475 | 476 | `ifdef DEBUG 477 | $display("filter_lookup: %b", mmcm_pll_filter_lookup); 478 | `endif 479 | end 480 | endfunction 481 | 482 | // This function takes in the divide, phase, and duty cycle 483 | // setting to calculate the upper and lower counter registers. 484 | function [37:0] mmcm_pll_count_calc 485 | ( 486 | input [7:0] divide, // Max divide is 128 487 | input signed [31:0] phase, 488 | input [31:0] duty_cycle // Multiplied by 100,000 489 | ); 490 | 491 | reg [13:0] div_calc; 492 | reg [16:0] phase_calc; 493 | 494 | begin 495 | `ifdef DEBUG 496 | $display("mmcm_pll_count_calc- divide:%h, phase:%d, duty_cycle:%d", 497 | divide, phase, duty_cycle); 498 | `endif 499 | 500 | // w_edge[13], no_count[12], high_time[11:6], low_time[5:0] 501 | div_calc = mmcm_pll_divider(divide, duty_cycle); 502 | // mx[10:9], pm[8:6], dt[5:0] 503 | phase_calc = mmcm_pll_phase(divide, phase); 504 | 505 | // Return value is the upper and lower address of counter 506 | // Upper address is: 507 | // RESERVED [31:26] 508 | // MX [25:24] 509 | // EDGE [23] 510 | // NOCOUNT [22] 511 | // DELAY_TIME [21:16] 512 | // Lower Address is: 513 | // PHASE_MUX [15:13] 514 | // RESERVED [12] 515 | // HIGH_TIME [11:6] 516 | // LOW_TIME [5:0] 517 | 518 | `ifdef DEBUG 519 | $display("div:%d dc:%d phase:%d ht:%d lt:%d ed:%d nc:%d mx:%d dt:%d pm:%d", 520 | divide, duty_cycle, phase, div_calc[11:6], div_calc[5:0], 521 | div_calc[13], div_calc[12], 522 | phase_calc[16:15], phase_calc[5:0], phase_calc[14:12]); 523 | `endif 524 | 525 | mmcm_pll_count_calc = 526 | { 527 | // Upper Address 528 | 6'h00, phase_calc[10:9], div_calc[13:12], phase_calc[5:0], 529 | // Lower Address 530 | phase_calc[8:6], 1'b0, div_calc[11:0] 531 | }; 532 | end 533 | endfunction 534 | 535 | 536 | // This function takes in the divide, phase, and duty cycle 537 | // setting to calculate the upper and lower counter registers. 538 | // for fractional multiply/divide functions. 539 | // 540 | // 541 | function [37:0] mmcm_frac_count_calc 542 | ( 543 | input [7:0] divide, // Max divide is 128 544 | input signed [31:0] phase, 545 | input [31:0] duty_cycle, // Multiplied by 1,000 546 | input [9:0] frac // Multiplied by 1000 547 | ); 548 | 549 | //Required for fractional divide calculations 550 | reg [7:0] lt_frac; 551 | reg [7:0] ht_frac; 552 | 553 | reg /*[7:0]*/ wf_fall_frac; 554 | reg /*[7:0]*/ wf_rise_frac; 555 | 556 | reg [31:0] a; 557 | reg [7:0] pm_rise_frac_filtered ; 558 | reg [7:0] pm_fall_frac_filtered ; 559 | reg [7:0] clkout0_divide_int; 560 | reg [2:0] clkout0_divide_frac; 561 | reg [7:0] even_part_high; 562 | reg [7:0] even_part_low; 563 | 564 | reg [7:0] odd; 565 | reg [7:0] odd_and_frac; 566 | 567 | reg [7:0] pm_fall; 568 | reg [7:0] pm_rise; 569 | reg [7:0] dt; 570 | reg [7:0] dt_int; 571 | reg [63:0] dt_calc; 572 | 573 | reg [7:0] pm_rise_frac; 574 | reg [7:0] pm_fall_frac; 575 | 576 | reg [31:0] a_per_in_octets; 577 | reg [31:0] a_phase_in_cycles; 578 | 579 | parameter precision = 0.125; 580 | 581 | reg [31:0] phase_fixed; // changed to 31:0 from 32:1 jt 5/2/11 582 | reg [31: 0] phase_pos; 583 | reg [31: 0] phase_vco; 584 | reg [31:0] temp;// changed to 31:0 from 32:1 jt 5/2/11 585 | reg [13:0] div_calc; 586 | reg [16:0] phase_calc; 587 | 588 | begin 589 | `ifdef DEBUG 590 | $display("mmcm_frac_count_calc- divide:%h, phase:%d, duty_cycle:%d", 591 | divide, phase, duty_cycle); 592 | `endif 593 | 594 | //convert phase to fixed 595 | if ((phase < -360000) || (phase > 360000)) begin 596 | `ifndef SYNTHESIS 597 | $display("ERROR: phase of $phase is not between -360000 and 360000"); 598 | `endif 599 | $finish; 600 | end 601 | 602 | 603 | // Return value is 604 | // Transfer data 605 | // RESERVED [37:36] 606 | // FRAC_TIME [35:33] 607 | // FRAC_WF_FALL [32] 608 | // Upper address is: 609 | // RESERVED [31:26] 610 | // MX [25:24] 611 | // EDGE [23] 612 | // NOCOUNT [22] 613 | // DELAY_TIME [21:16] 614 | // Lower Address is: 615 | // PHASE_MUX [15:13] 616 | // RESERVED [12] 617 | // HIGH_TIME [11:6] 618 | // LOW_TIME [5:0] 619 | 620 | 621 | 622 | clkout0_divide_frac = frac / 125; 623 | clkout0_divide_int = divide; 624 | 625 | even_part_high = clkout0_divide_int >> 1;//$rtoi(clkout0_divide_int / 2); 626 | even_part_low = even_part_high; 627 | 628 | odd = clkout0_divide_int - even_part_high - even_part_low; 629 | odd_and_frac = (8*odd) + clkout0_divide_frac; 630 | 631 | lt_frac = even_part_high - (odd_and_frac <= 9);//IF(odd_and_frac>9,even_part_high, even_part_high - 1) 632 | ht_frac = even_part_low - (odd_and_frac <= 8);//IF(odd_and_frac>8,even_part_low, even_part_low- 1) 633 | 634 | pm_fall = {odd[6:0],2'b00} + {6'h00, clkout0_divide_frac[2:1]}; // using >> instead of clkout0_divide_frac / 2 635 | pm_rise = 0; //0 636 | 637 | wf_fall_frac = ((odd_and_frac >=2) && (odd_and_frac <=9)) || ((clkout0_divide_frac == 1) && (clkout0_divide_int == 2));//CRS610807 638 | wf_rise_frac = (odd_and_frac >=1) && (odd_and_frac <=8);//IF(odd_and_frac>=1,IF(odd_and_frac <= 8,1,0),0) 639 | 640 | 641 | 642 | //Calculate phase in fractional cycles 643 | a_per_in_octets = (8 * divide) + (frac / 125) ; 644 | a_phase_in_cycles = (phase+10) * a_per_in_octets / 360000 ;//Adding 1 due to rounding errors 645 | pm_rise_frac = (a_phase_in_cycles[7:0] ==8'h00)?8'h00:a_phase_in_cycles[7:0] - {a_phase_in_cycles[7:3],3'b000}; 646 | 647 | dt_calc = ((phase+10) * a_per_in_octets / 8 )/360000 ;//TRUNC(phase* divide / 360); //or_simply (a_per_in_octets / 8) 648 | dt = dt_calc[7:0]; 649 | 650 | pm_rise_frac_filtered = (pm_rise_frac >=8) ? (pm_rise_frac ) - 8: pm_rise_frac ; //((phase_fixed * (divide + frac / 1000)) / 360) - {pm_rise_frac[7:3],3'b000};//$rtoi(clkout0_phase * clkout0_divide / 45);//a; 651 | 652 | dt_int = dt + (& pm_rise_frac[7:4]); //IF(pm_rise_overwriting>7,dt+1,dt) 653 | pm_fall_frac = pm_fall + pm_rise_frac; 654 | pm_fall_frac_filtered = pm_fall + pm_rise_frac - {pm_fall_frac[7:3], 3'b000}; 655 | 656 | div_calc = mmcm_pll_divider(divide, duty_cycle); //Use to determine edge[7], no count[6] 657 | phase_calc = mmcm_pll_phase(divide, phase);// returns{mx[1:0], phase_mux[2:0], delay_time[5:0]} 658 | 659 | mmcm_frac_count_calc[37:0] = 660 | { 2'b00, pm_fall_frac_filtered[2:0], wf_fall_frac, 661 | 1'b0, clkout0_divide_frac[2:0], 1'b1, wf_rise_frac, phase_calc[10:9], div_calc[13:12], dt[5:0], 662 | pm_rise_frac_filtered[2], pm_rise_frac_filtered[1], pm_rise_frac_filtered[0], 1'b0, ht_frac[5:0], lt_frac[5:0] 663 | } ; 664 | 665 | `ifdef DEBUG 666 | $display("-%d.%d p%d>> :DADDR_9_15 frac30to28.frac_en.wf_r_frac.dt:%b%d%d_%b:DADDR_7_13 pm_f_frac_filtered_29to27.wf_f_frac_26:%b%d:DADDR_8_14.pm_r_frac_filt_15to13.ht_frac.lt_frac:%b%b%b:", divide, frac, phase, clkout0_divide_frac, 1, wf_rise_frac, dt, pm_fall_frac_filtered, wf_fall_frac, pm_rise_frac_filtered, ht_frac, lt_frac); 667 | `endif 668 | 669 | end 670 | endfunction 671 | 672 | -------------------------------------------------------------------------------- /FPGA/fft.srcs/sources_1/ip/clk_wiz_0/mmcm_pll_drp_func_7s_pll.vh: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Company: Xilinx 4 | // Engineer: Jim Tatsukawa, Karl Kurbjun and Carl Ribbing 5 | // Date: 7/30/2014 6 | // Design Name: PLLE2 DRP 7 | // Module Name: plle2_drp_func.h 8 | // Version: 2.00 9 | // Target Devices: 7 Series || PLL 10 | // Tool versions: 2014.3 11 | // Description: This header provides the functions necessary to 12 | // calculate the DRP register values for the V6 PLL. 13 | // Updated for CR663854. 14 | // 15 | // Disclaimer: XILINX IS PROVIDING THIS DESIGN, CODE, OR 16 | // INFORMATION "AS IS" SOLELY FOR USE IN DEVELOPING 17 | // PROGRAMS AND SOLUTIONS FOR XILINX DEVICES. BY 18 | // PROVIDING THIS DESIGN, CODE, OR INFORMATION AS 19 | // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, 20 | // APPLICATION OR STANDARD, XILINX IS MAKING NO 21 | // REPRESENTATION THAT THIS IMPLEMENTATION IS FREE 22 | // FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE 23 | // RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY 24 | // REQUIRE FOR YOUR IMPLEMENTATION. XILINX 25 | // EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH 26 | // RESPECT TO THE ADEQUACY OF THE IMPLEMENTATION, 27 | // INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR 28 | // REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE 29 | // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES 30 | // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 31 | // PURPOSE. 32 | // 33 | // (c) Copyright 2009-2010 Xilinx, Inc. 34 | // All rights reserved. 35 | // 36 | /////////////////////////////////////////////////////////////////////////////// 37 | 38 | // These are user functions that should not be modified. Changes to the defines 39 | // or code within the functions may alter the accuracy of the calculations. 40 | 41 | // Define debug to provide extra messages durring elaboration 42 | //`define DEBUG 1 43 | 44 | // FRAC_PRECISION describes the width of the fractional portion of the fixed 45 | // point numbers. These should not be modified, they are for development 46 | // only 47 | `define FRAC_PRECISION 10 48 | // FIXED_WIDTH describes the total size for fixed point calculations(int+frac). 49 | // Warning: L.50 and below will not calculate properly with FIXED_WIDTHs 50 | // greater than 32 51 | `define FIXED_WIDTH 32 52 | 53 | // This function takes a fixed point number and rounds it to the nearest 54 | // fractional precision bit. 55 | function [`FIXED_WIDTH:1] round_frac 56 | ( 57 | // Input is (FIXED_WIDTH-FRAC_PRECISION).FRAC_PRECISION fixed point number 58 | input [`FIXED_WIDTH:1] decimal, 59 | 60 | // This describes the precision of the fraction, for example a value 61 | // of 1 would modify the fractional so that instead of being a .16 62 | // fractional, it would be a .1 (rounded to the nearest 0.5 in turn) 63 | input [`FIXED_WIDTH:1] precision 64 | ); 65 | 66 | begin 67 | 68 | `ifdef DEBUG 69 | $display("round_frac - decimal: %h, precision: %h", decimal, precision); 70 | `endif 71 | // If the fractional precision bit is high then round up 72 | if( decimal[(`FRAC_PRECISION-precision)] == 1'b1) begin 73 | round_frac = decimal + (1'b1 << (`FRAC_PRECISION-precision)); 74 | end else begin 75 | round_frac = decimal; 76 | end 77 | `ifdef DEBUG 78 | $display("round_frac: %h", round_frac); 79 | `endif 80 | end 81 | endfunction 82 | 83 | // This function calculates high_time, low_time, w_edge, and no_count 84 | // of a non-fractional counter based on the divide and duty cycle 85 | // 86 | // NOTE: high_time and low_time are returned as integers between 0 and 63 87 | // inclusive. 64 should equal 6'b000000 (in other words it is okay to 88 | // ignore the overflow) 89 | function [13:0] mmcm_pll_divider 90 | ( 91 | input [7:0] divide, // Max divide is 128 92 | input [31:0] duty_cycle // Duty cycle is multiplied by 100,000 93 | ); 94 | 95 | reg [`FIXED_WIDTH:1] duty_cycle_fix; 96 | 97 | // High/Low time is initially calculated with a wider integer to prevent a 98 | // calculation error when it overflows to 64. 99 | reg [6:0] high_time; 100 | reg [6:0] low_time; 101 | reg w_edge; 102 | reg no_count; 103 | 104 | reg [`FIXED_WIDTH:1] temp; 105 | 106 | begin 107 | // Duty Cycle must be between 0 and 1,000 108 | if(duty_cycle <=0 || duty_cycle >= 100000) begin 109 | `ifndef SYNTHESIS 110 | $display("ERROR: duty_cycle: %d is invalid", duty_cycle); 111 | `endif 112 | $finish; 113 | end 114 | 115 | // Convert to FIXED_WIDTH-FRAC_PRECISION.FRAC_PRECISION fixed point 116 | duty_cycle_fix = (duty_cycle << `FRAC_PRECISION) / 100_000; 117 | 118 | `ifdef DEBUG 119 | $display("duty_cycle_fix: %h", duty_cycle_fix); 120 | `endif 121 | 122 | // If the divide is 1 nothing needs to be set except the no_count bit. 123 | // Other values are dummies 124 | if(divide == 7'h01) begin 125 | high_time = 7'h01; 126 | w_edge = 1'b0; 127 | low_time = 7'h01; 128 | no_count = 1'b1; 129 | end else begin 130 | temp = round_frac(duty_cycle_fix*divide, 1); 131 | 132 | // comes from above round_frac 133 | high_time = temp[`FRAC_PRECISION+7:`FRAC_PRECISION+1]; 134 | // If the duty cycle * divide rounded is .5 or greater then this bit 135 | // is set. 136 | w_edge = temp[`FRAC_PRECISION]; // comes from round_frac 137 | 138 | // If the high time comes out to 0, it needs to be set to at least 1 139 | // and w_edge set to 0 140 | if(high_time == 7'h00) begin 141 | high_time = 7'h01; 142 | w_edge = 1'b0; 143 | end 144 | 145 | if(high_time == divide) begin 146 | high_time = divide - 1; 147 | w_edge = 1'b1; 148 | end 149 | 150 | // Calculate low_time based on the divide setting and set no_count to 151 | // 0 as it is only used when divide is 1. 152 | low_time = divide - high_time; 153 | no_count = 1'b0; 154 | end 155 | 156 | // Set the return value. 157 | mmcm_pll_divider = {w_edge,no_count,high_time[5:0],low_time[5:0]}; 158 | end 159 | endfunction 160 | 161 | // This function calculates mx, delay_time, and phase_mux 162 | // of a non-fractional counter based on the divide and phase 163 | // 164 | // NOTE: The only valid value for the MX bits is 2'b00 to ensure the coarse mux 165 | // is used. 166 | function [10:0] mmcm_pll_phase 167 | ( 168 | // divide must be an integer (use fractional if not) 169 | // assumed that divide already checked to be valid 170 | input [7:0] divide, // Max divide is 128 171 | 172 | // Phase is given in degrees (-360,000 to 360,000) 173 | input signed [31:0] phase 174 | ); 175 | 176 | reg [`FIXED_WIDTH:1] phase_in_cycles; 177 | reg [`FIXED_WIDTH:1] phase_fixed; 178 | reg [1:0] mx; 179 | reg [5:0] delay_time; 180 | reg [2:0] phase_mux; 181 | 182 | reg [`FIXED_WIDTH:1] temp; 183 | 184 | begin 185 | `ifdef DEBUG 186 | $display("mmcm_pll_phase-divide:%d,phase:%d", 187 | divide, phase); 188 | `endif 189 | 190 | if ((phase < -360000) || (phase > 360000)) begin 191 | `ifndef SYNTHESIS 192 | $display("ERROR: phase of $phase is not between -360000 and 360000"); 193 | `endif 194 | $finish; 195 | end 196 | 197 | // If phase is less than 0, convert it to a positive phase shift 198 | // Convert to (FIXED_WIDTH-FRAC_PRECISION).FRAC_PRECISION fixed point 199 | if(phase < 0) begin 200 | phase_fixed = ( (phase + 360000) << `FRAC_PRECISION ) / 1000; 201 | end else begin 202 | phase_fixed = ( phase << `FRAC_PRECISION ) / 1000; 203 | end 204 | 205 | // Put phase in terms of decimal number of vco clock cycles 206 | phase_in_cycles = ( phase_fixed * divide ) / 360; 207 | 208 | `ifdef DEBUG 209 | $display("phase_in_cycles: %h", phase_in_cycles); 210 | `endif 211 | 212 | 213 | temp = round_frac(phase_in_cycles, 3); 214 | 215 | // set mx to 2'b00 that the phase mux from the VCO is enabled 216 | mx = 2'b00; 217 | phase_mux = temp[`FRAC_PRECISION:`FRAC_PRECISION-2]; 218 | delay_time = temp[`FRAC_PRECISION+6:`FRAC_PRECISION+1]; 219 | 220 | `ifdef DEBUG 221 | $display("temp: %h", temp); 222 | `endif 223 | 224 | // Setup the return value 225 | mmcm_pll_phase={mx, phase_mux, delay_time}; 226 | end 227 | endfunction 228 | 229 | // This function takes the divide value and outputs the necessary lock values 230 | function [39:0] mmcm_pll_lock_lookup 231 | ( 232 | input [6:0] divide // Max divide is 64 233 | ); 234 | 235 | reg [2559:0] lookup; 236 | 237 | begin 238 | lookup = { 239 | // This table is composed of: 240 | // LockRefDly_LockFBDly_LockCnt_LockSatHigh_UnlockCnt 241 | 40'b00110_00110_1111101000_1111101001_0000000001, 242 | 40'b00110_00110_1111101000_1111101001_0000000001, 243 | 40'b01000_01000_1111101000_1111101001_0000000001, 244 | 40'b01011_01011_1111101000_1111101001_0000000001, 245 | 40'b01110_01110_1111101000_1111101001_0000000001, 246 | 40'b10001_10001_1111101000_1111101001_0000000001, 247 | 40'b10011_10011_1111101000_1111101001_0000000001, 248 | 40'b10110_10110_1111101000_1111101001_0000000001, 249 | 40'b11001_11001_1111101000_1111101001_0000000001, 250 | 40'b11100_11100_1111101000_1111101001_0000000001, 251 | 40'b11111_11111_1110000100_1111101001_0000000001, 252 | 40'b11111_11111_1100111001_1111101001_0000000001, 253 | 40'b11111_11111_1011101110_1111101001_0000000001, 254 | 40'b11111_11111_1010111100_1111101001_0000000001, 255 | 40'b11111_11111_1010001010_1111101001_0000000001, 256 | 40'b11111_11111_1001110001_1111101001_0000000001, 257 | 40'b11111_11111_1000111111_1111101001_0000000001, 258 | 40'b11111_11111_1000100110_1111101001_0000000001, 259 | 40'b11111_11111_1000001101_1111101001_0000000001, 260 | 40'b11111_11111_0111110100_1111101001_0000000001, 261 | 40'b11111_11111_0111011011_1111101001_0000000001, 262 | 40'b11111_11111_0111000010_1111101001_0000000001, 263 | 40'b11111_11111_0110101001_1111101001_0000000001, 264 | 40'b11111_11111_0110010000_1111101001_0000000001, 265 | 40'b11111_11111_0110010000_1111101001_0000000001, 266 | 40'b11111_11111_0101110111_1111101001_0000000001, 267 | 40'b11111_11111_0101011110_1111101001_0000000001, 268 | 40'b11111_11111_0101011110_1111101001_0000000001, 269 | 40'b11111_11111_0101000101_1111101001_0000000001, 270 | 40'b11111_11111_0101000101_1111101001_0000000001, 271 | 40'b11111_11111_0100101100_1111101001_0000000001, 272 | 40'b11111_11111_0100101100_1111101001_0000000001, 273 | 40'b11111_11111_0100101100_1111101001_0000000001, 274 | 40'b11111_11111_0100010011_1111101001_0000000001, 275 | 40'b11111_11111_0100010011_1111101001_0000000001, 276 | 40'b11111_11111_0100010011_1111101001_0000000001, 277 | 40'b11111_11111_0011111010_1111101001_0000000001, 278 | 40'b11111_11111_0011111010_1111101001_0000000001, 279 | 40'b11111_11111_0011111010_1111101001_0000000001, 280 | 40'b11111_11111_0011111010_1111101001_0000000001, 281 | 40'b11111_11111_0011111010_1111101001_0000000001, 282 | 40'b11111_11111_0011111010_1111101001_0000000001, 283 | 40'b11111_11111_0011111010_1111101001_0000000001, 284 | 40'b11111_11111_0011111010_1111101001_0000000001, 285 | 40'b11111_11111_0011111010_1111101001_0000000001, 286 | 40'b11111_11111_0011111010_1111101001_0000000001, 287 | 40'b11111_11111_0011111010_1111101001_0000000001, 288 | 40'b11111_11111_0011111010_1111101001_0000000001, 289 | 40'b11111_11111_0011111010_1111101001_0000000001, 290 | 40'b11111_11111_0011111010_1111101001_0000000001, 291 | 40'b11111_11111_0011111010_1111101001_0000000001, 292 | 40'b11111_11111_0011111010_1111101001_0000000001, 293 | 40'b11111_11111_0011111010_1111101001_0000000001, 294 | 40'b11111_11111_0011111010_1111101001_0000000001, 295 | 40'b11111_11111_0011111010_1111101001_0000000001, 296 | 40'b11111_11111_0011111010_1111101001_0000000001, 297 | 40'b11111_11111_0011111010_1111101001_0000000001, 298 | 40'b11111_11111_0011111010_1111101001_0000000001, 299 | 40'b11111_11111_0011111010_1111101001_0000000001, 300 | 40'b11111_11111_0011111010_1111101001_0000000001, 301 | 40'b11111_11111_0011111010_1111101001_0000000001, 302 | 40'b11111_11111_0011111010_1111101001_0000000001, 303 | 40'b11111_11111_0011111010_1111101001_0000000001, 304 | 40'b11111_11111_0011111010_1111101001_0000000001 305 | }; 306 | 307 | // Set lookup_entry with the explicit bits from lookup with a part select 308 | mmcm_pll_lock_lookup = lookup[ ((64-divide)*40) +: 40]; 309 | `ifdef DEBUG 310 | $display("lock_lookup: %b", mmcm_pll_lock_lookup); 311 | `endif 312 | end 313 | endfunction 314 | 315 | // This function takes the divide value and the bandwidth setting of the PLL 316 | // and outputs the digital filter settings necessary. 317 | function [9:0] mmcm_pll_filter_lookup 318 | ( 319 | input [6:0] divide, // Max divide is 64 320 | input [8*9:0] BANDWIDTH 321 | ); 322 | 323 | reg [639:0] lookup_low; 324 | reg [639:0] lookup_high; 325 | 326 | reg [9:0] lookup_entry; 327 | 328 | begin 329 | lookup_low = { 330 | // CP_RES_LFHF 331 | 10'b0010_1111_00, 332 | 10'b0010_1111_00, 333 | 10'b0010_0111_00, 334 | 10'b0010_1101_00, 335 | 10'b0010_0101_00, 336 | 10'b0010_0101_00, 337 | 10'b0010_1001_00, 338 | 10'b0010_1110_00, 339 | 10'b0010_1110_00, 340 | 10'b0010_0001_00, 341 | 10'b0010_0001_00, 342 | 10'b0010_0110_00, 343 | 10'b0010_0110_00, 344 | 10'b0010_0110_00, 345 | 10'b0010_0110_00, 346 | 10'b0010_1010_00, 347 | 10'b0010_1010_00, 348 | 10'b0010_1010_00, 349 | 10'b0010_1010_00, 350 | 10'b0010_1100_00, 351 | 10'b0010_1100_00, 352 | 10'b0010_1100_00, 353 | 10'b0010_1100_00, 354 | 10'b0010_1100_00, 355 | 10'b0010_1100_00, 356 | 10'b0010_1100_00, 357 | 10'b0010_1100_00, 358 | 10'b0010_1100_00, 359 | 10'b0010_1100_00, 360 | 10'b0010_1100_00, 361 | 10'b0010_0010_00, 362 | 10'b0010_0010_00, 363 | 10'b0010_0010_00, 364 | 10'b0010_0010_00, 365 | 10'b0010_0010_00, 366 | 10'b0010_0010_00, 367 | 10'b0010_0010_00, 368 | 10'b0010_0010_00, 369 | 10'b0010_0010_00, 370 | 10'b0010_0010_00, 371 | 10'b0011_1100_00, 372 | 10'b0011_1100_00, 373 | 10'b0011_1100_00, 374 | 10'b0011_1100_00, 375 | 10'b0011_1100_00, 376 | 10'b0011_1100_00, 377 | 10'b0011_1100_00, 378 | 10'b0010_0100_00, 379 | 10'b0010_0100_00, 380 | 10'b0010_0100_00, 381 | 10'b0010_0100_00, 382 | 10'b0010_0100_00, 383 | 10'b0010_0100_00, 384 | 10'b0010_0100_00, 385 | 10'b0010_0100_00, 386 | 10'b0010_0100_00, 387 | 10'b0010_0100_00, 388 | 10'b0010_0100_00, 389 | 10'b0010_0100_00, 390 | 10'b0010_0100_00, 391 | 10'b0010_0100_00, 392 | 10'b0010_0100_00, 393 | 10'b0010_0100_00, 394 | 10'b0010_0100_00 395 | }; 396 | 397 | lookup_high = { 398 | // CP_RES_LFHF 399 | 10'b0011_0111_00, 400 | 10'b0011_0111_00, 401 | 10'b0101_1111_00, 402 | 10'b0111_1111_00, 403 | 10'b0111_1011_00, 404 | 10'b1101_0111_00, 405 | 10'b1110_1011_00, 406 | 10'b1110_1101_00, 407 | 10'b1111_1101_00, 408 | 10'b1111_0111_00, 409 | 10'b1111_1011_00, 410 | 10'b1111_1101_00, 411 | 10'b1111_0011_00, 412 | 10'b1110_0101_00, 413 | 10'b1111_0101_00, 414 | 10'b1111_0101_00, 415 | 10'b1111_0101_00, 416 | 10'b1111_0101_00, 417 | 10'b0111_0110_00, 418 | 10'b0111_0110_00, 419 | 10'b0111_0110_00, 420 | 10'b0111_0110_00, 421 | 10'b0101_1100_00, 422 | 10'b0101_1100_00, 423 | 10'b0101_1100_00, 424 | 10'b1100_0001_00, 425 | 10'b1100_0001_00, 426 | 10'b1100_0001_00, 427 | 10'b1100_0001_00, 428 | 10'b1100_0001_00, 429 | 10'b1100_0001_00, 430 | 10'b1100_0001_00, 431 | 10'b1100_0001_00, 432 | 10'b0100_0010_00, 433 | 10'b0100_0010_00, 434 | 10'b0100_0010_00, 435 | 10'b0010_1000_00, 436 | 10'b0010_1000_00, 437 | 10'b0010_1000_00, 438 | 10'b0011_0100_00, 439 | 10'b0010_1000_00, 440 | 10'b0010_1000_00, 441 | 10'b0010_1000_00, 442 | 10'b0010_1000_00, 443 | 10'b0010_1000_00, 444 | 10'b0010_1000_00, 445 | 10'b0010_1000_00, 446 | 10'b0010_1000_00, 447 | 10'b0010_1000_00, 448 | 10'b0010_1000_00, 449 | 10'b0010_1000_00, 450 | 10'b0010_1000_00, 451 | 10'b0010_1000_00, 452 | 10'b0100_1100_00, 453 | 10'b0100_1100_00, 454 | 10'b0100_1100_00, 455 | 10'b0100_1100_00, 456 | 10'b0100_1100_00, 457 | 10'b0100_1100_00, 458 | 10'b0100_1100_00, 459 | 10'b0010_0100_00, 460 | 10'b0010_0100_00, 461 | 10'b0010_0100_00, 462 | 10'b0010_0100_00 463 | }; 464 | 465 | // Set lookup_entry with the explicit bits from lookup with a part select 466 | if(BANDWIDTH == "LOW") begin 467 | // Low Bandwidth 468 | mmcm_pll_filter_lookup = lookup_low[ ((64-divide)*10) +: 10]; 469 | end else begin 470 | // High or optimized bandwidth 471 | mmcm_pll_filter_lookup = lookup_high[ ((64-divide)*10) +: 10]; 472 | end 473 | 474 | `ifdef DEBUG 475 | $display("filter_lookup: %b", mmcm_pll_filter_lookup); 476 | `endif 477 | end 478 | endfunction 479 | 480 | // This function takes in the divide, phase, and duty cycle 481 | // setting to calculate the upper and lower counter registers. 482 | function [37:0] mmcm_pll_count_calc 483 | ( 484 | input [7:0] divide, // Max divide is 128 485 | input signed [31:0] phase, 486 | input [31:0] duty_cycle // Multiplied by 100,000 487 | ); 488 | 489 | reg [13:0] div_calc; 490 | reg [16:0] phase_calc; 491 | 492 | begin 493 | `ifdef DEBUG 494 | $display("mmcm_pll_count_calc- divide:%h, phase:%d, duty_cycle:%d", 495 | divide, phase, duty_cycle); 496 | `endif 497 | 498 | // w_edge[13], no_count[12], high_time[11:6], low_time[5:0] 499 | div_calc = mmcm_pll_divider(divide, duty_cycle); 500 | // mx[10:9], pm[8:6], dt[5:0] 501 | phase_calc = mmcm_pll_phase(divide, phase); 502 | 503 | // Return value is the upper and lower address of counter 504 | // Upper address is: 505 | // RESERVED [31:26] 506 | // MX [25:24] 507 | // EDGE [23] 508 | // NOCOUNT [22] 509 | // DELAY_TIME [21:16] 510 | // Lower Address is: 511 | // PHASE_MUX [15:13] 512 | // RESERVED [12] 513 | // HIGH_TIME [11:6] 514 | // LOW_TIME [5:0] 515 | 516 | `ifdef DEBUG 517 | $display("div:%d dc:%d phase:%d ht:%d lt:%d ed:%d nc:%d mx:%d dt:%d pm:%d", 518 | divide, duty_cycle, phase, div_calc[11:6], div_calc[5:0], 519 | div_calc[13], div_calc[12], 520 | phase_calc[16:15], phase_calc[5:0], phase_calc[14:12]); 521 | `endif 522 | 523 | mmcm_pll_count_calc = 524 | { 525 | // Upper Address 526 | 6'h00, phase_calc[10:9], div_calc[13:12], phase_calc[5:0], 527 | // Lower Address 528 | phase_calc[8:6], 1'b0, div_calc[11:0] 529 | }; 530 | end 531 | endfunction 532 | -------------------------------------------------------------------------------- /FPGA/fft.srcs/sources_1/ip/clk_wiz_0/mmcm_pll_drp_func_us_mmcm.vh: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Company: Xilinx 4 | // Engineer: Jim Tatsukawa 5 | // Date: 7/30/2014 6 | // Design Name: MMCME2 DRP 7 | // Module Name: mmcme2_drp_func.h 8 | // Version: 1.04 9 | // Target Devices: UltraScale Architecture || MMCM 10 | // Tool versions: 2014.3 11 | // Description: This header provides the functions necessary to 12 | // calculate the DRP register values for the V6 MMCM. 13 | // 14 | // Revision Notes: 3/22 - Updating lookup_low/lookup_high (CR) 15 | // 4/13 - Fractional divide function in mmcm_frac_count_calc function. CRS610807 16 | // 17 | // Disclaimer: XILINX IS PROVIDING THIS DESIGN, CODE, OR 18 | // INFORMATION "AS IS" SOLELY FOR USE IN DEVELOPING 19 | // PROGRAMS AND SOLUTIONS FOR XILINX DEVICES. BY 20 | // PROVIDING THIS DESIGN, CODE, OR INFORMATION AS 21 | // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, 22 | // APPLICATION OR STANDARD, XILINX IS MAKING NO 23 | // REPRESENTATION THAT THIS IMPLEMENTATION IS FREE 24 | // FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE 25 | // RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY 26 | // REQUIRE FOR YOUR IMPLEMENTATION. XILINX 27 | // EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH 28 | // RESPECT TO THE ADEQUACY OF THE IMPLEMENTATION, 29 | // INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR 30 | // REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE 31 | // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES 32 | // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 33 | // PURPOSE. 34 | // 35 | // (c) Copyright 2009-2010 Xilinx, Inc. 36 | // All rights reserved. 37 | // 38 | /////////////////////////////////////////////////////////////////////////////// 39 | 40 | // These are user functions that should not be modified. Changes to the defines 41 | // or code within the functions may alter the accuracy of the calculations. 42 | 43 | // Define debug to provide extra messages durring elaboration 44 | //`define DEBUG 1 45 | 46 | // FRAC_PRECISION describes the width of the fractional portion of the fixed 47 | // point numbers. These should not be modified, they are for development 48 | // only 49 | `define FRAC_PRECISION 10 50 | // FIXED_WIDTH describes the total size for fixed point calculations(int+frac). 51 | // Warning: L.50 and below will not calculate properly with FIXED_WIDTHs 52 | // greater than 32 53 | `define FIXED_WIDTH 32 54 | 55 | // This function takes a fixed point number and rounds it to the nearest 56 | // fractional precision bit. 57 | function [`FIXED_WIDTH:1] round_frac 58 | ( 59 | // Input is (FIXED_WIDTH-FRAC_PRECISION).FRAC_PRECISION fixed point number 60 | input [`FIXED_WIDTH:1] decimal, 61 | 62 | // This describes the precision of the fraction, for example a value 63 | // of 1 would modify the fractional so that instead of being a .16 64 | // fractional, it would be a .1 (rounded to the nearest 0.5 in turn) 65 | input [`FIXED_WIDTH:1] precision 66 | ); 67 | 68 | begin 69 | 70 | `ifdef DEBUG 71 | $display("round_frac - decimal: %h, precision: %h", decimal, precision); 72 | `endif 73 | // If the fractional precision bit is high then round up 74 | if( decimal[(`FRAC_PRECISION-precision)] == 1'b1) begin 75 | round_frac = decimal + (1'b1 << (`FRAC_PRECISION-precision)); 76 | end else begin 77 | round_frac = decimal; 78 | end 79 | `ifdef DEBUG 80 | $display("round_frac: %h", round_frac); 81 | `endif 82 | end 83 | endfunction 84 | 85 | // This function calculates high_time, low_time, w_edge, and no_count 86 | // of a non-fractional counter based on the divide and duty cycle 87 | // 88 | // NOTE: high_time and low_time are returned as integers between 0 and 63 89 | // inclusive. 64 should equal 6'b000000 (in other words it is okay to 90 | // ignore the overflow) 91 | function [13:0] mmcm_pll_divider 92 | ( 93 | input [7:0] divide, // Max divide is 128 94 | input [31:0] duty_cycle // Duty cycle is multiplied by 100,000 95 | ); 96 | 97 | reg [`FIXED_WIDTH:1] duty_cycle_fix; 98 | 99 | // High/Low time is initially calculated with a wider integer to prevent a 100 | // calculation error when it overflows to 64. 101 | reg [6:0] high_time; 102 | reg [6:0] low_time; 103 | reg w_edge; 104 | reg no_count; 105 | 106 | reg [`FIXED_WIDTH:1] temp; 107 | 108 | begin 109 | // Duty Cycle must be between 0 and 1,000 110 | if(duty_cycle <=0 || duty_cycle >= 100000) begin 111 | `ifndef SYNTHESIS 112 | $display("ERROR: duty_cycle: %d is invalid", duty_cycle); 113 | `endif 114 | $finish; 115 | end 116 | 117 | // Convert to FIXED_WIDTH-FRAC_PRECISION.FRAC_PRECISION fixed point 118 | duty_cycle_fix = (duty_cycle << `FRAC_PRECISION) / 100_000; 119 | 120 | `ifdef DEBUG 121 | $display("duty_cycle_fix: %h", duty_cycle_fix); 122 | `endif 123 | 124 | // If the divide is 1 nothing needs to be set except the no_count bit. 125 | // Other values are dummies 126 | if(divide == 7'h01) begin 127 | high_time = 7'h01; 128 | w_edge = 1'b0; 129 | low_time = 7'h01; 130 | no_count = 1'b1; 131 | end else begin 132 | temp = round_frac(duty_cycle_fix*divide, 1); 133 | 134 | // comes from above round_frac 135 | high_time = temp[`FRAC_PRECISION+7:`FRAC_PRECISION+1]; 136 | // If the duty cycle * divide rounded is .5 or greater then this bit 137 | // is set. 138 | w_edge = temp[`FRAC_PRECISION]; // comes from round_frac 139 | 140 | // If the high time comes out to 0, it needs to be set to at least 1 141 | // and w_edge set to 0 142 | if(high_time == 7'h00) begin 143 | high_time = 7'h01; 144 | w_edge = 1'b0; 145 | end 146 | 147 | if(high_time == divide) begin 148 | high_time = divide - 1; 149 | w_edge = 1'b1; 150 | end 151 | 152 | // Calculate low_time based on the divide setting and set no_count to 153 | // 0 as it is only used when divide is 1. 154 | low_time = divide - high_time; 155 | no_count = 1'b0; 156 | end 157 | 158 | // Set the return value. 159 | mmcm_pll_divider = {w_edge,no_count,high_time[5:0],low_time[5:0]}; 160 | end 161 | endfunction 162 | 163 | // This function calculates mx, delay_time, and phase_mux 164 | // of a non-fractional counter based on the divide and phase 165 | // 166 | // NOTE: The only valid value for the MX bits is 2'b00 to ensure the coarse mux 167 | // is used. 168 | function [10:0] mmcm_pll_phase 169 | ( 170 | // divide must be an integer (use fractional if not) 171 | // assumed that divide already checked to be valid 172 | input [7:0] divide, // Max divide is 128 173 | 174 | // Phase is given in degrees (-360,000 to 360,000) 175 | input signed [31:0] phase 176 | ); 177 | 178 | reg [`FIXED_WIDTH:1] phase_in_cycles; 179 | reg [`FIXED_WIDTH:1] phase_fixed; 180 | reg [1:0] mx; 181 | reg [5:0] delay_time; 182 | reg [2:0] phase_mux; 183 | 184 | reg [`FIXED_WIDTH:1] temp; 185 | 186 | begin 187 | `ifdef DEBUG 188 | $display("mmcm_pll_phase-divide:%d,phase:%d", 189 | divide, phase); 190 | `endif 191 | 192 | if ((phase < -360000) || (phase > 360000)) begin 193 | `ifndef SYNTHESIS 194 | $display("ERROR: phase of $phase is not between -360000 and 360000"); 195 | `endif 196 | $finish; 197 | end 198 | 199 | // If phase is less than 0, convert it to a positive phase shift 200 | // Convert to (FIXED_WIDTH-FRAC_PRECISION).FRAC_PRECISION fixed point 201 | if(phase < 0) begin 202 | phase_fixed = ( (phase + 360000) << `FRAC_PRECISION ) / 1000; 203 | end else begin 204 | phase_fixed = ( phase << `FRAC_PRECISION ) / 1000; 205 | end 206 | 207 | // Put phase in terms of decimal number of vco clock cycles 208 | phase_in_cycles = ( phase_fixed * divide ) / 360; 209 | 210 | `ifdef DEBUG 211 | $display("phase_in_cycles: %h", phase_in_cycles); 212 | `endif 213 | 214 | 215 | temp = round_frac(phase_in_cycles, 3); 216 | 217 | // set mx to 2'b00 that the phase mux from the VCO is enabled 218 | mx = 2'b00; 219 | phase_mux = temp[`FRAC_PRECISION:`FRAC_PRECISION-2]; 220 | delay_time = temp[`FRAC_PRECISION+6:`FRAC_PRECISION+1]; 221 | 222 | `ifdef DEBUG 223 | $display("temp: %h", temp); 224 | `endif 225 | 226 | // Setup the return value 227 | mmcm_pll_phase={mx, phase_mux, delay_time}; 228 | end 229 | endfunction 230 | 231 | // This function takes the divide value and outputs the necessary lock values 232 | function [39:0] mmcm_pll_lock_lookup 233 | ( 234 | input [6:0] divide // Max divide is 64 235 | ); 236 | 237 | reg [2559:0] lookup; 238 | 239 | begin 240 | lookup = { 241 | // This table is composed of: 242 | // LockRefDly_LockFBDly_LockCnt_LockSatHigh_UnlockCnt 243 | 40'b00110_00110_1111101000_1111101001_0000000001, 244 | 40'b00110_00110_1111101000_1111101001_0000000001, 245 | 40'b01000_01000_1111101000_1111101001_0000000001, 246 | 40'b01011_01011_1111101000_1111101001_0000000001, 247 | 40'b01110_01110_1111101000_1111101001_0000000001, 248 | 40'b10001_10001_1111101000_1111101001_0000000001, 249 | 40'b10011_10011_1111101000_1111101001_0000000001, 250 | 40'b10110_10110_1111101000_1111101001_0000000001, 251 | 40'b11001_11001_1111101000_1111101001_0000000001, 252 | 40'b11100_11100_1111101000_1111101001_0000000001, 253 | 40'b11111_11111_1110000100_1111101001_0000000001, 254 | 40'b11111_11111_1100111001_1111101001_0000000001, 255 | 40'b11111_11111_1011101110_1111101001_0000000001, 256 | 40'b11111_11111_1010111100_1111101001_0000000001, 257 | 40'b11111_11111_1010001010_1111101001_0000000001, 258 | 40'b11111_11111_1001110001_1111101001_0000000001, 259 | 40'b11111_11111_1000111111_1111101001_0000000001, 260 | 40'b11111_11111_1000100110_1111101001_0000000001, 261 | 40'b11111_11111_1000001101_1111101001_0000000001, 262 | 40'b11111_11111_0111110100_1111101001_0000000001, 263 | 40'b11111_11111_0111011011_1111101001_0000000001, 264 | 40'b11111_11111_0111000010_1111101001_0000000001, 265 | 40'b11111_11111_0110101001_1111101001_0000000001, 266 | 40'b11111_11111_0110010000_1111101001_0000000001, 267 | 40'b11111_11111_0110010000_1111101001_0000000001, 268 | 40'b11111_11111_0101110111_1111101001_0000000001, 269 | 40'b11111_11111_0101011110_1111101001_0000000001, 270 | 40'b11111_11111_0101011110_1111101001_0000000001, 271 | 40'b11111_11111_0101000101_1111101001_0000000001, 272 | 40'b11111_11111_0101000101_1111101001_0000000001, 273 | 40'b11111_11111_0100101100_1111101001_0000000001, 274 | 40'b11111_11111_0100101100_1111101001_0000000001, 275 | 40'b11111_11111_0100101100_1111101001_0000000001, 276 | 40'b11111_11111_0100010011_1111101001_0000000001, 277 | 40'b11111_11111_0100010011_1111101001_0000000001, 278 | 40'b11111_11111_0100010011_1111101001_0000000001, 279 | 40'b11111_11111_0011111010_1111101001_0000000001, 280 | 40'b11111_11111_0011111010_1111101001_0000000001, 281 | 40'b11111_11111_0011111010_1111101001_0000000001, 282 | 40'b11111_11111_0011111010_1111101001_0000000001, 283 | 40'b11111_11111_0011111010_1111101001_0000000001, 284 | 40'b11111_11111_0011111010_1111101001_0000000001, 285 | 40'b11111_11111_0011111010_1111101001_0000000001, 286 | 40'b11111_11111_0011111010_1111101001_0000000001, 287 | 40'b11111_11111_0011111010_1111101001_0000000001, 288 | 40'b11111_11111_0011111010_1111101001_0000000001, 289 | 40'b11111_11111_0011111010_1111101001_0000000001, 290 | 40'b11111_11111_0011111010_1111101001_0000000001, 291 | 40'b11111_11111_0011111010_1111101001_0000000001, 292 | 40'b11111_11111_0011111010_1111101001_0000000001, 293 | 40'b11111_11111_0011111010_1111101001_0000000001, 294 | 40'b11111_11111_0011111010_1111101001_0000000001, 295 | 40'b11111_11111_0011111010_1111101001_0000000001, 296 | 40'b11111_11111_0011111010_1111101001_0000000001, 297 | 40'b11111_11111_0011111010_1111101001_0000000001, 298 | 40'b11111_11111_0011111010_1111101001_0000000001, 299 | 40'b11111_11111_0011111010_1111101001_0000000001, 300 | 40'b11111_11111_0011111010_1111101001_0000000001, 301 | 40'b11111_11111_0011111010_1111101001_0000000001, 302 | 40'b11111_11111_0011111010_1111101001_0000000001, 303 | 40'b11111_11111_0011111010_1111101001_0000000001, 304 | 40'b11111_11111_0011111010_1111101001_0000000001, 305 | 40'b11111_11111_0011111010_1111101001_0000000001, 306 | 40'b11111_11111_0011111010_1111101001_0000000001 307 | }; 308 | 309 | // Set lookup_entry with the explicit bits from lookup with a part select 310 | mmcm_pll_lock_lookup = lookup[ ((64-divide)*40) +: 40]; 311 | `ifdef DEBUG 312 | $display("lock_lookup: %b", mmcm_pll_lock_lookup); 313 | `endif 314 | end 315 | endfunction 316 | 317 | // This function takes the divide value and the bandwidth setting of the MMCM 318 | // and outputs the digital filter settings necessary. 319 | function [9:0] mmcm_pll_filter_lookup 320 | ( 321 | input [6:0] divide, // Max divide is 64 322 | input [8*9:0] BANDWIDTH 323 | ); 324 | 325 | reg [639:0] lookup_low; 326 | reg [639:0] lookup_high; 327 | 328 | reg [9:0] lookup_entry; 329 | 330 | begin 331 | lookup_low = { 332 | // CP_RES_LFHF 333 | 10'b0010_1111_11, 334 | 10'b0010_1111_11, 335 | 10'b0010_1111_11, 336 | 10'b0010_1111_11, 337 | 10'b0010_1111_11, 338 | 10'b0010_1111_11, 339 | 10'b0010_0111_11, 340 | 10'b0010_0111_11, 341 | 10'b0010_0111_11, 342 | 10'b0010_1101_11, 343 | 10'b0010_1101_11, 344 | 10'b0010_1101_11, 345 | 10'b0010_0011_11, 346 | 10'b0010_0101_11, 347 | 10'b0010_0101_11, 348 | 10'b0010_0101_11, 349 | 10'b0010_1001_11, 350 | 10'b0010_1001_11, 351 | 10'b0010_1110_11, 352 | 10'b0010_1110_11, 353 | 10'b0010_1110_11, 354 | 10'b0010_1110_11, 355 | 10'b0010_1110_11, 356 | 10'b0010_1110_11, 357 | 10'b0010_0001_11, 358 | 10'b0010_0001_11, 359 | 10'b0010_0001_11, 360 | 10'b0010_0001_11, 361 | 10'b0010_0001_11, 362 | 10'b0010_0110_11, 363 | 10'b0010_0110_11, 364 | 10'b0010_0110_11, 365 | 10'b0010_0110_11, 366 | 10'b0010_0110_11, 367 | 10'b0010_0110_11, 368 | 10'b0010_0110_11, 369 | 10'b0010_0110_11, 370 | 10'b0010_0110_11, 371 | 10'b0010_0110_11, 372 | 10'b0010_1010_11, 373 | 10'b0010_1010_11, 374 | 10'b0010_1010_11, 375 | 10'b0010_1010_11, 376 | 10'b0010_1010_11, 377 | 10'b0010_1010_11, 378 | 10'b0010_1010_11, 379 | 10'b0010_1010_11, 380 | 10'b0010_1100_11, 381 | 10'b0010_1100_11, 382 | 10'b0010_1100_11, 383 | 10'b0010_1100_11, 384 | 10'b0010_1100_11, 385 | 10'b0010_1100_11, 386 | 10'b0010_1100_11, 387 | 10'b0010_1100_11, 388 | 10'b0010_1100_11, 389 | 10'b0010_1100_11, 390 | 10'b0010_1100_11, 391 | 10'b0010_1100_11, 392 | 10'b0010_1100_11, 393 | 10'b0010_1100_11, 394 | 10'b0010_1100_11, 395 | 10'b0010_1100_11, 396 | 10'b0010_1100_11 397 | }; 398 | 399 | lookup_high = { 400 | // CP_RES_LFHF 401 | 10'b0010_1111_11, 402 | 10'b0010_1111_11, 403 | 10'b0010_1011_11, 404 | 10'b0011_1111_11, 405 | 10'b0100_1111_11, 406 | 10'b0100_1111_11, 407 | 10'b0101_1111_11, 408 | 10'b0110_1111_11, 409 | 10'b0111_1111_11, 410 | 10'b0111_1111_11, 411 | 10'b1100_1111_11, 412 | 10'b1101_1111_11, 413 | 10'b1110_1111_11, 414 | 10'b1111_1111_11, 415 | 10'b1111_1111_11, 416 | 10'b1110_0111_11, 417 | 10'b1110_1011_11, 418 | 10'b1111_0111_11, 419 | 10'b1111_1011_11, 420 | 10'b1111_1011_11, 421 | 10'b1110_1101_11, 422 | 10'b1111_1101_11, 423 | 10'b1111_1101_11, 424 | 10'b1111_0011_11, 425 | 10'b1111_0011_11, 426 | 10'b1111_0011_11, 427 | 10'b1110_0101_11, 428 | 10'b1110_0101_11, 429 | 10'b1110_0101_11, 430 | 10'b1111_0101_11, 431 | 10'b1111_0101_11, 432 | 10'b1111_0101_11, 433 | 10'b1111_1001_11, 434 | 10'b1111_1001_11, 435 | 10'b1111_1001_11, 436 | 10'b1111_1001_11, 437 | 10'b1111_1001_11, 438 | 10'b1110_1110_11, 439 | 10'b1110_1110_11, 440 | 10'b1110_1110_11, 441 | 10'b1110_1110_11, 442 | 10'b1111_1110_11, 443 | 10'b1111_1110_11, 444 | 10'b1111_1110_11, 445 | 10'b1111_1110_11, 446 | 10'b1111_1110_11, 447 | 10'b1111_1110_11, 448 | 10'b1111_1110_11, 449 | 10'b1110_0001_11, 450 | 10'b1110_0001_11, 451 | 10'b1110_0001_11, 452 | 10'b1110_0001_11, 453 | 10'b1110_0001_11, 454 | 10'b1100_0110_11, 455 | 10'b1100_0110_11, 456 | 10'b1100_0110_11, 457 | 10'b1100_0110_11, 458 | 10'b1100_0110_11, 459 | 10'b1100_0110_11, 460 | 10'b1100_0110_11, 461 | 10'b1100_1010_11, 462 | 10'b1100_1010_11, 463 | 10'b1100_1010_11, 464 | 10'b1100_1010_11 465 | }; 466 | 467 | // Set lookup_entry with the explicit bits from lookup with a part select 468 | if(BANDWIDTH == "LOW") begin 469 | // Low Bandwidth 470 | mmcm_pll_filter_lookup = lookup_low[ ((64-divide)*10) +: 10]; 471 | end else begin 472 | // High or optimized bandwidth 473 | mmcm_pll_filter_lookup = lookup_high[ ((64-divide)*10) +: 10]; 474 | end 475 | 476 | `ifdef DEBUG 477 | $display("filter_lookup: %b", mmcm_pll_filter_lookup); 478 | `endif 479 | end 480 | endfunction 481 | 482 | // This function takes in the divide, phase, and duty cycle 483 | // setting to calculate the upper and lower counter registers. 484 | function [37:0] mmcm_pll_count_calc 485 | ( 486 | input [7:0] divide, // Max divide is 128 487 | input signed [31:0] phase, 488 | input [31:0] duty_cycle // Multiplied by 100,000 489 | ); 490 | 491 | reg [13:0] div_calc; 492 | reg [16:0] phase_calc; 493 | 494 | begin 495 | `ifdef DEBUG 496 | $display("mmcm_pll_count_calc- divide:%h, phase:%d, duty_cycle:%d", 497 | divide, phase, duty_cycle); 498 | `endif 499 | 500 | // w_edge[13], no_count[12], high_time[11:6], low_time[5:0] 501 | div_calc = mmcm_pll_divider(divide, duty_cycle); 502 | // mx[10:9], pm[8:6], dt[5:0] 503 | phase_calc = mmcm_pll_phase(divide, phase); 504 | 505 | // Return value is the upper and lower address of counter 506 | // Upper address is: 507 | // RESERVED [31:26] 508 | // MX [25:24] 509 | // EDGE [23] 510 | // NOCOUNT [22] 511 | // DELAY_TIME [21:16] 512 | // Lower Address is: 513 | // PHASE_MUX [15:13] 514 | // RESERVED [12] 515 | // HIGH_TIME [11:6] 516 | // LOW_TIME [5:0] 517 | 518 | `ifdef DEBUG 519 | $display("div:%d dc:%d phase:%d ht:%d lt:%d ed:%d nc:%d mx:%d dt:%d pm:%d", 520 | divide, duty_cycle, phase, div_calc[11:6], div_calc[5:0], 521 | div_calc[13], div_calc[12], 522 | phase_calc[16:15], phase_calc[5:0], phase_calc[14:12]); 523 | `endif 524 | 525 | mmcm_pll_count_calc = 526 | { 527 | // Upper Address 528 | 6'h00, phase_calc[10:9], div_calc[13:12], phase_calc[5:0], 529 | // Lower Address 530 | phase_calc[8:6], 1'b0, div_calc[11:0] 531 | }; 532 | end 533 | endfunction 534 | 535 | 536 | // This function takes in the divide, phase, and duty cycle 537 | // setting to calculate the upper and lower counter registers. 538 | // for fractional multiply/divide functions. 539 | // 540 | // 541 | function [37:0] mmcm_frac_count_calc 542 | ( 543 | input [7:0] divide, // Max divide is 128 544 | input signed [31:0] phase, 545 | input [31:0] duty_cycle, // Multiplied by 1,000 546 | input [9:0] frac // Multiplied by 1000 547 | ); 548 | 549 | //Required for fractional divide calculations 550 | reg [7:0] lt_frac; 551 | reg [7:0] ht_frac; 552 | 553 | reg /*[7:0]*/ wf_fall_frac; 554 | reg /*[7:0]*/ wf_rise_frac; 555 | 556 | reg [31:0] a; 557 | reg [7:0] pm_rise_frac_filtered ; 558 | reg [7:0] pm_fall_frac_filtered ; 559 | reg [7:0] clkout0_divide_int; 560 | reg [2:0] clkout0_divide_frac; 561 | reg [7:0] even_part_high; 562 | reg [7:0] even_part_low; 563 | 564 | reg [7:0] odd; 565 | reg [7:0] odd_and_frac; 566 | 567 | reg [7:0] pm_fall; 568 | reg [7:0] pm_rise; 569 | reg [7:0] dt; 570 | reg [7:0] dt_int; 571 | reg [63:0] dt_calc; 572 | 573 | reg [7:0] pm_rise_frac; 574 | reg [7:0] pm_fall_frac; 575 | 576 | reg [31:0] a_per_in_octets; 577 | reg [31:0] a_phase_in_cycles; 578 | 579 | parameter precision = 0.125; 580 | 581 | reg [31:0] phase_fixed; // changed to 31:0 from 32:1 jt 5/2/11 582 | reg [31: 0] phase_pos; 583 | reg [31: 0] phase_vco; 584 | reg [31:0] temp;// changed to 31:0 from 32:1 jt 5/2/11 585 | reg [13:0] div_calc; 586 | reg [16:0] phase_calc; 587 | 588 | begin 589 | `ifdef DEBUG 590 | $display("mmcm_frac_count_calc- divide:%h, phase:%d, duty_cycle:%d", 591 | divide, phase, duty_cycle); 592 | `endif 593 | 594 | //convert phase to fixed 595 | if ((phase < -360000) || (phase > 360000)) begin 596 | `ifndef SYNTHESIS 597 | $display("ERROR: phase of $phase is not between -360000 and 360000"); 598 | `endif 599 | $finish; 600 | end 601 | 602 | 603 | // Return value is 604 | // Transfer data 605 | // RESERVED [37:36] 606 | // FRAC_TIME [35:33] 607 | // FRAC_WF_FALL [32] 608 | // Upper address is: 609 | // RESERVED [31:26] 610 | // MX [25:24] 611 | // EDGE [23] 612 | // NOCOUNT [22] 613 | // DELAY_TIME [21:16] 614 | // Lower Address is: 615 | // PHASE_MUX [15:13] 616 | // RESERVED [12] 617 | // HIGH_TIME [11:6] 618 | // LOW_TIME [5:0] 619 | 620 | 621 | 622 | clkout0_divide_frac = frac / 125; 623 | clkout0_divide_int = divide; 624 | 625 | even_part_high = clkout0_divide_int >> 1;//$rtoi(clkout0_divide_int / 2); 626 | even_part_low = even_part_high; 627 | 628 | odd = clkout0_divide_int - even_part_high - even_part_low; 629 | odd_and_frac = (8*odd) + clkout0_divide_frac; 630 | 631 | lt_frac = even_part_high - (odd_and_frac <= 9);//IF(odd_and_frac>9,even_part_high, even_part_high - 1) 632 | ht_frac = even_part_low - (odd_and_frac <= 8);//IF(odd_and_frac>8,even_part_low, even_part_low- 1) 633 | 634 | pm_fall = {odd[6:0],2'b00} + {6'h00, clkout0_divide_frac[2:1]}; // using >> instead of clkout0_divide_frac / 2 635 | pm_rise = 0; //0 636 | 637 | wf_fall_frac = ((odd_and_frac >=2) && (odd_and_frac <=9)) || ((clkout0_divide_frac == 1) && (clkout0_divide_int == 2));//CRS610807 638 | wf_rise_frac = (odd_and_frac >=1) && (odd_and_frac <=8);//IF(odd_and_frac>=1,IF(odd_and_frac <= 8,1,0),0) 639 | 640 | 641 | 642 | //Calculate phase in fractional cycles 643 | a_per_in_octets = (8 * divide) + (frac / 125) ; 644 | a_phase_in_cycles = (phase+10) * a_per_in_octets / 360000 ;//Adding 1 due to rounding errors 645 | pm_rise_frac = (a_phase_in_cycles[7:0] ==8'h00)?8'h00:a_phase_in_cycles[7:0] - {a_phase_in_cycles[7:3],3'b000}; 646 | 647 | dt_calc = ((phase+10) * a_per_in_octets / 8 )/360000 ;//TRUNC(phase* divide / 360); //or_simply (a_per_in_octets / 8) 648 | dt = dt_calc[7:0]; 649 | 650 | pm_rise_frac_filtered = (pm_rise_frac >=8) ? (pm_rise_frac ) - 8: pm_rise_frac ; //((phase_fixed * (divide + frac / 1000)) / 360) - {pm_rise_frac[7:3],3'b000};//$rtoi(clkout0_phase * clkout0_divide / 45);//a; 651 | 652 | dt_int = dt + (& pm_rise_frac[7:4]); //IF(pm_rise_overwriting>7,dt+1,dt) 653 | pm_fall_frac = pm_fall + pm_rise_frac; 654 | pm_fall_frac_filtered = pm_fall + pm_rise_frac - {pm_fall_frac[7:3], 3'b000}; 655 | 656 | div_calc = mmcm_pll_divider(divide, duty_cycle); //Use to determine edge[7], no count[6] 657 | phase_calc = mmcm_pll_phase(divide, phase);// returns{mx[1:0], phase_mux[2:0], delay_time[5:0]} 658 | 659 | mmcm_frac_count_calc[37:0] = 660 | { 2'b00, pm_fall_frac_filtered[2:0], wf_fall_frac, 661 | 1'b0, clkout0_divide_frac[2:0], 1'b1, wf_rise_frac, phase_calc[10:9], div_calc[13:12], dt[5:0], 662 | pm_rise_frac_filtered[2], pm_rise_frac_filtered[1], pm_rise_frac_filtered[0], 1'b0, ht_frac[5:0], lt_frac[5:0] 663 | } ; 664 | 665 | `ifdef DEBUG 666 | $display("-%d.%d p%d>> :DADDR_9_15 frac30to28.frac_en.wf_r_frac.dt:%b%d%d_%b:DADDR_7_13 pm_f_frac_filtered_29to27.wf_f_frac_26:%b%d:DADDR_8_14.pm_r_frac_filt_15to13.ht_frac.lt_frac:%b%b%b:", divide, frac, phase, clkout0_divide_frac, 1, wf_rise_frac, dt, pm_fall_frac_filtered, wf_fall_frac, pm_rise_frac_filtered, ht_frac, lt_frac); 667 | `endif 668 | 669 | end 670 | endfunction 671 | 672 | -------------------------------------------------------------------------------- /FPGA/fft.srcs/sources_1/ip/clk_wiz_0/mmcm_pll_drp_func_us_pll.vh: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Company: Xilinx 4 | // Engineer: Jim Tatsukawa 5 | // Date: 6/15/2015 6 | // Design Name: PLLE3 DRP 7 | // Module Name: plle3_drp_func.h 8 | // Version: 1.10 9 | // Target Devices: UltraScale Architecture 10 | // Tool versions: 2015.1 11 | // Description: This header provides the functions necessary to 12 | // calculate the DRP register values for the V6 PLL. 13 | // 14 | // Revision Notes: 8/11 - PLLE3 updated for PLLE3 file 4564419 15 | // Revision Notes: 6/15 - pll_filter_lookup fixed for max M of 19 16 | // PM_Rise bits have been removed for PLLE3 17 | // 18 | // Disclaimer: XILINX IS PROVIDING THIS DESIGN, CODE, OR 19 | // INFORMATION "AS IS" SOLELY FOR USE IN DEVELOPING 20 | // PROGRAMS AND SOLUTIONS FOR XILINX DEVICES. BY 21 | // PROVIDING THIS DESIGN, CODE, OR INFORMATION AS 22 | // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, 23 | // APPLICATION OR STANDARD, XILINX IS MAKING NO 24 | // REPRESENTATION THAT THIS IMPLEMENTATION IS FREE 25 | // FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE 26 | // RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY 27 | // REQUIRE FOR YOUR IMPLEMENTATION. XILINX 28 | // EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH 29 | // RESPECT TO THE ADEQUACY OF THE IMPLEMENTATION, 30 | // INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR 31 | // REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE 32 | // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES 33 | // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 34 | // PURPOSE. 35 | // 36 | // (c) Copyright 2009-2010 Xilinx, Inc. 37 | // All rights reserved. 38 | // 39 | /////////////////////////////////////////////////////////////////////////////// 40 | 41 | // These are user functions that should not be modified. Changes to the defines 42 | // or code within the functions may alter the accuracy of the calculations. 43 | 44 | // Define debug to provide extra messages durring elaboration 45 | //`define DEBUG 1 46 | 47 | // FRAC_PRECISION describes the width of the fractional portion of the fixed 48 | // point numbers. These should not be modified, they are for development 49 | // only 50 | `define FRAC_PRECISION 10 51 | // FIXED_WIDTH describes the total size for fixed point calculations(int+frac). 52 | // Warning: L.50 and below will not calculate properly with FIXED_WIDTHs 53 | // greater than 32 54 | `define FIXED_WIDTH 32 55 | 56 | // This function takes a fixed point number and rounds it to the nearest 57 | // fractional precision bit. 58 | function [`FIXED_WIDTH:1] round_frac 59 | ( 60 | // Input is (FIXED_WIDTH-FRAC_PRECISION).FRAC_PRECISION fixed point number 61 | input [`FIXED_WIDTH:1] decimal, 62 | 63 | // This describes the precision of the fraction, for example a value 64 | // of 1 would modify the fractional so that instead of being a .16 65 | // fractional, it would be a .1 (rounded to the nearest 0.5 in turn) 66 | input [`FIXED_WIDTH:1] precision 67 | ); 68 | 69 | begin 70 | 71 | `ifdef DEBUG 72 | $display("round_frac - decimal: %h, precision: %h", decimal, precision); 73 | `endif 74 | // If the fractional precision bit is high then round up 75 | if( decimal[(`FRAC_PRECISION-precision)] == 1'b1) begin 76 | round_frac = decimal + (1'b1 << (`FRAC_PRECISION-precision)); 77 | end else begin 78 | round_frac = decimal; 79 | end 80 | `ifdef DEBUG 81 | $display("round_frac: %h", round_frac); 82 | `endif 83 | end 84 | endfunction 85 | 86 | // This function calculates high_time, low_time, w_edge, and no_count 87 | // of a non-fractional counter based on the divide and duty cycle 88 | // 89 | // NOTE: high_time and low_time are returned as integers between 0 and 63 90 | // inclusive. 64 should equal 6'b000000 (in other words it is okay to 91 | // ignore the overflow) 92 | function [13:0] mmcm_pll_divider 93 | ( 94 | input [7:0] divide, // Max divide is 128 95 | input [31:0] duty_cycle // Duty cycle is multiplied by 100,000 96 | ); 97 | 98 | reg [`FIXED_WIDTH:1] duty_cycle_fix; 99 | 100 | // High/Low time is initially calculated with a wider integer to prevent a 101 | // calculation error when it overflows to 64. 102 | reg [6:0] high_time; 103 | reg [6:0] low_time; 104 | reg w_edge; 105 | reg no_count; 106 | 107 | reg [`FIXED_WIDTH:1] temp; 108 | 109 | begin 110 | // Duty Cycle must be between 0 and 1,000 111 | if(duty_cycle <=0 || duty_cycle >= 100000) begin 112 | `ifndef SYNTHESIS 113 | $display("ERROR: duty_cycle: %d is invalid", duty_cycle); 114 | `endif 115 | $finish; 116 | end 117 | 118 | // Convert to FIXED_WIDTH-FRAC_PRECISION.FRAC_PRECISION fixed point 119 | duty_cycle_fix = (duty_cycle << `FRAC_PRECISION) / 100_000; 120 | 121 | `ifdef DEBUG 122 | $display("duty_cycle_fix: %h", duty_cycle_fix); 123 | `endif 124 | 125 | // If the divide is 1 nothing needs to be set except the no_count bit. 126 | // Other values are dummies 127 | if(divide == 7'h01) begin 128 | high_time = 7'h01; 129 | w_edge = 1'b0; 130 | low_time = 7'h01; 131 | no_count = 1'b1; 132 | end else begin 133 | temp = round_frac(duty_cycle_fix*divide, 1); 134 | 135 | // comes from above round_frac 136 | high_time = temp[`FRAC_PRECISION+7:`FRAC_PRECISION+1]; 137 | // If the duty cycle * divide rounded is .5 or greater then this bit 138 | // is set. 139 | w_edge = temp[`FRAC_PRECISION]; // comes from round_frac 140 | 141 | // If the high time comes out to 0, it needs to be set to at least 1 142 | // and w_edge set to 0 143 | if(high_time == 7'h00) begin 144 | high_time = 7'h01; 145 | w_edge = 1'b0; 146 | end 147 | 148 | if(high_time == divide) begin 149 | high_time = divide - 1; 150 | w_edge = 1'b1; 151 | end 152 | 153 | // Calculate low_time based on the divide setting and set no_count to 154 | // 0 as it is only used when divide is 1. 155 | low_time = divide - high_time; 156 | no_count = 1'b0; 157 | end 158 | 159 | // Set the return value. 160 | mmcm_pll_divider = {w_edge,no_count,high_time[5:0],low_time[5:0]}; 161 | end 162 | endfunction 163 | 164 | // This function calculates mx, delay_time, and phase_mux 165 | // of a non-fractional counter based on the divide and phase 166 | // 167 | // NOTE: The only valid value for the MX bits is 2'b00 to ensure the coarse mux 168 | // is used. 169 | function [10:0] mmcm_pll_phase 170 | ( 171 | // divide must be an integer (use fractional if not) 172 | // assumed that divide already checked to be valid 173 | input [7:0] divide, // Max divide is 128 174 | 175 | // Phase is given in degrees (-360,000 to 360,000) 176 | input signed [31:0] phase 177 | ); 178 | 179 | reg [`FIXED_WIDTH:1] phase_in_cycles; 180 | reg [`FIXED_WIDTH:1] phase_fixed; 181 | reg [1:0] mx; 182 | reg [5:0] delay_time; 183 | reg [2:0] phase_mux; 184 | 185 | reg [`FIXED_WIDTH:1] temp; 186 | 187 | begin 188 | `ifdef DEBUG 189 | $display("mmcm_pll_phase-divide:%d,phase:%d", 190 | divide, phase); 191 | `endif 192 | 193 | if ((phase < -360000) || (phase > 360000)) begin 194 | `ifndef SYNTHESIS 195 | $display("ERROR: phase of $phase is not between -360000 and 360000"); 196 | `endif 197 | $finish; 198 | end 199 | 200 | // If phase is less than 0, convert it to a positive phase shift 201 | // Convert to (FIXED_WIDTH-FRAC_PRECISION).FRAC_PRECISION fixed point 202 | if(phase < 0) begin 203 | phase_fixed = ( (phase + 360000) << `FRAC_PRECISION ) / 1000; 204 | end else begin 205 | phase_fixed = ( phase << `FRAC_PRECISION ) / 1000; 206 | end 207 | 208 | // Put phase in terms of decimal number of vco clock cycles 209 | phase_in_cycles = ( phase_fixed * divide ) / 360; 210 | 211 | `ifdef DEBUG 212 | $display("phase_in_cycles: %h", phase_in_cycles); 213 | `endif 214 | 215 | 216 | temp = round_frac(phase_in_cycles, 3); 217 | 218 | // set mx to 2'b00 that the phase mux from the VCO is enabled 219 | mx = 2'b00; 220 | phase_mux = temp[`FRAC_PRECISION:`FRAC_PRECISION-2]; 221 | delay_time = temp[`FRAC_PRECISION+6:`FRAC_PRECISION+1]; 222 | 223 | `ifdef DEBUG 224 | $display("temp: %h", temp); 225 | `endif 226 | 227 | // Setup the return value 228 | mmcm_pll_phase={mx, phase_mux, delay_time}; 229 | end 230 | endfunction 231 | 232 | // This function takes the divide value and outputs the necessary lock values 233 | function [39:0] mmcm_pll_lock_lookup 234 | ( 235 | input [6:0] divide // Max divide is 64 236 | ); 237 | 238 | reg [759:0] lookup; 239 | 240 | begin 241 | lookup = { 242 | // This table is composed of: 243 | // LockRefDly_LockFBDly_LockCnt_LockSatHigh_UnlockCnt 244 | 40'b00110_00110_1111101000_1111101001_0000000001, //1 245 | 40'b00110_00110_1111101000_1111101001_0000000001, //2 246 | 40'b01000_01000_1111101000_1111101001_0000000001, //3 247 | 40'b01011_01011_1111101000_1111101001_0000000001, //4 248 | 40'b01110_01110_1111101000_1111101001_0000000001, //5 249 | 40'b10001_10001_1111101000_1111101001_0000000001, //6 250 | 40'b10011_10011_1111101000_1111101001_0000000001, //7 251 | 40'b10110_10110_1111101000_1111101001_0000000001, //8 252 | 40'b11001_11001_1111101000_1111101001_0000000001, //9 253 | 40'b11100_11100_1111101000_1111101001_0000000001, //10 254 | 40'b11111_11111_1110000100_1111101001_0000000001, //11 255 | 40'b11111_11111_1100111001_1111101001_0000000001, //12 256 | 40'b11111_11111_1011101110_1111101001_0000000001, //13 257 | 40'b11111_11111_1010111100_1111101001_0000000001, //14 258 | 40'b11111_11111_1010001010_1111101001_0000000001, //15 259 | 40'b11111_11111_1001110001_1111101001_0000000001, //16 260 | 40'b11111_11111_1000111111_1111101001_0000000001, //17 261 | 40'b11111_11111_1000100110_1111101001_0000000001, //18 262 | 40'b11111_11111_1000001101_1111101001_0000000001 //19 263 | 264 | }; 265 | 266 | // Set lookup_entry with the explicit bits from lookup with a part select 267 | mmcm_pll_lock_lookup = lookup[ ((19-divide)*40) +: 40]; 268 | `ifdef DEBUG 269 | $display("lock_lookup: %b", mmcm_pll_lock_lookup); 270 | `endif 271 | end 272 | endfunction 273 | 274 | // This function takes the divide value and the bandwidth setting of the PLL 275 | // and outputs the digital filter settings necessary. Removing bandwidth setting for PLLE3. 276 | function [9:0] mmcm_pll_filter_lookup 277 | ( 278 | input [6:0] divide // Max divide is 19 279 | ); 280 | 281 | reg [639:0] lookup; 282 | reg [9:0] lookup_entry; 283 | 284 | begin 285 | 286 | lookup = { 287 | // CP_RES_LFHF 288 | 10'b0010_1111_01, //1 289 | 10'b0010_0011_11, //2 290 | 10'b0011_0011_11, //3 291 | 10'b0010_0001_11, //4 292 | 10'b0010_0110_11, //5 293 | 10'b0010_1010_11, //6 294 | 10'b0010_1010_11, //7 295 | 10'b0011_0110_11, //8 296 | 10'b0010_1100_11, //9 297 | 10'b0010_1100_11, //10 298 | 10'b0010_1100_11, //11 299 | 10'b0010_0010_11, //12 300 | 10'b0011_1100_11, //13 301 | 10'b0011_1100_11, //14 302 | 10'b0011_1100_11, //15 303 | 10'b0011_1100_11, //16 304 | 10'b0011_0010_11, //17 305 | 10'b0011_0010_11, //18 306 | 10'b0011_0010_11 //19 307 | }; 308 | 309 | mmcm_pll_filter_lookup = lookup [ ((19-divide)*10) +: 10]; 310 | 311 | `ifdef DEBUG 312 | $display("filter_lookup: %b", mmcm_pll_filter_lookup); 313 | `endif 314 | end 315 | endfunction 316 | 317 | // This function set the CLKOUTPHY divide settings to match 318 | // the desired CLKOUTPHY_MODE setting. To create VCO_X2, then 319 | // the CLKOUTPHY will be set to 2'b00 since the VCO is internally 320 | // doubled and 2'b00 will represent divide by 1. Similarly "VCO" // will need to divide the doubled clock VCO clock frequency by // 2 therefore 2'b01 will match a divide by 2.And VCO_HALF will // need to divide the doubled VCO by 4, therefore 2'b10 321 | function [9:0] mmcm_pll_clkoutphy_calc 322 | ( 323 | input [8*9:0] CLKOUTPHY_MODE 324 | ); 325 | 326 | if(CLKOUTPHY_MODE == "VCO_X2") begin 327 | mmcm_pll_clkoutphy_calc= 2'b00; 328 | end else if(CLKOUTPHY_MODE == "VCO") begin 329 | mmcm_pll_clkoutphy_calc= 2'b01; 330 | end else if(CLKOUTPHY_MODE == "CLKIN") begin 331 | mmcm_pll_clkoutphy_calc= 2'b11; 332 | end else begin // Assume "VCO_HALF" 333 | mmcm_pll_clkoutphy_calc= 2'b10; 334 | end 335 | 336 | endfunction 337 | 338 | 339 | // This function takes in the divide, phase, and duty cycle 340 | // setting to calculate the upper and lower counter registers. 341 | function [37:0] mmcm_pll_count_calc 342 | ( 343 | input [7:0] divide, // Max divide is 128 344 | input signed [31:0] phase, 345 | input [31:0] duty_cycle // Multiplied by 100,000 346 | ); 347 | 348 | reg [13:0] div_calc; 349 | reg [16:0] phase_calc; 350 | 351 | begin 352 | `ifdef DEBUG 353 | $display("mmcm_pll_count_calc- divide:%h, phase:%d, duty_cycle:%d", 354 | divide, phase, duty_cycle); 355 | `endif 356 | 357 | // w_edge[13], no_count[12], high_time[11:6], low_time[5:0] 358 | div_calc = mmcm_pll_divider(divide, duty_cycle); 359 | // mx[10:9], pm[8:6], dt[5:0] 360 | phase_calc = mmcm_pll_phase(divide, phase); 361 | 362 | // Return value is the upper and lower address of counter 363 | // Upper address is: 364 | // RESERVED [31:26] 365 | // MX [25:24] 366 | // EDGE [23] 367 | // NOCOUNT [22] 368 | // DELAY_TIME [21:16] 369 | // Lower Address is: 370 | // PHASE_MUX [15:13] 371 | // RESERVED [12] 372 | // HIGH_TIME [11:6] 373 | // LOW_TIME [5:0] 374 | 375 | `ifdef DEBUG 376 | $display("div:%d dc:%d phase:%d ht:%d lt:%d ed:%d nc:%d mx:%d dt:%d pm:%d", 377 | divide, duty_cycle, phase, div_calc[11:6], div_calc[5:0], 378 | div_calc[13], div_calc[12], 379 | phase_calc[16:15], phase_calc[5:0], 3'b000);//Removed PM_Rise bits 380 | `endif 381 | 382 | mmcm_pll_count_calc = 383 | { 384 | // Upper Address 385 | 6'h00, phase_calc[10:9], div_calc[13:12], phase_calc[5:0], 386 | // Lower Address 387 | phase_calc[8:6], 1'b0, div_calc[11:0] 388 | }; 389 | end 390 | endfunction 391 | 392 | 393 | // This function takes in the divide, phase, and duty cycle 394 | // setting to calculate the upper and lower counter registers. 395 | // for fractional multiply/divide functions. 396 | // 397 | // 398 | function [37:0] mmcm_pll_frac_count_calc 399 | ( 400 | input [7:0] divide, // Max divide is 128 401 | input signed [31:0] phase, 402 | input [31:0] duty_cycle, // Multiplied by 1,000 403 | input [9:0] frac // Multiplied by 1000 404 | ); 405 | 406 | //Required for fractional divide calculations 407 | reg [7:0] lt_frac; 408 | reg [7:0] ht_frac; 409 | 410 | reg /*[7:0]*/ wf_fall_frac; 411 | reg /*[7:0]*/ wf_rise_frac; 412 | 413 | reg [31:0] a; 414 | reg [7:0] pm_rise_frac_filtered ; 415 | reg [7:0] pm_fall_frac_filtered ; 416 | reg [7:0] clkout0_divide_int; 417 | reg [2:0] clkout0_divide_frac; 418 | reg [7:0] even_part_high; 419 | reg [7:0] even_part_low; 420 | 421 | reg [7:0] odd; 422 | reg [7:0] odd_and_frac; 423 | 424 | reg [7:0] pm_fall; 425 | reg [7:0] pm_rise; 426 | reg [7:0] dt; 427 | reg [7:0] dt_int; 428 | reg [63:0] dt_calc; 429 | 430 | reg [7:0] pm_rise_frac; 431 | reg [7:0] pm_fall_frac; 432 | 433 | reg [31:0] a_per_in_octets; 434 | reg [31:0] a_phase_in_cycles; 435 | 436 | parameter precision = 0.125; 437 | 438 | reg [31:0] phase_fixed; // changed to 31:0 from 32:1 jt 5/2/11 439 | reg [31: 0] phase_pos; 440 | reg [31: 0] phase_vco; 441 | reg [31:0] temp;// changed to 31:0 from 32:1 jt 5/2/11 442 | reg [13:0] div_calc; 443 | reg [16:0] phase_calc; 444 | 445 | begin 446 | `ifdef DEBUG 447 | $display("mmcm_pll_frac_count_calc- divide:%h, phase:%d, duty_cycle:%d", 448 | divide, phase, duty_cycle); 449 | `endif 450 | 451 | //convert phase to fixed 452 | if ((phase < -360000) || (phase > 360000)) begin 453 | `ifndef SYNTHESIS 454 | $display("ERROR: phase of $phase is not between -360000 and 360000"); 455 | `endif 456 | $finish; 457 | end 458 | 459 | 460 | // Return value is 461 | // Transfer data 462 | // RESERVED [37:36] 463 | // FRAC_TIME [35:33] 464 | // FRAC_WF_FALL [32] 465 | // Upper address is: 466 | // RESERVED [31:26] 467 | // MX [25:24] 468 | // EDGE [23] 469 | // NOCOUNT [22] 470 | // DELAY_TIME [21:16] 471 | // Lower Address is: 472 | // PHASE_MUX [15:13] 473 | // RESERVED [12] 474 | // HIGH_TIME [11:6] 475 | // LOW_TIME [5:0] 476 | 477 | 478 | 479 | clkout0_divide_frac = frac / 125; 480 | clkout0_divide_int = divide; 481 | 482 | even_part_high = clkout0_divide_int >> 1;//$rtoi(clkout0_divide_int / 2); 483 | even_part_low = even_part_high; 484 | 485 | odd = clkout0_divide_int - even_part_high - even_part_low; 486 | odd_and_frac = (8*odd) + clkout0_divide_frac; 487 | 488 | lt_frac = even_part_high - (odd_and_frac <= 9);//IF(odd_and_frac>9,even_part_high, even_part_high - 1) 489 | ht_frac = even_part_low - (odd_and_frac <= 8);//IF(odd_and_frac>8,even_part_low, even_part_low- 1) 490 | 491 | pm_fall = {odd[6:0],2'b00} + {6'h00, clkout0_divide_frac[2:1]}; // using >> instead of clkout0_divide_frac / 2 492 | pm_rise = 0; //0 493 | 494 | wf_fall_frac = (odd_and_frac >=2) && (odd_and_frac <=9);//IF(odd_and_frac>=2,IF(odd_and_frac <= 9,1,0),0) 495 | wf_rise_frac = (odd_and_frac >=1) && (odd_and_frac <=8);//IF(odd_and_frac>=1,IF(odd_and_frac <= 8,1,0),0) 496 | 497 | 498 | 499 | //Calculate phase in fractional cycles 500 | a_per_in_octets = (8 * divide) + (frac / 125) ; 501 | a_phase_in_cycles = (phase+10) * a_per_in_octets / 360000 ;//Adding 1 due to rounding errors 502 | pm_rise_frac = (a_phase_in_cycles[7:0] ==8'h00)?8'h00:a_phase_in_cycles[7:0] - {a_phase_in_cycles[7:3],3'b000}; 503 | 504 | dt_calc = ((phase+10) * a_per_in_octets / 8 )/360000 ;//TRUNC(phase* divide / 360); //or_simply (a_per_in_octets / 8) 505 | dt = dt_calc[7:0]; 506 | 507 | pm_rise_frac_filtered = (pm_rise_frac >=8) ? (pm_rise_frac ) - 8: pm_rise_frac ; //((phase_fixed * (divide + frac / 1000)) / 360) - {pm_rise_frac[7:3],3'b000};//$rtoi(clkout0_phase * clkout0_divide / 45);//a; 508 | 509 | dt_int = dt + (& pm_rise_frac[7:4]); //IF(pm_rise_overwriting>7,dt+1,dt) 510 | pm_fall_frac = pm_fall + pm_rise_frac; 511 | pm_fall_frac_filtered = pm_fall + pm_rise_frac - {pm_fall_frac[7:3], 3'b000}; 512 | 513 | div_calc = mmcm_pll_divider(divide, duty_cycle); //Use to determine edge[7], no count[6] 514 | phase_calc = mmcm_pll_phase(divide, phase);// returns{mx[1:0], phase_mux[2:0], delay_time[5:0]} 515 | 516 | mmcm_pll_frac_count_calc[37:0] = 517 | { 2'b00, pm_fall_frac_filtered[2:0], wf_fall_frac, 518 | 1'b0, clkout0_divide_frac[2:0], 1'b1, wf_rise_frac, phase_calc[10:9], div_calc[13:12], dt[5:0], 519 | 3'b000, 1'b0, ht_frac[5:0], lt_frac[5:0] //Removed PM_Rise bits 520 | // pm_rise_frac_filtered[2], pm_rise_frac_filtered[1], pm_rise_frac_filtered[0], 1'b0, ht_frac[5:0], lt_frac[5:0] 521 | } ; 522 | 523 | `ifdef DEBUG 524 | $display("-%d.%d p%d>> :DADDR_9_15 frac30to28.frac_en.wf_r_frac.dt:%b%d%d_%b:DADDR_7_13 pm_f_frac_filtered_29to27.wf_f_frac_26:%b%d:DADDR_8_14.pm_r_frac_filt_15to13.ht_frac.lt_frac:%b%b%b:", divide, frac, phase, clkout0_divide_frac, 1, wf_rise_frac, dt, pm_fall_frac_filtered, wf_fall_frac, 3'b000, ht_frac, lt_frac); 525 | `endif 526 | 527 | end 528 | endfunction 529 | 530 | 531 | -------------------------------------------------------------------------------- /FPGA/fft.srcs/sources_1/ip/clk_wiz_0/mmcm_pll_drp_func_us_plus_pll.vh: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Company: Xilinx 4 | // Engineer: Jim Tatsukawa, Ralf Krueger, updated for Ultrascale+ 5 | // Date: 6/15/2015 6 | // Design Name: PLLE4 DRP 7 | // Module Name: plle4_drp_func.h 8 | // Version: 2.0 9 | // Target Devices: UltraScale+ Architecture 10 | // Tool versions: 2017.1 11 | // Description: This header provides the functions necessary to 12 | // calculate the DRP register values for the V6 PLL. 13 | // 14 | // Revision Notes: 8/11 - PLLE3 updated for PLLE3 file 4564419 15 | // Revision Notes: 6/15 - pll_filter_lookup fixed for max M of 19 16 | // M_Rise bits have been removed for PLLE3 17 | // Revision Notes: 2/28/17 - pll_filter_lookup and CPRES updated for 18 | // Ultrascale+ and for max M of 21 19 | // 20 | // Disclaimer: XILINX IS PROVIDING THIS DESIGN, CODE, OR 21 | // INFORMATION "AS IS" SOLELY FOR USE IN DEVELOPING 22 | // PROGRAMS AND SOLUTIONS FOR XILINX DEVICES. BY 23 | // PROVIDING THIS DESIGN, CODE, OR INFORMATION AS 24 | // ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, 25 | // APPLICATION OR STANDARD, XILINX IS MAKING NO 26 | // REPRESENTATION THAT THIS IMPLEMENTATION IS FREE 27 | // FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE 28 | // RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY 29 | // REQUIRE FOR YOUR IMPLEMENTATION. XILINX 30 | // EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH 31 | // RESPECT TO THE ADEQUACY OF THE IMPLEMENTATION, 32 | // INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR 33 | // REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE 34 | // FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES 35 | // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 36 | // PURPOSE. 37 | // 38 | // (c) Copyright 2009-2017 Xilinx, Inc. 39 | // All rights reserved. 40 | // 41 | /////////////////////////////////////////////////////////////////////////////// 42 | 43 | // These are user functions that should not be modified. Changes to the defines 44 | // or code within the functions may alter the accuracy of the calculations. 45 | 46 | // Define debug to provide extra messages durring elaboration 47 | //`define DEBUG 1 48 | 49 | // FRAC_PRECISION describes the width of the fractional portion of the fixed 50 | // point numbers. These should not be modified, they are for development 51 | // only 52 | `define FRAC_PRECISION 10 53 | // FIXED_WIDTH describes the total size for fixed point calculations(int+frac). 54 | // Warning: L.50 and below will not calculate properly with FIXED_WIDTHs 55 | // greater than 32 56 | `define FIXED_WIDTH 32 57 | 58 | // This function takes a fixed point number and rounds it to the nearest 59 | // fractional precision bit. 60 | function [`FIXED_WIDTH:1] round_frac 61 | ( 62 | // Input is (FIXED_WIDTH-FRAC_PRECISION).FRAC_PRECISION fixed point number 63 | input [`FIXED_WIDTH:1] decimal, 64 | 65 | // This describes the precision of the fraction, for example a value 66 | // of 1 would modify the fractional so that instead of being a .16 67 | // fractional, it would be a .1 (rounded to the nearest 0.5 in turn) 68 | input [`FIXED_WIDTH:1] precision 69 | ); 70 | 71 | begin 72 | 73 | `ifdef DEBUG 74 | $display("round_frac - decimal: %h, precision: %h", decimal, precision); 75 | `endif 76 | // If the fractional precision bit is high then round up 77 | if( decimal[(`FRAC_PRECISION-precision)] == 1'b1) begin 78 | round_frac = decimal + (1'b1 << (`FRAC_PRECISION-precision)); 79 | end else begin 80 | round_frac = decimal; 81 | end 82 | `ifdef DEBUG 83 | $display("round_frac: %h", round_frac); 84 | `endif 85 | end 86 | endfunction 87 | 88 | // This function calculates high_time, low_time, w_edge, and no_count 89 | // of a non-fractional counter based on the divide and duty cycle 90 | // 91 | // NOTE: high_time and low_time are returned as integers between 0 and 63 92 | // inclusive. 64 should equal 6'b000000 (in other words it is okay to 93 | // ignore the overflow) 94 | function [13:0] mmcm_pll_divider 95 | ( 96 | input [7:0] divide, // Max divide is 128 97 | input [31:0] duty_cycle // Duty cycle is multiplied by 100,000 98 | ); 99 | 100 | reg [`FIXED_WIDTH:1] duty_cycle_fix; 101 | 102 | // High/Low time is initially calculated with a wider integer to prevent a 103 | // calculation error when it overflows to 64. 104 | reg [6:0] high_time; 105 | reg [6:0] low_time; 106 | reg w_edge; 107 | reg no_count; 108 | 109 | reg [`FIXED_WIDTH:1] temp; 110 | 111 | begin 112 | // Duty Cycle must be between 0 and 1,000 113 | if(duty_cycle <=0 || duty_cycle >= 100000) begin 114 | `ifndef SYNTHESIS 115 | $display("ERROR: duty_cycle: %d is invalid", duty_cycle); 116 | `endif 117 | $finish; 118 | end 119 | 120 | // Convert to FIXED_WIDTH-FRAC_PRECISION.FRAC_PRECISION fixed point 121 | duty_cycle_fix = (duty_cycle << `FRAC_PRECISION) / 100_000; 122 | 123 | `ifdef DEBUG 124 | $display("duty_cycle_fix: %h", duty_cycle_fix); 125 | `endif 126 | 127 | // If the divide is 1 nothing needs to be set except the no_count bit. 128 | // Other values are dummies 129 | if(divide == 7'h01) begin 130 | high_time = 7'h01; 131 | w_edge = 1'b0; 132 | low_time = 7'h01; 133 | no_count = 1'b1; 134 | end else begin 135 | temp = round_frac(duty_cycle_fix*divide, 1); 136 | 137 | // comes from above round_frac 138 | high_time = temp[`FRAC_PRECISION+7:`FRAC_PRECISION+1]; 139 | // If the duty cycle * divide rounded is .5 or greater then this bit 140 | // is set. 141 | w_edge = temp[`FRAC_PRECISION]; // comes from round_frac 142 | 143 | // If the high time comes out to 0, it needs to be set to at least 1 144 | // and w_edge set to 0 145 | if(high_time == 7'h00) begin 146 | high_time = 7'h01; 147 | w_edge = 1'b0; 148 | end 149 | 150 | if(high_time == divide) begin 151 | high_time = divide - 1; 152 | w_edge = 1'b1; 153 | end 154 | 155 | // Calculate low_time based on the divide setting and set no_count to 156 | // 0 as it is only used when divide is 1. 157 | low_time = divide - high_time; 158 | no_count = 1'b0; 159 | end 160 | 161 | // Set the return value. 162 | mmcm_pll_divider = {w_edge,no_count,high_time[5:0],low_time[5:0]}; 163 | end 164 | endfunction 165 | 166 | // This function calculates mx, delay_time, and phase_mux 167 | // of a non-fractional counter based on the divide and phase 168 | // 169 | // NOTE: The only valid value for the MX bits is 2'b00 to ensure the coarse mux 170 | // is used. 171 | function [10:0] mmcm_pll_phase 172 | ( 173 | // divide must be an integer (use fractional if not) 174 | // assumed that divide already checked to be valid 175 | input [7:0] divide, // Max divide is 128 176 | 177 | // Phase is given in degrees (-360,000 to 360,000) 178 | input signed [31:0] phase 179 | ); 180 | 181 | reg [`FIXED_WIDTH:1] phase_in_cycles; 182 | reg [`FIXED_WIDTH:1] phase_fixed; 183 | reg [1:0] mx; 184 | reg [5:0] delay_time; 185 | reg [2:0] phase_mux; 186 | 187 | reg [`FIXED_WIDTH:1] temp; 188 | 189 | begin 190 | `ifdef DEBUG 191 | $display("pll_phase-divide:%d,phase:%d", 192 | divide, phase); 193 | `endif 194 | 195 | if ((phase < -360000) || (phase > 360000)) begin 196 | `ifndef SYNTHESIS 197 | $display("ERROR: phase of $phase is not between -360000 and 360000"); 198 | `endif 199 | $finish; 200 | end 201 | 202 | // If phase is less than 0, convert it to a positive phase shift 203 | // Convert to (FIXED_WIDTH-FRAC_PRECISION).FRAC_PRECISION fixed point 204 | if(phase < 0) begin 205 | phase_fixed = ( (phase + 360000) << `FRAC_PRECISION ) / 1000; 206 | end else begin 207 | phase_fixed = ( phase << `FRAC_PRECISION ) / 1000; 208 | end 209 | 210 | // Put phase in terms of decimal number of vco clock cycles 211 | phase_in_cycles = ( phase_fixed * divide ) / 360; 212 | 213 | `ifdef DEBUG 214 | $display("phase_in_cycles: %h", phase_in_cycles); 215 | `endif 216 | 217 | 218 | temp = round_frac(phase_in_cycles, 3); 219 | 220 | // set mx to 2'b00 that the phase mux from the VCO is enabled 221 | mx = 2'b00; 222 | phase_mux = temp[`FRAC_PRECISION:`FRAC_PRECISION-2]; 223 | delay_time = temp[`FRAC_PRECISION+6:`FRAC_PRECISION+1]; 224 | 225 | `ifdef DEBUG 226 | $display("temp: %h", temp); 227 | `endif 228 | 229 | // Setup the return value 230 | mmcm_pll_phase={mx, phase_mux, delay_time}; 231 | end 232 | endfunction 233 | 234 | // This function takes the divide value and outputs the necessary lock values 235 | function [39:0] mmcm_pll_lock_lookup 236 | ( 237 | input [6:0] divide // Max divide is 21 238 | ); 239 | 240 | reg [839:0] lookup; 241 | 242 | begin 243 | lookup = { 244 | // This table is composed of: 245 | // LockRefDly_LockFBDly_LockCnt_LockSatHigh_UnlockCnt 246 | 40'b00110_00110_1111101000_1111101001_0000000001, //1 illegal in Ultrascale+ 247 | 40'b00110_00110_1111101000_1111101001_0000000001, //2 248 | 40'b01000_01000_1111101000_1111101001_0000000001, //3 249 | 40'b01011_01011_1111101000_1111101001_0000000001, //4 250 | 40'b01110_01110_1111101000_1111101001_0000000001, //5 251 | 40'b10001_10001_1111101000_1111101001_0000000001, //6 252 | 40'b10011_10011_1111101000_1111101001_0000000001, //7 253 | 40'b10110_10110_1111101000_1111101001_0000000001, //8 254 | 40'b11001_11001_1111101000_1111101001_0000000001, //9 255 | 40'b11100_11100_1111101000_1111101001_0000000001, //10 256 | 40'b11111_11111_1110000100_1111101001_0000000001, //11 257 | 40'b11111_11111_1100111001_1111101001_0000000001, //12 258 | 40'b11111_11111_1011101110_1111101001_0000000001, //13 259 | 40'b11111_11111_1010111100_1111101001_0000000001, //14 260 | 40'b11111_11111_1010001010_1111101001_0000000001, //15 261 | 40'b11111_11111_1001110001_1111101001_0000000001, //16 262 | 40'b11111_11111_1000111111_1111101001_0000000001, //17 263 | 40'b11111_11111_1000100110_1111101001_0000000001, //18 264 | 40'b11111_11111_1000001101_1111101001_0000000001, //19 265 | 40'b11111_11111_0111110100_1111101001_0000000001, //20 266 | 40'b11111_11111_0111011011_1111101001_0000000001 //21 267 | }; 268 | 269 | // Set lookup_entry with the explicit bits from lookup with a part select 270 | mmcm_pll_lock_lookup = lookup[ ((21-divide)*40) +: 40]; 271 | `ifdef DEBUG 272 | $display("lock_lookup: %b", pll_lock_lookup); 273 | `endif 274 | end 275 | endfunction 276 | 277 | // This function takes the divide value and the bandwidth setting of the PLL 278 | // and outputs the digital filter settings necessary. Removing bandwidth setting for PLLE3. 279 | function [9:0] mmcm_pll_filter_lookup 280 | ( 281 | input [6:0] divide // Max divide is 21 282 | ); 283 | 284 | reg [209:0] lookup; 285 | reg [9:0] lookup_entry; 286 | 287 | begin 288 | 289 | lookup = { 290 | // CP_RES_LFHF 291 | 10'b0011_0111_11, //1 not legal in Ultrascale+ 292 | 10'b0011_0111_11, //2 293 | 10'b0011_0011_11, //3 294 | 10'b0011_1001_11, //4 295 | 10'b0011_0001_11, //5 296 | 10'b0100_1110_11, //6 297 | 10'b0011_0110_11, //7 298 | 10'b0011_1010_11, //8 299 | 10'b0111_1001_11, //9 300 | 10'b0111_1001_11, //10 301 | 10'b0101_0110_11, //11 302 | 10'b1100_0101_11, //12 303 | 10'b0101_1010_11, //13 304 | 10'b0110_0110_11, //14 305 | 10'b0110_1010_11, //15 306 | 10'b0111_0110_11, //16 307 | 10'b1111_0101_11, //17 308 | 10'b1100_0110_11, //18 309 | 10'b1110_0001_11, //19 310 | 10'b1101_0110_11, //20 311 | 10'b1111_0001_11 //21 312 | }; 313 | 314 | mmcm_pll_filter_lookup = lookup [ ((21-divide)*10) +: 10]; 315 | 316 | `ifdef DEBUG 317 | $display("filter_lookup: %b", pll_filter_lookup); 318 | `endif 319 | end 320 | endfunction 321 | 322 | // This function set the CLKOUTPHY divide settings to match 323 | // the desired CLKOUTPHY_MODE setting. To create VCO_X2, then 324 | // the CLKOUTPHY will be set to 2'b00 since the VCO is internally 325 | // doubled and 2'b00 will represent divide by 1. Similarly "VCO" 326 | // will need to divide the doubled clock VCO clock frequency by 327 | // 2 therefore 2'b01 will match a divide by 2.And VCO_HALF will 328 | // need to divide the doubled VCO by 4, therefore 2'b10 329 | function [9:0] mmcm_pll_clkoutphy_calc 330 | ( 331 | input [8*9:0] CLKOUTPHY_MODE 332 | ); 333 | 334 | if(CLKOUTPHY_MODE == "VCO_X2") begin 335 | mmcm_pll_clkoutphy_calc= 2'b00; 336 | end else if(CLKOUTPHY_MODE == "VCO") begin 337 | mmcm_pll_clkoutphy_calc= 2'b01; 338 | end else if(CLKOUTPHY_MODE == "CLKIN") begin 339 | mmcm_pll_clkoutphy_calc= 2'b11; 340 | end else begin // Assume "VCO_HALF" 341 | mmcm_pll_clkoutphy_calc= 2'b10; 342 | end 343 | 344 | endfunction 345 | 346 | 347 | // This function takes in the divide, phase, and duty cycle 348 | // setting to calculate the upper and lower counter registers. 349 | function [37:0] mmcm_pll_count_calc 350 | ( 351 | input [7:0] divide, // Max divide is 128 352 | input signed [31:0] phase, 353 | input [31:0] duty_cycle // Multiplied by 100,000 354 | ); 355 | 356 | reg [13:0] div_calc; 357 | reg [16:0] phase_calc; 358 | 359 | begin 360 | `ifdef DEBUG 361 | $display("pll_count_calc- divide:%h, phase:%d, duty_cycle:%d", 362 | divide, phase, duty_cycle); 363 | `endif 364 | 365 | // w_edge[13], no_count[12], high_time[11:6], low_time[5:0] 366 | div_calc = mmcm_pll_divider(divide, duty_cycle); 367 | // mx[10:9], pm[8:6], dt[5:0] 368 | phase_calc = mmcm_pll_phase(divide, phase); 369 | 370 | // Return value is the upper and lower address of counter 371 | // Upper address is: 372 | // RESERVED [31:26] 373 | // MX [25:24] 374 | // EDGE [23] 375 | // NOCOUNT [22] 376 | // DELAY_TIME [21:16] 377 | // Lower Address is: 378 | // PHASE_MUX [15:13] 379 | // RESERVED [12] 380 | // HIGH_TIME [11:6] 381 | // LOW_TIME [5:0] 382 | 383 | `ifdef DEBUG 384 | $display("div:%d dc:%d phase:%d ht:%d lt:%d ed:%d nc:%d mx:%d dt:%d pm:%d", 385 | divide, duty_cycle, phase, div_calc[11:6], div_calc[5:0], 386 | div_calc[13], div_calc[12], 387 | phase_calc[16:15], phase_calc[5:0], 3'b000); //Removed PM_Rise bits 388 | `endif 389 | 390 | mmcm_pll_count_calc = 391 | { 392 | // Upper Address 393 | 6'h00, phase_calc[10:9], div_calc[13:12], phase_calc[5:0], 394 | // Lower Address 395 | phase_calc[8:6], 1'b0, div_calc[11:0] 396 | }; 397 | end 398 | endfunction 399 | 400 | 401 | // This function takes in the divide, phase, and duty cycle 402 | // setting to calculate the upper and lower counter registers. 403 | // for fractional multiply/divide functions. 404 | // 405 | // 406 | function [37:0] mmcm_pll_frac_count_calc 407 | ( 408 | input [7:0] divide, // Max divide is 128 409 | input signed [31:0] phase, 410 | input [31:0] duty_cycle, // Multiplied by 1,000 411 | input [9:0] frac // Multiplied by 1000 412 | ); 413 | 414 | //Required for fractional divide calculations 415 | reg [7:0] lt_frac; 416 | reg [7:0] ht_frac; 417 | 418 | reg /*[7:0]*/ wf_fall_frac; 419 | reg /*[7:0]*/ wf_rise_frac; 420 | 421 | reg [31:0] a; 422 | reg [7:0] pm_rise_frac_filtered ; 423 | reg [7:0] pm_fall_frac_filtered ; 424 | reg [7:0] clkout0_divide_int; 425 | reg [2:0] clkout0_divide_frac; 426 | reg [7:0] even_part_high; 427 | reg [7:0] even_part_low; 428 | 429 | reg [7:0] odd; 430 | reg [7:0] odd_and_frac; 431 | 432 | reg [7:0] pm_fall; 433 | reg [7:0] pm_rise; 434 | reg [7:0] dt; 435 | reg [7:0] dt_int; 436 | reg [63:0] dt_calc; 437 | 438 | reg [7:0] pm_rise_frac; 439 | reg [7:0] pm_fall_frac; 440 | 441 | reg [31:0] a_per_in_octets; 442 | reg [31:0] a_phase_in_cycles; 443 | 444 | parameter precision = 0.125; 445 | 446 | reg [31:0] phase_fixed; // changed to 31:0 from 32:1 jt 5/2/11 447 | reg [31: 0] phase_pos; 448 | reg [31: 0] phase_vco; 449 | reg [31:0] temp;// changed to 31:0 from 32:1 jt 5/2/11 450 | reg [13:0] div_calc; 451 | reg [16:0] phase_calc; 452 | 453 | begin 454 | `ifdef DEBUG 455 | $display("pll_frac_count_calc- divide:%h, phase:%d, duty_cycle:%d", 456 | divide, phase, duty_cycle); 457 | `endif 458 | 459 | //convert phase to fixed 460 | if ((phase < -360000) || (phase > 360000)) begin 461 | `ifndef SYNTHESIS 462 | $display("ERROR: phase of $phase is not between -360000 and 360000"); 463 | `endif 464 | $finish; 465 | end 466 | 467 | 468 | // Return value is 469 | // Transfer data 470 | // RESERVED [37:36] 471 | // FRAC_TIME [35:33] 472 | // FRAC_WF_FALL [32] 473 | // Upper address is: 474 | // RESERVED [31:26] 475 | // MX [25:24] 476 | // EDGE [23] 477 | // NOCOUNT [22] 478 | // DELAY_TIME [21:16] 479 | // Lower Address is: 480 | // PHASE_MUX [15:13] 481 | // RESERVED [12] 482 | // HIGH_TIME [11:6] 483 | // LOW_TIME [5:0] 484 | 485 | 486 | 487 | clkout0_divide_frac = frac / 125; 488 | clkout0_divide_int = divide; 489 | 490 | even_part_high = clkout0_divide_int >> 1;//$rtoi(clkout0_divide_int / 2); 491 | even_part_low = even_part_high; 492 | 493 | odd = clkout0_divide_int - even_part_high - even_part_low; 494 | odd_and_frac = (8*odd) + clkout0_divide_frac; 495 | 496 | lt_frac = even_part_high - (odd_and_frac <= 9);//IF(odd_and_frac>9,even_part_high, even_part_high - 1) 497 | ht_frac = even_part_low - (odd_and_frac <= 8);//IF(odd_and_frac>8,even_part_low, even_part_low- 1) 498 | 499 | pm_fall = {odd[6:0],2'b00} + {6'h00, clkout0_divide_frac[2:1]}; // using >> instead of clkout0_divide_frac / 2 500 | pm_rise = 0; //0 501 | 502 | wf_fall_frac = (odd_and_frac >=2) && (odd_and_frac <=9);//IF(odd_and_frac>=2,IF(odd_and_frac <= 9,1,0),0) 503 | wf_rise_frac = (odd_and_frac >=1) && (odd_and_frac <=8);//IF(odd_and_frac>=1,IF(odd_and_frac <= 8,1,0),0) 504 | 505 | 506 | 507 | //Calculate phase in fractional cycles 508 | a_per_in_octets = (8 * divide) + (frac / 125) ; 509 | a_phase_in_cycles = (phase+10) * a_per_in_octets / 360000 ;//Adding 1 due to rounding errors 510 | pm_rise_frac = (a_phase_in_cycles[7:0] ==8'h00)?8'h00:a_phase_in_cycles[7:0] - {a_phase_in_cycles[7:3],3'b000}; 511 | 512 | dt_calc = ((phase+10) * a_per_in_octets / 8 )/360000 ;//TRUNC(phase* divide / 360); //or_simply (a_per_in_octets / 8) 513 | dt = dt_calc[7:0]; 514 | 515 | pm_rise_frac_filtered = (pm_rise_frac >=8) ? (pm_rise_frac ) - 8: pm_rise_frac ; //((phase_fixed * (divide + frac / 1000)) / 360) - {pm_rise_frac[7:3],3'b000};//$rtoi(clkout0_phase * clkout0_divide / 45);//a; 516 | 517 | dt_int = dt + (& pm_rise_frac[7:4]); //IF(pm_rise_overwriting>7,dt+1,dt) 518 | pm_fall_frac = pm_fall + pm_rise_frac; 519 | pm_fall_frac_filtered = pm_fall + pm_rise_frac - {pm_fall_frac[7:3], 3'b000}; 520 | 521 | div_calc = mmcm_pll_divider(divide, duty_cycle); //Use to determine edge[7], no count[6] 522 | phase_calc = mmcm_pll_phase(divide, phase);// returns{mx[1:0], phase_mux[2:0], delay_time[5:0]} 523 | 524 | mmcm_pll_frac_count_calc[37:0] = 525 | { 2'b00, pm_fall_frac_filtered[2:0], wf_fall_frac, 526 | 1'b0, clkout0_divide_frac[2:0], 1'b1, wf_rise_frac, phase_calc[10:9], div_calc[13:12], dt[5:0], 527 | 3'b000, 1'b0, ht_frac[5:0], lt_frac[5:0] //Removed PM_Rise bits 528 | } ; 529 | 530 | `ifdef DEBUG 531 | $display("-%d.%d p%d>> :DADDR_9_15 frac30to28.frac_en.wf_r_frac.dt:%b%d%d_%b:DADDR_7_13 pm_f_frac_filtered_29to27.wf_f_frac_26:%b%d:DADDR_8_14.pm_r_frac_filt_15to13.ht_frac.lt_frac:%b%b%b:", divide, frac, phase, clkout0_divide_frac, 1, wf_rise_frac, dt, pm_fall_frac_filtered, wf_fall_frac, 3'b000, ht_frac, lt_frac); 532 | `endif 533 | 534 | end 535 | endfunction 536 | 537 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Chisel-FFT 2 | *NOTE: 3 | The branch **BRAM** contains codes using BRAM explicitely in FPGA flow. 4 | The branch **STFT** contains a **Chisel-STFT** project applied to Short-time Fourier transform. 5 | The branch **FFT-Generator** contains a project supporting more configurations for the flexiblity of construction and datafromat.This is the latest and most complete version.For more details, please refer to this branch's README.md* 6 | 7 | This Chisel project implements a [R2MDC](https://ieeexplore.ieee.org/document/7421167) (Radix-2 Multipath Delay Commutator) FFT hardware design, and the source and test files are organized as follows. 8 | 9 | ``` 10 | src/ 11 | main/ 12 | scala/ 13 | FFT/ 14 | Butterfly.scala 15 | Config.scala 16 | FFT.scala 17 | VerilogEmitter.scala 18 | test/ 19 | scala/ 20 | FFT/ 21 | FFTTest.scala 22 | ``` 23 | 24 | The FPGA folder contains the tcl script and other necessary files for the FPGA flow running on Vivado 2019.2 25 | 26 | ## How to generate Verilog ? 27 | 28 | We designed *VerilogEmitter.scala* to handle all the generations of Verilog code. 29 | 30 | In IntelliJ, you can click the green button near the *elaborateFFT* object defined in *VerilogEmitter.scala* to run this object and generate Verilog codes. 31 | 32 | The object *elaborateFFT* is defined as follows, and some arguments (like the destination directory, etc) could be configured in this process. 33 | 34 | ``` 35 | object elaborateFFT extends App { 36 | (new chisel3.stage.ChiselStage).execute( 37 | Array("-X", "verilog", "--full-stacktrace"), 38 | Seq(ChiselGeneratorAnnotation(() => new FFT()), 39 | TargetDirAnnotation("Verilog")) 40 | ) 41 | } 42 | ``` 43 | 44 | Or you can run the following command in your terminal. 45 | 46 | ``` 47 | sbt 'test:runMain FFT.elaborateFFT' 48 | ``` 49 | 50 | ## How to run the test ? 51 | 52 | The testbench is defined in *FFTTest.scala*, and you could run the object *FFTTestMain* like what we did before to get the simulation results (like the error rate and the overflow rate, etc). 53 | 54 | The object *FFTTestMain* is defined as follows. 55 | 56 | ``` 57 | object FFTTestMain extends App { 58 | iotesters.Driver.execute(args, () => new FFT) { 59 | c => new FFTTest(c) 60 | } 61 | } 62 | ``` 63 | 64 | Or you can run the following command in your terminal. 65 | 66 | ``` 67 | sbt 'test:runMain FFT.FFTTestMain' 68 | ``` 69 | 70 | ## How to run the FPGA flow ? 71 | 72 | We have already generated three Verilog files *FFT128*, *FFT256* and *FFT512* for the FPGA project, which adopts 128, 256 and 512 as the length of FFT. You can import the tcl script directly in the Vivado to run the FPGA implementation and evaluation. 73 | 74 | For more information, please see our article published on https://zhuanlan.zhihu.com/p/137260660 75 | 76 | # Optimization1: Chisel-FFT with reorder buffer 77 | 78 | For the complete process of FFT, a reorder buffer hardware is attached to the FFT module, which can be found in 79 | 80 | ``` 81 | src/ 82 | main/ 83 | scala/ 84 | FFT/ 85 | Butterfly.scala 86 | Config.scala 87 | FFT.scala 88 | Reorder.scala 89 | VerilogEmitter.scala 90 | ``` 91 | 92 | The reorder buffer change the sequences with bit-reversed order to the sequences with normal order. And a new top module is got by connecting the two modules. 93 | 94 | ## How to generater verilog 95 | 96 | We designed *VerilogEmitter.scala* to handle all the generations of Verilog code. 97 | 98 | In IntelliJ, you can click the green button near the *elaborateFFTReorder* object defined in *VerilogEmitter.scala* to run this object and generate Verilog codes. 99 | 100 | The object *elaborateFFTReorder* is defined as follows, and some arguments (like the destination directory, etc) could be configured in this process. 101 | 102 | ``` 103 | object elaborateFFTReorder extends App { 104 | (new chisel3.stage.ChiselStage).execute( 105 | Array("-X", "verilog", "--full-stacktrace"), 106 | Seq(ChiselGeneratorAnnotation(() => new FFTReorder()), 107 | TargetDirAnnotation("Verilog")) 108 | ) 109 | } 110 | ``` 111 | 112 | Or you can run the following command in your terminal. 113 | 114 | ``` 115 | sbt 'test:runMain FFT.elaborateFFTReorder' 116 | ``` 117 | 118 | # How to run the test ? 119 | 120 | The testbench is defined in *FFTTest3.scala*, and you could run the object *FFTTestMain3* like what we did before to get the simulation results (like the error rate and the overflow rate, etc). 121 | 122 | The object *FFTTestMain3* is defined as follows. 123 | 124 | ``` 125 | object FFTTestMain3 extends App { 126 | iotesters.Driver.execute(Array("--backend-name", "verilator"), () => new FFTReorder) { 127 | c => new FFTTest3(c) 128 | } 129 | } 130 | ``` 131 | 132 | Or you can run the following command in your terminal. 133 | 134 | ``` 135 | sbt 'test:runMain FFT.FFTTestMain' 136 | ``` 137 | 138 | Moreover, we can view the wave of the simualation of the generated verilog by the file with an extension *.vcd*. 139 | 140 | ## How to run the FPGA flow ? 141 | 142 | You need to generate the verilog file for the FPGA project and run the the FPGA implementation and evaluation by yourself 143 | -------------------------------------------------------------------------------- /build.sbt: -------------------------------------------------------------------------------- 1 | // See README.md for license details. 2 | 3 | def scalacOptionsVersion(scalaVersion: String): Seq[String] = { 4 | Seq() ++ { 5 | // If we're building with Scala > 2.11, enable the compile option 6 | // switch to support our anonymous Bundle definitions: 7 | // https://github.com/scala/bug/issues/10047 8 | CrossVersion.partialVersion(scalaVersion) match { 9 | case Some((2, scalaMajor: Long)) if scalaMajor < 12 => Seq() 10 | case _ => Seq("-Xsource:2.11") 11 | } 12 | } 13 | } 14 | 15 | def javacOptionsVersion(scalaVersion: String): Seq[String] = { 16 | Seq() ++ { 17 | // Scala 2.12 requires Java 8. We continue to generate 18 | // Java 7 compatible code for Scala 2.11 19 | // for compatibility with old clients. 20 | CrossVersion.partialVersion(scalaVersion) match { 21 | case Some((2, scalaMajor: Long)) if scalaMajor < 12 => 22 | Seq("-source", "1.7", "-target", "1.7") 23 | case _ => 24 | Seq("-source", "1.8", "-target", "1.8") 25 | } 26 | } 27 | } 28 | 29 | name := "chisel-module-template" 30 | 31 | version := "3.3.0" 32 | 33 | scalaVersion := "2.12.10" 34 | 35 | crossScalaVersions := Seq("2.12.10", "2.11.12") 36 | 37 | resolvers ++= Seq( 38 | Resolver.sonatypeRepo("snapshots"), 39 | Resolver.sonatypeRepo("releases") 40 | ) 41 | 42 | // Provide a managed dependency on X if -DXVersion="" is supplied on the command line. 43 | val defaultVersions = Map( 44 | "chisel3" -> "3.2.+", 45 | "chisel-iotesters" -> "1.3.+" 46 | ) 47 | 48 | libraryDependencies ++= Seq("chisel3","chisel-iotesters").map { 49 | dep: String => "edu.berkeley.cs" %% dep % sys.props.getOrElse(dep + "Version", defaultVersions(dep)) } 50 | 51 | scalacOptions ++= scalacOptionsVersion(scalaVersion.value) 52 | 53 | javacOptions ++= javacOptionsVersion(scalaVersion.value) 54 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version = 1.3.2 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | logLevel := Level.Warn -------------------------------------------------------------------------------- /scalastyle-config.xml: -------------------------------------------------------------------------------- 1 | 2 | Scalastyle standard configuration 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | No lines ending with a ; 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | |\|\||&&|:=|<>|<=|>=|!=|===|<<|>>|##|unary_(~|\-%?|!))$]]> 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /scalastyle-test-config.xml: -------------------------------------------------------------------------------- 1 | 2 | Scalastyle configuration for Chisel3 unit tests 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | No lines ending with a ; 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | |\|\||&&|:=|<>|<=|>=|!=|===|<<|>>|##|unary_(~|\-%?|!))$]]> 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /src/main/scala/FFT/Butterfly.scala: -------------------------------------------------------------------------------- 1 | 2 | package FFT 3 | 4 | import chisel3._ 5 | import chisel3.experimental._ 6 | 7 | class MyComplex extends Bundle 8 | with HasDataConfig { 9 | val re = FixedPoint(DataWidth.W, BinaryPoint.BP) 10 | val im = FixedPoint(DataWidth.W, BinaryPoint.BP) 11 | } 12 | 13 | class ComplexOperationIO extends Bundle { 14 | val op1 = Input(new MyComplex()) 15 | val op2= Input(new MyComplex()) 16 | val res = Output(new MyComplex()) 17 | } 18 | 19 | class ComplexAdd extends Module { 20 | val io = IO(new ComplexOperationIO) 21 | io.res.re := io.op1.re + io.op2.re 22 | io.res.im := io.op1.im + io.op2.im 23 | } 24 | object ComplexAdd { 25 | def apply(op1: MyComplex, op2: MyComplex):MyComplex = { 26 | val inst = Module(new ComplexAdd) 27 | inst.io.op1 := op1 28 | inst.io.op2 := op2 29 | inst.io.res 30 | } 31 | } 32 | 33 | class ComplexSub extends Module { 34 | val io = IO(new ComplexOperationIO) 35 | io.res.re := io.op1.re - io.op2.re 36 | io.res.im := io.op1.im - io.op2.im 37 | } 38 | object ComplexSub { 39 | def apply(op1: MyComplex, op2: MyComplex):MyComplex = { 40 | val inst = Module(new ComplexSub) 41 | inst.io.op1 := op1 42 | inst.io.op2 := op2 43 | inst.io.res 44 | } 45 | } 46 | 47 | class ComplexMul extends Module 48 | with HasElaborateConfig { 49 | val io = IO(new ComplexOperationIO) 50 | if (useGauss) { 51 | val k1 = io.op2.re * (io.op1.re + io.op1.im) 52 | val k2 = io.op1.re * (io.op2.im - io.op2.re) 53 | val k3 = io.op1.im * (io.op2.re + io.op2.im) 54 | io.res.re := k1 - k3 55 | io.res.im := k1 + k2 56 | } else { 57 | io.res.re := io.op1.re * io.op2.re - io.op1.im * io.op2.im 58 | io.res.im := io.op1.re * io.op2.im + io.op1.im * io.op2.re 59 | } 60 | } 61 | object ComplexMul { 62 | def apply(op1: MyComplex, op2: MyComplex):MyComplex = { 63 | val inst = Module(new ComplexMul) 64 | inst.io.op1 := op1 65 | inst.io.op2 := op2 66 | inst.io.res 67 | } 68 | } 69 | 70 | class ButterflyIO extends Bundle 71 | with HasDataConfig { 72 | val in1 = Input(new MyComplex()) 73 | val in2 = Input(new MyComplex()) 74 | val wn = Input(new MyComplex()) 75 | val out1 = Output(new MyComplex()) 76 | val out2 = Output(new MyComplex()) 77 | } 78 | 79 | class Butterfly extends Module { 80 | val io = IO(new ButterflyIO()) 81 | val add1 = ComplexAdd(io.in1, io.in2) 82 | val sub2 = ComplexSub(io.in1, io.in2) 83 | val mul2 = ComplexMul(sub2, io.wn) 84 | io.out1 := add1 85 | io.out2 := mul2 86 | } 87 | object Butterfly { 88 | def apply(in1: MyComplex, in2: MyComplex, wn: MyComplex): (MyComplex, MyComplex) = { 89 | val inst = Module(new Butterfly) 90 | inst.io.in1 := in1 91 | inst.io.in2 := in2 92 | inst.io.wn := wn 93 | (inst.io.out1, inst.io.out2) 94 | } 95 | } 96 | 97 | class Switch extends Module { 98 | val io = IO(new Bundle{ 99 | val in1 = Input(new MyComplex) 100 | val in2 = Input(new MyComplex) 101 | val sel = Input(Bool()) 102 | val out1 = Output(new MyComplex) 103 | val out2 = Output(new MyComplex) 104 | }) 105 | io.out1 := Mux(io.sel, io.in2, io.in1) 106 | io.out2 := Mux(io.sel, io.in1, io.in2) 107 | } 108 | object Switch { 109 | def apply(in1: MyComplex, in2: MyComplex, sel: Bool): (MyComplex, MyComplex) = { 110 | val inst = Module(new Switch) 111 | inst.io.in1 := in1 112 | inst.io.in2 := in2 113 | inst.io.sel := sel 114 | (inst.io.out1, inst.io.out2) 115 | } 116 | } -------------------------------------------------------------------------------- /src/main/scala/FFT/Config.scala: -------------------------------------------------------------------------------- 1 | 2 | package FFT 3 | 4 | trait HasDataConfig { 5 | val DataWidth = 32 6 | val BinaryPoint = 16 7 | } 8 | 9 | trait HasElaborateConfig { 10 | val FFTLength = 512 11 | val useGauss = false 12 | val supportIFFT = false 13 | } 14 | -------------------------------------------------------------------------------- /src/main/scala/FFT/FFT.scala: -------------------------------------------------------------------------------- 1 | 2 | package FFT 3 | 4 | import chisel3._ 5 | import chisel3.experimental._ 6 | import chisel3.util._ 7 | import scala.math._ 8 | 9 | // R2MDC 10 | class FFT extends Module 11 | with HasDataConfig 12 | with HasElaborateConfig { 13 | val io = IO(new Bundle { 14 | // 0: FFT 1: IFFT 15 | val mode = if(supportIFFT) Some(Input(Bool())) else None 16 | val dIn = Input(new MyComplex) 17 | val din_valid = Input(Bool()) 18 | val dOut1 = Output(new MyComplex) 19 | val dOut2 = Output(new MyComplex) 20 | val dout_valid = Output(Bool()) 21 | val busy = Output(Bool()) 22 | }) 23 | 24 | val mode = io.mode.getOrElse(false.B) 25 | val stages = log2Ceil(FFTLength) 26 | def sinTable(k: Int): Vec[FixedPoint] = { 27 | val times = (0 until FFTLength / 2 by pow(2, k).toInt) 28 | .map(i => -(i * 2 * Pi) / FFTLength.toDouble) 29 | val inits = times.map(t => FixedPoint.fromDouble(sin(t), DataWidth.W, BinaryPoint.BP)) 30 | VecInit(inits) 31 | } 32 | def cosTable(k: Int): Vec[FixedPoint] = { 33 | val times = (0 until FFTLength / 2 by pow(2, k).toInt) 34 | .map(i => -(i * 2 * Pi) / FFTLength.toDouble) 35 | val inits = times.map(t => FixedPoint.fromDouble(cos(t), DataWidth.W, BinaryPoint.BP)) 36 | VecInit(inits) 37 | } 38 | def sinTable2(k: Int): Vec[FixedPoint] = { 39 | val times = (0 until FFTLength / 2 by pow(2, k).toInt) 40 | .map(i => (i * 2 * Pi) / FFTLength.toDouble) 41 | val inits = times.map(t => FixedPoint.fromDouble(sin(t), DataWidth.W, BinaryPoint.BP)) 42 | VecInit(inits) 43 | } 44 | def cosTable2(k: Int): Vec[FixedPoint] = { 45 | val times = (0 until FFTLength / 2 by pow(2, k).toInt) 46 | .map(i => (i * 2 * Pi) / FFTLength.toDouble) 47 | val inits = times.map(t => FixedPoint.fromDouble(cos(t), DataWidth.W, BinaryPoint.BP)) 48 | VecInit(inits) 49 | } 50 | def wnTable(k: Int)(idx: UInt): MyComplex = { 51 | val res = Wire(new MyComplex) 52 | res.re := Mux(mode, cosTable2(k)(idx), cosTable(k)(idx)) 53 | res.im := Mux(mode, sinTable2(k)(idx), sinTable(k)(idx)) 54 | res 55 | } 56 | def timesInvn(a: MyComplex): MyComplex = { 57 | val b = Wire(new MyComplex) 58 | b.re := a.re >> stages 59 | b.im := a.im >> stages 60 | b 61 | } 62 | 63 | val cnt = RegInit(0.U((stages + 1).W)) 64 | val busy = cnt =/= 0.U 65 | when(io.din_valid || busy){ 66 | cnt := Mux(cnt === (FFTLength * 3 / 2 - 1).asUInt(), 0.U, cnt + 1.U) 67 | } 68 | io.busy := busy 69 | 70 | val out1 = VecInit(Seq.fill(stages + 1)(0.S((2 * DataWidth).W).asTypeOf(new MyComplex))) 71 | val out2 = VecInit(Seq.fill(stages + 1)(0.S((2 * DataWidth).W).asTypeOf(new MyComplex))) 72 | out1(0) := io.dIn 73 | out2(0) := io.dIn 74 | 75 | for (i <- 0 until stages - 1) { 76 | val wnCtrl = cnt(stages-2-i, 0) 77 | val wn = wnTable(i)(wnCtrl) 78 | val BF12 = Butterfly(ShiftRegister(out1(i), (FFTLength / pow(2, i + 1)).toInt), out2(i), wn) 79 | val swCtrl = cnt(stages-2-i) 80 | val sw12 = Switch(BF12._1, ShiftRegister(BF12._2, (FFTLength / pow(2, i + 2)).toInt), swCtrl) 81 | out1(i + 1) := sw12._1 82 | out2(i + 1) := sw12._2 83 | } 84 | val out1D1 = RegNext(out1(stages - 1)) 85 | out1(stages) := ComplexAdd(out1D1, out2(stages - 1)) 86 | out2(stages) := ComplexSub(out1D1, out2(stages - 1)) 87 | val dout1 = Mux(mode, timesInvn(out1(stages)), out1(stages)) 88 | val dout2 = Mux(mode, timesInvn(out2(stages)), out2(stages)) 89 | 90 | io.dOut1 := RegNext(dout1) 91 | io.dOut2 := RegNext(dout2) 92 | io.dout_valid := RegNext(cnt) === (FFTLength - 1).asUInt() 93 | } -------------------------------------------------------------------------------- /src/main/scala/FFT/Reorder.scala: -------------------------------------------------------------------------------- 1 | 2 | package FFT 3 | 4 | import chisel3._ 5 | import chisel3.experimental._ 6 | import chisel3.util._ 7 | import scala.math._ 8 | 9 | class Reorder extends Module with HasDataConfig with HasElaborateConfig{ //整理倒位序数据成正序数据 10 | val io = IO(new Bundle{ 11 | val in1 = Input(new MyComplex) 12 | val in2 = Input(new MyComplex) 13 | val in_valid = Input(Bool()) 14 | val out = Output(new MyComplex) 15 | val out_valid = Output(Bool()) 16 | }) 17 | 18 | val rambank0 = Mem(FFTLength/2, new MyComplex) 19 | val rambank1 = Mem(FFTLength/2, new MyComplex) 20 | 21 | val times = log2Ceil(FFTLength / 2) 22 | val in_counter = RegInit(0.U(times.W)) //接收数据的次数,每次接受2数据 23 | val out_counter = RegInit(0.U((times + 1).W)) //输出数据的次数,每次输出1数据 24 | val index1 = Reverse(Cat(in_counter, 0.U(1.W))) //位反序 25 | val index2 = Reverse(Cat(in_counter, 1.U(1.W))) //周期0 就会有in_counter == 0,此时index1 = b000……00, index2 == b100……00. 26 | when(io.in_valid || in_counter =/= 0.U){ //每次有效读入2数据 27 | in_counter := in_counter + 1.U 28 | rambank0.write(index1, io.in1) 29 | rambank1.write(index2, io.in2) 30 | } 31 | 32 | io.out_valid := (RegNext(in_counter) === (FFTLength / 2 - 1).asUInt()) || (out_counter =/= 0.U) 33 | when(io.out_valid) { 34 | out_counter := out_counter + 1.U 35 | } 36 | 37 | when(out_counter < (FFTLength / 2).U) { 38 | io.out := rambank0.read(out_counter) 39 | }.otherwise{ 40 | io.out := rambank1.read(out_counter) 41 | } 42 | } 43 | 44 | class FFTReorder extends Module 45 | with HasDataConfig 46 | with HasElaborateConfig { 47 | val io = IO(new Bundle{ 48 | val mode = if(supportIFFT) Some(Input(Bool())) else None 49 | val dIn = Input(new MyComplex) 50 | val din_valid = Input(Bool()) 51 | val dOut = Output(new MyComplex) 52 | val dout_valid: Bool = Output(Bool()) 53 | val busy = Output(Bool()) 54 | }) 55 | 56 | val fftblock: FFT = Module(new FFT) 57 | fftblock.io.dIn := io.dIn 58 | fftblock.io.din_valid := io.din_valid 59 | 60 | val reorderblock = Module(new Reorder) 61 | reorderblock.io.in1 := fftblock.io.dOut1 62 | reorderblock.io.in2 := fftblock.io.dOut2 63 | reorderblock.io.in_valid := fftblock.io.dout_valid 64 | 65 | io.dOut := reorderblock.io.out 66 | io.dout_valid := reorderblock.io.out_valid 67 | io.busy := fftblock.io.busy 68 | } 69 | -------------------------------------------------------------------------------- /src/main/scala/FFT/TOP.scala: -------------------------------------------------------------------------------- 1 | 2 | package FFT 3 | 4 | import chisel3._ 5 | import chisel3.util._ 6 | 7 | /** 8 | * 9 | * FFT top with output FIFO and decoupled IO 10 | * 11 | */ 12 | 13 | class TOP extends Module 14 | with HasDataConfig 15 | with HasElaborateConfig { 16 | val io = IO(new Bundle{ 17 | val mode = if(supportIFFT) Some(Input(Bool())) else None 18 | val din = Flipped(DecoupledIO(new MyComplex)) 19 | val dout = DecoupledIO(new MyComplex) 20 | }) 21 | val FFT = Module(new FFTReorder) 22 | val FIFOcmd = Wire(DecoupledIO(new MyComplex)) 23 | FIFOcmd.valid := FFT.io.dout_valid 24 | FIFOcmd.bits := FFT.io.dOut 25 | val FIFO = Queue(FIFOcmd, 2 * FFTLength) 26 | FIFO.ready := io.dout.ready 27 | 28 | io.din.ready := FIFOcmd.ready && !FFT.io.busy 29 | FFT.io.din_valid := io.din.fire() 30 | FFT.io.dIn := io.din.bits 31 | 32 | io.dout.valid := FIFO.fire() 33 | io.dout.bits := FIFO.bits 34 | } 35 | -------------------------------------------------------------------------------- /src/main/scala/FFT/VerilogEmitter.scala: -------------------------------------------------------------------------------- 1 | 2 | package FFT 3 | 4 | import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} 5 | import firrtl.options.TargetDirAnnotation 6 | 7 | object elaborateButterfly extends App { 8 | (new chisel3.stage.ChiselStage).execute( 9 | Array("-X", "verilog"), 10 | Seq(ChiselGeneratorAnnotation(() => new Butterfly()), 11 | TargetDirAnnotation("Verilog")) 12 | ) 13 | } 14 | 15 | object elaborateFFT extends App { 16 | (new chisel3.stage.ChiselStage).execute( 17 | Array("-X", "verilog", "--full-stacktrace"), 18 | Seq(ChiselGeneratorAnnotation(() => new FFT()), 19 | TargetDirAnnotation("Verilog")) 20 | ) 21 | } 22 | 23 | object elaborateFFTReorder extends App { 24 | (new chisel3.stage.ChiselStage).execute( 25 | Array("-X", "verilog", "--full-stacktrace"), 26 | Seq(ChiselGeneratorAnnotation(() => new FFTReorder()), 27 | TargetDirAnnotation("Verilog")) 28 | ) 29 | } 30 | 31 | object elaborateTOP extends App { 32 | (new chisel3.stage.ChiselStage).execute( 33 | Array("-X", "verilog", "--full-stacktrace"), 34 | Seq(ChiselGeneratorAnnotation(() => new TOP()), 35 | TargetDirAnnotation("Verilog")) 36 | ) 37 | } 38 | -------------------------------------------------------------------------------- /src/main/scala/gcd/GCD.scala: -------------------------------------------------------------------------------- 1 | // See README.md for license details. 2 | 3 | package gcd 4 | 5 | import chisel3._ 6 | 7 | /** 8 | * Compute GCD using subtraction method. 9 | * Subtracts the smaller from the larger until register y is zero. 10 | * value in register x is then the GCD 11 | */ 12 | class GCD extends Module { 13 | val io = IO(new Bundle { 14 | val value1 = Input(UInt(16.W)) 15 | val value2 = Input(UInt(16.W)) 16 | val loadingValues = Input(Bool()) 17 | val outputGCD = Output(UInt(16.W)) 18 | val outputValid = Output(Bool()) 19 | }) 20 | 21 | val x = Reg(UInt()) 22 | val y = Reg(UInt()) 23 | 24 | when(x > y) { x := x - y } 25 | .otherwise { y := y - x } 26 | 27 | when(io.loadingValues) { 28 | x := io.value1 29 | y := io.value2 30 | } 31 | 32 | io.outputGCD := x 33 | io.outputValid := y === 0.U 34 | } 35 | -------------------------------------------------------------------------------- /src/test/scala/FFT/FFTTest.scala: -------------------------------------------------------------------------------- 1 | 2 | 3 | package FFT 4 | 5 | import chisel3.iotesters 6 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester} 7 | import chisel3.util._ 8 | 9 | class Complex(val re: Double, val im: Double) { 10 | def +(rhs: Complex): Complex = new Complex(re + rhs.re, im + rhs.im) 11 | def -(rhs: Complex): Complex = new Complex(re - rhs.re, im - rhs.im) 12 | def *(rhs: Complex): Complex = new Complex(re * rhs.re - im * rhs.im, rhs.re * im + re * rhs.im) 13 | //def r = re 14 | 15 | def magnitude: Double = Math.hypot(re, im) 16 | def phase: Double = Math.atan2(im, re) 17 | 18 | override def toString: String = s"Complex($re, $im)" 19 | } 20 | 21 | // only support FFT 22 | class FFTTest(c:FFT) extends PeekPokeTester(c) 23 | with HasDataConfig 24 | with HasElaborateConfig { 25 | require(!supportIFFT) 26 | def fft(x: Array[Complex]): Array[Complex] = { 27 | require(x.length > 0 && (x.length & (x.length - 1)) == 0, "array size should be power of two") 28 | fft(x, 0, x.length, 1) 29 | } 30 | 31 | def fft(x: Array[Double]): Array[Complex] = fft(x.map(re => new Complex(re, 0.0))) 32 | def rfft(x: Array[Double]): Array[Complex] = fft(x).take(x.length / 2 + 1) 33 | 34 | private def fft(x: Array[Complex], start: Int, n: Int, stride: Int) : Array[Complex] = { 35 | if (n == 1) { 36 | return Array(x(start)) 37 | } 38 | 39 | val X = fft(x, start, n / 2, 2 * stride) ++ fft(x, start + stride, n / 2, 2 * stride) 40 | 41 | for (k <- 0 until n / 2) { 42 | val t = X(k) 43 | val arg = -2 * math.Pi * k / n 44 | val c = new Complex(math.cos(arg), math.sin(arg)) * X(k + n / 2) 45 | X(k) = t + c 46 | X(k + n / 2) = t - c 47 | } 48 | X 49 | } 50 | 51 | def range(a: Int, upBound: Int, downBound: Int) : Int = { 52 | assert(upBound < 32) 53 | assert(downBound >= 0) 54 | return (a >> downBound) & (0xffffffff >>> (31 - upBound + downBound)) 55 | } 56 | 57 | def reverse(a: Int, len: Int): Int = { 58 | var res: Int = 0 59 | for(i <- 0 until len) { 60 | res = res | range(a, i, i) << (len-1-i) 61 | } 62 | res 63 | } 64 | 65 | val r = new scala.util.Random 66 | var bound: Double = math.pow(2.0, BinaryPoint) 67 | var error: Double = 0 68 | var ovNum: Int = 0 69 | var iterNum: Int = 10 70 | 71 | for (t <- 0 until iterNum) { 72 | var a = new Array[Complex](FFTLength) 73 | var cnt = 0 74 | for (i <- 0 until FFTLength) { 75 | var re = -bound.toInt / 2 + r.nextInt(bound.toInt) 76 | var im = -bound.toInt / 2 + r.nextInt(bound.toInt) 77 | a(cnt) = new Complex(2 * re / bound, 2 * im / bound) 78 | poke(c.io.dIn.re, re) 79 | poke(c.io.dIn.im, im) 80 | if (i == 0) { 81 | poke(c.io.din_valid, 1) 82 | } else { 83 | poke(c.io.din_valid, 0) 84 | } 85 | step(1) 86 | cnt += 1 87 | } 88 | var ref = fft(a) 89 | 90 | var errorOne: Double = 0 91 | var error1: Double = 0 92 | var ovNum1: Int = 0 93 | var eps: Double = 1e-9 94 | for (i <- 0 until FFTLength / 2) { 95 | var ref1 = ref(reverse(i * 2, log2Ceil(FFTLength))) 96 | var d1 = peek(c.io.dOut1) 97 | error1 = math.abs((((2 * d1("re").toDouble / bound) - ref1.re) / (ref1.re + eps) + ((2 * d1("im").toDouble / bound) - ref1.im) / (ref1.im + eps)) / 2.0) 98 | if (error1 <= 0.5) { 99 | errorOne += error1 100 | } else { 101 | ovNum1 += 1 102 | } 103 | var ref2 = ref(reverse(i * 2 + 1, log2Ceil(FFTLength))) 104 | var d2 = peek(c.io.dOut2) 105 | error1 = math.abs((((2 * d2("re").toDouble / bound) - ref2.re) / (ref2.re + eps) + ((2 * d2("im").toDouble / bound) - ref2.im) / (ref2.im + eps)) / 2.0) 106 | if (error1 <= 0.5) { 107 | errorOne += error1 108 | } else { 109 | ovNum1 += 1 110 | } 111 | step(1) 112 | } 113 | errorOne = errorOne / (FFTLength - ovNum1) 114 | ovNum += ovNum1 115 | error += errorOne 116 | var errorOnePercent = errorOne*100 117 | printf("In this sample, Error rate: %.2f%% | number of ovs: %d\n", errorOnePercent, ovNum1) 118 | } 119 | error /= iterNum 120 | print("Total error rate is: " + error*100 + "%\n") 121 | print(ovNum + " of " + iterNum * FFTLength + " overflowed! " + "The overlow ratio is " + 100 * ovNum / (FFTLength * iterNum).toDouble + "%" + "\n") 122 | } 123 | 124 | // support FFT / IFFT 125 | class FFTTest2(c:FFT) extends PeekPokeTester(c) 126 | with HasDataConfig 127 | with HasElaborateConfig { 128 | require(supportIFFT) 129 | def fft(x: Array[Complex]): Array[Complex] = { 130 | require(x.length > 0 && (x.length & (x.length - 1)) == 0, "array size should be power of two") 131 | fft(x, 0, x.length, 1) 132 | } 133 | 134 | def fft(x: Array[Double]): Array[Complex] = fft(x.map(re => new Complex(re, 0.0))) 135 | def rfft(x: Array[Double]): Array[Complex] = fft(x).take(x.length / 2 + 1) 136 | 137 | private def fft(x: Array[Complex], start: Int, n: Int, stride: Int) : Array[Complex] = { 138 | if (n == 1) { 139 | return Array(x(start)) 140 | } 141 | 142 | val X = fft(x, start, n / 2, 2 * stride) ++ fft(x, start + stride, n / 2, 2 * stride) 143 | 144 | for (k <- 0 until n / 2) { 145 | val t = X(k) 146 | val arg = -2 * math.Pi * k / n 147 | val c = new Complex(math.cos(arg), math.sin(arg)) * X(k + n / 2) 148 | X(k) = t + c 149 | X(k + n / 2) = t - c 150 | } 151 | X 152 | } 153 | 154 | def ifft(x: Array[Complex]): Array[Complex] = { 155 | val n = x.length 156 | val res = new Array[Complex](n) 157 | for (i <- 0 until n) { 158 | res(i) = new Complex(0, 0) 159 | } 160 | for (i <- 0 until n) { 161 | for (j <- 0 until n) { 162 | val arg = 2 * math.Pi * j * i / n 163 | res(i) += new Complex(math.cos(arg), math.sin(arg)) * x(j) 164 | } 165 | res(i) = new Complex(1.0 / n, 0) * res(i) 166 | } 167 | res 168 | } 169 | 170 | def range(a: Int, upBound: Int, downBound: Int) : Int = { 171 | assert(upBound < 32) 172 | assert(downBound >= 0) 173 | return (a >> downBound) & (0xffffffff >>> (31 - upBound + downBound)) 174 | } 175 | 176 | def reverse(a: Int, len: Int): Int = { 177 | var res: Int = 0 178 | for(i <- 0 until len) { 179 | res = res | range(a, i, i) << (len-1-i) 180 | } 181 | res 182 | } 183 | 184 | val r = new scala.util.Random 185 | var bound: Double = math.pow(2.0, BinaryPoint) 186 | var error: Double = 0 187 | var ovNum: Int = 0 188 | var iterNum: Int = 100 189 | 190 | for (t <- 0 until iterNum) { 191 | var a = new Array[Complex](FFTLength) 192 | var cnt = 0 193 | for (i <- 0 until FFTLength) { 194 | var re = -bound.toInt / 2 + r.nextInt(bound.toInt) 195 | var im = -bound.toInt / 2 + r.nextInt(bound.toInt) 196 | a(cnt) = new Complex(2 * re / bound, 2 * im / bound) 197 | poke(c.io.dIn.re, re) 198 | poke(c.io.dIn.im, im) 199 | poke(c.io.din_valid, 1) 200 | poke(c.io.mode.get, 0) 201 | step(1) 202 | cnt += 1 203 | } 204 | var ref = fft(a) 205 | 206 | var errorOne: Double = 0 207 | var error1: Double = 0 208 | var ovNum1: Int = 0 209 | var eps: Double = 1e-9 210 | for (i <- 0 until FFTLength / 2) { 211 | var ref1 = ref(reverse(i * 2, log2Ceil(FFTLength))) 212 | var d1 = peek(c.io.dOut1) 213 | error1 = math.abs((((2 * d1("re").toDouble / bound) - ref1.re) / (ref1.re + eps) + ((2 * d1("im").toDouble / bound) - ref1.im) / (ref1.im + eps)) / 2.0) 214 | if (error1 <= 0.5) { 215 | errorOne += error1 216 | } else { 217 | ovNum1 += 1 218 | } 219 | var ref2 = ref(reverse(i * 2 + 1, log2Ceil(FFTLength))) 220 | var d2 = peek(c.io.dOut2) 221 | error1 = math.abs((((2 * d2("re").toDouble / bound) - ref2.re) / (ref2.re + eps) + ((2 * d2("im").toDouble / bound) - ref2.im) / (ref2.im + eps)) / 2.0) 222 | if (error1 <= 0.5) { 223 | errorOne += error1 224 | } else { 225 | ovNum1 += 1 226 | } 227 | step(1) 228 | } 229 | errorOne = errorOne / (FFTLength - ovNum1) 230 | ovNum += ovNum1 231 | error += errorOne 232 | var errorOnePercent = errorOne*100 233 | printf("In this FFT sample, Error rate: %.2f%% | number of ovs: %d\n", errorOnePercent, ovNum1) 234 | } 235 | error /= iterNum 236 | print("Total error rate in FFT is: " + error*100 + "%\n") 237 | print(ovNum + " of " + iterNum * FFTLength + " overflowed! " + "The overlow ratio is " + 100 * ovNum / (FFTLength * iterNum).toDouble + "%" + "\n") 238 | 239 | 240 | error = 0 241 | ovNum = 0 242 | for (t <- 0 until iterNum) { 243 | var a = new Array[Complex](FFTLength) 244 | var cnt = 0 245 | for (i <- 0 until FFTLength) { 246 | var re = -bound.toInt / 2 + r.nextInt(bound.toInt) 247 | var im = -bound.toInt / 2 + r.nextInt(bound.toInt) 248 | a(cnt) = new Complex(2 * re / bound, 2 * im / bound) 249 | poke(c.io.dIn.re, re) 250 | poke(c.io.dIn.im, im) 251 | poke(c.io.din_valid, 1) 252 | poke(c.io.mode.get, 1) 253 | step(1) 254 | cnt += 1 255 | } 256 | var ref = ifft(a) 257 | 258 | var errorOne: Double = 0 259 | var error1: Double = 0 260 | var ovNum1: Int = 0 261 | var eps: Double = 1e-9 262 | for (i <- 0 until FFTLength / 2) { 263 | var ref1 = ref(reverse(i * 2, log2Ceil(FFTLength))) 264 | var d1 = peek(c.io.dOut1) 265 | error1 = math.abs((((2 * d1("re").toDouble / bound) - ref1.re) / (ref1.re + eps) + ((2 * d1("im").toDouble / bound) - ref1.im) / (ref1.im + eps)) / 2.0) 266 | if (error1 <= 0.5) { 267 | errorOne += error1 268 | } else { 269 | ovNum1 += 1 270 | } 271 | var ref2 = ref(reverse(i * 2 + 1, log2Ceil(FFTLength))) 272 | var d2 = peek(c.io.dOut2) 273 | error1 = math.abs((((2 * d2("re").toDouble / bound) - ref2.re) / (ref2.re + eps) + ((2 * d2("im").toDouble / bound) - ref2.im) / (ref2.im + eps)) / 2.0) 274 | if (error1 <= 0.5) { 275 | errorOne += error1 276 | } else { 277 | ovNum1 += 1 278 | } 279 | step(1) 280 | } 281 | errorOne = errorOne / (FFTLength - ovNum1) 282 | ovNum += ovNum1 283 | error += errorOne 284 | var errorOnePercent = errorOne*100 285 | printf("In this IFFT sample, Error rate: %.2f%% | number of ovs: %d\n", errorOnePercent, ovNum1) 286 | } 287 | error /= iterNum 288 | print("Total error rate in IFFT is: " + error*100 + "%\n") 289 | print(ovNum + " of " + iterNum * FFTLength + " overflowed! " + "The overlow ratio is " + 100 * ovNum / (FFTLength * iterNum).toDouble + "%" + "\n") 290 | } 291 | 292 | // only support FFTtop 293 | class FFTTest3(c:FFTReorder) extends PeekPokeTester(c) 294 | with HasDataConfig 295 | with HasElaborateConfig { 296 | require(!supportIFFT) 297 | def fft(x: Array[Complex]): Array[Complex] = { 298 | require(x.length > 0 && (x.length & (x.length - 1)) == 0, "array size should be power of two") 299 | fft(x, 0, x.length, 1) 300 | } 301 | 302 | def fft(x: Array[Double]): Array[Complex] = fft(x.map(re => new Complex(re, 0.0))) 303 | def rfft(x: Array[Double]): Array[Complex] = fft(x).take(x.length / 2 + 1) 304 | 305 | private def fft(x: Array[Complex], start: Int, n: Int, stride: Int) : Array[Complex] = { 306 | if (n == 1) { 307 | return Array(x(start)) 308 | } 309 | 310 | val X = fft(x, start, n / 2, 2 * stride) ++ fft(x, start + stride, n / 2, 2 * stride) 311 | 312 | for (k <- 0 until n / 2) { 313 | val t = X(k) 314 | val arg = -2 * math.Pi * k / n 315 | val c = new Complex(math.cos(arg), math.sin(arg)) * X(k + n / 2) 316 | X(k) = t + c 317 | X(k + n / 2) = t - c 318 | } 319 | X 320 | } 321 | 322 | def range(a: Int, upBound: Int, downBound: Int) : Int = { 323 | assert(upBound < 32) 324 | assert(downBound >= 0) 325 | return (a >> downBound) & (0xffffffff >>> (31 - upBound + downBound)) 326 | } 327 | 328 | def reverse(a: Int, len: Int): Int = { 329 | var res: Int = 0 330 | for(i <- 0 until len) { 331 | res = res | range(a, i, i) << (len-1-i) 332 | } 333 | res 334 | } 335 | 336 | val r = new scala.util.Random 337 | var bound: Double = math.pow(2.0, BinaryPoint) 338 | var error: Double = 0 339 | var ovNum: Int = 0 340 | var iterNum: Int = 10 341 | 342 | for (t <- 0 until iterNum) { 343 | var a = new Array[Complex](FFTLength) 344 | var cnt = 0 345 | for (i <- 0 until FFTLength) { 346 | var re = -bound.toInt / 2 + r.nextInt(bound.toInt) 347 | var im = -bound.toInt / 2 + r.nextInt(bound.toInt) 348 | a(cnt) = new Complex(2 * re / bound, 2 * im / bound) 349 | poke(c.io.dIn.re, re) 350 | poke(c.io.dIn.im, im) 351 | if (i == 0) { 352 | poke(c.io.din_valid, 1) 353 | } else { 354 | poke(c.io.din_valid, 0) 355 | } 356 | step(1) 357 | cnt += 1 358 | } 359 | var ref = fft(a) 360 | 361 | var errorOne: Double = 0 362 | var error1: Double = 0 363 | var ovNum1: Int = 0 364 | var eps: Double = 1e-9 365 | step(FFTLength / 2) 366 | for (i <- 0 until FFTLength) { 367 | var ref1 = ref(i) 368 | var d1 = peek(c.io.dOut) 369 | error1 = math.abs((((2 * d1("re").toDouble / bound) - ref1.re) / (ref1.re + eps) + ((2 * d1("im").toDouble / bound) - ref1.im) / (ref1.im + eps)) / 2.0) 370 | if (error1 <= 0.5) { 371 | errorOne += error1 372 | } else { 373 | ovNum1 += 1 374 | } 375 | step(1) 376 | } 377 | errorOne = errorOne / (FFTLength - ovNum1) 378 | ovNum += ovNum1 379 | error += errorOne 380 | var errorOnePercent = errorOne * 100 381 | printf("In this sample, Error rate: %.2f%% | number of ovs: %d\n", errorOnePercent, ovNum1) 382 | } 383 | } 384 | 385 | class FFTTest4(c:TOP) extends PeekPokeTester(c) 386 | with HasDataConfig 387 | with HasElaborateConfig { 388 | require(!supportIFFT) 389 | def fft(x: Array[Complex]): Array[Complex] = { 390 | require(x.length > 0 && (x.length & (x.length - 1)) == 0, "array size should be power of two") 391 | fft(x, 0, x.length, 1) 392 | } 393 | 394 | def fft(x: Array[Double]): Array[Complex] = fft(x.map(re => new Complex(re, 0.0))) 395 | def rfft(x: Array[Double]): Array[Complex] = fft(x).take(x.length / 2 + 1) 396 | 397 | private def fft(x: Array[Complex], start: Int, n: Int, stride: Int) : Array[Complex] = { 398 | if (n == 1) { 399 | return Array(x(start)) 400 | } 401 | 402 | val X = fft(x, start, n / 2, 2 * stride) ++ fft(x, start + stride, n / 2, 2 * stride) 403 | 404 | for (k <- 0 until n / 2) { 405 | val t = X(k) 406 | val arg = -2 * math.Pi * k / n 407 | val c = new Complex(math.cos(arg), math.sin(arg)) * X(k + n / 2) 408 | X(k) = t + c 409 | X(k + n / 2) = t - c 410 | } 411 | X 412 | } 413 | 414 | def range(a: Int, upBound: Int, downBound: Int) : Int = { 415 | assert(upBound < 32) 416 | assert(downBound >= 0) 417 | return (a >> downBound) & (0xffffffff >>> (31 - upBound + downBound)) 418 | } 419 | 420 | def reverse(a: Int, len: Int): Int = { 421 | var res: Int = 0 422 | for(i <- 0 until len) { 423 | res = res | range(a, i, i) << (len-1-i) 424 | } 425 | res 426 | } 427 | 428 | val r = new scala.util.Random 429 | var bound: Double = math.pow(2.0, BinaryPoint) 430 | var error: Double = 0 431 | var ovNum: Int = 0 432 | var iterNum: Int = 5 433 | 434 | for (t <- 0 until iterNum) { 435 | var a = new Array[Complex](FFTLength) 436 | var cnt = 0 437 | poke(c.io.dout.ready, 1) 438 | for (i <- 0 until FFTLength) { 439 | var re = -bound.toInt / 2 + r.nextInt(bound.toInt) 440 | var im = -bound.toInt / 2 + r.nextInt(bound.toInt) 441 | a(cnt) = new Complex(2 * re / bound, 2 * im / bound) 442 | poke(c.io.din.bits.re, re) 443 | poke(c.io.din.bits.im, im) 444 | if (i == 0) { 445 | poke(c.io.din.valid, 1) 446 | } else { 447 | poke(c.io.din.valid, 0) 448 | } 449 | step(1) 450 | cnt += 1 451 | } 452 | var ref = fft(a) 453 | 454 | var errorOne: Double = 0 455 | var error1: Double = 0 456 | var ovNum1: Int = 0 457 | var eps: Double = 1e-9 458 | step(FFTLength / 2 + 1) 459 | for (i <- 0 until FFTLength) { 460 | var ref1 = ref(i) 461 | var d1 = peek(c.io.dout.bits) 462 | error1 = math.abs((((2 * d1("re").toDouble / bound) - ref1.re) / (ref1.re + eps) + ((2 * d1("im").toDouble / bound) - ref1.im) / (ref1.im + eps)) / 2.0) 463 | if (error1 <= 0.5) { 464 | errorOne += error1 465 | } else { 466 | ovNum1 += 1 467 | } 468 | step(1) 469 | } 470 | errorOne = errorOne / (FFTLength - ovNum1) 471 | ovNum += ovNum1 472 | error += errorOne 473 | var errorOnePercent = errorOne * 100 474 | printf("In this sample, Error rate: %.2f%% | number of ovs: %d\n", errorOnePercent, ovNum1) 475 | } 476 | } 477 | 478 | object FFTTestMain extends App { 479 | iotesters.Driver.execute(args, () => new FFT) { 480 | c => new FFTTest(c) 481 | } 482 | } 483 | object FFTTestMain2 extends App { 484 | iotesters.Driver.execute(args, () => new FFT) { 485 | c => new FFTTest2(c) 486 | } 487 | } 488 | object FFTTestMain3 extends App { 489 | iotesters.Driver.execute(args, () => new FFTReorder) { 490 | c => new FFTTest3(c) 491 | } 492 | } 493 | 494 | object FFTTestMain4 extends App { 495 | iotesters.Driver.execute(args, () => new TOP) { 496 | c => new FFTTest4(c) 497 | } 498 | } 499 | -------------------------------------------------------------------------------- /src/test/scala/gcd/GCDMain.scala: -------------------------------------------------------------------------------- 1 | // See README.md for license details. 2 | 3 | package gcd 4 | 5 | import chisel3._ 6 | 7 | /** 8 | * This provides an alternate way to run tests, by executing then as a main 9 | * From sbt (Note: the test: prefix is because this main is under the test package hierarchy): 10 | * {{{ 11 | * test:runMain gcd.GCDMain 12 | * }}} 13 | * To see all command line options use: 14 | * {{{ 15 | * test:runMain gcd.GCDMain --help 16 | * }}} 17 | * To run with verilator: 18 | * {{{ 19 | * test:runMain gcd.GCDMain --backend-name verilator 20 | * }}} 21 | * To run with verilator from your terminal shell use: 22 | * {{{ 23 | * sbt 'test:runMain gcd.GCDMain --backend-name verilator' 24 | * }}} 25 | */ 26 | object GCDMain extends App { 27 | iotesters.Driver.execute(args, () => new GCD) { 28 | c => new GCDUnitTester(c) 29 | } 30 | } 31 | 32 | /** 33 | * This provides a way to run the firrtl-interpreter REPL (or shell) 34 | * on the lowered firrtl generated by your circuit. You will be placed 35 | * in an interactive shell. This can be very helpful as a debugging 36 | * technique. Type help to see a list of commands. 37 | * 38 | * To run from sbt 39 | * {{{ 40 | * test:runMain gcd.GCDRepl 41 | * }}} 42 | * To run from sbt and see the half a zillion options try 43 | * {{{ 44 | * test:runMain gcd.GCDRepl --help 45 | * }}} 46 | */ 47 | object GCDRepl extends App { 48 | iotesters.Driver.executeFirrtlRepl(args, () => new GCD) 49 | } -------------------------------------------------------------------------------- /src/test/scala/gcd/GCDUnitTest.scala: -------------------------------------------------------------------------------- 1 | // See README.md for license details. 2 | 3 | package gcd 4 | 5 | import java.io.File 6 | 7 | import chisel3.iotesters 8 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester} 9 | 10 | class GCDUnitTester(c: GCD) extends PeekPokeTester(c) { 11 | /** 12 | * compute the gcd and the number of steps it should take to do it 13 | * 14 | * @param a positive integer 15 | * @param b positive integer 16 | * @return the GCD of a and b 17 | */ 18 | def computeGcd(a: Int, b: Int): (Int, Int) = { 19 | var x = a 20 | var y = b 21 | var depth = 1 22 | while(y > 0 ) { 23 | if (x > y) { 24 | x -= y 25 | } 26 | else { 27 | y -= x 28 | } 29 | depth += 1 30 | } 31 | (x, depth) 32 | } 33 | 34 | private val gcd = c 35 | 36 | for(i <- 1 to 40 by 3) { 37 | for (j <- 1 to 40 by 7) { 38 | poke(gcd.io.value1, i) 39 | poke(gcd.io.value2, j) 40 | poke(gcd.io.loadingValues, 1) 41 | step(1) 42 | poke(gcd.io.loadingValues, 0) 43 | 44 | val (expected_gcd, steps) = computeGcd(i, j) 45 | 46 | step(steps - 1) // -1 is because we step(1) already to toggle the enable 47 | expect(gcd.io.outputGCD, expected_gcd) 48 | expect(gcd.io.outputValid, 1) 49 | } 50 | } 51 | } 52 | 53 | /** 54 | * This is a trivial example of how to run this Specification 55 | * From within sbt use: 56 | * {{{ 57 | * testOnly gcd.GCDTester 58 | * }}} 59 | * From a terminal shell use: 60 | * {{{ 61 | * sbt 'testOnly gcd.GCDTester' 62 | * }}} 63 | */ 64 | class GCDTester extends ChiselFlatSpec { 65 | // Disable this until we fix isCommandAvailable to swallow stderr along with stdout 66 | private val backendNames = if(firrtl.FileUtils.isCommandAvailable(Seq("verilator", "--version"))) { 67 | Array("firrtl", "verilator") 68 | } 69 | else { 70 | Array("firrtl") 71 | } 72 | for ( backendName <- backendNames ) { 73 | "GCD" should s"calculate proper greatest common denominator (with $backendName)" in { 74 | Driver(() => new GCD, backendName) { 75 | c => new GCDUnitTester(c) 76 | } should be (true) 77 | } 78 | } 79 | 80 | "Basic test using Driver.execute" should "be used as an alternative way to run specification" in { 81 | iotesters.Driver.execute(Array(), () => new GCD) { 82 | c => new GCDUnitTester(c) 83 | } should be (true) 84 | } 85 | 86 | if(backendNames.contains("verilator")) { 87 | "using --backend-name verilator" should "be an alternative way to run using verilator" in { 88 | iotesters.Driver.execute(Array("--backend-name", "verilator"), () => new GCD) { 89 | c => new GCDUnitTester(c) 90 | } should be(true) 91 | } 92 | } 93 | 94 | "running with --is-verbose" should "show more about what's going on in your tester" in { 95 | iotesters.Driver.execute(Array("--is-verbose"), () => new GCD) { 96 | c => new GCDUnitTester(c) 97 | } should be(true) 98 | } 99 | 100 | /** 101 | * By default verilator backend produces vcd file, and firrtl and treadle backends do not. 102 | * Following examples show you how to turn on vcd for firrtl and treadle and how to turn it off for verilator 103 | */ 104 | 105 | "running with --generate-vcd-output on" should "create a vcd file from your test" in { 106 | iotesters.Driver.execute( 107 | Array("--generate-vcd-output", "on", "--target-dir", "test_run_dir/make_a_vcd", "--top-name", "make_a_vcd"), 108 | () => new GCD 109 | ) { 110 | 111 | c => new GCDUnitTester(c) 112 | } should be(true) 113 | 114 | new File("test_run_dir/make_a_vcd/make_a_vcd.vcd").exists should be (true) 115 | } 116 | 117 | "running with --generate-vcd-output off" should "not create a vcd file from your test" in { 118 | iotesters.Driver.execute( 119 | Array("--generate-vcd-output", "off", "--target-dir", "test_run_dir/make_no_vcd", "--top-name", "make_no_vcd", 120 | "--backend-name", "verilator"), 121 | () => new GCD 122 | ) { 123 | 124 | c => new GCDUnitTester(c) 125 | } should be(true) 126 | 127 | new File("test_run_dir/make_no_vcd/make_a_vcd.vcd").exists should be (false) 128 | 129 | } 130 | 131 | } 132 | --------------------------------------------------------------------------------