├── README.md ├── dist ├── Assets │ └── superbreakout │ │ └── common │ │ └── .keep ├── Cores │ └── ericlewis.SuperBreakout │ │ ├── audio.json │ │ ├── bitstream.rbf_r │ │ ├── core.json │ │ ├── data.json │ │ ├── icon.bin │ │ ├── input.json │ │ ├── interact.json │ │ ├── variants.json │ │ └── video.json └── Platforms │ ├── _images │ └── superbreakout.bin │ └── superbreakout.json ├── mra └── Super Breakout (Rev 04).mra └── src └── fpga ├── .gitignore ├── ap_core.qpf ├── ap_core.qsf ├── ap_core_assignment_defaults.qdf ├── apf ├── apf.qip ├── apf_constraints.sdc ├── apf_top.v ├── build_id.mif ├── build_id_gen.tcl ├── common.v ├── io_bridge_peripheral.v ├── io_pad_controller.v ├── mf_datatable.qip ├── mf_datatable.v ├── mf_ddio_bidir_12.ppf ├── mf_ddio_bidir_12.qip └── mf_ddio_bidir_12.v ├── core ├── core_bridge_cmd.v ├── core_constraints.sdc ├── core_top.v ├── data_loader.sv ├── mf_pllbase.bsf ├── mf_pllbase.ppf ├── mf_pllbase.qip ├── mf_pllbase.sip ├── mf_pllbase.spd ├── mf_pllbase.v ├── mf_pllbase │ ├── mf_pllbase_0002.qip │ └── mf_pllbase_0002.v ├── mf_pllbase_sim.f ├── mf_pllbase_sim │ ├── aldec │ │ └── rivierapro_setup.tcl │ ├── cadence │ │ ├── cds.lib │ │ ├── hdl.var │ │ └── ncsim_setup.sh │ ├── mentor │ │ └── msim_setup.tcl │ ├── mf_pllbase.vo │ └── synopsys │ │ ├── vcs │ │ └── vcs_setup.sh │ │ └── vcsmx │ │ ├── synopsys_sim.setup │ │ └── vcsmx_setup.sh ├── pin_ddio_clk.ppf ├── pin_ddio_clk.qip ├── pin_ddio_clk.v ├── rtl │ ├── IO.vhd │ ├── K6_PROM.vhd │ ├── T65 │ │ ├── T65.vhd │ │ ├── T65_ALU.vhd │ │ ├── T65_MCode.vhd │ │ ├── T65_Pack.vhd │ │ └── t65.qip │ ├── audio.vhd │ ├── cpu_mem.vhd │ ├── deltasigma.vhd │ ├── dpram.vhd │ ├── joy2quad.sv │ ├── motion.vhd │ ├── paddle.vhd │ ├── paddle_analog.vhd │ ├── playfield.vhd │ ├── quadrature_decoder.vhd │ ├── super_breakout.vhd │ └── sync.vhd └── stp1.stp └── output_files ├── .gitignore ├── ap_core.jdi ├── ap_core.rbf ├── ap_core.sof ├── bitstream.rbf_r ├── reverse_bits.exe └── run.bat /README.md: -------------------------------------------------------------------------------- 1 | # Super Breakout for Analogue Pocket 2 | 3 | + FPGA implementation by james10952001 of Arcade _Super Breakout_ (Atari, 1978) for Analogue Pocket. 4 | + Ported from [MiSTer.](https://github.com/MiSTer-devel/Arcade-SuperBreakout_MiSTer/) 5 | + Multiplayer support via dock. 6 | 7 | ## Known Issues 8 | 9 | + Double / Progressive modes not implemented. 10 | + Audio is probably not quite right. 11 | 12 | ## ROM Instructions 13 | 14 | ROM files are not included, you must use [mra-tools-c](https://github.com/sebdel/mra-tools-c/) to convert to a singular `sbrkout.rom` file, then place the ROM file in `/Assets/superbreakout/common`. -------------------------------------------------------------------------------- /dist/Assets/superbreakout/common/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericlewis/openfpga-superbreakout/d4e70e5cc7748c2e1db8ed39aba373d97f7b33e7/dist/Assets/superbreakout/common/.keep -------------------------------------------------------------------------------- /dist/Cores/ericlewis.SuperBreakout/audio.json: -------------------------------------------------------------------------------- 1 | { 2 | "audio": { 3 | "magic": "APF_VER_1" 4 | } 5 | } -------------------------------------------------------------------------------- /dist/Cores/ericlewis.SuperBreakout/bitstream.rbf_r: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericlewis/openfpga-superbreakout/d4e70e5cc7748c2e1db8ed39aba373d97f7b33e7/dist/Cores/ericlewis.SuperBreakout/bitstream.rbf_r -------------------------------------------------------------------------------- /dist/Cores/ericlewis.SuperBreakout/core.json: -------------------------------------------------------------------------------- 1 | { 2 | "core": { 3 | "magic": "APF_VER_1", 4 | "metadata": { 5 | "platform_ids": ["superbreakout"], 6 | "shortname": "SuperBreakout", 7 | "description": "Atari's Super Breakout released in 1978.", 8 | "author": "ericlewis", 9 | "url": "https://github.com/ericlewis/openfpga-superbreakout", 10 | "version": "0.0.1", 11 | "date_release": "2022-09-14" 12 | }, 13 | "framework": { 14 | "target_product": "Analogue Pocket", 15 | "version_required": "1.1", 16 | "sleep_supported": false, 17 | "dock": { 18 | "supported": true, 19 | "analog_output": false 20 | }, 21 | "hardware": { 22 | "link_port": false, 23 | "cartridge_adapter": -1 24 | } 25 | }, 26 | "cores": [ 27 | { 28 | "name": "default", 29 | "id": 0, 30 | "filename": "bitstream.rbf_r" 31 | } 32 | ] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /dist/Cores/ericlewis.SuperBreakout/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "magic": "APF_VER_1", 4 | "data_slots": [ 5 | { 6 | "name": "ROM", 7 | "required": true, 8 | "parameters": 8, 9 | "filename": "sbrkout.rom", 10 | "address": "0x00000000" 11 | } 12 | ] 13 | } 14 | } -------------------------------------------------------------------------------- /dist/Cores/ericlewis.SuperBreakout/icon.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericlewis/openfpga-superbreakout/d4e70e5cc7748c2e1db8ed39aba373d97f7b33e7/dist/Cores/ericlewis.SuperBreakout/icon.bin -------------------------------------------------------------------------------- /dist/Cores/ericlewis.SuperBreakout/input.json: -------------------------------------------------------------------------------- 1 | { 2 | "input": { 3 | "magic": "APF_VER_1", 4 | "controllers": [ 5 | { 6 | "type": "default", 7 | "mappings": [ 8 | { 9 | "id": 0, 10 | "name": "Serve", 11 | "key": "pad_btn_a" 12 | }, 13 | { 14 | "id": 1, 15 | "name": "Insert Coin", 16 | "key": "pad_trig_r" 17 | }, 18 | { 19 | "id": 2, 20 | "name": "Start", 21 | "key": "pad_btn_start" 22 | } 23 | ] 24 | } 25 | ] 26 | } 27 | } -------------------------------------------------------------------------------- /dist/Cores/ericlewis.SuperBreakout/interact.json: -------------------------------------------------------------------------------- 1 | { 2 | "interact": { 3 | "magic": "APF_VER_1", 4 | "variables": [], 5 | "messages": [] 6 | } 7 | } -------------------------------------------------------------------------------- /dist/Cores/ericlewis.SuperBreakout/variants.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "magic": "APF_VER_1", 4 | "variant_list": [] 5 | } 6 | } -------------------------------------------------------------------------------- /dist/Cores/ericlewis.SuperBreakout/video.json: -------------------------------------------------------------------------------- 1 | { 2 | "video": { 3 | "magic": "APF_VER_1", 4 | "scaler_modes": [ 5 | { 6 | "width": 256, 7 | "height": 224, 8 | "aspect_w": 8, 9 | "aspect_h": 7, 10 | "rotation": 270, 11 | "mirror": 0 12 | } 13 | ] 14 | } 15 | } -------------------------------------------------------------------------------- /dist/Platforms/_images/superbreakout.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericlewis/openfpga-superbreakout/d4e70e5cc7748c2e1db8ed39aba373d97f7b33e7/dist/Platforms/_images/superbreakout.bin -------------------------------------------------------------------------------- /dist/Platforms/superbreakout.json: -------------------------------------------------------------------------------- 1 | { 2 | "platform": { 3 | "category": "Arcade", 4 | "name": "Super Breakout", 5 | "year": 1978, 6 | "manufacturer": "Atari" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /mra/Super Breakout (Rev 04).mra: -------------------------------------------------------------------------------- 1 | 2 | Super Breakout 3 | 4 | no 5 | no 6 | Rev 04 7 | 8 | 9 | Breakout 10 | 1978 11 | Atari 12 | Ball and Paddle 13 | 14 | sbrkout 15 | sbrkout 16 | 0220 17 | superbreakout 18 | 19 | 20 | 15kHz 21 | vertical (ccw) 22 | no 23 | 24 | 1 25 | 26 | spinner 27 | 1 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 20210430005030 52 | 53 | -------------------------------------------------------------------------------- /src/fpga/.gitignore: -------------------------------------------------------------------------------- 1 | */db/ 2 | */incremental_db/ 3 | */simulation/ 4 | */greybox_tmp/ 5 | incremental_db/ 6 | db/ 7 | PLLJ_PLLSPE_INFO.txt 8 | c5_pin_model_dump.txt 9 | cr_ie_info.json 10 | *.pin 11 | *.pof 12 | *.ptf.* 13 | *.qar 14 | *.qarlog 15 | *.qws 16 | *.rpt 17 | *.smsg 18 | *.sof 19 | *.sopc_builder 20 | *.summary 21 | *.txt 22 | *.bak 23 | *.cmp 24 | *.done 25 | *.xml 26 | *.sld 27 | *.cdf 28 | 29 | -------------------------------------------------------------------------------- /src/fpga/ap_core.qpf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- # 2 | # 3 | # Copyright (C) 2019 Intel Corporation. All rights reserved. 4 | # Your use of Intel Corporation's design tools, logic functions 5 | # and other software and tools, and any partner logic 6 | # functions, and any output files from any of the foregoing 7 | # (including device programming or simulation files), and any 8 | # associated documentation or information are expressly subject 9 | # to the terms and conditions of the Intel Program License 10 | # Subscription Agreement, the Intel Quartus Prime License Agreement, 11 | # the Intel FPGA IP License Agreement, or other applicable license 12 | # agreement, including, without limitation, that your use is for 13 | # the sole purpose of programming logic devices manufactured by 14 | # Intel and sold by Intel or its authorized distributors. Please 15 | # refer to the applicable agreement for further details, at 16 | # https://fpgasoftware.intel.com/eula. 17 | # 18 | # -------------------------------------------------------------------------- # 19 | # 20 | # Quartus Prime 21 | # Version 18.1.1 Build 646 04/11/2019 SJ Lite Edition 22 | # Date created = 21:31:36 January 22, 2020 23 | # 24 | # -------------------------------------------------------------------------- # 25 | 26 | QUARTUS_VERSION = "18.1" 27 | DATE = "21:31:36 January 22, 2020" 28 | 29 | # Revisions 30 | 31 | PROJECT_REVISION = "ap_core" 32 | -------------------------------------------------------------------------------- /src/fpga/apf/apf.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "apf_top.v"] 2 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "common.v"] 3 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "io_bridge_peripheral.v"] 4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "io_pad_controller.v"] 5 | set_global_assignment -name SDC_FILE [file join $::quartus(qip_path) "apf_constraints.sdc"] 6 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "mf_ddio_bidir_12.qip"] 7 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "mf_datatable.qip"] 8 | -------------------------------------------------------------------------------- /src/fpga/apf/apf_constraints.sdc: -------------------------------------------------------------------------------- 1 | # 2 | # APF constraints 3 | # Do not edit this file. 4 | # 5 | # Add your own constraints in the \core_constraints.sdc in the core directory, which will also be loaded. 6 | 7 | create_clock -name clk_74a -period 13.468 [get_ports clk_74a] 8 | create_clock -name clk_74b -period 13.468 [get_ports clk_74b] 9 | create_clock -name bridge_spiclk -period 13.468 [get_ports bridge_spiclk] 10 | 11 | # autogenerate PLL clock names for use down below 12 | derive_pll_clocks 13 | 14 | 15 | # io constraints go here 16 | # 17 | 18 | 19 | # load in user constraints 20 | read_sdc "core/core_constraints.sdc" -------------------------------------------------------------------------------- /src/fpga/apf/build_id.mif: -------------------------------------------------------------------------------- 1 | -- Build ID Memory Initialization File 2 | -- 3 | 4 | DEPTH = 256; 5 | WIDTH = 32; 6 | ADDRESS_RADIX = HEX; 7 | DATA_RADIX = HEX; 8 | 9 | CONTENT 10 | BEGIN 11 | 12 | 0E0 : 20220916; 13 | 0E1 : 00140352; 14 | 0E2 : 50a677ea; 15 | 16 | END; 17 | -------------------------------------------------------------------------------- /src/fpga/apf/build_id_gen.tcl: -------------------------------------------------------------------------------- 1 | # ================================================================================ 2 | # (c) 2011 Altera Corporation. All rights reserved. 3 | # Altera products are protected under numerous U.S. and foreign patents, maskwork 4 | # rights, copyrights and other intellectual property laws. 5 | # 6 | # This reference design file, and your use thereof, is subject to and governed 7 | # by the terms and conditions of the applicable Altera Reference Design License 8 | # Agreement (either as signed by you, agreed by you upon download or as a 9 | # "click-through" agreement upon installation andor found at www.altera.com). 10 | # By using this reference design file, you indicate your acceptance of such terms 11 | # and conditions between you and Altera Corporation. In the event that you do 12 | # not agree with such terms and conditions, you may not use the reference design 13 | # file and please promptly destroy any copies you have made. 14 | # 15 | # This reference design file is being provided on an "as-is" basis and as an 16 | # accommodation and therefore all warranties, representations or guarantees of 17 | # any kind (whether express, implied or statutory) including, without limitation, 18 | # warranties of merchantability, non-infringement, or fitness for a particular 19 | # purpose, are specifically disclaimed. By making this reference design file 20 | # available, Altera expressly does not recommend, suggest or require that this 21 | # reference design file be used in combination with any other product not 22 | # provided by Altera. 23 | # ================================================================================ 24 | # 25 | # Build ID Verilog Module Script 26 | # Jeff Wiencrot - 8/1/2011 27 | # 28 | # Generates a Verilog module that contains a timestamp, physical address, and host name 29 | # from the current build. These values are available from the build_date, build_time, 30 | # physical_address, and host_name output ports of the build_id module in the build_id.v 31 | # Verilog source file. 32 | # 33 | # The format for each value is as follows: 34 | # Date - 32-bit decimal number of the format mmddyyyy 35 | # Time - 32-bit decimal number of the format hhmmss 36 | # Phyiscal Address - 48-bit hexadecimal number 37 | # Host name - 120-bit hexadecimal number with pairs of digits equal to the 38 | # hexadecimal code for the first 15 ASCII characters of the host 39 | # name. For added clarity, host names that have fewer than 30 40 | # hexadecimal digits (15 characters) are padded on the left with 41 | # zeros. 42 | # 43 | # Usage: 44 | # 45 | # To manually execute this script, source this file using the following Tcl commands: 46 | # source build_id_verilog.tcl 47 | # 48 | # To have this script automatically execute each time your project is built, use the 49 | # following command (see: http://www.altera.com/support/examples/tcl/auto_processing.html): 50 | # set_global_assignment -name PRE_FLOW_SCRIPT_FILE quartus_sh:build_id_verilog.tcl 51 | # 52 | # Comment out the last line to prevent the process from automatically executing when 53 | # the file is sourced. The process can then be executed with the following command: 54 | # generateBuildID_Verilog 55 | # 56 | # 57 | # For more information, see "build_identification.pdf" 58 | # 59 | # ================================================================================ 60 | # 61 | # 2021-01-21 Analogue 62 | # 63 | # Only care about generating build date/time, so the rest was removed. 64 | # The original can be downloaded from the Intel resource page 65 | # 66 | 67 | proc generateBuildID_Verilog {} { 68 | 69 | # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) 70 | set buildDate [ clock format [ clock seconds ] -format %Y%m%d ] 71 | set buildTime [ clock format [ clock seconds ] -format %H%M%S ] 72 | 73 | # Create a Verilog file for output 74 | set outputFileName "apf/build_id.v" 75 | set outputFile [open $outputFileName "w"] 76 | 77 | # Output the Verilog source 78 | puts $outputFile "// Build ID Verilog Module" 79 | puts $outputFile "//" 80 | puts $outputFile "// Note - these are stored as binary coded decimal" 81 | puts $outputFile "// Date: $buildDate" 82 | puts $outputFile "// Time: $buildTime" 83 | puts $outputFile "" 84 | puts $outputFile "module build_id" 85 | puts $outputFile "(" 86 | puts $outputFile " output \[31:0\] build_date," 87 | puts $outputFile " output \[31:0\] build_time" 88 | puts $outputFile ");" 89 | puts $outputFile "" 90 | puts $outputFile " assign build_date = 32'h$buildDate;" 91 | puts $outputFile " assign build_time = 32'h$buildTime;" 92 | puts $outputFile "" 93 | puts $outputFile "endmodule" 94 | close $outputFile 95 | 96 | 97 | 98 | # Send confirmation message to the Messages window 99 | #post_message "APF core build date/time generated: [pwd]/$outputFileName" 100 | #post_message "Date: $buildDate" 101 | #post_message "Time: $buildTime" 102 | } 103 | 104 | 105 | proc generateBuildID_MIF {} { 106 | 107 | # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) 108 | set buildDate [ clock format [ clock seconds ] -format %Y%m%d ] 109 | set buildTime [ clock format [ clock seconds ] -format %H%M%S ] 110 | set buildUnique [expr {int(rand()*(4294967295))}] 111 | 112 | set buildDateNoLeadingZeros [string trimleft $buildDate "0"] 113 | set buildTimeNoLeadingZeros [string trimleft $buildTime "0"] 114 | set buildDate4Byte [format "%08d" $buildDateNoLeadingZeros] 115 | set buildTime4Byte [format "%08d" $buildTimeNoLeadingZeros] 116 | set buildUnique4Byte [format "%08x" $buildUnique] 117 | 118 | #set buildDate4Byte \ 119 | [concat [string range $buildDate 0 1] \ 120 | [string range $buildDate 2 3] \ 121 | [string range $buildDate 4 5] \ 122 | [string range $buildDate 6 7] ] 123 | 124 | 125 | set buildDateNumBytes 4 126 | set buildTimeNumBytes 4 127 | 128 | # Calculate depth of the memory (8-bit) words 129 | set memoryDepth [expr $buildDateNumBytes + $buildTimeNumBytes] 130 | 131 | # Create a Memory Initialization File for output 132 | set outputFileName "apf/build_id.mif" 133 | set outputFile [open $outputFileName "w"] 134 | 135 | # Output the MIF header (see: http://quartushelp.altera.com/current/mergedProjects/reference/glossary/def_mif.htm) 136 | puts $outputFile "-- Build ID Memory Initialization File" 137 | puts $outputFile "--" 138 | puts $outputFile "" 139 | puts $outputFile "DEPTH = 256;" 140 | puts $outputFile "WIDTH = 32;" 141 | puts $outputFile "ADDRESS_RADIX = HEX;" 142 | puts $outputFile "DATA_RADIX = HEX;" 143 | puts $outputFile "" 144 | puts $outputFile "CONTENT" 145 | puts $outputFile "BEGIN" 146 | puts $outputFile "" 147 | puts $outputFile " 0E0 : $buildDate4Byte;" 148 | puts $outputFile " 0E1 : $buildTime4Byte;" 149 | puts $outputFile " 0E2 : $buildUnique4Byte;" 150 | puts $outputFile "" 151 | puts $outputFile "END;" 152 | 153 | # Close file to complete write 154 | close $outputFile 155 | 156 | # Send confirmation message to the Messages window 157 | post_message "APF core build date/time generated: [pwd]/$outputFileName" 158 | } 159 | 160 | generateBuildID_MIF 161 | 162 | # 2021-01-21 Analogue 163 | # 164 | # There are some circumstances where you want all parts of a FPGA flow to be deterministic, especially 165 | # when trying to hash out timing issues. 166 | # You should comment this line out and temporarily bypass buildid generation so that synthesis/par 167 | # have consistent working input. MIF bram contents like above won't affect the random seed or trigger 168 | # recompilation. 169 | # Don't forget to re-enable before you release. 170 | # 171 | # generateBuildID_Verilog 172 | -------------------------------------------------------------------------------- /src/fpga/apf/common.v: -------------------------------------------------------------------------------- 1 | // Software License Agreement 2 | 3 | // The software supplied herewith by Analogue Enterprises Limited (the "Company”), 4 | // the Analogue Pocket Framework (“APF”), is provided and licensed to you, the 5 | // Company's customer, solely for use in designing, testing and creating 6 | // applications for use with Company's Products or Services. The software is 7 | // owned by the Company and/or its licensors, and is protected under applicable 8 | // laws, including, but not limited to, U.S. copyright law. All rights are 9 | // reserved. By using the APF code you are agreeing to the terms of the End User 10 | // License Agreement (“EULA”) located at [https://www.analogue.link/pocket-eula] 11 | // and incorporated herein by reference. To the extent any use of the APF requires 12 | // application of the MIT License or the GNU General Public License and terms of 13 | // this APF Software License Agreement and EULA are inconsistent with such license, 14 | // the applicable terms of the MIT License or the GNU General Public License, as 15 | // applicable, will prevail. 16 | 17 | // THE SOFTWARE IS PROVIDED "AS-IS" AND WE EXPRESSLY DISCLAIM ANY IMPLIED 18 | // WARRANTIES TO THE FULLEST EXTENT PROVIDED BY LAW, INCLUDING BUT NOT LIMITED TO, 19 | // ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR 20 | // NON-INFRINGEMENT. TO THE EXTENT APPLICABLE LAWS PROHIBIT TERMS OF USE FROM 21 | // DISCLAIMING ANY IMPLIED WARRANTY, SUCH IMPLIED WARRANTY SHALL BE LIMITED TO THE 22 | // MINIMUM WARRANTY PERIOD REQUIRED BY LAW, AND IF NO SUCH PERIOD IS REQUIRED, 23 | // THEN THIRTY (30) DAYS FROM FIRST USE OF THE SOFTWARE. WE CANNOT GUARANTEE AND 24 | // DO NOT PROMISE ANY SPECIFIC RESULTS FROM USE OF THE SOFTWARE. WITHOUT LIMITING 25 | // THE FOREGOING, WE DO NOT WARRANT THAT THE SOFTWARE WILL BE UNINTERRUPTED OR 26 | // ERROR-FREE. IN NO EVENT WILL WE BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY 27 | // INDIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, SPECIAL OR PUNITIVE DAMAGES, 28 | // INCLUDING BUT NOT LIMITED TO, LOST PROFITS ARISING OUT OF YOUR USE, OR 29 | // INABILITY TO USE, THE SOFTWARE, EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY 30 | // OF SUCH DAMAGES. UNDER NO CIRCUMSTANCES SHALL OUR LIABILITY TO YOU FOR ANY 31 | // CLAIM OR CAUSE OF ACTION WHATSOEVER, AND REGARDLESS OF THE FORM OF THE ACTION, 32 | // WHETHER ARISING IN CONTRACT, TORT OR OTHERWISE, EXCEED THE AMOUNT PAID BY YOU 33 | // TO US, IF ANY, DURING THE 90 DAY PERIOD IMMEDIATELY PRECEDING THE DATE ON WHICH 34 | // YOU FIRST ASSERT ANY SUCH CLAIM. THE FOREGOING LIMITATIONS SHALL APPLY TO THE 35 | // FULLEST EXTENT PERMITTED BY APPLICABLE LAW. 36 | // 37 | // 2-stage synchronizer 38 | // 39 | module synch_2 #(parameter WIDTH = 1) ( 40 | input wire [WIDTH-1:0] i, // input signal 41 | output reg [WIDTH-1:0] o, // synchronized output 42 | input wire clk, // clock to synchronize on 43 | output wire rise, // one-cycle rising edge pulse 44 | output wire fall // one-cycle falling edge pulse 45 | ); 46 | 47 | reg [WIDTH-1:0] stage_1; 48 | reg [WIDTH-1:0] stage_2; 49 | reg [WIDTH-1:0] stage_3; 50 | 51 | assign rise = (WIDTH == 1) ? (o & ~stage_2) : 1'b0; 52 | assign fall = (WIDTH == 1) ? (~o & stage_2) : 1'b0; 53 | always @(posedge clk) 54 | {stage_2, o, stage_1} <= {o, stage_1, i}; 55 | 56 | endmodule 57 | 58 | 59 | // 60 | // 3-stage synchronizer 61 | // 62 | module synch_3 #(parameter WIDTH = 1) ( 63 | input wire [WIDTH-1:0] i, // input signal 64 | output reg [WIDTH-1:0] o, // synchronized output 65 | input wire clk, // clock to synchronize on 66 | output wire rise, // one-cycle rising edge pulse 67 | output wire fall // one-cycle falling edge pulse 68 | ); 69 | 70 | reg [WIDTH-1:0] stage_1; 71 | reg [WIDTH-1:0] stage_2; 72 | reg [WIDTH-1:0] stage_3; 73 | 74 | assign rise = (WIDTH == 1) ? (o & ~stage_3) : 1'b0; 75 | assign fall = (WIDTH == 1) ? (~o & stage_3) : 1'b0; 76 | always @(posedge clk) 77 | {stage_3, o, stage_2, stage_1} <= {o, stage_2, stage_1, i}; 78 | 79 | endmodule 80 | 81 | 82 | module bram_block_dp #( 83 | parameter DATA = 32, 84 | parameter ADDR = 7 85 | ) ( 86 | input wire a_clk, 87 | input wire a_wr, 88 | input wire [ADDR-1:0] a_addr, 89 | input wire [DATA-1:0] a_din, 90 | output reg [DATA-1:0] a_dout, 91 | 92 | input wire b_clk, 93 | input wire b_wr, 94 | input wire [ADDR-1:0] b_addr, 95 | input wire [DATA-1:0] b_din, 96 | output reg [DATA-1:0] b_dout 97 | ); 98 | 99 | reg [DATA-1:0] mem [(2**ADDR)-1:0]; 100 | 101 | always @(posedge a_clk) begin 102 | if(a_wr) begin 103 | a_dout <= a_din; 104 | mem[a_addr] <= a_din; 105 | end else 106 | a_dout <= mem[a_addr]; 107 | end 108 | 109 | always @(posedge b_clk) begin 110 | if(b_wr) begin 111 | b_dout <= b_din; 112 | mem[b_addr] <= b_din; 113 | end else 114 | b_dout <= mem[b_addr]; 115 | end 116 | 117 | endmodule 118 | 119 | 120 | module bram_block_dp_nonstd #( 121 | parameter DATA = 32, 122 | parameter ADDR = 7, 123 | parameter DEPTH = 128 124 | ) ( 125 | input wire a_clk, 126 | input wire a_wr, 127 | input wire [ADDR-1:0] a_addr, 128 | input wire [DATA-1:0] a_din, 129 | output reg [DATA-1:0] a_dout, 130 | 131 | input wire b_clk, 132 | input wire b_wr, 133 | input wire [ADDR-1:0] b_addr, 134 | input wire [DATA-1:0] b_din, 135 | output reg [DATA-1:0] b_dout 136 | ); 137 | 138 | reg [DATA-1:0] mem [DEPTH-1:0]; 139 | 140 | always @(posedge a_clk) begin 141 | if(a_wr) begin 142 | a_dout <= a_din; 143 | mem[a_addr] <= a_din; 144 | end else 145 | a_dout <= mem[a_addr]; 146 | end 147 | 148 | always @(posedge b_clk) begin 149 | if(b_wr) begin 150 | b_dout <= b_din; 151 | mem[b_addr] <= b_din; 152 | end else 153 | b_dout <= mem[b_addr]; 154 | end 155 | 156 | endmodule 157 | -------------------------------------------------------------------------------- /src/fpga/apf/io_bridge_peripheral.v: -------------------------------------------------------------------------------- 1 | // Software License Agreement 2 | 3 | // The software supplied herewith by Analogue Enterprises Limited (the "Company”), 4 | // the Analogue Pocket Framework (“APF”), is provided and licensed to you, the 5 | // Company's customer, solely for use in designing, testing and creating 6 | // applications for use with Company's Products or Services. The software is 7 | // owned by the Company and/or its licensors, and is protected under applicable 8 | // laws, including, but not limited to, U.S. copyright law. All rights are 9 | // reserved. By using the APF code you are agreeing to the terms of the End User 10 | // License Agreement (“EULA”) located at [https://www.analogue.link/pocket-eula] 11 | // and incorporated herein by reference. To the extent any use of the APF requires 12 | // application of the MIT License or the GNU General Public License and terms of 13 | // this APF Software License Agreement and EULA are inconsistent with such license, 14 | // the applicable terms of the MIT License or the GNU General Public License, as 15 | // applicable, will prevail. 16 | 17 | // THE SOFTWARE IS PROVIDED "AS-IS" AND WE EXPRESSLY DISCLAIM ANY IMPLIED 18 | // WARRANTIES TO THE FULLEST EXTENT PROVIDED BY LAW, INCLUDING BUT NOT LIMITED TO, 19 | // ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR 20 | // NON-INFRINGEMENT. TO THE EXTENT APPLICABLE LAWS PROHIBIT TERMS OF USE FROM 21 | // DISCLAIMING ANY IMPLIED WARRANTY, SUCH IMPLIED WARRANTY SHALL BE LIMITED TO THE 22 | // MINIMUM WARRANTY PERIOD REQUIRED BY LAW, AND IF NO SUCH PERIOD IS REQUIRED, 23 | // THEN THIRTY (30) DAYS FROM FIRST USE OF THE SOFTWARE. WE CANNOT GUARANTEE AND 24 | // DO NOT PROMISE ANY SPECIFIC RESULTS FROM USE OF THE SOFTWARE. WITHOUT LIMITING 25 | // THE FOREGOING, WE DO NOT WARRANT THAT THE SOFTWARE WILL BE UNINTERRUPTED OR 26 | // ERROR-FREE. IN NO EVENT WILL WE BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY 27 | // INDIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, SPECIAL OR PUNITIVE DAMAGES, 28 | // INCLUDING BUT NOT LIMITED TO, LOST PROFITS ARISING OUT OF YOUR USE, OR 29 | // INABILITY TO USE, THE SOFTWARE, EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY 30 | // OF SUCH DAMAGES. UNDER NO CIRCUMSTANCES SHALL OUR LIABILITY TO YOU FOR ANY 31 | // CLAIM OR CAUSE OF ACTION WHATSOEVER, AND REGARDLESS OF THE FORM OF THE ACTION, 32 | // WHETHER ARISING IN CONTRACT, TORT OR OTHERWISE, EXCEED THE AMOUNT PAID BY YOU 33 | // TO US, IF ANY, DURING THE 90 DAY PERIOD IMMEDIATELY PRECEDING THE DATE ON WHICH 34 | // YOU FIRST ASSERT ANY SUCH CLAIM. THE FOREGOING LIMITATIONS SHALL APPLY TO THE 35 | // FULLEST EXTENT PERMITTED BY APPLICABLE LAW. 36 | // 37 | // bridge peripheral for socrates PMP bridge to heraclitus+aristotle 38 | // 2020-2022 Analogue 39 | // 40 | // please note that while writes are immediate, 41 | // reads are buffered by 1 word. this is necessary to maintain 42 | // data throughput while reading from slower data sources like 43 | // sdram. 44 | // reads should always return the current bus value, and kickstart 45 | // into the next read immediately. this way, you have the entire 46 | // next word time to retrieve the data, instead of just a few 47 | // cycles. 48 | // 49 | // the worst-case read/write timing is every 88 cycles @ 74.25mhz 50 | // which is about 1180ns. 51 | 52 | module io_bridge_peripheral ( 53 | 54 | input wire clk, 55 | input wire reset_n, 56 | 57 | input wire endian_little, 58 | 59 | output reg [31:0] pmp_addr, 60 | output reg pmp_addr_valid, 61 | output reg pmp_rd, 62 | input wire [31:0] pmp_rd_data, 63 | output reg pmp_wr, 64 | output reg [31:0] pmp_wr_data, 65 | 66 | inout reg phy_spimosi, 67 | inout reg phy_spimiso, 68 | inout reg phy_spiclk, 69 | input wire phy_spiss 70 | 71 | ); 72 | 73 | // 74 | // clock domain: clk (74.25mhz) rising edge 75 | // 76 | wire reset_n_s; 77 | synch_3 s00(reset_n, reset_n_s, clk); 78 | 79 | wire endian_little_s; 80 | synch_3 s01(endian_little, endian_little_s, clk); 81 | 82 | wire phy_spiss_s, phy_spiss_r, phy_spiss_f; 83 | synch_3 s02(phy_spiss, phy_spiss_s, clk, phy_spiss_r, phy_spiss_f); 84 | 85 | 86 | reg [4:0] state; 87 | localparam ST_RESET = 'd0; 88 | localparam ST_IDLE = 'd1; 89 | localparam ST_READ_0 = 'd2; 90 | localparam ST_READ_1 = 'd3; 91 | localparam ST_READ_2 = 'd4; 92 | localparam ST_READ_3 = 'd5; 93 | localparam ST_WRITE_0 = 'd6; 94 | localparam ST_WRITE_1 = 'd7; 95 | localparam ST_WRITE_2 = 'd8; 96 | localparam ST_ADDR_0 = 'd9; 97 | 98 | reg [1:0] addr_cnt; 99 | reg [1:0] data_cnt; 100 | reg [6:0] read_cnt; 101 | 102 | // synchronize rd byte flag's rising edge into clk 103 | wire rx_byte_done_s, rx_byte_done_r; 104 | synch_3 s03(rx_byte_done, rx_byte_done_s, clk, rx_byte_done_r); 105 | 106 | reg [4:0] spis; 107 | localparam ST_SIDLE = 'd1; 108 | localparam ST_SEND_N = 'd6; 109 | localparam ST_SEND_0 = 'd2; 110 | localparam ST_SEND_1 = 'd3; 111 | localparam ST_SEND_2 = 'd4; 112 | localparam ST_SEND_3 = 'd5; 113 | reg spis_tx; 114 | reg [31:0] spis_word_tx; 115 | reg [31:0] spis_word; 116 | reg [4:0] spis_count; 117 | reg spis_done; 118 | 119 | reg rx_byte_done_r_1, rx_byte_done_r_2; 120 | reg [7:0] rx_byte_1, rx_byte_2; 121 | 122 | // handle reversing endianness on both ports 123 | reg [31:0] pmp_wr_data_latch; 124 | reg [31:0] pmp_rd_data_e; // asynchronous 125 | reg [31:0] pmp_rd_data_buf; // buffer the last word for immediate response 126 | always @(*) begin 127 | pmp_wr_data <= endian_little_s ? { pmp_wr_data_latch[7:0], 128 | pmp_wr_data_latch[15:8], 129 | pmp_wr_data_latch[23:16], 130 | pmp_wr_data_latch[31:24] 131 | } : pmp_wr_data_latch; 132 | 133 | pmp_rd_data_e <= endian_little_s ? {pmp_rd_data[7:0], 134 | pmp_rd_data[15:8], 135 | pmp_rd_data[23:16], 136 | pmp_rd_data[31:24] 137 | } : pmp_rd_data; 138 | end 139 | 140 | always @(posedge clk) begin 141 | 142 | rx_byte_2 <= rx_byte_1; 143 | rx_byte_1 <= rx_byte; 144 | 145 | rx_byte_done_r_1 <= rx_byte_done_r; 146 | rx_byte_done_r_2 <= rx_byte_done_r_1; 147 | 148 | case(state) 149 | ST_RESET: begin 150 | addr_cnt <= 0; 151 | data_cnt <= 0; 152 | pmp_wr <= 0; 153 | pmp_rd <= 0; 154 | pmp_addr_valid <= 0; 155 | spis_tx <= 0; 156 | 157 | state <= ST_ADDR_0; 158 | end 159 | ST_ADDR_0: begin 160 | // transaction has started 161 | 162 | if(rx_byte_done_r_2) begin 163 | case(addr_cnt) 164 | 0: pmp_addr[31:24] <= rx_byte_2; 165 | 1: pmp_addr[23:16] <= rx_byte_2; 166 | 2: pmp_addr[15: 8] <= rx_byte_2; 167 | 3: begin 168 | pmp_addr[ 7: 0] <= {rx_byte_2[7:2], 2'b00}; 169 | // address is latched 170 | if( rx_byte_2[0] ) begin 171 | data_cnt <= 0; 172 | state <= ST_WRITE_0; 173 | end else begin 174 | data_cnt <= 0; 175 | read_cnt <= 0; 176 | state <= ST_READ_0; 177 | end 178 | end 179 | endcase 180 | 181 | addr_cnt <= addr_cnt + 1'b1; 182 | end 183 | end 184 | ST_WRITE_0: begin 185 | // give notice, address has become valid 186 | pmp_addr_valid <= 1; 187 | 188 | if(rx_byte_done_r_2) begin 189 | case(data_cnt) 190 | 0: pmp_wr_data_latch[31:24] <= rx_byte_2; 191 | 1: pmp_wr_data_latch[23:16] <= rx_byte_2; 192 | 2: pmp_wr_data_latch[15: 8] <= rx_byte_2; 193 | 3: begin 194 | pmp_wr_data_latch[ 7: 0] <= rx_byte_2; 195 | state <= ST_WRITE_1; 196 | end 197 | endcase 198 | data_cnt <= data_cnt + 1'b1; 199 | end 200 | end 201 | ST_WRITE_1: begin 202 | pmp_wr <= 1; 203 | state <= ST_WRITE_2; 204 | end 205 | ST_WRITE_2: begin 206 | // exited upon new transaction 207 | pmp_wr <= 0; 208 | end 209 | ST_READ_0: begin 210 | pmp_addr_valid <= 1; 211 | 212 | // delay a few cycles 213 | read_cnt <= read_cnt + 1'b1; 214 | if(read_cnt == 4-1) begin 215 | // load the buffer with the current data 216 | // and give the current buffer contents to bridge 217 | spis_word_tx <= pmp_rd_data_e; 218 | spis_tx <= 1; 219 | 220 | state <= ST_READ_1; 221 | end 222 | end 223 | ST_READ_1: begin 224 | pmp_rd <= 1; 225 | state <= ST_READ_2; 226 | end 227 | ST_READ_2: begin 228 | pmp_rd <= 0; 229 | if(spis_done) begin 230 | spis_tx <= 0; 231 | state <= ST_READ_3; 232 | end 233 | end 234 | ST_READ_3: begin 235 | // exited upon new transaction 236 | end 237 | endcase 238 | 239 | 240 | 241 | 242 | // 243 | // word transmit 244 | // 245 | spis_done <= 0; 246 | case(spis) 247 | ST_SIDLE: begin 248 | spis_count <= 0; 249 | 250 | phy_spiclk <= 1'bZ; 251 | phy_spimosi <= 1'bZ; 252 | phy_spimiso <= 1'bZ; 253 | 254 | if(spis_tx) begin 255 | spis_word <= spis_word_tx; 256 | spis <= ST_SEND_N; 257 | end 258 | end 259 | // drive high first 260 | ST_SEND_N: begin 261 | phy_spiclk <= 1'b1; 262 | phy_spimosi <= 1'b1; 263 | phy_spimiso <= 1'b1; 264 | spis <= ST_SEND_0; 265 | end 266 | // tx, shift out bits 267 | ST_SEND_0: begin 268 | phy_spiclk <= 0; 269 | spis <= ST_SEND_1; 270 | phy_spimosi <= spis_word[31]; 271 | phy_spimiso <= spis_word[30]; 272 | spis_word <= {spis_word[29:0], 2'b00}; 273 | end 274 | ST_SEND_1: begin 275 | phy_spiclk <= 1; 276 | spis <= ST_SEND_0; 277 | spis_count <= spis_count + 1'b1; 278 | if(spis_count == 15) spis <= ST_SEND_2; 279 | end 280 | ST_SEND_2: begin 281 | phy_spiclk <= 1'b1; 282 | phy_spimosi <= 1'b1; 283 | phy_spimiso <= 1'b1; 284 | spis <= ST_SEND_3; 285 | spis_done <= 1; 286 | end 287 | ST_SEND_3: begin 288 | spis <= ST_SIDLE; 289 | end 290 | endcase 291 | 292 | if(phy_spiss_s) begin 293 | // select is high, go back to reset 294 | state <= ST_RESET; 295 | spis <= ST_SIDLE; 296 | end 297 | 298 | end 299 | 300 | 301 | // 302 | // clock domain: phy_spiclk rising edge 303 | // 304 | reg [1:0] rx_latch_idx; 305 | reg [7:0] rx_dat; 306 | reg [7:0] rx_byte; // latched by clk, but upon a synchronized trigger 307 | reg rx_byte_done; 308 | 309 | always @(posedge phy_spiclk or posedge phy_spiss) begin 310 | 311 | if(phy_spiss) begin 312 | // reset 313 | rx_byte_done <= 0; 314 | rx_latch_idx <= 0; 315 | 316 | end else begin 317 | // spiclk rising edge, latch data 318 | rx_byte_done <= 0; 319 | 320 | case(rx_latch_idx) 321 | 0: begin rx_dat[7:6] <= {phy_spimosi, phy_spimiso}; rx_latch_idx <= 1; end 322 | 1: begin rx_dat[5:4] <= {phy_spimosi, phy_spimiso}; rx_latch_idx <= 2; end 323 | 2: begin rx_dat[3:2] <= {phy_spimosi, phy_spimiso}; rx_latch_idx <= 3; end 324 | 3: begin 325 | // final 2 bits 326 | rx_byte <= {rx_dat[7:2], phy_spimosi, phy_spimiso}; 327 | rx_latch_idx <= 0; 328 | rx_byte_done <= 1; 329 | end 330 | endcase 331 | end 332 | end 333 | 334 | endmodule 335 | -------------------------------------------------------------------------------- /src/fpga/apf/io_pad_controller.v: -------------------------------------------------------------------------------- 1 | // Software License Agreement 2 | 3 | // The software supplied herewith by Analogue Enterprises Limited (the "Company”), 4 | // the Analogue Pocket Framework (“APF”), is provided and licensed to you, the 5 | // Company's customer, solely for use in designing, testing and creating 6 | // applications for use with Company's Products or Services. The software is 7 | // owned by the Company and/or its licensors, and is protected under applicable 8 | // laws, including, but not limited to, U.S. copyright law. All rights are 9 | // reserved. By using the APF code you are agreeing to the terms of the End User 10 | // License Agreement (“EULA”) located at [https://www.analogue.link/pocket-eula] 11 | // and incorporated herein by reference. To the extent any use of the APF requires 12 | // application of the MIT License or the GNU General Public License and terms of 13 | // this APF Software License Agreement and EULA are inconsistent with such license, 14 | // the applicable terms of the MIT License or the GNU General Public License, as 15 | // applicable, will prevail. 16 | 17 | // THE SOFTWARE IS PROVIDED "AS-IS" AND WE EXPRESSLY DISCLAIM ANY IMPLIED 18 | // WARRANTIES TO THE FULLEST EXTENT PROVIDED BY LAW, INCLUDING BUT NOT LIMITED TO, 19 | // ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR 20 | // NON-INFRINGEMENT. TO THE EXTENT APPLICABLE LAWS PROHIBIT TERMS OF USE FROM 21 | // DISCLAIMING ANY IMPLIED WARRANTY, SUCH IMPLIED WARRANTY SHALL BE LIMITED TO THE 22 | // MINIMUM WARRANTY PERIOD REQUIRED BY LAW, AND IF NO SUCH PERIOD IS REQUIRED, 23 | // THEN THIRTY (30) DAYS FROM FIRST USE OF THE SOFTWARE. WE CANNOT GUARANTEE AND 24 | // DO NOT PROMISE ANY SPECIFIC RESULTS FROM USE OF THE SOFTWARE. WITHOUT LIMITING 25 | // THE FOREGOING, WE DO NOT WARRANT THAT THE SOFTWARE WILL BE UNINTERRUPTED OR 26 | // ERROR-FREE. IN NO EVENT WILL WE BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY 27 | // INDIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, SPECIAL OR PUNITIVE DAMAGES, 28 | // INCLUDING BUT NOT LIMITED TO, LOST PROFITS ARISING OUT OF YOUR USE, OR 29 | // INABILITY TO USE, THE SOFTWARE, EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY 30 | // OF SUCH DAMAGES. UNDER NO CIRCUMSTANCES SHALL OUR LIABILITY TO YOU FOR ANY 31 | // CLAIM OR CAUSE OF ACTION WHATSOEVER, AND REGARDLESS OF THE FORM OF THE ACTION, 32 | // WHETHER ARISING IN CONTRACT, TORT OR OTHERWISE, EXCEED THE AMOUNT PAID BY YOU 33 | // TO US, IF ANY, DURING THE 90 DAY PERIOD IMMEDIATELY PRECEDING THE DATE ON WHICH 34 | // YOU FIRST ASSERT ANY SUCH CLAIM. THE FOREGOING LIMITATIONS SHALL APPLY TO THE 35 | // FULLEST EXTENT PERMITTED BY APPLICABLE LAW. 36 | // 37 | // pad controller 38 | // 2020-08-17 Analogue 39 | // 40 | 41 | module io_pad_controller ( 42 | 43 | input wire clk, 44 | input wire reset_n, 45 | 46 | inout reg pad_1wire, 47 | 48 | output reg [15:0] cont1_key, 49 | output reg [15:0] cont2_key, 50 | output reg [15:0] cont3_key, 51 | output reg [15:0] cont4_key, 52 | output reg [31:0] cont1_joy, 53 | output reg [31:0] cont2_joy, 54 | output reg [31:0] cont3_joy, 55 | output reg [31:0] cont4_joy, 56 | output reg [15:0] cont1_trig, 57 | output reg [15:0] cont2_trig, 58 | output reg [15:0] cont3_trig, 59 | output reg [15:0] cont4_trig, 60 | 61 | output reg rx_timed_out 62 | ); 63 | 64 | wire reset_n_s; 65 | synch_3 s00(reset_n, reset_n_s, clk); 66 | 67 | wire pad_1wire_s, pad_1wire_r, pad_1wire_f; 68 | synch_3 s01(pad_1wire, pad_1wire_s, clk, pad_1wire_r, pad_1wire_f); 69 | 70 | 71 | // 72 | // protocol fsm 73 | // 74 | 75 | reg [20:0] rx_timeout; // ~28ms 76 | 77 | reg [15:0] auto_poll_cnt; // 882us 78 | reg auto_poll_queue; 79 | 80 | reg [18:0] heartbeat_cnt; // 7ms 81 | reg heartbeat_queue; 82 | 83 | 84 | localparam ST_RESET = 'd0; 85 | localparam ST_IDLE = 'd1; 86 | localparam ST_RX_BUTTON_1 = 'd2; 87 | localparam ST_RX_BUTTON_2 = 'd3; 88 | localparam ST_TX_SCALER = 'd4; 89 | localparam ST_END_TX = 'd5; 90 | 91 | reg [3:0] state; 92 | reg [3:0] cnt; 93 | 94 | always @(posedge clk) begin 95 | tx_word_start <= 0; 96 | 97 | auto_poll_cnt <= auto_poll_cnt + 1'b1; 98 | heartbeat_cnt <= heartbeat_cnt + 1'b1; 99 | 100 | // increment rx timeout, override and reset when idle below 101 | rx_timeout <= rx_timeout + 1'b1; 102 | 103 | case(state) 104 | ST_RESET: begin 105 | reset_tr_n <= 0; 106 | rx_timed_out <= 0; 107 | 108 | if(&rx_timeout[19:0]) begin 109 | state <= ST_IDLE; 110 | end 111 | end 112 | ST_IDLE: begin 113 | // idle state 114 | reset_tr_n <= 1; 115 | rx_timeout <= 0; 116 | cnt <= 0; 117 | if(auto_poll_queue) begin 118 | auto_poll_queue <= 0; 119 | 120 | tx_word_start <= 1; 121 | tx_word <= 32'h4A10000C; 122 | 123 | state <= ST_RX_BUTTON_1; 124 | end else if(heartbeat_queue) begin 125 | heartbeat_queue <= 0; 126 | 127 | tx_word_start <= 1; 128 | tx_word <= 32'h4AFE0000; 129 | 130 | state <= ST_END_TX; 131 | end 132 | end 133 | // receive button words 134 | ST_RX_BUTTON_1: begin 135 | if(tx_word_done) begin 136 | state <= ST_RX_BUTTON_2; 137 | end 138 | end 139 | ST_RX_BUTTON_2: begin 140 | if(rx_word_done) begin 141 | cnt <= cnt + 1'b1; 142 | case(cnt) 143 | 0: cont1_key <= rx_word[15:0]; 144 | 1: cont1_joy <= rx_word; 145 | 2: cont1_trig <= rx_word[15:0]; 146 | 147 | 3: cont2_key <= rx_word[15:0]; 148 | 4: cont2_joy <= rx_word; 149 | 5: cont2_trig <= rx_word[15:0]; 150 | 151 | 6: cont3_key <= rx_word[15:0]; 152 | 7: cont3_joy <= rx_word; 153 | 8: cont3_trig <= rx_word[15:0]; 154 | 155 | 9: cont4_key <= rx_word[15:0]; 156 | 10: cont4_joy <= rx_word; 157 | 11: begin 158 | cont4_trig <= rx_word[15:0]; 159 | state <= ST_IDLE; 160 | end 161 | endcase 162 | end 163 | end 164 | // do nothing 165 | ST_END_TX: begin 166 | // done sending, idle again 167 | if(tx_word_done) begin 168 | state <= ST_IDLE; 169 | end 170 | end 171 | endcase 172 | 173 | 174 | if(&auto_poll_cnt) begin 175 | auto_poll_queue <= 1; 176 | end 177 | if(&heartbeat_cnt) begin 178 | heartbeat_queue <= 1; 179 | end 180 | 181 | if(&rx_timeout) begin 182 | // reset protocol FSM which will also reset t/r engine 183 | rx_timed_out <= 1; 184 | rx_timeout <= 0; 185 | state <= ST_RESET; 186 | end 187 | 188 | if(~reset_n_s) begin 189 | state <= ST_RESET; 190 | end 191 | end 192 | 193 | 194 | 195 | 196 | 197 | // 198 | // word receive/transmit engine 199 | // 200 | reg reset_tr_n; 201 | localparam BITLEN = 60; 202 | 203 | reg rx_word_done; 204 | reg [31:0] rx_word_shift; 205 | reg [31:0] rx_word; 206 | 207 | reg tx_word_start, tx_word_start_1; 208 | reg tx_word_done; 209 | reg [31:0] tx_word; 210 | reg [31:0] tx_word_shift; 211 | 212 | reg [7:0] tr_cnt; 213 | reg [5:0] tr_bit; 214 | 215 | localparam TR_IDLE = 'd1; 216 | localparam TR_TX_START = 'd2; 217 | localparam TR_TX_CONTINUE = 'd3; 218 | localparam TR_TX_DONE = 'd4; 219 | localparam TR_RX_START = 'd5; 220 | localparam TR_RX_WAITEDGE = 'd6; 221 | localparam TR_RX_DONE = 'd7; 222 | 223 | reg [3:0] tr_state; 224 | 225 | always @(posedge clk) begin 226 | 227 | rx_word_done <= 0; 228 | tx_word_done <= 0; 229 | 230 | tx_word_start_1 <= tx_word_start; 231 | 232 | case(tr_state) 233 | TR_IDLE: begin 234 | tr_bit <= 0; 235 | tr_cnt <= 0; 236 | 237 | pad_1wire <= 1'bZ; 238 | 239 | if(tx_word_start & ~tx_word_start_1) begin 240 | // transmit word 241 | tx_word_shift <= tx_word; 242 | tr_state <= TR_TX_START; 243 | end 244 | 245 | if(pad_1wire_f) begin 246 | // receive word 247 | tr_state <= TR_RX_START; 248 | end 249 | end 250 | 251 | // transmit 32bit 252 | TR_TX_START: begin 253 | // insert delay 254 | tr_cnt <= tr_cnt + 1'b1; 255 | if(&tr_cnt) begin 256 | // drive from tristate(high) to explicitly high to prevent glitching 257 | pad_1wire <= 1'b1; 258 | tr_state <= TR_TX_CONTINUE; 259 | end 260 | end 261 | TR_TX_CONTINUE: begin 262 | tr_cnt <= tr_cnt + 1'b1; 263 | case(tr_cnt) 264 | 0: begin 265 | pad_1wire <= 1'b0; 266 | end 267 | (BITLEN/3): begin 268 | pad_1wire <= tx_word_shift[31]; 269 | end 270 | (BITLEN*2/3): begin 271 | pad_1wire <= 1'b1; 272 | end 273 | (BITLEN-1): begin 274 | tr_cnt <= 0; 275 | tx_word_shift <= {tx_word_shift[30:0], 1'b1}; 276 | 277 | tr_bit <= tr_bit + 1'b1; 278 | if(tr_bit == 31) begin 279 | tr_state <= TR_TX_DONE; 280 | end 281 | end 282 | endcase 283 | end 284 | TR_TX_DONE: begin 285 | tx_word_done <= 1; 286 | tr_state <= TR_IDLE; 287 | end 288 | 289 | // receive 32bit 290 | TR_RX_START: begin 291 | tr_cnt <= tr_cnt + 1'b1; 292 | case(tr_cnt) 293 | (BITLEN/2-4): begin 294 | rx_word_shift <= {rx_word_shift[30:0], pad_1wire_s}; 295 | end 296 | (BITLEN*5/6): begin 297 | tr_cnt <= 0; 298 | 299 | // wait for next falling edge 300 | tr_state <= TR_RX_WAITEDGE; 301 | tr_bit <= tr_bit + 1'b1; 302 | if(tr_bit == 31) begin 303 | // if this is bit32, don't wait and finish 304 | tr_state <= TR_RX_DONE; 305 | end 306 | end 307 | endcase 308 | end 309 | TR_RX_WAITEDGE: begin 310 | if(pad_1wire_f) begin 311 | tr_state <= TR_RX_START; 312 | end 313 | end 314 | TR_RX_DONE: begin 315 | rx_word <= rx_word_shift; 316 | rx_word_done <= 1; 317 | tr_state <= TR_IDLE; 318 | end 319 | 320 | default: begin 321 | tr_state <= TR_IDLE; 322 | end 323 | endcase 324 | 325 | if(~reset_n_s | ~reset_tr_n) tr_state <= TR_IDLE; 326 | end 327 | 328 | endmodule 329 | -------------------------------------------------------------------------------- /src/fpga/apf/mf_datatable.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT" 2 | set_global_assignment -name IP_TOOL_VERSION "21.1" 3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" 4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "mf_datatable.v"] 5 | -------------------------------------------------------------------------------- /src/fpga/apf/mf_datatable.v: -------------------------------------------------------------------------------- 1 | // megafunction wizard: %RAM: 2-PORT% 2 | // GENERATION: STANDARD 3 | // VERSION: WM1.0 4 | // MODULE: altsyncram 5 | 6 | // ============================================================ 7 | // File Name: mf_datatable.v 8 | // Megafunction Name(s): 9 | // altsyncram 10 | // 11 | // Simulation Library Files(s): 12 | // altera_mf 13 | // ============================================================ 14 | // ************************************************************ 15 | // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! 16 | // 17 | // 21.1.1 Build 850 06/23/2022 SJ Lite Edition 18 | // ************************************************************ 19 | 20 | 21 | //Copyright (C) 2022 Intel Corporation. All rights reserved. 22 | //Your use of Intel Corporation's design tools, logic functions 23 | //and other software and tools, and any partner logic 24 | //functions, and any output files from any of the foregoing 25 | //(including device programming or simulation files), and any 26 | //associated documentation or information are expressly subject 27 | //to the terms and conditions of the Intel Program License 28 | //Subscription Agreement, the Intel Quartus Prime License Agreement, 29 | //the Intel FPGA IP License Agreement, or other applicable license 30 | //agreement, including, without limitation, that your use is for 31 | //the sole purpose of programming logic devices manufactured by 32 | //Intel and sold by Intel or its authorized distributors. Please 33 | //refer to the applicable agreement for further details, at 34 | //https://fpgasoftware.intel.com/eula. 35 | 36 | 37 | // synopsys translate_off 38 | `timescale 1 ps / 1 ps 39 | // synopsys translate_on 40 | module mf_datatable ( 41 | address_a, 42 | address_b, 43 | clock_a, 44 | clock_b, 45 | data_a, 46 | data_b, 47 | wren_a, 48 | wren_b, 49 | q_a, 50 | q_b); 51 | 52 | input [7:0] address_a; 53 | input [7:0] address_b; 54 | input clock_a; 55 | input clock_b; 56 | input [31:0] data_a; 57 | input [31:0] data_b; 58 | input wren_a; 59 | input wren_b; 60 | output [31:0] q_a; 61 | output [31:0] q_b; 62 | `ifndef ALTERA_RESERVED_QIS 63 | // synopsys translate_off 64 | `endif 65 | tri1 clock_a; 66 | tri0 wren_a; 67 | tri0 wren_b; 68 | `ifndef ALTERA_RESERVED_QIS 69 | // synopsys translate_on 70 | `endif 71 | 72 | wire [31:0] sub_wire0; 73 | wire [31:0] sub_wire1; 74 | wire [31:0] q_a = sub_wire0[31:0]; 75 | wire [31:0] q_b = sub_wire1[31:0]; 76 | 77 | altsyncram altsyncram_component ( 78 | .address_a (address_a), 79 | .address_b (address_b), 80 | .clock0 (clock_a), 81 | .clock1 (clock_b), 82 | .data_a (data_a), 83 | .data_b (data_b), 84 | .wren_a (wren_a), 85 | .wren_b (wren_b), 86 | .q_a (sub_wire0), 87 | .q_b (sub_wire1), 88 | .aclr0 (1'b0), 89 | .aclr1 (1'b0), 90 | .addressstall_a (1'b0), 91 | .addressstall_b (1'b0), 92 | .byteena_a (1'b1), 93 | .byteena_b (1'b1), 94 | .clocken0 (1'b1), 95 | .clocken1 (1'b1), 96 | .clocken2 (1'b1), 97 | .clocken3 (1'b1), 98 | .eccstatus (), 99 | .rden_a (1'b1), 100 | .rden_b (1'b1)); 101 | defparam 102 | altsyncram_component.address_reg_b = "CLOCK1", 103 | altsyncram_component.clock_enable_input_a = "BYPASS", 104 | altsyncram_component.clock_enable_input_b = "BYPASS", 105 | altsyncram_component.clock_enable_output_a = "BYPASS", 106 | altsyncram_component.clock_enable_output_b = "BYPASS", 107 | altsyncram_component.indata_reg_b = "CLOCK1", 108 | altsyncram_component.init_file = "./apf/build_id.mif", 109 | altsyncram_component.intended_device_family = "Cyclone V", 110 | altsyncram_component.lpm_type = "altsyncram", 111 | altsyncram_component.numwords_a = 256, 112 | altsyncram_component.numwords_b = 256, 113 | altsyncram_component.operation_mode = "BIDIR_DUAL_PORT", 114 | altsyncram_component.outdata_aclr_a = "NONE", 115 | altsyncram_component.outdata_aclr_b = "NONE", 116 | altsyncram_component.outdata_reg_a = "CLOCK0", 117 | altsyncram_component.outdata_reg_b = "CLOCK1", 118 | altsyncram_component.power_up_uninitialized = "FALSE", 119 | altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", 120 | altsyncram_component.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ", 121 | altsyncram_component.widthad_a = 8, 122 | altsyncram_component.widthad_b = 8, 123 | altsyncram_component.width_a = 32, 124 | altsyncram_component.width_b = 32, 125 | altsyncram_component.width_byteena_a = 1, 126 | altsyncram_component.width_byteena_b = 1, 127 | altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1"; 128 | 129 | 130 | endmodule 131 | 132 | // ============================================================ 133 | // CNX file retrieval info 134 | // ============================================================ 135 | // Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" 136 | // Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0" 137 | // Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0" 138 | // Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0" 139 | // Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0" 140 | // Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0" 141 | // Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" 142 | // Retrieval info: PRIVATE: BlankMemory NUMERIC "0" 143 | // Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" 144 | // Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "0" 145 | // Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" 146 | // Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0" 147 | // Retrieval info: PRIVATE: CLRdata NUMERIC "0" 148 | // Retrieval info: PRIVATE: CLRq NUMERIC "0" 149 | // Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0" 150 | // Retrieval info: PRIVATE: CLRrren NUMERIC "0" 151 | // Retrieval info: PRIVATE: CLRwraddress NUMERIC "0" 152 | // Retrieval info: PRIVATE: CLRwren NUMERIC "0" 153 | // Retrieval info: PRIVATE: Clock NUMERIC "5" 154 | // Retrieval info: PRIVATE: Clock_A NUMERIC "0" 155 | // Retrieval info: PRIVATE: Clock_B NUMERIC "0" 156 | // Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" 157 | // Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0" 158 | // Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "1" 159 | // Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" 160 | // Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" 161 | // Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone V" 162 | // Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" 163 | // Retrieval info: PRIVATE: JTAG_ID STRING "NONE" 164 | // Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" 165 | // Retrieval info: PRIVATE: MEMSIZE NUMERIC "8192" 166 | // Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0" 167 | // Retrieval info: PRIVATE: MIFfilename STRING "./apf/build_id.mif" 168 | // Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "3" 169 | // Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0" 170 | // Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "1" 171 | // Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" 172 | // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2" 173 | // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" 174 | // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3" 175 | // Retrieval info: PRIVATE: REGdata NUMERIC "1" 176 | // Retrieval info: PRIVATE: REGq NUMERIC "1" 177 | // Retrieval info: PRIVATE: REGrdaddress NUMERIC "0" 178 | // Retrieval info: PRIVATE: REGrren NUMERIC "0" 179 | // Retrieval info: PRIVATE: REGwraddress NUMERIC "1" 180 | // Retrieval info: PRIVATE: REGwren NUMERIC "1" 181 | // Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" 182 | // Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0" 183 | // Retrieval info: PRIVATE: UseDPRAM NUMERIC "1" 184 | // Retrieval info: PRIVATE: VarWidth NUMERIC "0" 185 | // Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "32" 186 | // Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "32" 187 | // Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "32" 188 | // Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "32" 189 | // Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0" 190 | // Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "1" 191 | // Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0" 192 | // Retrieval info: PRIVATE: enable NUMERIC "0" 193 | // Retrieval info: PRIVATE: rden NUMERIC "0" 194 | // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all 195 | // Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK1" 196 | // Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" 197 | // Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "BYPASS" 198 | // Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" 199 | // Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS" 200 | // Retrieval info: CONSTANT: INDATA_REG_B STRING "CLOCK1" 201 | // Retrieval info: CONSTANT: INIT_FILE STRING "./apf/build_id.mif" 202 | // Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone V" 203 | // Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" 204 | // Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "256" 205 | // Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "256" 206 | // Retrieval info: CONSTANT: OPERATION_MODE STRING "BIDIR_DUAL_PORT" 207 | // Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" 208 | // Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE" 209 | // Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" 210 | // Retrieval info: CONSTANT: OUTDATA_REG_B STRING "CLOCK1" 211 | // Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" 212 | // Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ" 213 | // Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_B STRING "NEW_DATA_NO_NBE_READ" 214 | // Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "8" 215 | // Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "8" 216 | // Retrieval info: CONSTANT: WIDTH_A NUMERIC "32" 217 | // Retrieval info: CONSTANT: WIDTH_B NUMERIC "32" 218 | // Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" 219 | // Retrieval info: CONSTANT: WIDTH_BYTEENA_B NUMERIC "1" 220 | // Retrieval info: CONSTANT: WRCONTROL_WRADDRESS_REG_B STRING "CLOCK1" 221 | // Retrieval info: USED_PORT: address_a 0 0 8 0 INPUT NODEFVAL "address_a[7..0]" 222 | // Retrieval info: USED_PORT: address_b 0 0 8 0 INPUT NODEFVAL "address_b[7..0]" 223 | // Retrieval info: USED_PORT: clock_a 0 0 0 0 INPUT VCC "clock_a" 224 | // Retrieval info: USED_PORT: clock_b 0 0 0 0 INPUT NODEFVAL "clock_b" 225 | // Retrieval info: USED_PORT: data_a 0 0 32 0 INPUT NODEFVAL "data_a[31..0]" 226 | // Retrieval info: USED_PORT: data_b 0 0 32 0 INPUT NODEFVAL "data_b[31..0]" 227 | // Retrieval info: USED_PORT: q_a 0 0 32 0 OUTPUT NODEFVAL "q_a[31..0]" 228 | // Retrieval info: USED_PORT: q_b 0 0 32 0 OUTPUT NODEFVAL "q_b[31..0]" 229 | // Retrieval info: USED_PORT: wren_a 0 0 0 0 INPUT GND "wren_a" 230 | // Retrieval info: USED_PORT: wren_b 0 0 0 0 INPUT GND "wren_b" 231 | // Retrieval info: CONNECT: @address_a 0 0 8 0 address_a 0 0 8 0 232 | // Retrieval info: CONNECT: @address_b 0 0 8 0 address_b 0 0 8 0 233 | // Retrieval info: CONNECT: @clock0 0 0 0 0 clock_a 0 0 0 0 234 | // Retrieval info: CONNECT: @clock1 0 0 0 0 clock_b 0 0 0 0 235 | // Retrieval info: CONNECT: @data_a 0 0 32 0 data_a 0 0 32 0 236 | // Retrieval info: CONNECT: @data_b 0 0 32 0 data_b 0 0 32 0 237 | // Retrieval info: CONNECT: @wren_a 0 0 0 0 wren_a 0 0 0 0 238 | // Retrieval info: CONNECT: @wren_b 0 0 0 0 wren_b 0 0 0 0 239 | // Retrieval info: CONNECT: q_a 0 0 32 0 @q_a 0 0 32 0 240 | // Retrieval info: CONNECT: q_b 0 0 32 0 @q_b 0 0 32 0 241 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable.v TRUE 242 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable.inc FALSE 243 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable.cmp FALSE 244 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable.bsf FALSE 245 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable_inst.v FALSE 246 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_datatable_bb.v FALSE 247 | // Retrieval info: LIB_FILE: altera_mf 248 | -------------------------------------------------------------------------------- /src/fpga/apf/mf_ddio_bidir_12.ppf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/fpga/apf/mf_ddio_bidir_12.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "ALTDDIO_BIDIR" 2 | set_global_assignment -name IP_TOOL_VERSION "21.1" 3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" 4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "mf_ddio_bidir_12.v"] 5 | set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "mf_ddio_bidir_12.ppf"] 6 | -------------------------------------------------------------------------------- /src/fpga/apf/mf_ddio_bidir_12.v: -------------------------------------------------------------------------------- 1 | // megafunction wizard: %ALTDDIO_BIDIR% 2 | // GENERATION: STANDARD 3 | // VERSION: WM1.0 4 | // MODULE: ALTDDIO_BIDIR 5 | 6 | // ============================================================ 7 | // File Name: mf_ddio_bidir_12.v 8 | // Megafunction Name(s): 9 | // ALTDDIO_BIDIR 10 | // 11 | // Simulation Library Files(s): 12 | // 13 | // ============================================================ 14 | // ************************************************************ 15 | // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! 16 | // 17 | // 21.1.1 Build 850 06/23/2022 SJ Lite Edition 18 | // ************************************************************ 19 | 20 | 21 | //Copyright (C) 2022 Intel Corporation. All rights reserved. 22 | //Your use of Intel Corporation's design tools, logic functions 23 | //and other software and tools, and any partner logic 24 | //functions, and any output files from any of the foregoing 25 | //(including device programming or simulation files), and any 26 | //associated documentation or information are expressly subject 27 | //to the terms and conditions of the Intel Program License 28 | //Subscription Agreement, the Intel Quartus Prime License Agreement, 29 | //the Intel FPGA IP License Agreement, or other applicable license 30 | //agreement, including, without limitation, that your use is for 31 | //the sole purpose of programming logic devices manufactured by 32 | //Intel and sold by Intel or its authorized distributors. Please 33 | //refer to the applicable agreement for further details, at 34 | //https://fpgasoftware.intel.com/eula. 35 | 36 | 37 | // synopsys translate_off 38 | `timescale 1 ps / 1 ps 39 | // synopsys translate_on 40 | module mf_ddio_bidir_12 ( 41 | datain_h, 42 | datain_l, 43 | inclock, 44 | oe, 45 | outclock, 46 | dataout_h, 47 | dataout_l, 48 | padio); 49 | 50 | input [11:0] datain_h; 51 | input [11:0] datain_l; 52 | input inclock; 53 | input oe; 54 | input outclock; 55 | output [11:0] dataout_h; 56 | output [11:0] dataout_l; 57 | inout [11:0] padio; 58 | 59 | wire [11:0] sub_wire0; 60 | wire [11:0] sub_wire1; 61 | wire [11:0] dataout_h = sub_wire0[11:0]; 62 | wire [11:0] dataout_l = sub_wire1[11:0]; 63 | 64 | altddio_bidir ALTDDIO_BIDIR_component ( 65 | .datain_h (datain_h), 66 | .datain_l (datain_l), 67 | .inclock (inclock), 68 | .oe (oe), 69 | .outclock (outclock), 70 | .padio (padio), 71 | .dataout_h (sub_wire0), 72 | .dataout_l (sub_wire1), 73 | .aclr (1'b0), 74 | .aset (1'b0), 75 | .combout (), 76 | .dqsundelayedout (), 77 | .inclocken (1'b1), 78 | .oe_out (), 79 | .outclocken (1'b1), 80 | .sclr (1'b0), 81 | .sset (1'b0)); 82 | defparam 83 | ALTDDIO_BIDIR_component.extend_oe_disable = "OFF", 84 | ALTDDIO_BIDIR_component.implement_input_in_lcell = "OFF", 85 | ALTDDIO_BIDIR_component.intended_device_family = "Cyclone V", 86 | ALTDDIO_BIDIR_component.invert_output = "OFF", 87 | ALTDDIO_BIDIR_component.lpm_hint = "UNUSED", 88 | ALTDDIO_BIDIR_component.lpm_type = "altddio_bidir", 89 | ALTDDIO_BIDIR_component.oe_reg = "UNREGISTERED", 90 | ALTDDIO_BIDIR_component.power_up_high = "OFF", 91 | ALTDDIO_BIDIR_component.width = 12; 92 | 93 | 94 | endmodule 95 | 96 | // ============================================================ 97 | // CNX file retrieval info 98 | // ============================================================ 99 | // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all 100 | // Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone V" 101 | // Retrieval info: CONSTANT: EXTEND_OE_DISABLE STRING "OFF" 102 | // Retrieval info: CONSTANT: IMPLEMENT_INPUT_IN_LCELL STRING "OFF" 103 | // Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone V" 104 | // Retrieval info: CONSTANT: INVERT_OUTPUT STRING "OFF" 105 | // Retrieval info: CONSTANT: LPM_HINT STRING "UNUSED" 106 | // Retrieval info: CONSTANT: LPM_TYPE STRING "altddio_bidir" 107 | // Retrieval info: CONSTANT: OE_REG STRING "UNREGISTERED" 108 | // Retrieval info: CONSTANT: POWER_UP_HIGH STRING "OFF" 109 | // Retrieval info: CONSTANT: WIDTH NUMERIC "12" 110 | // Retrieval info: USED_PORT: datain_h 0 0 12 0 INPUT NODEFVAL "datain_h[11..0]" 111 | // Retrieval info: CONNECT: @datain_h 0 0 12 0 datain_h 0 0 12 0 112 | // Retrieval info: USED_PORT: datain_l 0 0 12 0 INPUT NODEFVAL "datain_l[11..0]" 113 | // Retrieval info: CONNECT: @datain_l 0 0 12 0 datain_l 0 0 12 0 114 | // Retrieval info: USED_PORT: dataout_h 0 0 12 0 OUTPUT NODEFVAL "dataout_h[11..0]" 115 | // Retrieval info: CONNECT: dataout_h 0 0 12 0 @dataout_h 0 0 12 0 116 | // Retrieval info: USED_PORT: dataout_l 0 0 12 0 OUTPUT NODEFVAL "dataout_l[11..0]" 117 | // Retrieval info: CONNECT: dataout_l 0 0 12 0 @dataout_l 0 0 12 0 118 | // Retrieval info: USED_PORT: inclock 0 0 0 0 INPUT_CLK_EXT NODEFVAL "inclock" 119 | // Retrieval info: CONNECT: @inclock 0 0 0 0 inclock 0 0 0 0 120 | // Retrieval info: USED_PORT: oe 0 0 0 0 INPUT NODEFVAL "oe" 121 | // Retrieval info: CONNECT: @oe 0 0 0 0 oe 0 0 0 0 122 | // Retrieval info: USED_PORT: outclock 0 0 0 0 INPUT_CLK_EXT NODEFVAL "outclock" 123 | // Retrieval info: CONNECT: @outclock 0 0 0 0 outclock 0 0 0 0 124 | // Retrieval info: USED_PORT: padio 0 0 12 0 BIDIR NODEFVAL "padio[11..0]" 125 | // Retrieval info: CONNECT: padio 0 0 12 0 @padio 0 0 12 0 126 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.v TRUE FALSE 127 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.qip TRUE FALSE 128 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.bsf FALSE TRUE 129 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12_inst.v FALSE TRUE 130 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12_bb.v FALSE TRUE 131 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.inc FALSE TRUE 132 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.cmp FALSE TRUE 133 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.ppf TRUE FALSE 134 | -------------------------------------------------------------------------------- /src/fpga/core/core_constraints.sdc: -------------------------------------------------------------------------------- 1 | # 2 | # user core constraints 3 | # 4 | # put your clock groups in here as well as any net assignments 5 | # 6 | 7 | set_clock_groups -asynchronous \ 8 | -group { bridge_spiclk } \ 9 | -group { clk_74a } \ 10 | -group { clk_74b } \ 11 | -group { ic|mp1|mf_pllbase_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk } \ 12 | -group { ic|mp1|mf_pllbase_inst|altera_pll_i|general[1].gpll~PLL_OUTPUT_COUNTER|divclk } -------------------------------------------------------------------------------- /src/fpga/core/data_loader.sv: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2022 Adam Gastineau 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // 23 | //////////////////////////////////////////////////////////////////////////////// 24 | 25 | // A data loader for consuming APF bridge writes and directing them to some storage medium 26 | // 27 | // This takes the 32 bit words from APF, and splits it into four / OUTPUT_WORD_SIZE words (4 separate bytes, or 2 16-bit words). 28 | // You can configure the cycle delay by setting WRITE_MEM_CLOCK_DELAY 29 | module data_loader #( 30 | // Upper 4 bits of address 31 | parameter ADDRESS_MASK_UPPER_4 = 0, 32 | parameter ADDRESS_SIZE = 14, 33 | 34 | // Number of clk_memory cycles to delay each write output 35 | // Min 4. Component will assert this value is within the valid range 36 | // Be aware that APF sends data every ~75 74MHz cycles, so you cannot send data slower than this 37 | parameter WRITE_MEM_CLOCK_DELAY = 4, 38 | 39 | // Number of clk_memory cycles to hold the write_en signal high 40 | // Min 1. Component will assert this value is within the valid range 41 | parameter WRITE_MEM_EN_CYCLE_LENGTH = 1, 42 | 43 | // Word size in number of bytes. Can either be 1 (output 8 bits), or 2 (output 16 bits) 44 | // Component will assert this value is within the valid range 45 | parameter OUTPUT_WORD_SIZE = 1 46 | ) ( 47 | input wire clk_74a, 48 | input wire clk_memory, 49 | 50 | input wire bridge_wr, 51 | input wire bridge_endian_little, 52 | input wire [31:0] bridge_addr, 53 | input wire [31:0] bridge_wr_data, 54 | 55 | // These outputs are synced to the memory clock 56 | output reg write_en = 0, 57 | output reg [ADDRESS_SIZE:0] write_addr = 0, 58 | output reg [8 * OUTPUT_WORD_SIZE - 1:0] write_data = 0 59 | ); 60 | 61 | `define MAX(x, y) ((x > y) ? x : y) 62 | 63 | localparam WORD_SIZE = 8 * OUTPUT_WORD_SIZE; 64 | 65 | // Only use the lower 28 bits of the address 66 | localparam FIFO_SIZE = WORD_SIZE + 28; 67 | 68 | wire mem_empty; 69 | 70 | wire [FIFO_SIZE - 1:0] fifo_out; 71 | 72 | reg read_req = 0; 73 | reg write_req = 0; 74 | reg [31:0] shift_data; 75 | reg [27:0] buff_bridge_addr; 76 | 77 | wire [FIFO_SIZE - 1:0] fifo_in = {shift_data[WORD_SIZE-1:0], buff_bridge_addr[27:0]}; 78 | 79 | dcfifo dcfifo_component ( 80 | .data(fifo_in), 81 | .rdclk(clk_memory), 82 | .rdreq(read_req), 83 | .wrclk(clk_74a), 84 | .wrreq(write_req), 85 | .q(fifo_out), 86 | .rdempty(mem_empty) 87 | // .wrempty(), 88 | // .aclr(), 89 | // .eccstatus(), 90 | // .rdfull(), 91 | // .rdusedw(), 92 | // .wrfull(), 93 | // .wrusedw() 94 | ); 95 | defparam dcfifo_component.clocks_are_synchronized = "FALSE", 96 | dcfifo_component.intended_device_family = "Cyclone V", dcfifo_component.lpm_numwords = 4, 97 | dcfifo_component.lpm_showahead = "OFF", dcfifo_component.lpm_type = "dcfifo", 98 | dcfifo_component.lpm_width = FIFO_SIZE, dcfifo_component.lpm_widthu = 2, 99 | dcfifo_component.overflow_checking = "OFF", dcfifo_component.rdsync_delaypipe = 5, 100 | dcfifo_component.underflow_checking = "OFF", dcfifo_component.use_eab = "OFF", 101 | dcfifo_component.wrsync_delaypipe = 5; 102 | 103 | /// APF to Mem clock 104 | 105 | reg prev_bridge_wr = 0; 106 | reg [2:0] write_count = 0; 107 | reg [2:0] write_state = 0; 108 | 109 | localparam WRITE_START = 1; 110 | localparam WRITE_REQ_SHIFT = 2; 111 | 112 | // Receive APF writes and buffer them into the memory clock domain 113 | always @(posedge clk_74a) begin 114 | prev_bridge_wr <= bridge_wr; 115 | 116 | if (~prev_bridge_wr && bridge_wr && bridge_addr[31:28] == ADDRESS_MASK_UPPER_4) begin 117 | // Beginning APF write to core 118 | write_state <= WRITE_REQ_SHIFT; 119 | write_req <= 1; 120 | write_count <= 0; 121 | 122 | shift_data <= bridge_endian_little ? bridge_wr_data : { 123 | bridge_wr_data[7:0], bridge_wr_data[15:8], bridge_wr_data[23:16], bridge_wr_data[31:24] 124 | }; 125 | 126 | buff_bridge_addr <= bridge_addr[27:0]; 127 | end 128 | 129 | case (write_state) 130 | WRITE_START: begin 131 | write_req <= 1; 132 | 133 | write_state <= WRITE_REQ_SHIFT; 134 | end 135 | WRITE_REQ_SHIFT: begin 136 | write_req <= 0; 137 | 138 | // We will be writing again in the next cycle 139 | shift_data <= {8'h0, shift_data[31:WORD_SIZE]}; 140 | buff_bridge_addr <= buff_bridge_addr + OUTPUT_WORD_SIZE; 141 | 142 | write_count <= write_count + 1; 143 | 144 | if (write_count == (4 / OUTPUT_WORD_SIZE) - 1) begin 145 | // Finished write 146 | write_state <= 0; 147 | end else begin 148 | write_state <= WRITE_START; 149 | end 150 | end 151 | endcase 152 | end 153 | 154 | /// Mem clock to core 155 | 156 | reg [5:0] read_state = 0; 157 | 158 | localparam READ_DELAY = 1; 159 | localparam READ_WRITE = 2; 160 | localparam READ_WRITE_EN_CYCLE_OFF = READ_WRITE + WRITE_MEM_EN_CYCLE_LENGTH; 161 | localparam READ_WRITE_END_DEFAULT = WRITE_MEM_CLOCK_DELAY - 1; 162 | // Must use max to prevent READ_WRITE_END from being the same as READ_WRITE_EN_CYCLE_OFF 163 | localparam READ_WRITE_END = 164 | `MAX(READ_WRITE_END_DEFAULT, READ_WRITE_EN_CYCLE_OFF + 1); 165 | localparam HAS_DELAY = READ_WRITE_END_DEFAULT > READ_WRITE_EN_CYCLE_OFF; 166 | 167 | always @(posedge clk_memory) begin 168 | if (read_state != 0) begin 169 | read_state <= read_state + 1; 170 | end else if (~mem_empty) begin 171 | // Start read 172 | read_state <= READ_DELAY; 173 | read_req <= 1; 174 | end 175 | 176 | case (read_state) 177 | READ_DELAY: begin 178 | read_req <= 0; 179 | write_en <= 0; 180 | end 181 | READ_WRITE: begin 182 | // Read data is available 183 | write_en <= 1; 184 | 185 | // Lowest 28 bits are the address 186 | write_addr <= fifo_out[27:0]; 187 | 188 | write_data <= fifo_out[WORD_SIZE+27:28]; 189 | 190 | read_req <= 0; 191 | end 192 | READ_WRITE_EN_CYCLE_OFF: begin 193 | write_en <= 0; 194 | 195 | if (!HAS_DELAY) begin 196 | // No extra delay, immediately go back to start 197 | read_state <= 0; 198 | end 199 | end 200 | READ_WRITE_END: begin 201 | read_state <= 0; 202 | end 203 | endcase 204 | end 205 | 206 | initial begin 207 | // Verify parameters 208 | if (WRITE_MEM_CLOCK_DELAY < 4) begin 209 | $error("WRITE_MEM_CLOCK_DELAY has a minimum value of 4. Received %d", WRITE_MEM_CLOCK_DELAY); 210 | end 211 | 212 | if (WRITE_MEM_EN_CYCLE_LENGTH < 1 || WRITE_MEM_EN_CYCLE_LENGTH >= WRITE_MEM_CLOCK_DELAY - 2) begin 213 | $error( 214 | "WRITE_MEM_EN_CYCLE_LENGTH must be between 1 and %d (inclusive, based off of WRITE_MEM_CLOCK_DELAY). Received %d", 215 | WRITE_MEM_CLOCK_DELAY - 2 - 1, WRITE_MEM_EN_CYCLE_LENGTH); 216 | end 217 | 218 | if (OUTPUT_WORD_SIZE < 1 || OUTPUT_WORD_SIZE > 2) begin 219 | $error("OUTPUT_WORD_SIZE must be 1 or 2. Received %d", OUTPUT_WORD_SIZE); 220 | end 221 | end 222 | 223 | endmodule -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase.bsf: -------------------------------------------------------------------------------- 1 | /* 2 | WARNING: Do NOT edit the input and output ports in this file in a text 3 | editor if you plan to continue editing the block that represents it in 4 | the Block Editor! File corruption is VERY likely to occur. 5 | */ 6 | /* 7 | Copyright (C) 2018 Intel Corporation. All rights reserved. 8 | Your use of Intel Corporation's design tools, logic functions 9 | and other software and tools, and its AMPP partner logic 10 | functions, and any output files from any of the foregoing 11 | (including device programming or simulation files), and any 12 | associated documentation or information are expressly subject 13 | to the terms and conditions of the Intel Program License 14 | Subscription Agreement, the Intel Quartus Prime License Agreement, 15 | the Intel FPGA IP License Agreement, or other applicable license 16 | agreement, including, without limitation, that your use is for 17 | the sole purpose of programming logic devices manufactured by 18 | Intel and sold by Intel or its authorized distributors. Please 19 | refer to the applicable agreement for further details. 20 | */ 21 | (header "symbol" (version "1.1")) 22 | (symbol 23 | (rect 0 0 160 224) 24 | (text "mf_pllbase" (rect 48 -1 91 11)(font "Arial" (font_size 10))) 25 | (text "inst" (rect 8 208 20 220)(font "Arial" )) 26 | (port 27 | (pt 0 72) 28 | (input) 29 | (text "refclk" (rect 0 0 22 12)(font "Arial" (font_size 8))) 30 | (text "refclk" (rect 4 61 40 72)(font "Arial" (font_size 8))) 31 | (line (pt 0 72)(pt 48 72)(line_width 1)) 32 | ) 33 | (port 34 | (pt 0 112) 35 | (input) 36 | (text "rst" (rect 0 0 10 12)(font "Arial" (font_size 8))) 37 | (text "rst" (rect 4 101 22 112)(font "Arial" (font_size 8))) 38 | (line (pt 0 112)(pt 48 112)(line_width 1)) 39 | ) 40 | (port 41 | (pt 160 72) 42 | (output) 43 | (text "outclk_0" (rect 0 0 33 12)(font "Arial" (font_size 8))) 44 | (text "outclk_0" (rect 117 61 165 72)(font "Arial" (font_size 8))) 45 | (line (pt 160 72)(pt 112 72)(line_width 1)) 46 | ) 47 | (port 48 | (pt 160 112) 49 | (output) 50 | (text "outclk_1" (rect 0 0 31 12)(font "Arial" (font_size 8))) 51 | (text "outclk_1" (rect 119 101 167 112)(font "Arial" (font_size 8))) 52 | (line (pt 160 112)(pt 112 112)(line_width 1)) 53 | ) 54 | (port 55 | (pt 160 152) 56 | (output) 57 | (text "outclk_2" (rect 0 0 33 12)(font "Arial" (font_size 8))) 58 | (text "outclk_2" (rect 117 141 165 152)(font "Arial" (font_size 8))) 59 | (line (pt 160 152)(pt 112 152)(line_width 1)) 60 | ) 61 | (port 62 | (pt 160 192) 63 | (output) 64 | (text "locked" (rect 0 0 24 12)(font "Arial" (font_size 8))) 65 | (text "locked" (rect 127 181 163 192)(font "Arial" (font_size 8))) 66 | (line (pt 160 192)(pt 112 192)(line_width 1)) 67 | ) 68 | (drawing 69 | (text "refclk" (rect 16 43 68 99)(font "Arial" (color 128 0 0)(font_size 9))) 70 | (text "clk" (rect 53 67 124 144)(font "Arial" (color 0 0 0))) 71 | (text "reset" (rect 19 83 68 179)(font "Arial" (color 128 0 0)(font_size 9))) 72 | (text "reset" (rect 53 107 136 224)(font "Arial" (color 0 0 0))) 73 | (text "outclk0" (rect 113 43 268 99)(font "Arial" (color 128 0 0)(font_size 9))) 74 | (text "clk" (rect 97 67 212 144)(font "Arial" (color 0 0 0))) 75 | (text "outclk1" (rect 113 83 268 179)(font "Arial" (color 128 0 0)(font_size 9))) 76 | (text "clk" (rect 97 107 212 224)(font "Arial" (color 0 0 0))) 77 | (text "outclk2" (rect 113 123 268 259)(font "Arial" (color 128 0 0)(font_size 9))) 78 | (text "clk" (rect 97 147 212 304)(font "Arial" (color 0 0 0))) 79 | (text "locked" (rect 113 163 262 339)(font "Arial" (color 128 0 0)(font_size 9))) 80 | (text "export" (rect 82 187 200 384)(font "Arial" (color 0 0 0))) 81 | (text " altera_pll " (rect 118 208 308 426)(font "Arial" )) 82 | (line (pt 48 32)(pt 112 32)(line_width 1)) 83 | (line (pt 112 32)(pt 112 208)(line_width 1)) 84 | (line (pt 48 208)(pt 112 208)(line_width 1)) 85 | (line (pt 48 32)(pt 48 208)(line_width 1)) 86 | (line (pt 49 52)(pt 49 76)(line_width 1)) 87 | (line (pt 50 52)(pt 50 76)(line_width 1)) 88 | (line (pt 49 92)(pt 49 116)(line_width 1)) 89 | (line (pt 50 92)(pt 50 116)(line_width 1)) 90 | (line (pt 111 52)(pt 111 76)(line_width 1)) 91 | (line (pt 110 52)(pt 110 76)(line_width 1)) 92 | (line (pt 111 92)(pt 111 116)(line_width 1)) 93 | (line (pt 110 92)(pt 110 116)(line_width 1)) 94 | (line (pt 111 132)(pt 111 156)(line_width 1)) 95 | (line (pt 110 132)(pt 110 156)(line_width 1)) 96 | (line (pt 111 172)(pt 111 196)(line_width 1)) 97 | (line (pt 110 172)(pt 110 196)(line_width 1)) 98 | (line (pt 0 0)(pt 160 0)(line_width 1)) 99 | (line (pt 160 0)(pt 160 224)(line_width 1)) 100 | (line (pt 0 224)(pt 160 224)(line_width 1)) 101 | (line (pt 0 0)(pt 0 224)(line_width 1)) 102 | ) 103 | ) 104 | -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase.ppf: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase.sip: -------------------------------------------------------------------------------- 1 | set_global_assignment -entity "mf_pllbase" -library "lib_mf_pllbase" -name IP_TOOL_NAME "altera_pll" 2 | set_global_assignment -entity "mf_pllbase" -library "lib_mf_pllbase" -name IP_TOOL_VERSION "18.0" 3 | set_global_assignment -entity "mf_pllbase" -library "lib_mf_pllbase" -name IP_TOOL_ENV "mwpim" 4 | set_global_assignment -library "lib_mf_pllbase" -name SPD_FILE [file join $::quartus(sip_path) "mf_pllbase.spd"] 5 | 6 | set_global_assignment -library "lib_mf_pllbase" -name MISC_FILE [file join $::quartus(sip_path) "mf_pllbase_sim/mf_pllbase.vo"] 7 | -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase.spd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase/mf_pllbase_0002.qip: -------------------------------------------------------------------------------- 1 | set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*mf_pllbase_0002*|altera_pll:altera_pll_i*|*" 2 | 3 | set_instance_assignment -name PLL_AUTO_RESET OFF -to "*mf_pllbase_0002*|altera_pll:altera_pll_i*|*" 4 | set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*mf_pllbase_0002*|altera_pll:altera_pll_i*|*" 5 | -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase/mf_pllbase_0002.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/10ps 2 | module mf_pllbase_0002( 3 | 4 | // interface 'refclk' 5 | input wire refclk, 6 | 7 | // interface 'reset' 8 | input wire rst, 9 | 10 | // interface 'outclk0' 11 | output wire outclk_0, 12 | 13 | // interface 'outclk1' 14 | output wire outclk_1, 15 | 16 | // interface 'outclk2' 17 | output wire outclk_2, 18 | 19 | // interface 'locked' 20 | output wire locked 21 | ); 22 | 23 | altera_pll #( 24 | .fractional_vco_multiplier("false"), 25 | .reference_clock_frequency("74.25 MHz"), 26 | .operation_mode("direct"), 27 | .number_of_clocks(3), 28 | .output_clock_frequency0("12.000000 MHz"), 29 | .phase_shift0("0 ps"), 30 | .duty_cycle0(50), 31 | .output_clock_frequency1("6.000000 MHz"), 32 | .phase_shift1("0 ps"), 33 | .duty_cycle1(50), 34 | .output_clock_frequency2("6.000000 MHz"), 35 | .phase_shift2("41667 ps"), 36 | .duty_cycle2(50), 37 | .output_clock_frequency3("0 MHz"), 38 | .phase_shift3("0 ps"), 39 | .duty_cycle3(50), 40 | .output_clock_frequency4("0 MHz"), 41 | .phase_shift4("0 ps"), 42 | .duty_cycle4(50), 43 | .output_clock_frequency5("0 MHz"), 44 | .phase_shift5("0 ps"), 45 | .duty_cycle5(50), 46 | .output_clock_frequency6("0 MHz"), 47 | .phase_shift6("0 ps"), 48 | .duty_cycle6(50), 49 | .output_clock_frequency7("0 MHz"), 50 | .phase_shift7("0 ps"), 51 | .duty_cycle7(50), 52 | .output_clock_frequency8("0 MHz"), 53 | .phase_shift8("0 ps"), 54 | .duty_cycle8(50), 55 | .output_clock_frequency9("0 MHz"), 56 | .phase_shift9("0 ps"), 57 | .duty_cycle9(50), 58 | .output_clock_frequency10("0 MHz"), 59 | .phase_shift10("0 ps"), 60 | .duty_cycle10(50), 61 | .output_clock_frequency11("0 MHz"), 62 | .phase_shift11("0 ps"), 63 | .duty_cycle11(50), 64 | .output_clock_frequency12("0 MHz"), 65 | .phase_shift12("0 ps"), 66 | .duty_cycle12(50), 67 | .output_clock_frequency13("0 MHz"), 68 | .phase_shift13("0 ps"), 69 | .duty_cycle13(50), 70 | .output_clock_frequency14("0 MHz"), 71 | .phase_shift14("0 ps"), 72 | .duty_cycle14(50), 73 | .output_clock_frequency15("0 MHz"), 74 | .phase_shift15("0 ps"), 75 | .duty_cycle15(50), 76 | .output_clock_frequency16("0 MHz"), 77 | .phase_shift16("0 ps"), 78 | .duty_cycle16(50), 79 | .output_clock_frequency17("0 MHz"), 80 | .phase_shift17("0 ps"), 81 | .duty_cycle17(50), 82 | .pll_type("General"), 83 | .pll_subtype("General") 84 | ) altera_pll_i ( 85 | .rst (rst), 86 | .outclk ({outclk_2, outclk_1, outclk_0}), 87 | .locked (locked), 88 | .fboutclk ( ), 89 | .fbclk (1'b0), 90 | .refclk (refclk) 91 | ); 92 | endmodule 93 | 94 | -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase_sim.f: -------------------------------------------------------------------------------- 1 | mf_pllbase_sim/mf_pllbase.vo 2 | -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase_sim/aldec/rivierapro_setup.tcl: -------------------------------------------------------------------------------- 1 | 2 | # (C) 2001-2022 Altera Corporation. All rights reserved. 3 | # Your use of Altera Corporation's design tools, logic functions and 4 | # other software and tools, and its AMPP partner logic functions, and 5 | # any output files any of the foregoing (including device programming 6 | # or simulation files), and any associated documentation or information 7 | # are expressly subject to the terms and conditions of the Altera 8 | # Program License Subscription Agreement, Altera MegaCore Function 9 | # License Agreement, or other applicable license agreement, including, 10 | # without limitation, that your use is for the sole purpose of 11 | # programming logic devices manufactured by Altera and sold by Altera 12 | # or its authorized distributors. Please refer to the applicable 13 | # agreement for further details. 14 | 15 | # ACDS 18.0 614 win32 2022.09.16.12:00:45 16 | # ---------------------------------------- 17 | # Auto-generated simulation script rivierapro_setup.tcl 18 | # ---------------------------------------- 19 | # This script provides commands to simulate the following IP detected in 20 | # your Quartus project: 21 | # mf_pllbase 22 | # 23 | # Altera recommends that you source this Quartus-generated IP simulation 24 | # script from your own customized top-level script, and avoid editing this 25 | # generated script. 26 | # 27 | # To write a top-level script that compiles Altera simulation libraries and 28 | # the Quartus-generated IP in your project, along with your design and 29 | # testbench files, copy the text from the TOP-LEVEL TEMPLATE section below 30 | # into a new file, e.g. named "aldec.do", and modify the text as directed. 31 | # 32 | # ---------------------------------------- 33 | # # TOP-LEVEL TEMPLATE - BEGIN 34 | # # 35 | # # QSYS_SIMDIR is used in the Quartus-generated IP simulation script to 36 | # # construct paths to the files required to simulate the IP in your Quartus 37 | # # project. By default, the IP script assumes that you are launching the 38 | # # simulator from the IP script location. If launching from another 39 | # # location, set QSYS_SIMDIR to the output directory you specified when you 40 | # # generated the IP script, relative to the directory from which you launch 41 | # # the simulator. 42 | # # 43 | # set QSYS_SIMDIR