├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── BUG_REPORT.yml │ └── QUESTION.yml ├── .gitignore ├── LICENSE ├── README.md ├── docs └── PLL Reconfig.md ├── gateware.json ├── pkg └── pocket │ ├── Assets │ └── nes │ │ ├── agg23.NES │ │ └── palettes │ │ │ └── custom.pal │ │ └── common │ │ └── .gitkeep │ ├── Cores │ └── agg23.NES │ │ ├── audio.json │ │ ├── core.json │ │ ├── data.json │ │ ├── icon.bin │ │ ├── info.txt │ │ ├── input.json │ │ ├── interact.json │ │ ├── variants.json │ │ └── video.json │ └── Platforms │ ├── _images │ └── nes.bin │ └── nes.json ├── platform └── pocket │ ├── apf.qip │ ├── apf_constraints.sdc │ ├── apf_top.v │ ├── build_cdf.tcl │ ├── build_id_gen.tcl │ ├── common.v │ ├── io_bridge_peripheral.v │ ├── io_pad_controller.v │ ├── mf_datatable.qip │ ├── mf_datatable.v │ ├── mf_ddio_bidir_12.qip │ ├── mf_ddio_bidir_12.v │ └── pocket.tcl ├── projects ├── nes_pocket.qip ├── nes_pocket.qpf ├── nes_pocket.qsf └── nes_pocket.sdc ├── rtl ├── EEPROM_24C0x.sv ├── SOUND │ └── OPLL │ │ ├── OPLL.qip │ │ ├── VM2413 │ │ ├── attacktable.vhd │ │ ├── controller.vhd │ │ ├── envelopegenerator.vhd │ │ ├── envelopememory.vhd │ │ ├── feedbackmemory.vhd │ │ ├── lineartable.vhd │ │ ├── operator.vhd │ │ ├── opll.vhd │ │ ├── outputgenerator.vhd │ │ ├── outputmemory.vhd │ │ ├── phasegenerator.vhd │ │ ├── phasememory.vhd │ │ ├── registermemory.vhd │ │ ├── sinetable.vhd │ │ ├── slotcounter.vhd │ │ ├── temporalmixer.vhd │ │ ├── vm2413.vhd │ │ ├── voicememory.vhd │ │ └── voicerom.vhd │ │ └── eseopll.vhd ├── apu.sv ├── audio │ ├── audio.qip │ ├── audio_mixer.sv │ └── filters │ │ ├── audio_filters.sv │ │ ├── audio_mix.sv │ │ ├── dc_blocker.sv │ │ ├── filter_loader.sv │ │ ├── filters_rom.sv │ │ ├── iir_filter.sv │ │ └── iir_filter_tap.sv ├── bus_savestates.vhd ├── button_turbo.sv ├── cart.sv ├── cheatcodes.sv ├── compat.v ├── ddram.sv ├── dpram.vhd ├── dsp.v ├── font.chr ├── gameloader.sv ├── loopy_NSF.mif ├── mappers │ ├── FDS.sv │ ├── JYCompany.sv │ ├── MMC1.sv │ ├── MMC2.sv │ ├── MMC3.sv │ ├── MMC5.sv │ ├── Namco.sv │ ├── Sachen.sv │ ├── Sunsoft.sv │ ├── VRC.sv │ ├── generic.sv │ ├── mappers.qip │ └── misc.sv ├── miracle.sv ├── nes.qip ├── nes.v ├── nes_top.sv ├── nsf.asm ├── ppu.sv ├── regs_savestates.sv ├── savestate_ui.sv ├── savestates.vhd ├── sdram.sv ├── statemanager.vhd ├── t65 │ ├── T65.vhd │ ├── T65_ALU.vhd │ ├── T65_MCode.vhd │ ├── T65_Pack.vhd │ └── t65.qip ├── tao.mif ├── video.sv └── zapper.sv └── target └── pocket ├── core.qip ├── core_bridge_cmd.v ├── core_constraints.sdc ├── core_top.v ├── data_loader.sv ├── data_unloader.sv ├── mf_audio_pll.qip ├── mf_audio_pll.v ├── mf_audio_pll ├── mf_audio_pll_0002.qip └── mf_audio_pll_0002.v ├── mf_pllbase.ppf ├── mf_pllbase.qip ├── mf_pllbase.v ├── mf_pllbase ├── mf_pllbase_0002.qip └── mf_pllbase_0002.v ├── pll_reconfig.ppf ├── pll_reconfig.qip ├── pll_reconfig.v ├── pll_reconfig ├── altera_pll_reconfig_core.v ├── altera_pll_reconfig_top.v └── altera_std_synchronizer.v ├── save_state_controller.sv ├── sound_i2s.sv ├── stp1.stp └── sync_fifo.sv /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: agg23 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/BUG_REPORT.yml: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | # SPDX-License-Identifier: CC0-1.0 3 | # SPDX-FileType: OTHER 4 | # SPDX-FileCopyrightText: (c) 2022, OpenGateware authors and contributors, Adam Gastineau 5 | ##################################################################### 6 | name: "Bug Report" 7 | description: "Let us know about an unexpected error, a crash, or incorrect behavior." 8 | labels: 9 | - bug 10 | body: 11 | - type: markdown 12 | attributes: 13 | value: | 14 | Please note that the issue tracker is intended for bug reports. 15 | Make sure to [search for existing issues](https://github.com/agg23/openfpga-NES/issues) before filing a new one! 16 | 17 | - type: input 18 | id: version 19 | attributes: 20 | label: Version (or build number) 21 | placeholder: "0.1.0" 22 | description: | 23 | You can find the version in the About section, when you open the core. 24 | 25 | If you are not running the latest version, please try upgrading before reporting issues. 26 | validations: 27 | required: true 28 | 29 | - type: textarea 30 | id: steps 31 | attributes: 32 | label: Steps to reproduce 33 | description: | 34 | Please list the full steps required to reproduce the issue 35 | placeholder: | 36 | - Be precise 37 | - Include exact data used during testing for easy reference 38 | - The steps have to be in the exact order 39 | - Mention pre-requisites when applicable 40 | validations: 41 | required: false 42 | 43 | - type: textarea 44 | id: expected_behavior 45 | attributes: 46 | label: Expected Behavior 47 | description: If you want to include screenshots, paste them into the markdown editor below or follow up with a separate comment. 48 | placeholder: What were you expecting? 49 | validations: 50 | required: false 51 | 52 | - type: textarea 53 | id: actual_behavior 54 | attributes: 55 | label: Actual Behavior 56 | placeholder: What happened instead? 57 | validations: 58 | required: true 59 | 60 | - type: textarea 61 | id: bug_context 62 | attributes: 63 | label: Additional Context 64 | description: | 65 | Are there anything unusual about your situation that we should know? 66 | validations: 67 | required: false 68 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/QUESTION.yml: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | # SPDX-License-Identifier: CC0-1.0 3 | # SPDX-FileType: OTHER 4 | # SPDX-FileCopyrightText: (c) 2022, OpenGateware authors and contributors, Adam Gastineau 5 | ##################################################################### 6 | name: "Question" 7 | description: "Ask a question about the project." 8 | labels: 9 | - question 10 | body: 11 | - type: markdown 12 | attributes: 13 | value: | 14 | Please note that the issue tracker is intended for bug reports. 15 | Make sure to [search for existing issues](https://github.com/agg23/openfpga-NES/issues) before filing a new one! 16 | 17 | - type: textarea 18 | id: question 19 | attributes: 20 | label: Ask a question 21 | placeholder: | 22 | Ask your question here! Please keep the questions related to the core only. 23 | validations: 24 | required: true 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.rbf_r 2 | *.zip 3 | pkg/**/*.rev 4 | rtl/sim/work/ 5 | rtl/sim/*.hex 6 | rtl/sim/*.mem 7 | rtl/sim/*.bin 8 | 9 | # Quartus directories and files 10 | db 11 | greybox_tmp 12 | hps_isw_handoff 13 | incremental_db 14 | output_files 15 | PLLJ_PLLSPE_INFO.txt 16 | simulation 17 | vip 18 | .qsys_edit 19 | *_netlist 20 | *_sim 21 | *.bak 22 | *.bsf 23 | *.cdf 24 | *.cmp 25 | *.csv 26 | *.done 27 | *.f 28 | *.pin 29 | *.pof 30 | *.ptf.* 31 | *.qar 32 | *.qarlog 33 | *.qdf 34 | *.qws 35 | *.rbf 36 | *.rpt 37 | *.sip 38 | *.sld 39 | *.smsg 40 | *.sof 41 | *.sopc_builder 42 | *.sopcinfo 43 | *.spd 44 | *.summary 45 | *.txt 46 | *.xml 47 | *~ 48 | **/.DS_Store 49 | build_id.mif 50 | build_id.v 51 | c5_pin_model_dump.txt 52 | cr_ie_info.json 53 | # Gateman directories and files 54 | !.gateman/* 55 | !gateware.json 56 | !/pkg/* 57 | /pkg/**/*.rom 58 | /pkg/**/*.zip 59 | /staging/* 60 | /release/* 61 | # Editor directories and files 62 | .idea 63 | *.suo 64 | *.ntvs* 65 | *.njsproj 66 | *.sln 67 | *.sw? 68 | # Pocket directories and files 69 | !info.txt 70 | # ROMS Checklist 71 | !checklist.sha1 72 | !checklist.md5 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NES for Analogue Pocket 2 | 3 | Ported from the core originally developed by [Ludvig Strigeus](https://github.com/strigeus/fpganes) and heavily developed by [@sorgelig](https://github.com/sorgelig), [@greyrogue](https://github.com/greyrogue), [@Kitrinx](https://github.com/Kitrinx), [@paulb-nl](https://github.com/paulb-nl), and many more. Core icon by [spiritualized1997](https://github.com/spiritualized1997). Latest upstream available at https://github.com/MiSTer-devel/NES_MiSTer 4 | 5 | Please report any issues encountered to this repo. Most likely any problems are a result of my port, not the original core. Issues will be upstreamed as necessary. 6 | 7 | ## Installation 8 | 9 | ### Easy mode 10 | 11 | I highly recommend the updater tools by [@mattpannella](https://github.com/mattpannella) and [@RetroDriven](https://github.com/RetroDriven). If you're running Windows, use [the RetroDriven GUI](https://github.com/RetroDriven/Pocket_Updater), or if you prefer the CLI, use [the mattpannella tool](https://github.com/mattpannella/pocket_core_autoupdate_net). Either of these will allow you to automatically download and install openFPGA cores onto your Analogue Pocket. Go donate to them if you can 12 | 13 | ### Manual mode 14 | To install the core, copy the `Assets`, `Cores`, and `Platform` folders over to the root of your SD card. Please note that Finder on macOS automatically _replaces_ folders, rather than merging them like Windows does, so you have to manually merge the folders. 15 | 16 | ## Usage 17 | 18 | ROMs should be placed in `/Assets/nes/common` 19 | 20 | PAL ROMs should boot, but there will be timing and sound issues as the core currently doesn't properly support PAL (proper support coming soon). I highly recommend you do not play PAL games, and instead use NTSC games (if they exist) at this time. 21 | 22 | ## Features 23 | 24 | ### Dock Support 25 | 26 | Core supports four players/controllers via the Analogue Dock. To enable four player mode, turn on `Use Multitap` setting. 27 | 28 | ### Mappers 29 | 30 | This core has pairity with the MiSTer core's mapper support. [See the full breakdown here](https://github.com/MiSTer-devel/NES_MiSTer#supported-mappers). Please note that the VRC7 expansion audio chip is not supported in this core (but is in MiSTer) due to space constraints. 31 | 32 | ### Save States/Sleep + Wake 33 | 34 | Known as "Memories" on the Pocket, this core supports the creation and loading of save states for most mappers. See the full list in the [Mappers section](#mappers). By extension, the core supports Sleep + Wake functionality on the Pocket. In games with supported mappers, tapping the power button while playing will suspend the game, ready to be resumed when powering the Pocket back on. 35 | 36 | ### Saves 37 | 38 | Supports saves for most games and mappers. Saving on the NES is rather complicated due to the different scenarios for different mappers, so it's possible some less common mappers do not save correctly on this core. Please report all such issues to this repo. 39 | 40 | ### Controller Turbo 41 | 42 | By configuring the `Turbo Speed` controller option in `Core Settings`, you can use the `X` and `Y` buttons (by default) as `A`/`B` turbo buttons. The period for each of the settings in NTSC are below (PAL will have different timings): 43 | 44 | | Setting | Period | 45 | | ------- | ------ | 46 | | 0 | Off | 47 | | 1 | 3 Hz | 48 | | 2 | 5 Hz | 49 | | 3 | 7.5 Hz | 50 | | 4 | 10 Hz | 51 | | 5 | 15 Hz | 52 | | 6 | 30 Hz | 53 | 54 | ### Expansion Audio 55 | 56 | Expansion audio should be supported for every mapper except those that use VRC7. If you encounter a game that is not playing the expanded audio outside of VRC7, please report it. 57 | 58 | ### Palette Options 59 | 60 | The core has 5 palette options built in, changable in `Core Settings/Palette`. The palettes are known as: 61 | 62 | * Kitrinx 34 by Kitrinx 63 | * Smooth by FirebrandX (Default) 64 | * Wavebeam by NakedArthur 65 | * Sony CXA by FirebrandX 66 | * PC-10 Better by Kitrinx 67 | 68 | You can load external palettes as well. This palette is stored at `Assets/nes/agg23.NES/custom.pal`, and can be selected by the sixth option (`Custom`). 69 | 70 | For testing, or to temporarily load a new palette, you can choose the `Load Custom Palette` option (make sure to choose `Core Settings/Palette/Custom`). This palette selection is temporary, and will be reset when quitting and reopening the core. 71 | 72 | ### Video Options 73 | 74 | There are several options provided for tweaking the displayed video: 75 | 76 | * `Hide Overscan` - Hides the top and bottom 8 pixels of the video, which would normally be masked by the CRT. Adjusts the aspect ratio to correspond with this modification. This option does nothing in PAL mode 77 | * `Edge Masking` - Masks the sides of the screen in black, depending on the chosen option. The auto setting automatically masks the left side when certain conditions are met. 78 | * `Square Pixels` - The internal resolution of the NES is a 8:7 pixel aspect ratio (wide pixels), which roughly corresponds to what users would see on 4:3 display aspect ratio CRTs. Some games are designed to be displayed at 8:7 PAR (the core's default), and others at 1:1 PAR (square pixels). The `Square Pixels` option is provided to switch to a 1:1 pixel aspect ratio. 79 | * `Extra Sprites` - Allows an extra 8 sprites to be displayed per line (up to 16 from the original 8). Will decrease flickering in some games 80 | 81 | ### Lightguns 82 | 83 | Core supports virtual lightguns by enabling the "Use Zapper" setting. The crosshair can be controlled with the D-Pad or left joystick, using the A button to fire. D-Pad aim sensitivity can be adjusted with the "D-Pad Aim Speed" setting. 84 | 85 | **NOTE:** Joystick support for aiming only appears to work when a controller is paired over Bluetooth and not connected to the Analogue Dock directly by USB. 86 | -------------------------------------------------------------------------------- /docs/PLL Reconfig.md: -------------------------------------------------------------------------------- 1 | NTSC base clock: 21.477248 MHz 2 | PAL base clock: 21.281368 MHz 3 | 4 | # C Counter 5 | 6 | ## C0 7 | 8 | NTSC: 9 | Lo: 3 10 | Hi: 4 11 | Bypass: false 12 | Odd div: true 13 | 14 | 0x020403 15 | 16 | PAL: 17 | Lo: 4 18 | Hi: 4 19 | Bypass: false 20 | Odd div: false 21 | 22 | 0x000404 23 | 24 | ## C1 25 | 26 | NTSC: 27 | Lo: 14 28 | Hi: 14 29 | Bypass: false 30 | Odd div: false 31 | 32 | 0x040E0E 33 | 34 | PAL: 35 | Lo: 16 36 | Hi: 16 37 | Bypass: false 38 | Odd div: false 39 | 40 | 0x041010 41 | 42 | ## C2 43 | 44 | NTSC: 45 | Lo: 56 46 | Hi: 56 47 | Bypass: false 48 | Odd div: false 49 | 50 | 0x083838 51 | 52 | PAL: 53 | Lo: 64 54 | Hi: 64 55 | Bypass: false 56 | Odd div: false 57 | 58 | 0x084040 59 | 60 | ## C3 61 | 62 | NTSC: 63 | Lo: 56 64 | Hi: 56 65 | Bypass: false 66 | Odd div: false 67 | 68 | 0x0C3838 69 | 70 | PAL: 71 | Lo: 64 72 | Hi: 64 73 | Bypass: false 74 | Odd div: false 75 | // WARNING: Has prst3 value change from 29 to 33. This can't be represented in our reconfig 76 | 77 | 0x0C4040 78 | 79 | # M Counter 80 | 81 | NTSC: 82 | Lo: 4 83 | Hi: 4 84 | Bypass: false 85 | Odd div: false 86 | 87 | 0x00404 88 | 89 | PAL: 90 | Lo: 4 91 | Hi: 5 92 | Bypass: false 93 | Odd div: true 94 | 95 | 0x20504 96 | 97 | # Fractional division 98 | 99 | NTSC: 425907062 100 | PAL: 737738000 -------------------------------------------------------------------------------- /gateware.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nes", 3 | "displayName": "nes", 4 | "description": "Nintendo Entertainment System and Famicom. Nintendo's first home console", 5 | "author": "agg23", 6 | "version": "1.0.0", 7 | "license": "GPL-3.0-or-later", 8 | "repository": "https://github.com/agg23/openFPGA-NES", 9 | "keywords": [ 10 | "ecosystem:gateman" 11 | ], 12 | "scripts": { 13 | "verilator": "echo \"Error: no simulation specified\" && exit 1", 14 | "build:pocket": "quartus_sh --flow compile projects/nes_pocket.qpf", 15 | "program:pocket": "quartus_pgm -m jtag -c 1 -o \"p;projects/output_files/nes_pocket.sof@1\"" 16 | }, 17 | "platforms": { 18 | "pocket": "1.3.0" 19 | }, 20 | "modules": {} 21 | } -------------------------------------------------------------------------------- /pkg/pocket/Assets/nes/agg23.NES/palettes/custom.pal: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agg23/openfpga-NES/028501fb64cda7b126a817efeba1f69041bef5ee/pkg/pocket/Assets/nes/agg23.NES/palettes/custom.pal -------------------------------------------------------------------------------- /pkg/pocket/Assets/nes/common/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agg23/openfpga-NES/028501fb64cda7b126a817efeba1f69041bef5ee/pkg/pocket/Assets/nes/common/.gitkeep -------------------------------------------------------------------------------- /pkg/pocket/Cores/agg23.NES/audio.json: -------------------------------------------------------------------------------- 1 | { 2 | "audio": { 3 | "magic": "APF_VER_1" 4 | } 5 | } -------------------------------------------------------------------------------- /pkg/pocket/Cores/agg23.NES/core.json: -------------------------------------------------------------------------------- 1 | { 2 | "core": { 3 | "magic": "APF_VER_1", 4 | "metadata": { 5 | "platform_ids": [ 6 | "nes" 7 | ], 8 | "shortname": "NES", 9 | "description": "Nintendo Entertainment System and Famicom. Nintendo's first home console", 10 | "author": "agg23", 11 | "url": "https://github.com/agg23/openFPGA-NES", 12 | "version": "1.0.1", 13 | "date_release": "2024-09-16" 14 | }, 15 | "framework": { 16 | "target_product": "Analogue Pocket", 17 | "version_required": "1.1", 18 | "sleep_supported": true, 19 | "dock": { 20 | "supported": true, 21 | "analog_output": false 22 | }, 23 | "hardware": { 24 | "link_port": false, 25 | "cartridge_adapter": -1 26 | } 27 | }, 28 | "cores": [ 29 | { 30 | "name": "default", 31 | "id": 0, 32 | "filename": "nes.rev" 33 | } 34 | ] 35 | } 36 | } -------------------------------------------------------------------------------- /pkg/pocket/Cores/agg23.NES/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "magic": "APF_VER_1", 4 | "data_slots": [ 5 | { 6 | "name": "Cartridge", 7 | "id": 0, 8 | "required": true, 9 | "parameters": "0x109", 10 | "extensions": ["nes"], 11 | "address": "0x10000000" 12 | }, 13 | { 14 | "name": "Save", 15 | "id": 10, 16 | "required": false, 17 | "parameters": "0x84", 18 | "nonvolatile": true, 19 | "extensions": ["sav", "srm"], 20 | "address": "0x20000000", 21 | "size_maximum": "0x40000" 22 | }, 23 | { 24 | "name": "Custom Palette", 25 | "id": 11, 26 | "required": false, 27 | "filename": "palettes/custom.pal", 28 | "parameters": "0x3", 29 | "extensions": ["pal"], 30 | "size_maximum": "0xC0", 31 | "address": "0x10000000" 32 | } 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /pkg/pocket/Cores/agg23.NES/icon.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agg23/openfpga-NES/028501fb64cda7b126a817efeba1f69041bef5ee/pkg/pocket/Cores/agg23.NES/icon.bin -------------------------------------------------------------------------------- /pkg/pocket/Cores/agg23.NES/info.txt: -------------------------------------------------------------------------------- 1 | Port by agg23. Core by Ludvig Strigeus, sorgelig, greyrogue, Kitrinx, paulb-nl, and many others. 2 | 3 | Nintendo Entertainment System (NES), referred to as the Famicom in Japan was the first major home console produced by Nintendo. This console made gaming a household name, and is still popular to this day 4 | 5 | Core supports 4 controllers (when connected to the Dock), cartridge saves, and most mappers. Please report all issues to agg23, as most likely any issues experienced are issues with the port, not the core. -------------------------------------------------------------------------------- /pkg/pocket/Cores/agg23.NES/input.json: -------------------------------------------------------------------------------- 1 | { 2 | "input": { 3 | "magic": "APF_VER_1", 4 | "controllers": [ 5 | { 6 | "type": "default", 7 | "mappings": [ 8 | { 9 | "id": 0, 10 | "name": "A Button", 11 | "key": "pad_btn_a" 12 | }, 13 | { 14 | "id": 1, 15 | "name": "B Button", 16 | "key": "pad_btn_b" 17 | }, 18 | { 19 | "id": 4, 20 | "name": "A Turbo", 21 | "key": "pad_btn_x" 22 | }, 23 | { 24 | "id": 5, 25 | "name": "B Turbo", 26 | "key": "pad_btn_y" 27 | }, 28 | { 29 | "id": 2, 30 | "name": "Start", 31 | "key": "pad_btn_start" 32 | }, 33 | { 34 | "id": 3, 35 | "name": "Select", 36 | "key": "pad_btn_select" 37 | } 38 | ] 39 | } 40 | ] 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /pkg/pocket/Cores/agg23.NES/interact.json: -------------------------------------------------------------------------------- 1 | { 2 | "interact": { 3 | "magic": "APF_VER_1", 4 | "variables": [ 5 | { 6 | "name": "Reset core", 7 | "id": 10, 8 | "type": "action", 9 | "enabled": true, 10 | "address": "0x50", 11 | "value": 1 12 | }, 13 | { 14 | "name": "Use Multitap", 15 | "id": 20, 16 | "type": "check", 17 | "enabled": true, 18 | "address": "0x300", 19 | "persist": true, 20 | "writeonly": true, 21 | "defaultval": 0, 22 | "value": 1 23 | }, 24 | { 25 | "name": "Video Options", 26 | "id": 39, 27 | "type": "action", 28 | "enabled": false 29 | }, 30 | { 31 | "name": "Hide Overscan", 32 | "id": 40, 33 | "type": "check", 34 | "enabled": true, 35 | "address": "0x200", 36 | "persist": true, 37 | "writeonly": true, 38 | "defaultval": 1, 39 | "value": 1 40 | }, 41 | { 42 | "name": "Edge Masking", 43 | "id": 41, 44 | "type": "list", 45 | "enabled": true, 46 | "persist": true, 47 | "writeonly": true, 48 | "address": "0x204", 49 | "defaultval": 3, 50 | "options": [ 51 | { 52 | "value": 0, 53 | "name": "No Masking" 54 | }, 55 | { 56 | "value": 1, 57 | "name": "Mask Left" 58 | }, 59 | { 60 | "value": 2, 61 | "name": "Mask Both" 62 | }, 63 | { 64 | "value": 3, 65 | "name": "Auto Masking" 66 | } 67 | ] 68 | }, 69 | { 70 | "name": "Square Pixels", 71 | "id": 42, 72 | "type": "check", 73 | "enabled": true, 74 | "address": "0x210", 75 | "persist": true, 76 | "writeonly": true, 77 | "defaultval": 0, 78 | "value": 1 79 | }, 80 | { 81 | "name": "Extra Sprites", 82 | "id": 48, 83 | "type": "check", 84 | "enabled": true, 85 | "address": "0x208", 86 | "persist": true, 87 | "writeonly": true, 88 | "defaultval": 0, 89 | "value": 1 90 | }, 91 | { 92 | "name": "Palette", 93 | "id": 60, 94 | "type": "list", 95 | "enabled": true, 96 | "persist": true, 97 | "writeonly": true, 98 | "address": "0x20C", 99 | "defaultval": 1, 100 | "options": [ 101 | { 102 | "value": 0, 103 | "name": "Kitrinx 34" 104 | }, 105 | { 106 | "value": 1, 107 | "name": "Smooth" 108 | }, 109 | { 110 | "value": 2, 111 | "name": "Wavebeam" 112 | }, 113 | { 114 | "value": 3, 115 | "name": "Sony CXA" 116 | }, 117 | { 118 | "value": 4, 119 | "name": "PC-10 Better" 120 | }, 121 | { 122 | "value": 5, 123 | "name": "Custom" 124 | } 125 | ] 126 | }, 127 | { 128 | "name": "Controller Options", 129 | "id": 90, 130 | "type": "action", 131 | "enabled": false 132 | }, 133 | { 134 | "name": "Turbo Speed", 135 | "id": 91, 136 | "type": "slider_u32", 137 | "enabled": true, 138 | "address": "0x310", 139 | "persist": true, 140 | "writeonly": true, 141 | "defaultval": 0, 142 | "graphical": { 143 | "signed": false, 144 | "min": 0, 145 | "max": 6, 146 | "adjust_small": 1, 147 | "adjust_large": 1 148 | } 149 | }, 150 | { 151 | "name": "Swap P1 & P2", 152 | "id": 83, 153 | "type": "check", 154 | "enabled": true, 155 | "address": "0x30C", 156 | "persist": true, 157 | "writeonly": true, 158 | "defaultval": 0, 159 | "value": 1 160 | }, 161 | { 162 | "name": "Lightgun Options", 163 | "id": 80, 164 | "type": "action", 165 | "enabled": false 166 | }, 167 | { 168 | "name": "Use Zapper", 169 | "id": 81, 170 | "type": "check", 171 | "enabled": true, 172 | "address": "0x304", 173 | "persist": true, 174 | "writeonly": true, 175 | "defaultval": 0, 176 | "value": 1 177 | }, 178 | { 179 | "name": "D-Pad Aim Speed", 180 | "id": 82, 181 | "type": "slider_u32", 182 | "enabled": true, 183 | "address": "0x308", 184 | "persist": true, 185 | "writeonly": true, 186 | "defaultval": 3, 187 | "graphical": { 188 | "signed": false, 189 | "min": 1, 190 | "max": 10, 191 | "adjust_small": 1, 192 | "adjust_large": 4 193 | } 194 | } 195 | ], 196 | "messages": [] 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /pkg/pocket/Cores/agg23.NES/variants.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "magic": "APF_VER_1", 4 | "variant_list": [] 5 | } 6 | } -------------------------------------------------------------------------------- /pkg/pocket/Cores/agg23.NES/video.json: -------------------------------------------------------------------------------- 1 | { 2 | "video": { 3 | "magic": "APF_VER_1", 4 | "scaler_modes": [ 5 | { 6 | "width": 256, 7 | "height": 240, 8 | "aspect_w": 128, 9 | "aspect_h": 105, 10 | "rotation": 0, 11 | "mirror": 0 12 | }, 13 | { 14 | "width": 256, 15 | "height": 240, 16 | "aspect_w": 16, 17 | "aspect_h": 15, 18 | "rotation": 0, 19 | "mirror": 0 20 | }, 21 | { 22 | "width": 256, 23 | "height": 224, 24 | "aspect_w": 64, 25 | "aspect_h": 49, 26 | "rotation": 0, 27 | "mirror": 0 28 | }, 29 | { 30 | "width": 256, 31 | "height": 224, 32 | "aspect_w": 8, 33 | "aspect_h": 7, 34 | "rotation": 0, 35 | "mirror": 0 36 | } 37 | ], 38 | "display_modes": [ 39 | { 40 | "id": "0x10" 41 | }, 42 | { 43 | "id": "0x20" 44 | }, 45 | { 46 | "id": "0x30" 47 | }, 48 | { 49 | "id": "0x40" 50 | }, 51 | { 52 | "id": "0xE0" 53 | }, 54 | { 55 | "id": "0xE1" 56 | } 57 | ] 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /pkg/pocket/Platforms/_images/nes.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agg23/openfpga-NES/028501fb64cda7b126a817efeba1f69041bef5ee/pkg/pocket/Platforms/_images/nes.bin -------------------------------------------------------------------------------- /pkg/pocket/Platforms/nes.json: -------------------------------------------------------------------------------- 1 | { 2 | "platform": { 3 | "category": "Console", 4 | "name": "NES", 5 | "manufacturer": "Nintendo", 6 | "year": 1983 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /platform/pocket/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 | -------------------------------------------------------------------------------- /platform/pocket/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 | -------------------------------------------------------------------------------- /platform/pocket/build_cdf.tcl: -------------------------------------------------------------------------------- 1 | # ============================================================================== 2 | # SPDX-License-Identifier: CC0-1.0 3 | # SPDX-FileType: SOURCE 4 | # SPDX-FileCopyrightText: (c) 2022, OpenGateware authors and contributors 5 | # ============================================================================== 6 | # @file: build_cd.h 7 | # @brief: Generate a JTAG Chain Description File. 8 | # Create a .cdf file to be used with Quartus Prime Programmer 9 | # ============================================================================== 10 | proc createChainDescriptionFile {revision device outpath project_name} { 11 | set outputFileName "$project_name.cdf" 12 | set outputFile [open $outputFileName "w"] 13 | 14 | puts $outputFile "JedecChain;" 15 | puts $outputFile " FileRevision(JESD32A);" 16 | puts $outputFile " DefaultMfr(6E);" 17 | puts $outputFile "" 18 | puts $outputFile " P ActionCode(Cfg)" 19 | puts $outputFile " Device PartName($device) Path(\"$outpath/\") File(\"$revision.sof\") MfrSpec(OpMask(1));" 20 | puts $outputFile "ChainEnd;" 21 | puts $outputFile "" 22 | puts $outputFile "AlteraBegin;" 23 | puts $outputFile " ChainType(JTAG);" 24 | puts $outputFile "AlteraEnd;" 25 | } 26 | 27 | set project_name [lindex $quartus(args) 1] 28 | set revision [lindex $quartus(args) 2] 29 | 30 | if {[project_exists $project_name]} { 31 | if {[string equal "" $revision]} { 32 | project_open $project_name -revision [get_current_revision $project_name] 33 | } else { 34 | project_open $project_name -revision $revision 35 | } 36 | } else { 37 | post_message -type error "Project $project_name does not exist" 38 | exit 39 | } 40 | 41 | set device [get_global_assignment -name DEVICE] 42 | set outpath [get_global_assignment -name PROJECT_OUTPUT_DIRECTORY] 43 | 44 | if [is_project_open] { 45 | project_close 46 | } 47 | 48 | createChainDescriptionFile $revision $device $outpath $project_name 49 | -------------------------------------------------------------------------------- /platform/pocket/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 | -------------------------------------------------------------------------------- /platform/pocket/mf_datatable.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT" 2 | set_global_assignment -name IP_TOOL_VERSION "18.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 | -------------------------------------------------------------------------------- /platform/pocket/mf_ddio_bidir_12.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "ALTDDIO_BIDIR" 2 | set_global_assignment -name IP_TOOL_VERSION "18.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 | -------------------------------------------------------------------------------- /platform/pocket/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 | // altera_mf 13 | // ============================================================ 14 | // ************************************************************ 15 | // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! 16 | // 17 | // 18.1.1 Build 646 04/11/2019 SJ Lite Edition 18 | // ************************************************************ 19 | 20 | 21 | //Copyright (C) 2019 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 | // Retrieval info: LIB_FILE: altera_mf 135 | -------------------------------------------------------------------------------- /projects/nes_pocket.qip: -------------------------------------------------------------------------------- 1 | # ============================================================================== 2 | # Quartus Prime Platform Specific Modules File 3 | # Generated by OpenGateware - Gateman CLI v0.1.0 4 | # ============================================================================== 5 | # A single file that contains paths to platform specific third-party modules. 6 | # Quartus will use this file but won't edit it. 7 | # You need to edit it manually to add/remove files here. 8 | # ============================================================================== 9 | 10 | -------------------------------------------------------------------------------- /projects/nes_pocket.qpf: -------------------------------------------------------------------------------- 1 | # ============================================================================== 2 | # Quartus Prime Project File 3 | # Generated by OpenGateware - Gateman CLI v0.1.0 4 | # ============================================================================== 5 | 6 | QUARTUS_VERSION = "18.1" 7 | DATE = "16:33:14 September 23, 2023" 8 | 9 | # Revisions 10 | 11 | PROJECT_REVISION = "nes_pocket" 12 | -------------------------------------------------------------------------------- /projects/nes_pocket.qsf: -------------------------------------------------------------------------------- 1 | # ============================================================================== 2 | # Quartus Prime Settings File 3 | # Generated by OpenGateware - Gateman CLI v0.1.0 4 | # ============================================================================== 5 | # WARNING: DO NOT ADD FILES TO THE PROJECT VIA THE QUARTUS IDE! 6 | # Add them manually to nes_pocket.qip or Quartus will overwrite this file. 7 | # ============================================================================== 8 | 9 | # ============================================================================== 10 | # Project-Wide Assignments 11 | # ============================================================================== 12 | set_global_assignment -name ORIGINAL_QUARTUS_VERSION 18.1.1 13 | set_global_assignment -name LAST_QUARTUS_VERSION "21.1.1 Lite Edition" 14 | set_global_assignment -name TOP_LEVEL_ENTITY apf_top 15 | set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top 16 | set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top 17 | set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top 18 | set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files 19 | 20 | # ============================================================================== 21 | # Compiler Assignments 22 | # ============================================================================== 23 | set_global_assignment -name OPTIMIZATION_MODE "HIGH PERFORMANCE EFFORT" 24 | set_global_assignment -name SAVE_DISK_SPACE OFF 25 | set_global_assignment -name SEED 1 26 | set_global_assignment -name SMART_RECOMPILE ON 27 | 28 | # ============================================================================== 29 | # Analysis & Synthesis Assignments 30 | # ============================================================================== 31 | set_global_assignment -name ADV_NETLIST_OPT_SYNTH_WYSIWYG_REMAP ON 32 | set_global_assignment -name MUX_RESTRUCTURE OFF 33 | set_global_assignment -name OPTIMIZATION_TECHNIQUE SPEED 34 | set_global_assignment -name PRE_MAPPING_RESYNTHESIS ON 35 | set_global_assignment -name SAFE_STATE_MACHINE ON 36 | set_global_assignment -name SYNTH_PROTECT_SDC_CONSTRAINT ON 37 | 38 | # ============================================================================== 39 | # Fitter Assignments 40 | # ============================================================================== 41 | set_global_assignment -name ACTIVE_SERIAL_CLOCK FREQ_100MHZ 42 | set_global_assignment -name CRC_ERROR_OPEN_DRAIN ON 43 | set_global_assignment -name ECO_OPTIMIZE_TIMING ON 44 | set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 256 45 | set_global_assignment -name FITTER_EFFORT "AUTO FIT" 46 | set_global_assignment -name PERIPHERY_TO_CORE_PLACEMENT_AND_ROUTING_OPTIMIZATION ON 47 | set_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING ON 48 | set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC ON 49 | set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON 50 | set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON 51 | set_global_assignment -name ROUTER_CLOCKING_TOPOLOGY_ANALYSIS ON 52 | set_global_assignment -name ROUTER_LCELL_INSERTION_AND_LOGIC_DUPLICATION ON 53 | set_global_assignment -name STRATIXV_CONFIGURATION_SCHEME "PASSIVE SERIAL" 54 | 55 | # ============================================================================== 56 | # Platform/Core Assignments 57 | # ============================================================================== 58 | source ../platform/pocket/pocket.tcl 59 | set_global_assignment -name QIP_FILE nes_pocket.qip 60 | set_global_assignment -name SDC_FILE nes_pocket.sdc 61 | set_global_assignment -name QIP_FILE ../rtl/nes.qip 62 | 63 | # ============================================================================== 64 | 65 | 66 | set_global_assignment -name FITTER_AGGRESSIVE_ROUTABILITY_OPTIMIZATION ALWAYS 67 | set_global_assignment -name ALM_REGISTER_PACKING_EFFORT LOW 68 | set_global_assignment -name NUM_PARALLEL_PROCESSORS 4 69 | set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top -------------------------------------------------------------------------------- /projects/nes_pocket.sdc: -------------------------------------------------------------------------------- 1 | # ============================================================================== 2 | # Quartus Prime Synopsys Design Constraint File 3 | # Generated by OpenGateware - Gateman CLI v0.1.0 4 | # ============================================================================== 5 | # pocket SDC settings 6 | # Users are recommended to modify this file to match users logic. 7 | # Put your clock groups in here as well as any net assignments. 8 | # ============================================================================== 9 | 10 | # ============================================================================== 11 | # Time Information 12 | # ============================================================================== 13 | 14 | # ============================================================================== 15 | # Create Clock 16 | # ============================================================================== 17 | 18 | # ============================================================================== 19 | # Create Generated Clock 20 | # ============================================================================== 21 | 22 | # ============================================================================== 23 | # Set Clock Latency 24 | # ============================================================================== 25 | 26 | # ============================================================================== 27 | # Set Clock Uncertainty 28 | # ============================================================================== 29 | 30 | # ============================================================================== 31 | # Set Input Delay 32 | # ============================================================================== 33 | 34 | # ============================================================================== 35 | # Set Output Delay 36 | # ============================================================================== 37 | 38 | # ============================================================================== 39 | # Set Clock Groups 40 | # ============================================================================== 41 | 42 | # ============================================================================== 43 | # Set False Path 44 | # ============================================================================== 45 | 46 | # ============================================================================== 47 | # Set Multicycle Path 48 | # ============================================================================== 49 | 50 | # ============================================================================== 51 | # Set Maximum Delay 52 | # ============================================================================== 53 | 54 | # ============================================================================== 55 | # Set Minimum Delay 56 | # ============================================================================== 57 | 58 | # ============================================================================== 59 | # Set Input Transition 60 | # ============================================================================== 61 | 62 | -------------------------------------------------------------------------------- /rtl/EEPROM_24C0x.sv: -------------------------------------------------------------------------------- 1 | // 24C01, 24C02 EEPROM support 2 | // by GreyRogue for NES MiSTer 3 | 4 | module EEPROM_24C0x 5 | ( 6 | // Replace type_24C01 with EEPROM size and command size (Test State y/n and address bytes)? 7 | input type_24C01, // 24C01 is 128 bytes/no Test State?, 24C02 is 256 bytes/Test State 8 | input [ 3:0] page_mask, // Typically 0x3, 0x7, or 0xF; semi-correlated with size 9 | input no_test_state, // No control word (ID check/upper address bits); Usually only for X24C01 10 | input address_write_only, // Some models only set address in write mode (24C0xA?) 11 | input clk, 12 | input ce, 13 | input reset, 14 | input SCL, // Serial Clock 15 | input SDA_in, // Serial Data (same pin as below, split for convenience) 16 | output reg SDA_out, // Serial Data (same pin as above, split for convenience) 17 | input [ 2:0] E_id, // Chip Enable ID 18 | input WC_n, // ~Write Control 19 | input [ 7:0] data_from_ram, // Data read from RAM 20 | output [ 7:0] data_to_ram, // Data written to RAM 21 | output [ 7:0] ram_addr, // RAM Address 22 | output reg ram_read, // RAM read 23 | output reg ram_write, // RAM write 24 | input ram_done, // RAM access done 25 | // savestates 26 | input [63:0] SaveStateBus_Din, 27 | input [ 9:0] SaveStateBus_Adr, 28 | input SaveStateBus_wren, 29 | input SaveStateBus_rst, 30 | input SaveStateBus_load, 31 | output [63:0] SaveStateBus_Dout 32 | ); 33 | 34 | typedef enum bit [2:0] { 35 | STATE_STANDBY, 36 | STATE_TEST, 37 | STATE_ADDRESS, 38 | STATE_WRITE, 39 | STATE_READ 40 | } mystate; 41 | mystate state; 42 | 43 | reg [9:0] command; 44 | reg [7:0] address; 45 | reg [8:0] data; // 8 bits data, plus ack bit 46 | reg last_SCL; 47 | reg last_SDA; 48 | reg read_next; 49 | // Some X24C0x documents show it working with a test state, instead of combined address/read/write. 50 | // wire no_test_state = type_24C01; 51 | 52 | always @(posedge clk) if (reset) begin 53 | state <= STATE_STANDBY; 54 | command <= 0; 55 | last_SCL <= 0; 56 | last_SDA <= 0; 57 | SDA_out <= 1; // NoAck 58 | ram_read <= 0; 59 | ram_write <= 0; 60 | read_next <= 0; 61 | end else if (SaveStateBus_load) begin 62 | case (SS_MAP1[2:0]) 63 | 0: state <= STATE_STANDBY; 64 | 1: state <= STATE_TEST; 65 | 2: state <= STATE_ADDRESS; 66 | 3: state <= STATE_WRITE; 67 | 4: state <= STATE_READ; 68 | endcase 69 | command <= SS_MAP1[12: 3]; 70 | last_SCL <= SS_MAP1[ 13]; 71 | last_SDA <= SS_MAP1[ 14]; 72 | SDA_out <= SS_MAP1[ 15]; 73 | ram_read <= SS_MAP1[ 16]; 74 | ram_write <= SS_MAP1[ 17]; 75 | data <= SS_MAP1[26:18]; 76 | address <= SS_MAP1[34:27]; 77 | read_next <= SS_MAP1[ 35]; 78 | end else if (ce) begin 79 | last_SCL <= SCL; 80 | last_SDA <= SDA_in; 81 | if (ram_write && ram_done) begin 82 | ram_write <= 0; 83 | // address[3:0] <= (address[3:0] & ~page_mask) | (page_mask & (address[3:0] + 4'h1)); //Increment wraps at 4/8/16 byte boundary 84 | // Alternate for line above: 85 | address[3:0] <= address[3:0] + 4'h1; // Wrap at 4/8/16 byte boundary 86 | if (!page_mask[2]) begin 87 | address[2] <= address[2]; // Put back; Increment wraps at 4 byte boundary : mask = 0x3 88 | end 89 | if (!page_mask[3]) begin 90 | address[3] <= address[3]; // Put back; Increment wraps at 4/8 byte boundary : mask = 0x3 or 0x7 91 | end 92 | end 93 | if (ram_read && ram_done) begin 94 | ram_read <= 0; 95 | data <= {data_from_ram, 1'b1}; // NoAck at end 96 | end 97 | if (SCL && last_SCL && !SDA_in && last_SDA) begin 98 | if (no_test_state) state <= STATE_ADDRESS; 99 | else state <= STATE_TEST; 100 | command <= 10'd2; 101 | end else if (SCL && last_SCL && SDA_in && !last_SDA) begin 102 | state <= STATE_STANDBY; 103 | command <= 10'd0; 104 | end else if (state == STATE_STANDBY) begin 105 | // Do nothing 106 | end else if (SCL && !last_SCL) begin 107 | command <= {command[8:0], SDA_in}; 108 | end else if (!SCL && last_SCL) begin 109 | SDA_out <= 1; //NoAck 110 | if (state == STATE_READ) begin 111 | SDA_out <= data[8]; 112 | if (!ram_read) begin 113 | data[8:1] <= data[7:0]; 114 | end 115 | end 116 | if (command[9]) begin 117 | if (state == STATE_TEST) begin 118 | if (command[7:1] == {4'b1010, E_id}) begin 119 | if (command[0]) begin 120 | if (address_write_only) begin 121 | state <= STATE_READ; 122 | ram_read <= 1; 123 | end else begin 124 | state <= STATE_ADDRESS; 125 | end 126 | read_next <= 1; 127 | end else begin 128 | state <= STATE_ADDRESS; 129 | read_next <= 0; 130 | end 131 | SDA_out <= 0; //Ack 132 | end 133 | command <= 10'd1; 134 | end else if (state == STATE_ADDRESS) begin 135 | if (type_24C01) begin 136 | address <= {1'b0, command[7:1]}; 137 | if (command[0]) begin 138 | state <= STATE_READ; 139 | ram_read <= 1; 140 | end else begin 141 | state <= STATE_WRITE; 142 | end 143 | end else begin 144 | address <= command[7:0]; 145 | if (read_next & !address_write_only) begin 146 | state <= STATE_READ; 147 | ram_read <= 1; 148 | end else begin 149 | state <= STATE_WRITE; 150 | end 151 | end 152 | SDA_out <= 0; //Ack 153 | command <= 10'd1; 154 | end else if (state == STATE_WRITE) begin 155 | data <= {command[7:0], 1'b0}; 156 | if (!WC_n) begin 157 | ram_write <= 1; 158 | SDA_out <= 0; //Ack 159 | end 160 | command <= 10'd1; 161 | end else if (state == STATE_READ) begin 162 | ram_read <= 1; 163 | SDA_out <= 1; //NoAck 164 | address <= address + 8'b1; 165 | command <= 10'd1; 166 | end 167 | end 168 | end 169 | end 170 | 171 | assign ram_addr = (type_24C01 == 1) ? {1'b0, address[6:0]} : address; 172 | assign data_to_ram = data[8:1]; 173 | 174 | // savestate 175 | assign SS_MAP1_BACK[ 2: 0] = (state == STATE_STANDBY) ? 3'd0 : 176 | (state == STATE_TEST) ? 3'd1 : 177 | (state == STATE_ADDRESS) ? 3'd2 : 178 | (state == STATE_WRITE) ? 3'd3 : 179 | 3'd4; 180 | assign SS_MAP1_BACK[12: 3] = command; 181 | assign SS_MAP1_BACK[ 13] = last_SCL; 182 | assign SS_MAP1_BACK[ 14] = last_SDA; 183 | assign SS_MAP1_BACK[ 15] = SDA_out; 184 | assign SS_MAP1_BACK[ 16] = ram_read; 185 | assign SS_MAP1_BACK[ 17] = ram_write; 186 | assign SS_MAP1_BACK[26:18] = data; 187 | assign SS_MAP1_BACK[34:27] = address; 188 | assign SS_MAP1_BACK[ 35] = read_next; 189 | assign SS_MAP1_BACK[63:36] = 28'b0; // free to be used 190 | 191 | wire [63:0] SS_MAP1; 192 | wire [63:0] SS_MAP1_BACK; 193 | eReg_SavestateV #(SSREG_INDEX_L2MAP1, 64'h0000000000000000) iREG_SAVESTATE_MAP1 ( 194 | clk, 195 | SaveStateBus_Din, 196 | SaveStateBus_Adr, 197 | SaveStateBus_wren, 198 | SaveStateBus_rst, 199 | SaveStateBus_Dout, 200 | SS_MAP1_BACK, 201 | SS_MAP1 202 | ); 203 | 204 | endmodule 205 | -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/OPLL.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/attacktable.vhd ] 2 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/controller.vhd ] 3 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/envelopegenerator.vhd ] 4 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/envelopememory.vhd ] 5 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/feedbackmemory.vhd ] 6 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/lineartable.vhd ] 7 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/operator.vhd ] 8 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/opll.vhd ] 9 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/outputgenerator.vhd ] 10 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/outputmemory.vhd ] 11 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/phasegenerator.vhd ] 12 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/phasememory.vhd ] 13 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/registermemory.vhd ] 14 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/sinetable.vhd ] 15 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/slotcounter.vhd ] 16 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/temporalmixer.vhd ] 17 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/vm2413.vhd ] 18 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/voicememory.vhd ] 19 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) VM2413/voicerom.vhd ] 20 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) eseopll.vhd ] 21 | -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/VM2413/attacktable.vhd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agg23/openfpga-NES/028501fb64cda7b126a817efeba1f69041bef5ee/rtl/SOUND/OPLL/VM2413/attacktable.vhd -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/VM2413/controller.vhd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agg23/openfpga-NES/028501fb64cda7b126a817efeba1f69041bef5ee/rtl/SOUND/OPLL/VM2413/controller.vhd -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/VM2413/envelopegenerator.vhd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agg23/openfpga-NES/028501fb64cda7b126a817efeba1f69041bef5ee/rtl/SOUND/OPLL/VM2413/envelopegenerator.vhd -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/VM2413/envelopememory.vhd: -------------------------------------------------------------------------------- 1 | -- 2 | -- EnvelopeMemory.vhd 3 | -- 4 | -- Copyright (c) 2006 Mitsutaka Okazaki (brezza@pokipoki.org) 5 | -- All rights reserved. 6 | -- 7 | -- Redistribution and use of this source code or any derivative works, are 8 | -- permitted provided that the following conditions are met: 9 | -- 10 | -- 1. Redistributions of source code must retain the above copyright notice, 11 | -- this list of conditions and the following disclaimer. 12 | -- 2. Redistributions in binary form must reproduce the above copyright 13 | -- notice, this list of conditions and the following disclaimer in the 14 | -- documentation and/or other materials provided with the distribution. 15 | -- 3. Redistributions may not be sold, nor may they be used in a commercial 16 | -- product or activity without specific prior written permission. 17 | -- 18 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | -- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 | -- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 | -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | -- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | -- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | -- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25 | -- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | -- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 | -- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 | -- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -- 30 | -- 31 | library IEEE; 32 | use IEEE.STD_LOGIC_1164.ALL; 33 | use IEEE.STD_LOGIC_UNSIGNED.ALL; 34 | use WORK.VM2413.ALL; 35 | 36 | entity EnvelopeMemory is port ( 37 | clk : in std_logic; 38 | reset : in std_logic; 39 | 40 | waddr : in SLOT_TYPE; 41 | wr : in std_logic; 42 | wdata : in EGDATA_TYPE; 43 | raddr : in SLOT_TYPE; 44 | rdata : out EGDATA_TYPE 45 | ); 46 | end EnvelopeMemory; 47 | 48 | architecture RTL of EnvelopeMemory is 49 | 50 | type EGDATA_ARRAY is array (0 to 18-1) of EGDATA_VECTOR_TYPE; 51 | signal egdata_set : EGDATA_ARRAY; 52 | 53 | begin 54 | 55 | process (clk, reset) 56 | 57 | variable init_slot : integer range 0 to 18; 58 | 59 | begin 60 | 61 | if reset = '1' then 62 | 63 | init_slot := 0; 64 | 65 | elsif clk'event and clk = '1' then 66 | 67 | if init_slot /= 18 then 68 | egdata_set(init_slot) <= (others=>'1'); 69 | init_slot := init_slot + 1; 70 | elsif wr = '1' then 71 | egdata_set(conv_integer(waddr)) <= CONV_EGDATA_VECTOR(wdata); 72 | end if; 73 | rdata <= CONV_EGDATA(egdata_set(conv_integer(raddr))); 74 | 75 | end if; 76 | 77 | end process; 78 | 79 | end RTL; 80 | -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/VM2413/feedbackmemory.vhd: -------------------------------------------------------------------------------- 1 | -- 2 | -- FeedbackMemory.vhd 3 | -- 4 | -- Copyright (c) 2006 Mitsutaka Okazaki (brezza@pokipoki.org) 5 | -- All rights reserved. 6 | -- 7 | -- Redistribution and use of this source code or any derivative works, are 8 | -- permitted provided that the following conditions are met: 9 | -- 10 | -- 1. Redistributions of source code must retain the above copyright notice, 11 | -- this list of conditions and the following disclaimer. 12 | -- 2. Redistributions in binary form must reproduce the above copyright 13 | -- notice, this list of conditions and the following disclaimer in the 14 | -- documentation and/or other materials provided with the distribution. 15 | -- 3. Redistributions may not be sold, nor may they be used in a commercial 16 | -- product or activity without specific prior written permission. 17 | -- 18 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | -- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 | -- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 | -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | -- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | -- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | -- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25 | -- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | -- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 | -- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 | -- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -- 30 | -- 31 | library IEEE; 32 | use IEEE.STD_LOGIC_1164.ALL; 33 | use IEEE.STD_LOGIC_UNSIGNED.ALL; 34 | use WORK.VM2413.ALL; 35 | 36 | -- 37 | -- This module represents a store for feedback data of all OPLL channels. The feedback 38 | -- data is written by the OutputGenerator module. Then the value written is 39 | -- read from the Operator module. 40 | -- 41 | entity FeedbackMemory is port ( 42 | clk : in std_logic; 43 | reset : in std_logic; 44 | wr : in std_logic; 45 | waddr : in CH_TYPE; 46 | wdata : in SIGNED_LI_TYPE; 47 | raddr : in CH_TYPE; 48 | rdata : out SIGNED_LI_TYPE 49 | ); 50 | end FeedbackMemory; 51 | 52 | architecture RTL of FeedbackMemory is 53 | 54 | type SIGNED_LI_ARRAY_TYPE is array (0 to 9-1) of SIGNED_LI_VECTOR_TYPE; 55 | signal data_array : SIGNED_LI_ARRAY_TYPE; 56 | 57 | begin 58 | 59 | process(clk, reset) 60 | 61 | variable init_ch : integer range 0 to 9; 62 | 63 | begin 64 | 65 | if reset = '1' then 66 | 67 | init_ch := 0; 68 | 69 | elsif clk'event and clk='1' then 70 | 71 | if init_ch /= 9 then 72 | 73 | data_array(init_ch) <= (others=>'0'); 74 | init_ch := init_ch + 1; 75 | 76 | elsif wr='1' then 77 | 78 | data_array(waddr) <= CONV_SIGNED_LI_VECTOR(wdata); 79 | 80 | end if; 81 | 82 | rdata <= CONV_SIGNED_LI(data_array(raddr)); 83 | 84 | end if; 85 | 86 | end process; 87 | 88 | end RTL; -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/VM2413/lineartable.vhd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agg23/openfpga-NES/028501fb64cda7b126a817efeba1f69041bef5ee/rtl/SOUND/OPLL/VM2413/lineartable.vhd -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/VM2413/operator.vhd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agg23/openfpga-NES/028501fb64cda7b126a817efeba1f69041bef5ee/rtl/SOUND/OPLL/VM2413/operator.vhd -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/VM2413/outputgenerator.vhd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agg23/openfpga-NES/028501fb64cda7b126a817efeba1f69041bef5ee/rtl/SOUND/OPLL/VM2413/outputgenerator.vhd -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/VM2413/outputmemory.vhd: -------------------------------------------------------------------------------- 1 | -- 2 | -- OutputMemory.vhd 3 | -- 4 | -- Copyright (c) 2006 Mitsutaka Okazaki (brezza@pokipoki.org) 5 | -- All rights reserved. 6 | -- 7 | -- Redistribution and use of this source code or any derivative works, are 8 | -- permitted provided that the following conditions are met: 9 | -- 10 | -- 1. Redistributions of source code must retain the above copyright notice, 11 | -- this list of conditions and the following disclaimer. 12 | -- 2. Redistributions in binary form must reproduce the above copyright 13 | -- notice, this list of conditions and the following disclaimer in the 14 | -- documentation and/or other materials provided with the distribution. 15 | -- 3. Redistributions may not be sold, nor may they be used in a commercial 16 | -- product or activity without specific prior written permission. 17 | -- 18 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | -- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 | -- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 | -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | -- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | -- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | -- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25 | -- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | -- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 | -- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 | -- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -- 30 | -- 31 | library IEEE; 32 | use IEEE.STD_LOGIC_1164.ALL; 33 | use IEEE.STD_LOGIC_UNSIGNED.ALL; 34 | use WORK.VM2413.ALL; 35 | 36 | entity OutputMemory is port ( 37 | clk : in std_logic; 38 | reset : in std_logic; 39 | wr : in std_logic; 40 | addr : in SLOT_TYPE; 41 | wdata : in SIGNED_LI_TYPE; 42 | rdata : out SIGNED_LI_TYPE; 43 | addr2 : in SLOT_TYPE; 44 | rdata2 : out SIGNED_LI_TYPE 45 | ); 46 | end OutputMemory; 47 | 48 | architecture RTL of OutputMemory is 49 | 50 | type SIGNED_LI_ARRAY_TYPE is array (0 to 18) of SIGNED_LI_VECTOR_TYPE; 51 | signal data_array : SIGNED_LI_ARRAY_TYPE; 52 | 53 | begin 54 | 55 | process(clk, reset) 56 | 57 | variable init_ch : integer range 0 to 18; 58 | 59 | begin 60 | 61 | if (reset = '1') then 62 | 63 | init_ch := 0; 64 | 65 | elsif clk'event and clk='1' then 66 | 67 | if init_ch /= 18 then 68 | 69 | data_array(init_ch) <= (others=>'0'); 70 | init_ch := init_ch + 1; 71 | 72 | elsif wr='1' then 73 | 74 | data_array(conv_integer(addr)) <= CONV_SIGNED_LI_VECTOR(wdata); 75 | 76 | end if; 77 | 78 | rdata <= CONV_SIGNED_LI(data_array(conv_integer(addr))); 79 | rdata2 <= CONV_SIGNED_LI(data_array(conv_integer(addr2))); 80 | 81 | end if; 82 | 83 | end process; 84 | 85 | end RTL; -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/VM2413/phasegenerator.vhd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agg23/openfpga-NES/028501fb64cda7b126a817efeba1f69041bef5ee/rtl/SOUND/OPLL/VM2413/phasegenerator.vhd -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/VM2413/phasememory.vhd: -------------------------------------------------------------------------------- 1 | -- 2 | -- PhaseMemory.vhd 3 | -- 4 | -- Copyright (c) 2006 Mitsutaka Okazaki (brezza@pokipoki.org) 5 | -- All rights reserved. 6 | -- 7 | -- Redistribution and use of this source code or any derivative works, are 8 | -- permitted provided that the following conditions are met: 9 | -- 10 | -- 1. Redistributions of source code must retain the above copyright notice, 11 | -- this list of conditions and the following disclaimer. 12 | -- 2. Redistributions in binary form must reproduce the above copyright 13 | -- notice, this list of conditions and the following disclaimer in the 14 | -- documentation and/or other materials provided with the distribution. 15 | -- 3. Redistributions may not be sold, nor may they be used in a commercial 16 | -- product or activity without specific prior written permission. 17 | -- 18 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | -- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 | -- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 | -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | -- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | -- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | -- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25 | -- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | -- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 | -- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 | -- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -- 30 | -- 31 | library IEEE; 32 | use IEEE.STD_LOGIC_1164.ALL; 33 | use IEEE.STD_LOGIC_UNSIGNED.ALL; 34 | use WORK.VM2413.ALL; 35 | 36 | entity PhaseMemory is 37 | port ( 38 | clk : in std_logic; 39 | reset : in std_logic; 40 | slot : in SLOT_TYPE; 41 | memwr : in std_logic; 42 | memout : out PHASE_TYPE; 43 | memin : in PHASE_TYPE 44 | ); 45 | end PhaseMemory; 46 | 47 | architecture RTL of PhaseMemory is 48 | 49 | type PHASE_ARRAY_TYPE is array (0 to 18-1) of PHASE_TYPE; 50 | signal phase_array : PHASE_ARRAY_TYPE; 51 | 52 | begin 53 | 54 | process (clk, reset) 55 | 56 | variable init_slot : integer range 0 to 18; 57 | 58 | begin 59 | 60 | if reset = '1' then 61 | 62 | init_slot := 0; 63 | 64 | elsif clk'event and clk = '1' then 65 | 66 | if init_slot /= 18 then 67 | 68 | phase_array(init_slot) <= (others=>'0'); 69 | init_slot := init_slot + 1; 70 | 71 | elsif memwr = '1' then 72 | 73 | phase_array(conv_integer(slot)) <= memin; 74 | 75 | end if; 76 | 77 | memout <= phase_array(conv_integer(slot)); 78 | 79 | end if; 80 | 81 | end process; 82 | 83 | end RTL; -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/VM2413/registermemory.vhd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agg23/openfpga-NES/028501fb64cda7b126a817efeba1f69041bef5ee/rtl/SOUND/OPLL/VM2413/registermemory.vhd -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/VM2413/sinetable.vhd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agg23/openfpga-NES/028501fb64cda7b126a817efeba1f69041bef5ee/rtl/SOUND/OPLL/VM2413/sinetable.vhd -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/VM2413/slotcounter.vhd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agg23/openfpga-NES/028501fb64cda7b126a817efeba1f69041bef5ee/rtl/SOUND/OPLL/VM2413/slotcounter.vhd -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/VM2413/temporalmixer.vhd: -------------------------------------------------------------------------------- 1 | -- 2 | -- TemporalMixer.vhd 3 | -- 4 | -- Copyright (c) 2006 Mitsutaka Okazaki (brezza@pokipoki.org) 5 | -- All rights reserved. 6 | -- 7 | -- Redistribution and use of this source code or any derivative works, are 8 | -- permitted provided that the following conditions are met: 9 | -- 10 | -- 1. Redistributions of source code must retain the above copyright notice, 11 | -- this list of conditions and the following disclaimer. 12 | -- 2. Redistributions in binary form must reproduce the above copyright 13 | -- notice, this list of conditions and the following disclaimer in the 14 | -- documentation and/or other materials provided with the distribution. 15 | -- 3. Redistributions may not be sold, nor may they be used in a commercial 16 | -- product or activity without specific prior written permission. 17 | -- 18 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | -- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 | -- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 | -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | -- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | -- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | -- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25 | -- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | -- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 | -- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 | -- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -- 30 | -- 31 | library IEEE; 32 | use IEEE.STD_LOGIC_1164.ALL; 33 | use IEEE.STD_LOGIC_UNSIGNED.ALL; 34 | use ieee.std_logic_arith.all; 35 | use WORK.VM2413.ALL; 36 | 37 | entity TemporalMixer is 38 | port ( 39 | clk : in std_logic; 40 | reset : in std_logic; 41 | clkena : in std_logic; 42 | 43 | slot : in SLOT_TYPE; 44 | stage : in STAGE_TYPE; 45 | 46 | rhythm : in std_logic; 47 | 48 | maddr : out SLOT_TYPE; 49 | mdata : in SIGNED_LI_TYPE; 50 | 51 | mixout : out std_logic_vector(13 downto 0) 52 | ); 53 | end TemporalMixer; 54 | 55 | architecture RTL of TemporalMixer is 56 | 57 | signal mute : std_logic; 58 | signal mix : std_logic_vector(13 downto 0); 59 | 60 | begin 61 | 62 | process (clk, reset) 63 | begin 64 | 65 | if reset = '1' then 66 | 67 | maddr <= (others => '0'); 68 | mute <= '1'; 69 | mix <= (others =>'0'); 70 | mixout <= (others =>'0'); 71 | 72 | elsif clk'event and clk = '1' then if clkena='1' then 73 | 74 | if stage = 0 then 75 | 76 | if rhythm = '0' then 77 | 78 | case slot is 79 | when "00000" => maddr <= "00001"; mute <='0'; -- CH0 80 | when "00001" => maddr <= "00011"; mute <='0'; -- CH1 81 | when "00010" => maddr <= "00101"; mute <='0'; -- CH2 82 | when "00011" => mute <= '1'; 83 | when "00100" => mute <= '1'; 84 | when "00101" => mute <= '1'; 85 | when "00110" => maddr <= "00111"; mute<='0'; -- CH3 86 | when "00111" => maddr <= "01001"; mute<='0'; -- CH4 87 | when "01000" => maddr <= "01011"; mute<='0'; -- CH5 88 | when "01001" => mute <= '1'; 89 | when "01010" => mute <= '1'; 90 | when "01011" => mute <= '1'; 91 | --when "01100" => maddr <= "01101"; mute<='0'; -- CH6 92 | --when "01101" => maddr <= "01111"; mute<='0'; -- CH7 93 | --when "01110" => maddr <= "10001"; mute<='0'; -- CH8 94 | --VRC7 95 | when "01100" => mute<='1'; -- CH6 96 | when "01101" => mute<='1'; -- CH7 97 | when "01110" => mute<='1'; -- CH8 98 | when "01111" => mute <= '1'; 99 | when "10000" => mute <= '1'; 100 | when "10001" => mute <= '1'; 101 | when others => mute <= '1'; 102 | end case; 103 | 104 | else 105 | 106 | case slot is 107 | when "00000" => maddr <= "00001"; mute <='0'; -- CH0 108 | when "00001" => maddr <= "00011"; mute <='0'; -- CH1 109 | when "00010" => maddr <= "00101"; mute <='0'; -- CH2 110 | when "00011" => maddr <= "01111"; mute <='0'; -- SD 111 | when "00100" => maddr <= "10001"; mute <='0'; -- CYM 112 | when "00101" => mute <='1'; 113 | when "00110" => maddr <= "00111"; mute <='0'; -- CH3 114 | when "00111" => maddr <= "01001"; mute <='0'; -- CH4 115 | when "01000" => maddr <= "01011"; mute <='0'; -- CH5 116 | when "01001" => maddr <= "01110"; mute <='0'; -- HH 117 | when "01010" => maddr <= "10000"; mute <='0'; -- TOM 118 | when "01011" => maddr <= "01101"; mute <='0'; -- BD 119 | when "01100" => maddr <= "01111"; mute <='0'; -- SD 120 | when "01101" => maddr <= "10001"; mute <='0'; -- CYM 121 | when "01110" => maddr <= "01110"; mute <='0'; -- HH 122 | when "01111" => maddr <= "10000"; mute <='0'; -- TOM 123 | when "10000" => maddr <= "01101"; mute <='0'; -- BD 124 | when "10001" => mute <='1'; 125 | when others => mute <='1'; 126 | end case; 127 | 128 | end if; 129 | 130 | else 131 | if stage = 2 then 132 | if slot = "10001" then 133 | mixout <= mix; 134 | mix <= (others =>'0'); 135 | else 136 | if mute = '0' then 137 | if mdata.sign = '0' then 138 | mix <= mix + mdata.value; 139 | else 140 | mix <= mix - mdata.value; 141 | end if; 142 | end if; 143 | end if; 144 | end if; 145 | 146 | end if; 147 | 148 | end if; end if; 149 | 150 | end process; 151 | 152 | end RTL; -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/VM2413/voicememory.vhd: -------------------------------------------------------------------------------- 1 | -- 2 | -- VoiceMemory.vhd 3 | -- 4 | -- Copyright (c) 2006 Mitsutaka Okazaki (brezza@pokipoki.org) 5 | -- All rights reserved. 6 | -- 7 | -- Redistribution and use of this source code or any derivative works, are 8 | -- permitted provided that the following conditions are met: 9 | -- 10 | -- 1. Redistributions of source code must retain the above copyright notice, 11 | -- this list of conditions and the following disclaimer. 12 | -- 2. Redistributions in binary form must reproduce the above copyright 13 | -- notice, this list of conditions and the following disclaimer in the 14 | -- documentation and/or other materials provided with the distribution. 15 | -- 3. Redistributions may not be sold, nor may they be used in a commercial 16 | -- product or activity without specific prior written permission. 17 | -- 18 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | -- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 | -- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 | -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | -- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | -- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | -- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25 | -- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | -- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 | -- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 | -- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -- 30 | -- 31 | library IEEE; 32 | use IEEE.STD_LOGIC_1164.ALL; 33 | use IEEE.STD_LOGIC_UNSIGNED.ALL; 34 | use WORK.VM2413.ALL; 35 | 36 | entity VoiceMemory is 37 | port ( 38 | clk : in std_logic; 39 | reset : in std_logic; 40 | 41 | idata : in VOICE_TYPE; 42 | wr : in std_logic; 43 | rwaddr : in VOICE_ID_TYPE; -- read/write address 44 | roaddr : in VOICE_ID_TYPE; -- read only address 45 | odata : out VOICE_TYPE; 46 | rodata : out VOICE_TYPE 47 | ); 48 | end VoiceMemory; 49 | 50 | architecture RTL of VoiceMemory is 51 | 52 | -- The following array is mapped into a Single-Clock Synchronous RAM with two-read 53 | -- addresses by Altera's QuartusII compiler. 54 | type VOICE_ARRAY_TYPE is array (VOICE_ID_TYPE'range) of VOICE_VECTOR_TYPE; 55 | signal voices : VOICE_ARRAY_TYPE; 56 | 57 | component VoiceRom port ( 58 | clk : in std_logic; 59 | addr : in VOICE_ID_TYPE; 60 | data : out VOICE_TYPE 61 | ); 62 | end component; 63 | 64 | signal rom_addr : VOICE_ID_TYPE; 65 | signal rom_data : VOICE_TYPE; 66 | signal rstate : integer range 0 to 2; 67 | 68 | begin 69 | 70 | ROM2413 : VoiceRom port map(clk, rom_addr, rom_data); 71 | 72 | process (clk, reset) 73 | 74 | variable init_id : integer range 0 to VOICE_ID_TYPE'high+1; 75 | 76 | begin 77 | 78 | if reset = '1' then 79 | 80 | init_id := 0; 81 | rstate <= 0; 82 | 83 | elsif clk'event and clk = '1' then 84 | 85 | if init_id /= VOICE_ID_TYPE'high+1 then 86 | 87 | case rstate is 88 | when 0 => 89 | rom_addr <= init_id; 90 | rstate <= 1; 91 | when 1 => 92 | rstate <= 2; 93 | when 2 => 94 | voices(init_id) <= CONV_VOICE_VECTOR(rom_data); 95 | rstate <= 0; 96 | init_id := init_id + 1; 97 | end case; 98 | 99 | elsif wr = '1' then 100 | voices(rwaddr) <= CONV_VOICE_VECTOR(idata); 101 | end if; 102 | 103 | odata <= CONV_VOICE(voices(rwaddr)); 104 | rodata <= CONV_VOICE(voices(roaddr)); 105 | 106 | end if; 107 | 108 | end process; 109 | 110 | end RTL; -------------------------------------------------------------------------------- /rtl/SOUND/OPLL/eseopll.vhd: -------------------------------------------------------------------------------- 1 | -- 2 | -- eseopll.vhd 3 | -- A simple wrapper module for fitting VM2413 to ESE-MSX SYSTEM 4 | -- 5 | -- Copyright (c) 2006 Mitsutaka Okazaki (brezza@pokipoki.org) 6 | -- All rights reserved. 7 | -- 8 | -- Redistribution and use of this source code or any derivative works, are 9 | -- permitted provided that the following conditions are met: 10 | -- 11 | -- 1. Redistributions of source code must retain the above copyright notice, 12 | -- this list of conditions and the following disclaimer. 13 | -- 2. Redistributions in binary form must reproduce the above copyright 14 | -- notice, this list of conditions and the following disclaimer in the 15 | -- documentation and/or other materials provided with the distribution. 16 | -- 3. Redistributions may not be sold, nor may they be used in a commercial 17 | -- product or activity without specific prior written permission. 18 | -- 19 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | -- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 | -- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 | -- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 | -- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | -- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 | -- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 | -- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 | -- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 | -- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -- 31 | -- 32 | library IEEE; 33 | use IEEE.STD_LOGIC_1164.ALL; 34 | use IEEE.STD_LOGIC_UNSIGNED.ALL; 35 | use WORK.VM2413.ALL; 36 | 37 | entity eseopll is 38 | port( 39 | clk21m : in std_logic; 40 | reset : in std_logic; 41 | clkena : in std_logic; 42 | enawait : in std_logic; 43 | req : in std_logic; 44 | ack : out std_logic; 45 | wrt : in std_logic; 46 | adr : in std_logic_vector(15 downto 0); 47 | dbo : in std_logic_vector(7 downto 0); 48 | wav : out std_logic_vector(13 downto 0) 49 | ); 50 | end eseopll; 51 | 52 | architecture RTL of eseopll is 53 | 54 | signal XIN : std_logic; 55 | signal D : std_logic_vector(7 downto 0); 56 | signal A : std_logic; 57 | signal CS_n : std_logic; 58 | signal WE_n : std_logic; 59 | signal IC_n : std_logic; 60 | signal MO : std_logic_vector(9 downto 0); 61 | signal RO : std_logic_vector(9 downto 0); 62 | 63 | signal counter : integer range 0 to 72*6; 64 | 65 | signal A_buf : std_logic; 66 | signal dbo_buf : std_logic_vector(7 downto 0); 67 | signal CS_n_buf : std_logic; 68 | signal WE_n_buf : std_logic; 69 | 70 | begin 71 | 72 | IC_n <= not reset; 73 | 74 | process (clk21m, reset) 75 | 76 | begin 77 | 78 | if reset = '1' then 79 | 80 | counter <= 0; 81 | 82 | elsif clk21m'event and clk21m = '1' then 83 | 84 | if counter /= 0 then 85 | counter <= counter - 1; 86 | ack <= '0'; 87 | else 88 | if req = '1' then 89 | if enawait = '1' then 90 | if adr(0) = '0' then 91 | counter <= 4*6; 92 | else 93 | counter <= 72*6; 94 | end if; 95 | end if; 96 | A_buf <= adr(0); 97 | dbo_buf <= dbo; 98 | CS_n_buf <= not req; 99 | WE_n_buf <= not wrt; 100 | end if; 101 | ack <= req; 102 | end if; 103 | 104 | if (clkena = '1') then 105 | 106 | A <= A_buf; 107 | D <= dbo_buf; 108 | CS_n <= CS_n_buf; 109 | WE_n <= WE_n_buf; 110 | 111 | end if; 112 | 113 | end if; 114 | 115 | end process; 116 | 117 | U1 : opll port map (clk21m, open, clkena, D, A, CS_n, WE_n, IC_n, wav); 118 | 119 | end RTL; 120 | -------------------------------------------------------------------------------- /rtl/audio/audio.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "audio_mixer.sv"] 2 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "filters/audio_filters.sv"] 3 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "filters/audio_mix.sv"] 4 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "filters/dc_blocker.sv"] 5 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "filters/filter_loader.sv"] 6 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "filters/filters_rom.sv"] 7 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "filters/iir_filter_tap.sv"] 8 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "filters/iir_filter.sv"] -------------------------------------------------------------------------------- /rtl/audio/audio_mixer.sv: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // SPDX-License-Identifier: MIT 3 | // SPDX-FileType: SOURCE 4 | // SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors 5 | //------------------------------------------------------------------------------ 6 | // 7 | // Analogue Pocket Audio Mixer 8 | // 9 | // Copyright (c) 2023, Marcus Andrade 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | // SOFTWARE. 28 | // 29 | //------------------------------------------------------------------------------ 30 | 31 | `default_nettype none 32 | 33 | module audio_mixer #( 34 | parameter DW = 16, //! Audio Data Width 35 | // parameter MUTE_PAUSE = 1, //! Mute on Pause 36 | parameter STEREO = 1 //! Stereo Audio 37 | ) ( 38 | // Clocks and Reset 39 | input logic clk_74b, //! Clock 74.25Mhz 40 | input logic clk_audio, 41 | input logic reset, //! Reset 42 | // Controls 43 | // input logic [ 3:0] afilter_sw, //! Predefined Audio Filter Switch 44 | input logic [ 3:0] vol_att, //! Volume ([0] Max | [7] Min) 45 | input logic [ 1:0] mix, //! [0] No Mix | [1] 25% | [2] 50% | [3] 100% (mono) 46 | // input logic pause_core, //! Mute Audio 47 | // Audio From Core 48 | input logic is_signed, //! Signed Audio 49 | input logic [DW-1:0] core_l, //! Left Channel Audio from Core 50 | input logic [DW-1:0] core_r, //! Right Channel Audio from Core 51 | // Pocket I2S 52 | output logic audio_mclk, //! Serial Master Clock 53 | output logic audio_lrck, //! Left/Right clock 54 | output logic audio_dac //! Serialized data 55 | ); 56 | 57 | //! ------------------------------------------------------------------------ 58 | //! Audio Clocks 59 | //! MCLK: 12.288MHz (256*Fs, where Fs = 48000) 60 | //! SCLK: 3.072mhz (MCLK/4) 61 | //! ------------------------------------------------------------------------ 62 | wire audio_sclk; 63 | 64 | mf_audio_pll audio_pll ( 65 | .refclk (clk_74b), 66 | .rst (0), 67 | .outclk_0(audio_mclk), 68 | .outclk_1(audio_sclk) 69 | ); 70 | 71 | //! ------------------------------------------------------------------------ 72 | //! Pad core_l/core_r with zeros to maintain a consistent size of 16 bits 73 | //! ------------------------------------------------------------------------ 74 | logic [15:0] core_al, core_ar; 75 | 76 | always_comb begin 77 | core_al = DW == 16 ? core_l : {core_l, {16 - DW{1'b0}}}; 78 | core_ar = STEREO ? DW == 16 ? core_r : {core_r, {16 - DW{1'b0}}} : core_al; 79 | end 80 | 81 | //! ------------------------------------------------------------------------ 82 | //! Low Pass Filter 83 | //! ------------------------------------------------------------------------ 84 | reg [31:0] aflt_rate = 32'd7056000; // Sampling Frequency 85 | reg [39:0] acx = 40'd4258969; // Base gain 86 | reg [ 7:0] acx0 = 8'd3; // gain scale for X0 87 | reg [ 7:0] acx1 = 8'd3; // gain scale for X1 88 | reg [ 7:0] acx2 = 8'd1; // gain scale for X2 89 | reg [23:0] acy0 = -24'd6216759; // gain scale for Y0 90 | reg [23:0] acy1 = 24'd6143386; // gain scale for Y1 91 | reg [23:0] acy2 = -24'd2023767; // gain scale for Y2 92 | 93 | // logic [31:0] aflt_rate; 94 | // logic [39:0] acx; 95 | // logic [7:0] acx0, acx1, acx2; 96 | // logic [23:0] acy0, acy1, acy2; 97 | 98 | // arcade_filters arcade_filters 99 | // ( 100 | // .clk ( audio_mclk ), 101 | // .afilter_sw ( afilter_sw ), 102 | // .aflt_rate ( aflt_rate ), 103 | // .acx ( acx ), 104 | // .acx0 ( acx0 ), 105 | // .acx1 ( acx1 ), 106 | // .acx2 ( acx2 ), 107 | // .acy0 ( acy0 ), 108 | // .acy1 ( acy1 ), 109 | // .acy2 ( acy2 ) 110 | // ); 111 | 112 | //! ------------------------------------------------------------------------ 113 | //! Synchronization 114 | //! ------------------------------------------------------------------------ 115 | 116 | logic [15:0] core_al_s, core_ar_s; 117 | 118 | sync_fifo #( 119 | .WIDTH(32) 120 | ) sync_fifo ( 121 | .clk_write(clk_audio), 122 | .clk_read (audio_mclk), 123 | 124 | .write_en(write_en), 125 | .data({core_al, core_ar}), 126 | .data_s({core_al_s, core_ar_s}) 127 | ); 128 | 129 | reg write_en = 0; 130 | reg [15:0] prev_left; 131 | reg [15:0] prev_right; 132 | 133 | // Mark write when necessary 134 | always @(posedge clk_audio) begin 135 | prev_left <= core_al; 136 | prev_right <= core_ar; 137 | 138 | write_en <= 0; 139 | 140 | if (core_al != prev_left || core_ar != prev_right) begin 141 | write_en <= 1; 142 | end 143 | end 144 | 145 | //! ------------------------------------------------------------------------ 146 | //! Audio Filters 147 | //! ------------------------------------------------------------------------ 148 | logic [15:0] audio_l, audio_r; 149 | // logic mute_audio = MUTE_PAUSE ? pause_core : 1'b0; 150 | 151 | audio_filters audio_filters ( 152 | .clk (audio_mclk), 153 | .reset (reset), 154 | // Controls 155 | .att ({1'b0, vol_att}), 156 | .mix (mix), 157 | // Audio Filter 158 | .flt_rate (aflt_rate), 159 | .cx (acx), 160 | .cx0 (acx0), 161 | .cx1 (acx1), 162 | .cx2 (acx2), 163 | .cy0 (acy0), 164 | .cy1 (acy1), 165 | .cy2 (acy2), 166 | // Audio from Core 167 | .is_signed(is_signed), 168 | .core_l (core_al_s), 169 | .core_r (core_ar_s), 170 | // Filtered Audio Output 171 | .audio_l (audio_l), 172 | .audio_r (audio_r) 173 | ); 174 | 175 | //! ------------------------------------------------------------------------ 176 | //! Pocket I2S Output 177 | //! ------------------------------------------------------------------------ 178 | 179 | sound_i2s sound_i2s ( 180 | .audio_sclk(audio_sclk), 181 | 182 | .audio_l(audio_l), 183 | .audio_r(audio_r), 184 | 185 | .audio_lrck(audio_lrck), 186 | .audio_dac (audio_dac) 187 | ); 188 | 189 | endmodule 190 | -------------------------------------------------------------------------------- /rtl/audio/filters/audio_filters.sv: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // SPDX-License-Identifier: GPL-3.0-or-later 3 | // SPDX-FileType: SOURCE 4 | // SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors 5 | //------------------------------------------------------------------------------ 6 | // 7 | // Audio Filters 8 | // 9 | // Copyright (c) 2023, Marcus Andrade 10 | // Copyright (c) 2020, Alexey Melnikov 11 | // 12 | // This source file is free software: you can redistribute it and/or modify 13 | // it under the terms of the GNU General Public License as published 14 | // by the Free Software Foundation, either version 3 of the License, or 15 | // (at your option) any later version. 16 | // 17 | // This program is distributed in the hope that it will be useful, but 18 | // WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | // General Public License for more details. 21 | // 22 | // You should have received a copy of the GNU General Public License 23 | // along with this program. If not, see . 24 | // 25 | //------------------------------------------------------------------------------ 26 | 27 | `default_nettype none 28 | 29 | module audio_filters 30 | #( 31 | parameter CLK_RATE = 12288000 32 | ) ( 33 | input wire clk, 34 | input wire reset, 35 | 36 | input wire [31:0] flt_rate, 37 | input wire [39:0] cx, 38 | input wire [7:0] cx0, 39 | input wire [7:0] cx1, 40 | input wire [7:0] cx2, 41 | input wire [23:0] cy0, 42 | input wire [23:0] cy1, 43 | input wire [23:0] cy2, 44 | input wire [4:0] att, 45 | 46 | input wire is_signed, 47 | input wire [1:0] mix, 48 | 49 | input wire [15:0] core_l, 50 | input wire [15:0] core_r, 51 | 52 | // Audio Output 53 | output wire [15:0] audio_l, 54 | output wire [15:0] audio_r 55 | ); 56 | 57 | reg sample_rate = 0; //0 - 48KHz, 1 - 96KHz 58 | 59 | reg sample_ce; 60 | always @(posedge clk) begin 61 | reg [8:0] div = 0; 62 | reg [1:0] add = 0; 63 | 64 | div <= div + add; 65 | if(!div) begin 66 | div <= 2'd1 << sample_rate; 67 | add <= 2'd1 << sample_rate; 68 | end 69 | 70 | sample_ce <= !div; 71 | end 72 | 73 | reg flt_ce; 74 | always @(posedge clk) begin 75 | reg [31:0] cnt = 0; 76 | 77 | flt_ce = 0; 78 | cnt = cnt + {flt_rate[30:0],1'b0}; 79 | if(cnt >= CLK_RATE) begin 80 | cnt = cnt - CLK_RATE; 81 | flt_ce = 1; 82 | end 83 | end 84 | 85 | reg [15:0] cl,cr; 86 | always @(posedge clk) begin 87 | reg [15:0] cl1, cl2; 88 | reg [15:0] cr1, cr2; 89 | 90 | cl1 <= core_l; 91 | cl2 <= cl1; 92 | if(cl2 == cl1) 93 | cl <= cl2; 94 | 95 | cr1 <= core_r; 96 | cr2 <= cr1; 97 | if(cr2 == cr1) 98 | cr <= cr2; 99 | end 100 | 101 | reg a_en1 = 0, a_en2 = 0; 102 | always @(posedge clk, posedge reset) begin 103 | reg [1:0] dly1; 104 | reg [14:0] dly2; 105 | 106 | if(reset) begin 107 | dly1 <= 0; 108 | dly2 <= 0; 109 | a_en1 <= 0; 110 | a_en2 <= 0; 111 | end 112 | else begin 113 | if(flt_ce) begin 114 | if(~&dly1) 115 | dly1 <= dly1 + 1'd1; 116 | else 117 | a_en1 <= 1; 118 | end 119 | 120 | if(sample_ce) begin 121 | if(!dly2[13+sample_rate]) 122 | dly2 <= dly2 + 1'd1; 123 | else 124 | a_en2 <= 1; 125 | end 126 | end 127 | end 128 | 129 | wire [15:0] acl, acr; 130 | iir_filter #(.use_params(0)) iir_filter 131 | ( 132 | .clk ( clk ), 133 | .reset ( reset ), 134 | 135 | .ce ( flt_ce & a_en1 ), 136 | .sample_ce ( sample_ce ), 137 | 138 | .cx ( cx ), 139 | .cx0 ( cx0 ), 140 | .cx1 ( cx1 ), 141 | .cx2 ( cx2 ), 142 | .cy0 ( cy0 ), 143 | .cy1 ( cy1 ), 144 | .cy2 ( cy2 ), 145 | 146 | .input_l ( {~is_signed ^ cl[15], cl[14:0]} ), 147 | .input_r ( {~is_signed ^ cr[15], cr[14:0]} ), 148 | .output_l ( acl ), 149 | .output_r ( acr ) 150 | ); 151 | 152 | wire [15:0] adl; 153 | dc_blocker dcb_l 154 | ( 155 | .clk ( clk ), 156 | .ce ( sample_ce ), 157 | .sample_rate ( sample_rate ), 158 | .mute ( ~a_en2 ), 159 | .din ( acl ), 160 | .dout ( adl ) 161 | ); 162 | 163 | wire [15:0] adr; 164 | dc_blocker dcb_r 165 | ( 166 | .clk ( clk ), 167 | .ce ( sample_ce ), 168 | .sample_rate ( sample_rate ), 169 | .mute ( ~a_en2 ), 170 | .din ( acr ), 171 | .dout ( adr ) 172 | ); 173 | 174 | wire [15:0] audio_l_pre; 175 | audio_mix audmix_l 176 | ( 177 | .clk ( clk ), 178 | .ce ( sample_ce ), 179 | .att ( att ), 180 | .mix ( mix ), 181 | 182 | .core_audio ( adl ), 183 | .pre_in ( audio_r_pre ), 184 | 185 | .pre_out ( audio_l_pre ), 186 | .out ( audio_l ) 187 | ); 188 | 189 | wire [15:0] audio_r_pre; 190 | audio_mix audmix_r 191 | ( 192 | .clk ( clk ), 193 | .ce ( sample_ce ), 194 | .att ( att ), 195 | .mix ( mix ), 196 | 197 | .core_audio ( adr ), 198 | .pre_in ( audio_l_pre ), 199 | 200 | .pre_out ( audio_r_pre ), 201 | .out ( audio_r ) 202 | ); 203 | 204 | endmodule 205 | -------------------------------------------------------------------------------- /rtl/audio/filters/audio_mix.sv: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // SPDX-License-Identifier: GPL-3.0-or-later 3 | // SPDX-FileType: SOURCE 4 | // SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors 5 | //------------------------------------------------------------------------------ 6 | // 7 | // Audio Mix 8 | // 9 | // Copyright (c) 2023, Marcus Andrade 10 | // Copyright (c) 2020, Alexey Melnikov 11 | // 12 | // This source file is free software: you can redistribute it and/or modify 13 | // it under the terms of the GNU General Public License as published 14 | // by the Free Software Foundation, either version 3 of the License, or 15 | // (at your option) any later version. 16 | // 17 | // This program is distributed in the hope that it will be useful, but 18 | // WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | // General Public License for more details. 21 | // 22 | // You should have received a copy of the GNU General Public License 23 | // along with this program. If not, see . 24 | // 25 | //------------------------------------------------------------------------------ 26 | 27 | `default_nettype none 28 | 29 | module audio_mix 30 | ( 31 | input wire clk, // system clock 32 | input wire ce, // clock enable signal 33 | 34 | input wire [4:0] att, // attenuation value 35 | input wire [1:0] mix, // mixing value 36 | 37 | input wire [15:0] core_audio, // audio input from core 38 | input wire [15:0] pre_in, // audio input from preamp 39 | 40 | output reg [15:0] pre_out = 0, // preamp output 41 | output reg [15:0] out = 0 // final mixed audio output 42 | ); 43 | 44 | reg signed [16:0] a1, a2, a3; // signed registers for audio processing 45 | 46 | always @(posedge clk) begin 47 | if (ce) begin 48 | a1 <= {core_audio[15],core_audio}; // extend core_audio to 17 bits and store in a1 49 | pre_out <= a1[16:1]; // store the upper 16 bits of a1 in pre_out 50 | 51 | // select mixing options 52 | case(mix) 53 | 0: begin a2 <= a1; end // mix core_audio 54 | 1: begin a2 <= $signed(a1) - $signed(a1[16:3]) + $signed(pre_in[15:2]); end // mix core_audio, and pre_in with attenuation 55 | 2: begin a2 <= $signed(a1) - $signed(a1[16:2]) + $signed(pre_in[15:1]); end // mix core_audio, and pre_in with greater attenuation 56 | 3: begin a2 <= {a1[16],a1[16:1]} + {pre_in[15],pre_in}; end // mix core_audio, and pre_in with clipping 57 | endcase 58 | 59 | // if the highest bit of att is set, set a3 to 0 (Mute) else shift a2 right by att and store in a3 60 | a3 <= (att[4]) ? 0 : a2 >>> att[3:0]; 61 | 62 | // Clamping 63 | out <= ^a3[16:15] ? {a3[16],{15{a3[15]}}} : a3[15:0]; // clamp the upper 16 bits of a3 and store in out 64 | end 65 | end 66 | 67 | endmodule 68 | -------------------------------------------------------------------------------- /rtl/audio/filters/dc_blocker.sv: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // SPDX-License-Identifier: GPL-3.0-or-later 3 | // SPDX-FileType: SOURCE 4 | // SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors 5 | //------------------------------------------------------------------------------ 6 | // 7 | // DC blocker filter using a simplified IIR structure. 8 | // 9 | // Copyright (c) 2023, Marcus Andrade 10 | // Copyright (c) 2020, Alexey Melnikov 11 | // 12 | // This source file is free software: you can redistribute it and/or modify 13 | // it under the terms of the GNU General Public License as published 14 | // by the Free Software Foundation, either version 3 of the License, or 15 | // (at your option) any later version. 16 | // 17 | // This program is distributed in the hope that it will be useful, but 18 | // WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | // General Public License for more details. 21 | // 22 | // You should have received a copy of the GNU General Public License 23 | // along with this program. If not, see . 24 | // 25 | //------------------------------------------------------------------------------ 26 | // 27 | // It utilizes feedback to achieve filtering, operating on a delayed version of 28 | // the input signal (x0), a delayed version of the output signal (y1), and the 29 | // current input and output signals (x1 and y0, respectively). 30 | // The filter coefficients are determined by the sample rate of the input signal. 31 | // 32 | //------------------------------------------------------------------------------ 33 | 34 | `default_nettype none 35 | 36 | module dc_blocker 37 | ( 38 | input logic clk, // Input clock signal 39 | input logic ce, // Control enable signal 40 | input logic mute, // Mute output signal 41 | 42 | input logic sample_rate, // Sample rate input signal 43 | input logic [15:0] din, // Input data signal 44 | output logic [15:0] dout // Output data signal 45 | ); 46 | 47 | // Pad the input signal with zeros 48 | wire [39:0] x = {din[15], din, 23'd0}; 49 | // Subtract previous input sample from current input sample 50 | wire [39:0] x0 = x - (sample_rate ? {{11{x[39]}}, x[39:11]} : {{10{x[39]}}, x[39:10]}); 51 | // Subtract previous output sample from current output sample 52 | wire [39:0] y1 = y - (sample_rate ? {{10{y[39]}}, y[39:10]} : {{09{y[39]}}, y[39:09]}); 53 | // Subtract difference between previous input and output sample from current input sample 54 | wire [39:0] y0 = x0 - x1 + y1; 55 | 56 | // Registers to store previous input and output samples 57 | reg [39:0] x1, y; 58 | 59 | always @(posedge clk) begin 60 | if(ce) begin 61 | // Update the previous input sample 62 | x1 <= x0; 63 | // Update the previous output sample 64 | y <= ^y0[39:38] ? {{2{y0[39]}},{38{y0[38]}}} : y0; 65 | end 66 | end 67 | 68 | // Output the filtered sample, or zero if the mute signal is high 69 | assign dout = mute ? 16'd0 : y[38:23]; 70 | 71 | endmodule 72 | -------------------------------------------------------------------------------- /rtl/audio/filters/filter_loader.sv: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // SPDX-License-Identifier: MIT 3 | // SPDX-FileType: SOURCE 4 | // SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors 5 | //------------------------------------------------------------------------------ 6 | // 7 | // Analogue Pocket Audio Filter Loader 8 | // 9 | // Copyright (c) 2023, Marcus Andrade 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | // SOFTWARE. 28 | // 29 | //------------------------------------------------------------------------------ 30 | 31 | `default_nettype none 32 | 33 | module filter_loader 34 | ( 35 | // Clocks and Reset 36 | input logic clk_sys, 37 | input logic afilter_wr, 38 | input logic [7:0] afilter_addr, 39 | input logic [7:0] afilter_din, 40 | // Audio From Core 41 | output logic [31:0] flt_rate, // Sampling Frequency 42 | output logic [39:0] cx, // Base gain 43 | output logic [7:0] cx0, cx1, cx2, // gain scale for X0, X1, X2 44 | output logic [23:0] cy0, cy1, cy2 // gain scale for Y0, Y1, Y2 45 | ); 46 | 47 | always_comb begin 48 | flt_rate = r_flt_rate; 49 | cx = r_cx; 50 | cx0 = r_cx0; 51 | cx1 = r_cx1; 52 | cx2 = r_cx2; 53 | cy0 = r_cy0; 54 | cy1 = r_cy1; 55 | cy2 = r_cy2; 56 | end 57 | 58 | reg [31:0] r_flt_rate = 7056000; // Sampling Frequency 59 | reg [39:0] r_cx = 4258969; // Base gain 60 | reg [7:0] r_cx0 = 3; // gain scale for X0 61 | reg [7:0] r_cx1 = 3; // gain scale for X1 62 | reg [7:0] r_cx2 = 1; // gain scale for X2 63 | reg [23:0] r_cy0 = -24'd6216759; // gain scale for Y0 64 | reg [23:0] r_cy1 = 24'd6143386; // gain scale for Y1 65 | reg [23:0] r_cy2 = -24'd2023767; // gain scale for Y2 66 | 67 | always_ff @(posedge clk_sys) begin 68 | if (afilter_wr) begin 69 | case(afilter_addr) 70 | //! Sampling Frequency 71 | 8'h00: r_flt_rate[7:0] <= afilter_din; 72 | 8'h01: r_flt_rate[15:8] <= afilter_din; 73 | 8'h02: r_flt_rate[23:16] <= afilter_din; 74 | 8'h03: r_flt_rate[31:24] <= afilter_din; 75 | //! Base gain 76 | 8'h04: r_cx[7:0] <= afilter_din; 77 | 8'h05: r_cx[15:8] <= afilter_din; 78 | 8'h06: r_cx[23:16] <= afilter_din; 79 | 8'h07: r_cx[31:24] <= afilter_din; 80 | 8'h08: r_cx[39:32] <= afilter_din; 81 | // 8'h09: _SKIP_ 82 | // 8'h0a: _SKIP_ 83 | // 8'h0b: _SKIP_ 84 | //! gain scale for X0 85 | 8'h0c: r_cx0 <= afilter_din; 86 | //! gain scale for X1 87 | 8'h0d: r_cx1 <= afilter_din; 88 | //! gain scale for X2 89 | 8'h0e: r_cx2 <= afilter_din; 90 | //! gain scale for Y0 91 | 8'h0f: r_cy0[7:0] <= afilter_din; 92 | 8'h10: r_cy0[15:8] <= afilter_din; 93 | 8'h11: r_cy0[23:16] <= afilter_din; 94 | // 8'h12: _SKIP_ 95 | //! gain scale for Y1 96 | 8'h13: r_cy1[7:0] <= afilter_din; 97 | 8'h14: r_cy1[15:8] <= afilter_din; 98 | 8'h15: r_cy1[23:16] <= afilter_din; 99 | // 8'h16: _SKIP_ 100 | //! gain scale for Y2 101 | 8'h17: r_cy2[7:0] <= afilter_din; 102 | 8'h18: r_cy2[15:8] <= afilter_din; 103 | 8'h19: r_cy2[23:16] <= afilter_din; 104 | // 8'h1a: _SKIP_ 105 | // 8'h1b: _SKIP_ 106 | default:; 107 | endcase 108 | end 109 | end 110 | 111 | endmodule 112 | -------------------------------------------------------------------------------- /rtl/audio/filters/filters_rom.sv: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // SPDX-License-Identifier: MIT 3 | // SPDX-FileType: SOURCE 4 | // SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors 5 | //------------------------------------------------------------------------------ 6 | // 7 | // Analogue Pocket Audio Filters ROM 8 | // 9 | // Copyright (c) 2023, Marcus Andrade 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | // SOFTWARE. 28 | // 29 | //------------------------------------------------------------------------------ 30 | 31 | `default_nettype none 32 | 33 | module filters_rom 34 | ( 35 | // Clock 36 | input logic clk, 37 | // Filter Switch 38 | input logic [3:0] afilter_sw, 39 | // Filter Config 40 | output logic [31:0] aflt_rate, // Sampling Frequency 41 | output logic [39:0] acx, // Base gain 42 | output logic [7:0] acx0, acx1, acx2, // gain scale for X0, X1, X2 43 | output logic [23:0] acy0, acy1, acy2 // gain scale for Y0, Y1, Y2 44 | ); 45 | 46 | (* ramstyle = "no_rw_check" *) reg [31:0] flt_rate[9]; 47 | (* ramstyle = "no_rw_check" *) reg [39:0] cx[9]; 48 | (* ramstyle = "no_rw_check" *) reg [7:0] cx0[9]; 49 | (* ramstyle = "no_rw_check" *) reg [7:0] cx1[9]; 50 | (* ramstyle = "no_rw_check" *) reg [7:0] cx2[9]; 51 | (* ramstyle = "no_rw_check" *) reg [23:0] cy0[9]; 52 | (* ramstyle = "no_rw_check" *) reg [23:0] cy1[9]; 53 | (* ramstyle = "no_rw_check" *) reg [23:0] cy2[9]; 54 | 55 | always @(posedge clk) begin 56 | aflt_rate <= flt_rate[afilter_sw]; 57 | acx <= cx[afilter_sw]; 58 | acx0 <= cx0[afilter_sw]; 59 | acx1 <= cx1[afilter_sw]; 60 | acx2 <= cx2[afilter_sw]; 61 | acy0 <= cy0[afilter_sw]; 62 | acy1 <= cy1[afilter_sw]; 63 | acy2 <= cy2[afilter_sw]; 64 | end 65 | //! Assign Outputs --------------------------------------------------------- 66 | 67 | //! Arcade Filters --------------------------------------------------------- 68 | initial begin 69 | // Default 70 | flt_rate[0] = 7056000; 71 | cx[0] = 4258969; 72 | cx0[0] = 3; 73 | cx1[0] = 3; 74 | cx2[0] = 1; 75 | cy0[0] = -24'd6216759; 76 | cy1[0] = 24'd6143386; 77 | cy2[0] = -24'd2023767; 78 | 79 | // Arcade LPF 2khz 1st 80 | flt_rate[1] = 32'd7056000; 81 | cx[1] = 40'd425898; 82 | cx0[1] = 8'd3; 83 | cx1[1] = 8'd3; 84 | cx2[1] = 8'd1; 85 | cy0[1] = -24'd6234907; 86 | cy1[1] = 24'd6179109; 87 | cy2[1] = -24'd2041353; 88 | 89 | // Arcade LPF 2khz 2nd 90 | flt_rate[2] = 32'd7056000; 91 | cx[2] = 40'd2420697; 92 | cx0[2] = 8'd2; 93 | cx1[2] = 8'd1; 94 | cx2[2] = 8'd0; 95 | cy0[2] = -24'd4189022; 96 | cy1[2] = 24'd2091876; 97 | cy2[2] = 24'd0; 98 | 99 | // Arcade LPF 4khz 1st 100 | flt_rate[3] = 32'd7056000; 101 | cx[3] = 40'd851040; 102 | cx0[3] = 8'd3; 103 | cx1[3] = 8'd3; 104 | cx2[3] = 8'd1; 105 | cy0[3] = -24'd6231182; 106 | cy1[3] = 24'd6171753; 107 | cy2[3] = -24'd2037720; 108 | 109 | // Arcade LPF 4khz 2nd 110 | flt_rate[4] = 32'd7056000; 111 | cx[4] = 40'd9670619; 112 | cx0[4] = 8'd2; 113 | cx1[4] = 8'd1; 114 | cx2[4] = 8'd0; 115 | cy0[4] = -24'd4183740; 116 | cy1[4] = 24'd2086614; 117 | cy2[4] = 24'd0; 118 | 119 | // Arcade LPF 6khz 1st 120 | flt_rate[5] = 32'd7056000; 121 | cx[5] = 40'd1275428; 122 | cx0[5] = 8'd3; 123 | cx1[5] = 8'd3; 124 | cx2[5] = 8'd1; 125 | cy0[5] = -24'd6227464; 126 | cy1[5] = 24'd6164410; 127 | cy2[5] = -24'd2034094; 128 | 129 | // Arcade LPF 6khz 2nd 130 | flt_rate[6] = 32'd7056000; 131 | cx[6] = 40'd21731566; 132 | cx0[6] = 8'd2; 133 | cx1[6] = 8'd1; 134 | cx2[6] = 8'd0; 135 | cy0[6] = -24'd4178458; 136 | cy1[6] = 24'd2081365; 137 | cy2[6] = 24'd0; 138 | 139 | // Arcade LPF 8khz 1st 140 | flt_rate[7] = 32'd7056000; 141 | cx[7] = 40'd1699064; 142 | cx0[7] = 8'd3; 143 | cx1[7] = 8'd3; 144 | cx2[7] = 8'd1; 145 | cy0[7] = -24'd6223752; 146 | cy1[7] = 24'd6157080; 147 | cy2[7] = -24'd2030475; 148 | 149 | // Arcade LPF 8khz 2nd 150 | flt_rate[8] = 32'd7056000; 151 | cx[8] = 40'd38585417; 152 | cx0[8] = 8'd2; 153 | cx1[8] = 8'd1; 154 | cx2[8] = 8'd0; 155 | cy0[8] = -24'd4173176; 156 | cy1[8] = 24'd2076130; 157 | cy2[8] = 24'd0; 158 | 159 | end 160 | 161 | // [ 9 ] LPF 10khz 1st + Aa 162 | // [ 10 ] LPF 12khz 1st + Aa 163 | // [ 11 ] LPF 14khz 1st + Aa 164 | // [ 12 ] LPF 16khz 1st + Aa 165 | // [ 13 ] LPF 16khz 3rd Ch 1db 166 | // [ 14 ] LPF 18khz 3rd Ch 1db 167 | // [ 15 ] LPF 20khz 2nd Bw 168 | // [ 16 ] LPF 20khz 3rd Bw 169 | // [ 17 ] LPF 20khz 3rd Ch 1db 170 | 171 | // [ 18 ] SNES Gpm-02 LPF 172 | 173 | endmodule 174 | -------------------------------------------------------------------------------- /rtl/audio/filters/iir_filter.sv: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // SPDX-License-Identifier: GPL-3.0-or-later 3 | // SPDX-FileType: SOURCE 4 | // SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors 5 | //------------------------------------------------------------------------------ 6 | // 7 | // 3-tap IIR filter for 2 channels. 8 | // 9 | // Copyright (c) 2023, Marcus Andrade 10 | // Copyright (c) 2020, Alexey Melnikov 11 | // 12 | // This source file is free software: you can redistribute it and/or modify 13 | // it under the terms of the GNU General Public License as published 14 | // by the Free Software Foundation, either version 3 of the License, or 15 | // (at your option) any later version. 16 | // 17 | // This program is distributed in the hope that it will be useful, but 18 | // WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | // General Public License for more details. 21 | // 22 | // You should have received a copy of the GNU General Public License 23 | // along with this program. If not, see . 24 | // 25 | //------------------------------------------------------------------------------ 26 | // 27 | // Can be converted to: 28 | // - 2-tap (coeff_x2 = 0, coeff_y2 = 0) 29 | // - 1-tap (coeff_x1,2 = 0, coeff_y1,2 = 0) 30 | // 31 | //------------------------------------------------------------------------------ 32 | 33 | `default_nettype none 34 | 35 | module iir_filter 36 | #( 37 | parameter use_params = 1, // set to 1 to use following parameters, 0 for input port variables. 38 | parameter stereo = 1, // 0 for mono (input_l) 39 | 40 | parameter coeff_x = 0.00000774701983513660, // Base gain value for X. Float. Range: 0.0 ... 0.999(9) 41 | parameter coeff_x0 = 3, // Gain scale factor for X0. Integer. Range -7 ... +7 42 | parameter coeff_x1 = 3, // Gain scale factor for X1. Integer. Range -7 ... +7 43 | parameter coeff_x2 = 1, // Gain scale factor for X2. Integer. Range -7 ... +7 44 | parameter coeff_y0 = -2.96438150626551080000, // Coefficient for Y0. Float. Range -3.999(9) ... 3.999(9) 45 | parameter coeff_y1 = 2.92939452735121100000, // Coefficient for Y1. Float. Range -3.999(9) ... 3.999(9) 46 | parameter coeff_y2 = -0.96500747158831091000 // Coefficient for Y2. Float. Range -3.999(9) ... 3.999(9) 47 | ) ( 48 | input clk, 49 | input reset, 50 | 51 | input ce, // must be double of calculated rate for stereo! 52 | input sample_ce, // desired output sample rate 53 | 54 | input [39:0] cx, 55 | input [7:0] cx0, 56 | input [7:0] cx1, 57 | input [7:0] cx2, 58 | input [23:0] cy0, 59 | input [23:0] cy1, 60 | input [23:0] cy2, 61 | 62 | input [15:0] input_l, input_r, // signed samples 63 | output [15:0] output_l, output_r // signed samples 64 | ); 65 | 66 | localparam [39:0] pcoeff_x = coeff_x * 40'h8000000000; 67 | localparam [31:0] pcoeff_y0 = coeff_y0 * 24'h200000; 68 | localparam [31:0] pcoeff_y1 = coeff_y1 * 24'h200000; 69 | localparam [31:0] pcoeff_y2 = coeff_y2 * 24'h200000; 70 | 71 | wire [39:0] vcoeff = use_params ? pcoeff_x : cx; 72 | wire [23:0] vcoeff_y0 = use_params ? pcoeff_y0[23:0] : cy0; 73 | wire [23:0] vcoeff_y1 = use_params ? pcoeff_y1[23:0] : cy1; 74 | wire [23:0] vcoeff_y2 = use_params ? pcoeff_y2[23:0] : cy2; 75 | 76 | wire [59:0] inp_mul = $signed(inp) * $signed(vcoeff); 77 | 78 | wire [39:0] x = inp_mul[59:20]; 79 | wire [39:0] y = x + tap0; 80 | 81 | wire [39:0] tap0; 82 | iir_filter_tap iir_tap_0 83 | ( 84 | .clk ( clk ), 85 | .reset ( reset ), 86 | .ce ( ce ), 87 | .ch ( ch ), 88 | .cx ( use_params ? coeff_x0[7:0] : cx0 ), 89 | .cy ( vcoeff_y0 ), 90 | .x ( x ), 91 | .y ( y ), 92 | .z ( tap1 ), 93 | .tap ( tap0 ) 94 | ); 95 | 96 | wire [39:0] tap1; 97 | iir_filter_tap iir_tap_1 98 | ( 99 | .clk ( clk ), 100 | .reset ( reset ), 101 | .ce ( ce ), 102 | .ch ( ch ), 103 | .cx ( use_params ? coeff_x1[7:0] : cx1 ), 104 | .cy ( vcoeff_y1 ), 105 | .x ( x ), 106 | .y ( y ), 107 | .z ( tap2 ), 108 | .tap ( tap1 ) 109 | ); 110 | 111 | wire [39:0] tap2; 112 | iir_filter_tap iir_tap_2 113 | ( 114 | .clk ( clk ), 115 | .reset ( reset ), 116 | .ce ( ce ), 117 | .ch ( ch ), 118 | .cx ( use_params ? coeff_x2[7:0] : cx2 ), 119 | .cy ( vcoeff_y2 ), 120 | .x ( x ), 121 | .y ( y ), 122 | .z ( 0 ), 123 | .tap ( tap2 ) 124 | ); 125 | 126 | wire [15:0] y_clamp = (~y[39] & |y[38:35]) ? 16'h7FFF : (y[39] & ~&y[38:35]) ? 16'h8000 : y[35:20]; 127 | 128 | reg ch = 0; 129 | reg [15:0] out_l, out_r, out_m; 130 | reg [15:0] inp, inp_m; 131 | 132 | always @(posedge clk) begin 133 | if (ce) begin 134 | if(!stereo) begin 135 | ch <= 0; 136 | inp <= input_l; 137 | out_l <= y_clamp; 138 | out_r <= y_clamp; 139 | end 140 | else begin 141 | ch <= ~ch; 142 | if(ch) begin 143 | out_m <= y_clamp; 144 | inp <= inp_m; 145 | end 146 | else begin 147 | out_l <= out_m; 148 | out_r <= y_clamp; 149 | inp <= input_l; 150 | inp_m <= input_r; 151 | end 152 | end 153 | end 154 | end 155 | 156 | reg [31:0] out; 157 | always @(posedge clk) begin 158 | if (sample_ce) begin 159 | out <= {out_l, out_r}; 160 | end 161 | end 162 | 163 | assign {output_l, output_r} = out; 164 | 165 | endmodule 166 | -------------------------------------------------------------------------------- /rtl/audio/filters/iir_filter_tap.sv: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // SPDX-License-Identifier: GPL-3.0-or-later 3 | // SPDX-FileType: SOURCE 4 | // SPDX-FileCopyrightText: (c) 2023, OpenGateware authors and contributors 5 | //------------------------------------------------------------------------------ 6 | // 7 | // Infinite Impulse Response (IIR) filter tap. 8 | // 9 | // Copyright (c) 2023, Marcus Andrade 10 | // Copyright (c) 2020, Alexey Melnikov 11 | // 12 | // This source file is free software: you can redistribute it and/or modify 13 | // it under the terms of the GNU General Public License as published 14 | // by the Free Software Foundation, either version 3 of the License, or 15 | // (at your option) any later version. 16 | // 17 | // This program is distributed in the hope that it will be useful, but 18 | // WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | // General Public License for more details. 21 | // 22 | // You should have received a copy of the GNU General Public License 23 | // along with this program. If not, see . 24 | // 25 | //------------------------------------------------------------------------------ 26 | // 27 | // The iir_filter_tap module implements an infinite impulse response (IIR) filter 28 | // with one tap. It takes in input data x, previous output data y, and an input z 29 | // and calculates the output tap using a set of coefficients cx and cy. The 30 | // coefficients are used to multiply the input data and previous output data, 31 | // and the resulting values are then added together to produce the output tap. 32 | // The module stores intermediate values in a logic RAM, and updates the values 33 | // on each clock cycle based on the control signals ce and ch. The module uses 34 | // a Verilog function to perform the multiplication of the input data with the 35 | // coefficients. 36 | // 37 | //------------------------------------------------------------------------------ 38 | 39 | `default_nettype none 40 | 41 | module iir_filter_tap 42 | ( 43 | input wire clk, // clock signal 44 | input wire reset, // reset signal 45 | 46 | input wire ce, // control signal 47 | input wire ch, // control signal 48 | 49 | input wire [7:0] cx, // coefficient value 50 | input wire [23:0] cy, // coefficient value 51 | 52 | input wire [39:0] x, // input data 53 | input wire [39:0] y, // previous output data 54 | input wire [39:0] z, // input data 55 | output wire [39:0] tap // output data 56 | ); 57 | 58 | // multiply previous output y with coefficient cy 59 | wire signed [60:0] y_mul = $signed(y[36:0]) * $signed(cy); 60 | 61 | // multiply input x with coefficient cx 62 | function [39:0] x_mul; 63 | input [39:0] x; 64 | begin 65 | x_mul = 0; 66 | if(cx[0]) x_mul = x_mul + {{4{x[39]}}, x[39:4]}; // multiply x[39:36] with cx[0] 67 | if(cx[1]) x_mul = x_mul + {{3{x[39]}}, x[39:3]}; // multiply x[39:35] with cx[1] 68 | if(cx[2]) x_mul = x_mul + {{2{x[39]}}, x[39:2]}; // multiply x[39:34] with cx[2] 69 | if(cx[7]) x_mul = ~x_mul; // negate result if cx[7] is set 70 | end 71 | endfunction 72 | 73 | // use logic RAM to store intermediate values 74 | (* ramstyle = "logic" *) reg [39:0] intreg[2]; 75 | always @(posedge clk, posedge reset) begin 76 | if(reset) begin 77 | {intreg[0],intreg[1]} <= 80'd0; 78 | end 79 | else if(ce) begin 80 | // update intreg[ch] with new value 81 | intreg[ch] <= x_mul(x) - y_mul[60:21] + z; 82 | // multiply input x with cx, subtract a portion of previous output y (specified by cy), 83 | // add input z, and store the result in intreg[ch] 84 | end 85 | end 86 | 87 | // assign output tap to value in intreg corresponding to ch signal 88 | assign tap = intreg[ch]; 89 | 90 | endmodule 91 | -------------------------------------------------------------------------------- /rtl/bus_savestates.vhd: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------------- 2 | --------------- Bus Package -------------------------------- 3 | ----------------------------------------------------------------- 4 | 5 | library IEEE; 6 | use IEEE.std_logic_1164.all; 7 | use IEEE.numeric_std.all; 8 | 9 | package pBus_savestates is 10 | 11 | constant BUS_buswidth : integer := 64; 12 | constant BUS_busadr : integer := 10; 13 | 14 | end package; 15 | 16 | ----------------------------------------------------------------- 17 | --------------- Reg Interface, verbose for Verilog -------------- 18 | ----------------------------------------------------------------- 19 | 20 | library IEEE; 21 | use IEEE.std_logic_1164.all; 22 | use IEEE.numeric_std.all; 23 | 24 | library work; 25 | use work.pBus_savestates.all; 26 | 27 | entity eReg_SavestateV is 28 | generic 29 | ( 30 | Adr : integer range 0 to (2**BUS_busadr)-1; 31 | def : std_logic_vector(BUS_buswidth-1 downto 0) 32 | ); 33 | port 34 | ( 35 | clk : in std_logic; 36 | BUS_Din : in std_logic_vector(BUS_buswidth-1 downto 0); 37 | BUS_Adr : in std_logic_vector(BUS_busadr-1 downto 0); 38 | BUS_wren : in std_logic; 39 | BUS_rst : in std_logic; 40 | BUS_Dout : out std_logic_vector(BUS_buswidth-1 downto 0) := (others => '0'); 41 | Din : in std_logic_vector(BUS_buswidth-1 downto 0); 42 | Dout : out std_logic_vector(BUS_buswidth-1 downto 0) 43 | ); 44 | end entity; 45 | 46 | architecture arch of eReg_SavestateV is 47 | 48 | signal Dout_buffer : std_logic_vector(BUS_buswidth-1 downto 0) := def; 49 | 50 | signal AdrI : std_logic_vector(BUS_Adr'left downto 0); 51 | 52 | begin 53 | 54 | AdrI <= std_logic_vector(to_unsigned(Adr, BUS_Adr'length)); 55 | 56 | process (clk) 57 | begin 58 | if rising_edge(clk) then 59 | 60 | if (BUS_rst = '1') then 61 | 62 | Dout_buffer <= def; 63 | 64 | else 65 | 66 | if (BUS_Adr = AdrI and BUS_wren = '1') then 67 | for i in 0 to BUS_buswidth-1 loop 68 | Dout_buffer(i) <= BUS_Din(i); 69 | end loop; 70 | end if; 71 | 72 | end if; 73 | 74 | end if; 75 | end process; 76 | 77 | Dout <= Dout_buffer; 78 | 79 | goutputbit: for i in 0 to BUS_buswidth-1 generate 80 | BUS_Dout(i) <= Din(i) when BUS_Adr = AdrI else '0'; 81 | end generate; 82 | 83 | end architecture; 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /rtl/button_turbo.sv: -------------------------------------------------------------------------------- 1 | module button_turbo ( 2 | input wire clk, 3 | 4 | input wire [2:0] turbo_speed, 5 | input wire vsync, 6 | 7 | input wire a_button_turbo, 8 | input wire b_button_turbo, 9 | 10 | output reg a_turbo = 0, 11 | output reg b_turbo = 0 12 | ); 13 | reg [3:0] a_turbo_counter = 0; 14 | reg [3:0] b_turbo_counter = 0; 15 | reg prev_vsync = 0; 16 | 17 | always @(posedge clk) begin 18 | prev_vsync <= vsync; 19 | 20 | if (vsync && ~prev_vsync) begin 21 | // Tick turbo 22 | if (a_button_turbo || a_turbo) begin 23 | // Either button is pressed, or we're still outputting the turbo state 24 | a_turbo_counter <= a_turbo_counter + 4'h1; 25 | 26 | // I can't get a task to work for this, so I guess I have to deal with duplicating all of it :( 27 | case (turbo_speed) 28 | 3'h0: begin 29 | // No turbo enabled 30 | a_turbo_counter <= 0; 31 | a_turbo <= 0; 32 | end 33 | 3'h1: begin 34 | if (a_turbo_counter >= 4'h9) begin 35 | // 3hz 36 | a_turbo_counter <= 0; 37 | a_turbo <= ~a_turbo; 38 | end 39 | end 40 | 3'h2: begin 41 | if (a_turbo_counter >= 4'h5) begin 42 | // 5hz 43 | a_turbo_counter <= 0; 44 | a_turbo <= ~a_turbo; 45 | end 46 | end 47 | 3'h3: begin 48 | if (a_turbo_counter >= 4'h3) begin 49 | // 7.5hz 50 | a_turbo_counter <= 0; 51 | a_turbo <= ~a_turbo; 52 | end 53 | end 54 | 3'h4: begin 55 | if (a_turbo_counter >= 4'h2) begin 56 | // 10hz 57 | a_turbo_counter <= 0; 58 | a_turbo <= ~a_turbo; 59 | end 60 | end 61 | 3'h5: begin 62 | if (a_turbo_counter >= 4'h1) begin 63 | // Toggle every other frame (15hz) 64 | a_turbo_counter <= 0; 65 | a_turbo <= ~a_turbo; 66 | end 67 | end 68 | 3'h6: begin 69 | if (a_turbo_counter >= 4'h0) begin 70 | // Toggle every frame (30hz) 71 | a_turbo_counter <= 0; 72 | a_turbo <= ~a_turbo; 73 | end 74 | end 75 | endcase 76 | end 77 | 78 | if (b_button_turbo || b_turbo) begin 79 | // Either button is pressed, or we're still outputting the turbo state 80 | b_turbo_counter <= b_turbo_counter + 4'h1; 81 | 82 | case (turbo_speed) 83 | 3'h0: begin 84 | // No turbo enabled 85 | b_turbo_counter <= 0; 86 | b_turbo <= 0; 87 | end 88 | 3'h1: begin 89 | if (b_turbo_counter >= 4'h9) begin 90 | // 3hz 91 | b_turbo_counter <= 0; 92 | b_turbo <= ~b_turbo; 93 | end 94 | end 95 | 3'h2: begin 96 | if (b_turbo_counter >= 4'h5) begin 97 | // 5hz 98 | b_turbo_counter <= 0; 99 | b_turbo <= ~b_turbo; 100 | end 101 | end 102 | 3'h3: begin 103 | if (b_turbo_counter >= 4'h3) begin 104 | // 7.5hz 105 | b_turbo_counter <= 0; 106 | b_turbo <= ~b_turbo; 107 | end 108 | end 109 | 3'h4: begin 110 | if (b_turbo_counter >= 4'h2) begin 111 | // 10hz 112 | b_turbo_counter <= 0; 113 | b_turbo <= ~b_turbo; 114 | end 115 | end 116 | 3'h5: begin 117 | if (b_turbo_counter >= 4'h1) begin 118 | // Toggle every other frame (15hz) 119 | b_turbo_counter <= 0; 120 | b_turbo <= ~b_turbo; 121 | end 122 | end 123 | 3'h6: begin 124 | if (b_turbo_counter >= 4'h0) begin 125 | // Toggle every frame (30hz) 126 | b_turbo_counter <= 0; 127 | b_turbo <= ~b_turbo; 128 | end 129 | end 130 | endcase 131 | end 132 | end 133 | end 134 | 135 | endmodule 136 | -------------------------------------------------------------------------------- /rtl/cheatcodes.sv: -------------------------------------------------------------------------------- 1 | // Cheat Code handling by Kitrinx 2 | // Apr 21, 2019 3 | 4 | // Code layout: 5 | // {clock bit, 32'bcode flags, 32'b address, 32'b compare, 32'b replace} 6 | // 128 127:96 95:64 63:32 31:0 7 | // Integer values are in BIG endian byte order, so it up to the loader 8 | // or generator of the code to re-arrange them correctly. 9 | 10 | module CODES( 11 | input clk, // Best to not make it too high speed for timing reasons 12 | input reset, // This should only be triggered when a new rom is loaded or before new codes load, not warm reset 13 | input enable, 14 | output available, 15 | input [ADDR_WIDTH - 1:0] addr_in, 16 | input [DATA_WIDTH - 1:0] data_in, 17 | input [128:0] code, 18 | output genie_ovr, 19 | output [DATA_WIDTH - 1:0] genie_data 20 | ); 21 | 22 | parameter ADDR_WIDTH = 16; // Not more than 32 23 | parameter DATA_WIDTH = 8; // Not more than 32 24 | parameter MAX_CODES = 32; 25 | 26 | localparam INDEX_SIZE = $clog2(MAX_CODES-1); // Number of bits for index, must accomodate MAX_CODES 27 | 28 | localparam DATA_S = DATA_WIDTH - 1; 29 | localparam COMP_S = DATA_S + DATA_WIDTH; 30 | localparam ADDR_S = COMP_S + ADDR_WIDTH; 31 | localparam COMP_F_S = ADDR_S + 1; 32 | localparam ENA_F_S = COMP_F_S + 1; 33 | 34 | reg [ENA_F_S:0] codes[MAX_CODES]; 35 | 36 | wire [ADDR_WIDTH-1: 0] code_addr = code[64+:ADDR_WIDTH]; 37 | wire [DATA_WIDTH-1: 0] code_compare = code[32+:DATA_WIDTH]; 38 | wire [DATA_WIDTH-1: 0] code_data = code[0+:DATA_WIDTH]; 39 | wire code_comp_f = code[96]; 40 | 41 | wire [COMP_F_S:0] code_trimmed = {code_comp_f, code_addr, code_compare, code_data}; 42 | 43 | reg [INDEX_SIZE:0] index = '0; 44 | 45 | assign available = |index; 46 | 47 | reg code_change; 48 | always_ff @(posedge clk) begin 49 | int x; 50 | if (reset) begin 51 | index <= 0; 52 | code_change <= 0; 53 | for (x = 0; x < MAX_CODES; x = x + 1) codes[x] <= '0; 54 | end else begin 55 | code_change <= code[128]; 56 | if (code[128] && ~code_change && (index < MAX_CODES)) begin // detect posedge 57 | codes[index] <= {1'b1, code_trimmed}; 58 | index <= index + 1'b1; 59 | end 60 | end 61 | end 62 | 63 | always_comb begin 64 | int x; 65 | genie_ovr = 0; 66 | genie_data = '0; 67 | 68 | if (enable) begin 69 | for (x = 0; x < MAX_CODES; x = x + 1) begin 70 | if (codes[x][ENA_F_S] && codes[x][ADDR_S-:ADDR_WIDTH] == addr_in) begin 71 | if (!codes[x][COMP_F_S] || (codes[x][COMP_S-:DATA_WIDTH] == data_in)) begin 72 | genie_ovr = 1; 73 | genie_data = codes[x][DATA_S-:DATA_WIDTH]; 74 | end 75 | end 76 | end 77 | end 78 | end 79 | 80 | endmodule 81 | -------------------------------------------------------------------------------- /rtl/compat.v: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012-2013 Ludvig Strigeus 2 | // This program is GPL Licensed. See COPYING for the full license. 3 | module MUXCY(output O, input CI, input DI, input S); 4 | assign O = S ? CI : DI; 5 | endmodule 6 | module MUXCY_L(output LO, input CI, input DI, input S); 7 | assign LO = S ? CI : DI; 8 | endmodule 9 | module MUXCY_D(output LO, output O, input CI, input DI, input S); 10 | assign LO = S ? CI : DI; 11 | assign O = LO; 12 | endmodule 13 | module XORCY(output O, input CI, input LI); 14 | assign O = CI ^ LI; 15 | endmodule 16 | module XOR2(output O, input I0, input I1); 17 | assign O = I0 ^ I1; 18 | endmodule -------------------------------------------------------------------------------- /rtl/ddram.sv: -------------------------------------------------------------------------------- 1 | // 2 | // ddram.v 3 | // Copyright (c) 2019 Sorgelig 4 | // 5 | // 6 | // This source file is free software: you can redistribute it and/or modify 7 | // it under the terms of the GNU General Public License as published 8 | // by the Free Software Foundation, either version 3 of the License, or 9 | // (at your option) any later version. 10 | // 11 | // This source file is distributed in the hope that it will be useful, 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | // GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License 17 | // along with this program. If not, see . 18 | // 19 | // ------------------------------------------ 20 | // 21 | 22 | module ddram 23 | ( 24 | input DDRAM_CLK, 25 | input DDRAM_BUSY, 26 | output [7:0] DDRAM_BURSTCNT, 27 | output [28:0] DDRAM_ADDR, 28 | input [63:0] DDRAM_DOUT, 29 | input DDRAM_DOUT_READY, 30 | output DDRAM_RD, 31 | output [63:0] DDRAM_DIN, 32 | output [7:0] DDRAM_BE, 33 | output DDRAM_WE, 34 | 35 | // save state 36 | input [27:1] ch1_addr, 37 | output [63:0] ch1_dout, 38 | input [63:0] ch1_din, 39 | input ch1_req, 40 | input ch1_rnw, 41 | input [7:0] ch1_be, 42 | output ch1_ready 43 | ); 44 | 45 | reg [7:0] ram_burst; 46 | reg [63:0] ram_q[1:1]; 47 | reg [63:0] ram_data; 48 | reg [27:1] ram_address; 49 | reg ram_read = 0; 50 | reg ram_write = 0; 51 | reg [7:0] ram_be; 52 | 53 | reg [5:1] ready; 54 | 55 | assign DDRAM_BURSTCNT = ram_burst; 56 | assign DDRAM_BE = ram_read ? 8'hFF : ram_be; 57 | assign DDRAM_ADDR = {4'b0011, ram_address[27:3]}; // RAM at 0x30000000 58 | assign DDRAM_RD = ram_read; 59 | assign DDRAM_DIN = ram_data; 60 | assign DDRAM_WE = ram_write; 61 | 62 | assign ch1_dout = ram_q[1]; 63 | assign ch1_ready = ready[1]; 64 | 65 | reg state = 0; 66 | reg [0:0] ch = 0; 67 | reg [1:1] ch_rq; 68 | 69 | always @(posedge DDRAM_CLK) begin 70 | 71 | 72 | ch_rq <= ch_rq | {ch1_req}; 73 | ready <= 0; 74 | 75 | if(!DDRAM_BUSY) begin 76 | ram_write <= 0; 77 | ram_read <= 0; 78 | 79 | case(state) 80 | 0: if(ch_rq[1] || ch1_req) begin 81 | ch_rq[1] <= 0; 82 | ch <= 1; 83 | ram_data <= ch1_din; 84 | ram_be <= ch1_be; 85 | ram_address <= ch1_addr; 86 | ram_burst <= 1; 87 | if(~ch1_rnw) begin 88 | ram_write <= 1; 89 | ready[1] <= 1; 90 | end 91 | else begin 92 | ram_read <= 1; 93 | state <= 1; 94 | end 95 | end 96 | 97 | 1: if(DDRAM_DOUT_READY) begin 98 | ram_q[ch] <= DDRAM_DOUT; 99 | ready[ch] <= 1; 100 | state <= 0; 101 | end 102 | 103 | endcase 104 | end 105 | end 106 | 107 | endmodule 108 | -------------------------------------------------------------------------------- /rtl/dpram.vhd: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------- 2 | -- Single port Block RAM 3 | -------------------------------------------------------------- 4 | 5 | LIBRARY ieee; 6 | USE ieee.std_logic_1164.all; 7 | 8 | LIBRARY altera_mf; 9 | USE altera_mf.altera_mf_components.all; 10 | 11 | ENTITY spram IS 12 | generic ( 13 | addr_width : integer := 8; 14 | data_width : integer := 8; 15 | mem_init_file : string := " "; 16 | mem_name : string := "MEM" -- for InSystem Memory content editor. 17 | ); 18 | PORT 19 | ( 20 | clock : in STD_LOGIC; 21 | address : in STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0); 22 | data : in STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0'); 23 | enable : in STD_LOGIC := '1'; 24 | wren : in STD_LOGIC := '0'; 25 | q : out STD_LOGIC_VECTOR (data_width-1 DOWNTO 0); 26 | cs : in std_logic := '1' 27 | ); 28 | END spram; 29 | 30 | 31 | ARCHITECTURE SYN OF spram IS 32 | BEGIN 33 | spram_sz : work.spram_sz 34 | generic map(addr_width, data_width, 2**addr_width, mem_init_file, mem_name) 35 | port map(clock,address,data,enable,wren,q,cs); 36 | END SYN; 37 | 38 | 39 | -------------------------------------------------------------- 40 | -- Single port Block RAM with specific size 41 | -------------------------------------------------------------- 42 | 43 | LIBRARY ieee; 44 | USE ieee.std_logic_1164.all; 45 | 46 | LIBRARY altera_mf; 47 | USE altera_mf.altera_mf_components.all; 48 | 49 | ENTITY spram_sz IS 50 | generic ( 51 | addr_width : integer := 8; 52 | data_width : integer := 8; 53 | numwords : integer := 2**8; 54 | mem_init_file : string := " "; 55 | mem_name : string := "MEM" -- for InSystem Memory content editor. 56 | ); 57 | PORT 58 | ( 59 | clock : in STD_LOGIC; 60 | address : in STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0); 61 | data : in STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0'); 62 | enable : in STD_LOGIC := '1'; 63 | wren : in STD_LOGIC := '0'; 64 | q : out STD_LOGIC_VECTOR (data_width-1 DOWNTO 0); 65 | cs : in std_logic := '1' 66 | ); 67 | END ENTITY; 68 | 69 | ARCHITECTURE SYN OF spram_sz IS 70 | signal q0 : std_logic_vector((data_width - 1) downto 0); 71 | BEGIN 72 | q<= q0 when cs = '1' else (others => '1'); 73 | 74 | altsyncram_component : altsyncram 75 | GENERIC MAP ( 76 | clock_enable_input_a => "BYPASS", 77 | clock_enable_output_a => "BYPASS", 78 | intended_device_family => "Cyclone V", 79 | lpm_hint => "ENABLE_RUNTIME_MOD=YES,INSTANCE_NAME="&mem_name, 80 | lpm_type => "altsyncram", 81 | numwords_a => numwords, 82 | operation_mode => "SINGLE_PORT", 83 | outdata_aclr_a => "NONE", 84 | outdata_reg_a => "UNREGISTERED", 85 | power_up_uninitialized => "FALSE", 86 | read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", 87 | init_file => mem_init_file, 88 | widthad_a => addr_width, 89 | width_a => data_width, 90 | width_byteena_a => 1 91 | ) 92 | PORT MAP ( 93 | address_a => address, 94 | clock0 => clock, 95 | data_a => data, 96 | wren_a => wren and cs, 97 | q_a => q0 98 | ); 99 | 100 | END SYN; 101 | 102 | 103 | 104 | LIBRARY ieee; 105 | USE ieee.std_logic_1164.all; 106 | 107 | LIBRARY altera_mf; 108 | USE altera_mf.all; 109 | 110 | ENTITY dpram IS 111 | GENERIC 112 | ( 113 | init_file : string := " "; 114 | widthad_a : natural; 115 | width_a : natural := 8; 116 | outdata_reg_a : string := "UNREGISTERED"; 117 | outdata_reg_b : string := "UNREGISTERED" 118 | ); 119 | PORT 120 | ( 121 | address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); 122 | address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0) := (others => '0'); 123 | clock_a : IN STD_LOGIC ; 124 | clock_b : IN STD_LOGIC ; 125 | data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0'); 126 | data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0'); 127 | wren_a : IN STD_LOGIC := '0'; 128 | wren_b : IN STD_LOGIC := '0'; 129 | byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1'); 130 | byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1'); 131 | q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); 132 | q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) 133 | ); 134 | END dpram; 135 | 136 | 137 | ARCHITECTURE SYN OF dpram IS 138 | 139 | SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); 140 | SIGNAL sub_wire1 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); 141 | 142 | 143 | 144 | COMPONENT altsyncram 145 | GENERIC ( 146 | address_reg_b : STRING; 147 | clock_enable_input_a : STRING; 148 | clock_enable_input_b : STRING; 149 | clock_enable_output_a : STRING; 150 | clock_enable_output_b : STRING; 151 | indata_reg_b : STRING; 152 | init_file : STRING; 153 | intended_device_family : STRING; 154 | lpm_type : STRING; 155 | numwords_a : NATURAL; 156 | numwords_b : NATURAL; 157 | operation_mode : STRING; 158 | outdata_aclr_a : STRING; 159 | outdata_aclr_b : STRING; 160 | outdata_reg_a : STRING; 161 | outdata_reg_b : STRING; 162 | power_up_uninitialized : STRING; 163 | read_during_write_mode_port_a : STRING; 164 | read_during_write_mode_port_b : STRING; 165 | widthad_a : NATURAL; 166 | widthad_b : NATURAL; 167 | width_a : NATURAL; 168 | width_b : NATURAL; 169 | width_byteena_a : NATURAL; 170 | width_byteena_b : NATURAL; 171 | wrcontrol_wraddress_reg_b : STRING 172 | ); 173 | PORT ( 174 | wren_a : IN STD_LOGIC ; 175 | clock0 : IN STD_LOGIC ; 176 | wren_b : IN STD_LOGIC ; 177 | clock1 : IN STD_LOGIC ; 178 | address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); 179 | address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); 180 | q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); 181 | q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); 182 | byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ; 183 | byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ; 184 | data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); 185 | data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) 186 | ); 187 | END COMPONENT; 188 | 189 | BEGIN 190 | q_a <= sub_wire0(width_a-1 DOWNTO 0); 191 | q_b <= sub_wire1(width_a-1 DOWNTO 0); 192 | 193 | altsyncram_component : altsyncram 194 | GENERIC MAP ( 195 | address_reg_b => "CLOCK1", 196 | clock_enable_input_a => "BYPASS", 197 | clock_enable_input_b => "BYPASS", 198 | clock_enable_output_a => "BYPASS", 199 | clock_enable_output_b => "BYPASS", 200 | indata_reg_b => "CLOCK1", 201 | init_file => init_file, 202 | intended_device_family => "Cyclone III", 203 | lpm_type => "altsyncram", 204 | numwords_a => 2**widthad_a, 205 | numwords_b => 2**widthad_a, 206 | operation_mode => "BIDIR_DUAL_PORT", 207 | outdata_aclr_a => "NONE", 208 | outdata_aclr_b => "NONE", 209 | outdata_reg_a => outdata_reg_a, 210 | outdata_reg_b => outdata_reg_a, 211 | power_up_uninitialized => "FALSE", 212 | read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", 213 | read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ", 214 | widthad_a => widthad_a, 215 | widthad_b => widthad_a, 216 | width_a => width_a, 217 | width_b => width_a, 218 | width_byteena_a => width_a/8, 219 | width_byteena_b => width_a/8, 220 | wrcontrol_wraddress_reg_b => "CLOCK1" 221 | ) 222 | PORT MAP ( 223 | wren_a => wren_a, 224 | clock0 => clock_a, 225 | wren_b => wren_b, 226 | clock1 => clock_b, 227 | address_a => address_a, 228 | address_b => address_b, 229 | data_a => data_a, 230 | data_b => data_b, 231 | q_a => sub_wire0, 232 | q_b => sub_wire1, 233 | byteena_a => byteena_a, 234 | byteena_b => byteena_b 235 | ); 236 | 237 | 238 | 239 | END SYN; 240 | -------------------------------------------------------------------------------- /rtl/font.chr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agg23/openfpga-NES/028501fb64cda7b126a817efeba1f69041bef5ee/rtl/font.chr -------------------------------------------------------------------------------- /rtl/mappers/mappers.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) VRC.sv ] 2 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) Sunsoft.sv ] 3 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) Sachen.sv ] 4 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) Namco.sv ] 5 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) MMC5.sv ] 6 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) MMC3.sv ] 7 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) MMC2.sv ] 8 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) MMC1.sv ] 9 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) misc.sv ] 10 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) JYCompany.sv ] 11 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) generic.sv ] 12 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) FDS.sv ] 13 | -------------------------------------------------------------------------------- /rtl/nes.qip: -------------------------------------------------------------------------------- 1 | # ============================================================================== 2 | # RTL 3 | # ============================================================================== 4 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "gameloader.sv"] 5 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "nes_top.sv"] 6 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "mappers/VRC.sv"] 7 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "mappers/Sunsoft.sv"] 8 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "mappers/Sachen.sv"] 9 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "mappers/Namco.sv"] 10 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "mappers/MMC5.sv"] 11 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "mappers/MMC3.sv"] 12 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "mappers/MMC2.sv"] 13 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "mappers/MMC1.sv"] 14 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "mappers/misc.sv"] 15 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "mappers/mappers.qip"] 16 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "mappers/JYCompany.sv"] 17 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "mappers/generic.sv"] 18 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "mappers/FDS.sv"] 19 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/voicerom.vhd"] 20 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/voicememory.vhd"] 21 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/vm2413.vhd"] 22 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/temporalmixer.vhd"] 23 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/slotcounter.vhd"] 24 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/sinetable.vhd"] 25 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/registermemory.vhd"] 26 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/phasememory.vhd"] 27 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/phasegenerator.vhd"] 28 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/outputmemory.vhd"] 29 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/outputgenerator.vhd"] 30 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/opll.vhd"] 31 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/operator.vhd"] 32 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/lineartable.vhd"] 33 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/feedbackmemory.vhd"] 34 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/envelopememory.vhd"] 35 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/envelopegenerator.vhd"] 36 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/controller.vhd"] 37 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/VM2413/attacktable.vhd"] 38 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "SOUND/OPLL/OPLL.qip"] 39 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SOUND/OPLL/eseopll.vhd"] 40 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "t65/T65_Pack.vhd"] 41 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "t65/T65_MCode.vhd"] 42 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "t65/T65_ALU.vhd"] 43 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "t65/T65.vhd"] 44 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "t65/t65.qip"] 45 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "zapper.sv"] 46 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "video.sv"] 47 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "statemanager.vhd"] 48 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "sdram.sv"] 49 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "savestates.vhd"] 50 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "savestate_ui.sv"] 51 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "regs_savestates.sv"] 52 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "ppu.sv"] 53 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "nes.v"] 54 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "miracle.sv"] 55 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "EEPROM_24C0x.sv"] 56 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "dsp.v"] 57 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "dpram.vhd"] 58 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "ddram.sv"] 59 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "compat.v"] 60 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "cheatcodes.sv"] 61 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "cart.sv"] 62 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "bus_savestates.vhd"] 63 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "button_turbo.sv"] 64 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "apu.sv"] 65 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "audio/audio.qip"] 66 | 67 | # ============================================================================== 68 | # MODULES 69 | # ============================================================================== 70 | 71 | -------------------------------------------------------------------------------- /rtl/regs_savestates.sv: -------------------------------------------------------------------------------- 1 | package regs_savestates; 2 | 3 | parameter [9:0] SSREG_INDEX_CPU_1 = 10'd0; parameter [63:0] SSREG_DEFAULT_CPU_1 = 64'hE064000000000000; // warning: defined new with same values in T65.vhd, as file is VHDL 4 | parameter [9:0] SSREG_INDEX_CPU_2 = 10'd1; parameter [63:0] SSREG_DEFAULT_CPU_2 = 64'h0000012000000001; // warning: defined new with same values in T65.vhd, as file is VHDL 5 | parameter [9:0] SSREG_INDEX_CPU_3 = 10'd2; parameter [63:0] SSREG_DEFAULT_CPU_3 = 64'h0000000000000000; // warning: defined new with same values in T65.vhd, as file is VHDL 6 | 7 | parameter [9:0] SSREG_INDEX_PPU_1 = 10'd4; parameter [63:0] SSREG_DEFAULT_PPU_1 = 64'h0000000000000000; 8 | parameter [9:0] SSREG_INDEX_PPU_2 = 10'd5; parameter [63:0] SSREG_DEFAULT_PPU_2 = 64'h0000000000000000; 9 | parameter [9:0] SSREG_INDEX_CLOCKGEN = 10'd6; parameter [63:0] SSREG_DEFAULT_CLOCKGEN = 64'h0000000000000152; 10 | parameter [9:0] SSREG_INDEX_PAL0 = 10'd7; parameter [63:0] SSREG_DEFAULT_PAL0 = 64'h0008000900080000; 11 | parameter [9:0] SSREG_INDEX_PAL1 = 10'd8; parameter [63:0] SSREG_DEFAULT_PAL1 = 64'h203A040100100201; 12 | parameter [9:0] SSREG_INDEX_PAL2 = 10'd9; parameter [63:0] SSREG_DEFAULT_PAL2 = 64'h2C00003404080200; 13 | parameter [9:0] SSREG_INDEX_PAL3 = 10'd10; parameter [63:0] SSREG_DEFAULT_PAL3 = 64'h080214032C240D01; 14 | parameter [9:0] SSREG_INDEX_LOOPY = 10'd11; parameter [63:0] SSREG_DEFAULT_LOOPY = 64'h0000000000000000; 15 | parameter [9:0] SSREG_INDEX_OAMEVAL = 10'd12; parameter [63:0] SSREG_DEFAULT_OAMEVAL = 64'h00000000000001FF; 16 | 17 | parameter [9:0] SSREG_INDEX_APU_TOP = 10'd16; parameter [63:0] SSREG_DEFAULT_APU_TOP = 64'h0000000000000000; 18 | parameter [9:0] SSREG_INDEX_APU_DMC1 = 10'd17; parameter [63:0] SSREG_DEFAULT_APU_DMC1 = 64'h0000000000000000; 19 | parameter [9:0] SSREG_INDEX_APU_DMC2 = 10'd18; parameter [63:0] SSREG_DEFAULT_APU_DMC2 = 64'h0000000000000000; 20 | parameter [9:0] SSREG_INDEX_APU_FCT = 10'd19; parameter [63:0] SSREG_DEFAULT_APU_FCT = 64'h0000000000007FFF; 21 | 22 | parameter [9:0] SSREG_INDEX_TOP = 10'd24; parameter [63:0] SSREG_DEFAULT_TOP = 64'h0000000000000000; 23 | 24 | parameter [9:0] SSREG_INDEX_EXT = 10'd28; parameter [63:0] SSREG_DEFAULT_EXT = 64'h0000000000000000; 25 | 26 | // mapper savestates can be used by multiple mappers, only active mapper outputs. default values for mappers are defined local! 27 | parameter [9:0] SSREG_INDEX_MAP1 = 10'd32; 28 | parameter [9:0] SSREG_INDEX_MAP2 = 10'd33; 29 | parameter [9:0] SSREG_INDEX_MAP3 = 10'd34; 30 | parameter [9:0] SSREG_INDEX_MAP4 = 10'd35; 31 | parameter [9:0] SSREG_INDEX_MAP5 = 10'd36; 32 | parameter [9:0] SSREG_INDEX_MAP6 = 10'd37; 33 | 34 | // additional modules for mappers in hierachy level 2 35 | parameter [9:0] SSREG_INDEX_L2MAP1 = 10'd40; 36 | 37 | // additional modules for mapper sound modules 38 | parameter [9:0] SSREG_INDEX_SNDMAP1 = 10'd48; 39 | parameter [9:0] SSREG_INDEX_SNDMAP2 = 10'd49; 40 | parameter [9:0] SSREG_INDEX_SNDMAP3 = 10'd50; 41 | parameter [9:0] SSREG_INDEX_SNDMAP4 = 10'd51; 42 | parameter [9:0] SSREG_INDEX_SNDMAP5 = 10'd52; 43 | 44 | endpackage -------------------------------------------------------------------------------- /rtl/savestate_ui.sv: -------------------------------------------------------------------------------- 1 | module savestate_ui #(parameter INFO_TIMEOUT_BITS) 2 | ( 3 | input clk, 4 | input [10:0] ps2_key, 5 | input allow_ss, 6 | input joySS , 7 | input joyRight, 8 | input joyLeft , 9 | input joyDown , 10 | input joyUp , 11 | input joyStart, 12 | input [1:0] status_slot, 13 | input [1:0] OSD_saveload, 14 | output reg ss_save, 15 | output reg ss_load, 16 | output reg ss_info_req, 17 | output reg [7:0] ss_info, 18 | output reg statusUpdate, 19 | output [1:0] selected_slot 20 | ); 21 | 22 | reg [1:0] ss_base = 0; 23 | 24 | reg lastRight = 1'b0; 25 | reg lastLeft = 1'b0; 26 | reg lastDown = 1'b0; 27 | reg lastUp = 1'b0; 28 | 29 | reg [(INFO_TIMEOUT_BITS-1):0] InfoWaitcnt = 0; 30 | 31 | reg slotswitched = 1'b0; 32 | reg [1:0] lastOSDsetting = 2'b0; 33 | 34 | assign selected_slot = ss_base; 35 | 36 | wire pressed = ps2_key[9]; 37 | 38 | always @(posedge clk) begin 39 | reg old_state; 40 | reg alt = 0; 41 | reg [1:0] old_st; 42 | 43 | old_state <= ps2_key[10]; 44 | 45 | lastRight <= joyRight; 46 | lastLeft <= joyLeft; 47 | lastDown <= joyDown; 48 | lastUp <= joyUp; 49 | 50 | slotswitched <= 1'b0; 51 | 52 | ss_save <= 1'b0; 53 | ss_load <= 1'b0; 54 | ss_info_req <= 1'b0; 55 | statusUpdate <= 1'b0; 56 | 57 | lastOSDsetting <= status_slot; 58 | 59 | if(allow_ss) begin 60 | 61 | // keyboard 62 | if(old_state != ps2_key[10]) begin 63 | case(ps2_key[7:0]) 64 | 'h11: alt <= pressed; 65 | 'h05: begin ss_save <= pressed & alt; ss_load <= pressed & ~alt; ss_base <= 0; statusUpdate <= 1'b1; end // F1 66 | 'h06: begin ss_save <= pressed & alt; ss_load <= pressed & ~alt; ss_base <= 1; statusUpdate <= 1'b1; end // F2 67 | 'h04: begin ss_save <= pressed & alt; ss_load <= pressed & ~alt; ss_base <= 2; statusUpdate <= 1'b1; end // F3 68 | 'h0C: begin ss_save <= pressed & alt; ss_load <= pressed & ~alt; ss_base <= 3; statusUpdate <= 1'b1; end // F4 69 | endcase 70 | end 71 | 72 | if (lastOSDsetting != status_slot) begin 73 | ss_base <= status_slot; 74 | statusUpdate <= 1'b1; 75 | end 76 | 77 | // gamepad 78 | if (joySS) begin 79 | // timeout with no button pressed -> help text 80 | InfoWaitcnt <= InfoWaitcnt + 1'b1; 81 | if (InfoWaitcnt[(INFO_TIMEOUT_BITS-1)]) begin 82 | ss_info <= 7'd5; 83 | ss_info_req <= 1'b1; 84 | InfoWaitcnt <= 25'b0; 85 | end 86 | // switch slot 87 | if (joyRight & ~lastRight & ss_base < 3) begin 88 | ss_base <= ss_base + 1'd1; 89 | statusUpdate <= 1'b1; 90 | slotswitched <= 1'b1; 91 | InfoWaitcnt <= 25'b0; 92 | end 93 | if (joyLeft & ~lastLeft & ss_base > 0) begin 94 | ss_base <= ss_base - 1'd1; 95 | statusUpdate <= 1'b1; 96 | slotswitched <= 1'b1; 97 | InfoWaitcnt <= 25'b0; 98 | end 99 | // save and load 100 | if (joyStart & joyDown & ~lastDown) begin 101 | ss_save <= 1'b1; 102 | InfoWaitcnt <= 25'b0; 103 | end 104 | // save and load 105 | if (joyStart & joyUp & ~lastUp) begin 106 | ss_load <= 1'b1; 107 | InfoWaitcnt <= 25'b0; 108 | end 109 | end else begin 110 | InfoWaitcnt <= 25'b0; 111 | end 112 | 113 | // OSD 114 | old_st <= OSD_saveload; 115 | if(old_st[0] ^ OSD_saveload[0]) ss_save <= OSD_saveload[0]; 116 | if(old_st[1] ^ OSD_saveload[1]) ss_load <= OSD_saveload[1]; 117 | 118 | // infotexts 119 | if (slotswitched) begin 120 | ss_info <= 7'd6 + ss_base; 121 | ss_info_req <= 1'b1; 122 | end 123 | 124 | if(ss_load | ss_save) begin 125 | ss_info <= 7'd10 + {ss_base, ss_load}; 126 | ss_info_req <= 1'b1; 127 | end 128 | 129 | end 130 | end 131 | 132 | endmodule 133 | 134 | -------------------------------------------------------------------------------- /rtl/statemanager.vhd: -------------------------------------------------------------------------------- 1 | library IEEE; 2 | use IEEE.std_logic_1164.all; 3 | use IEEE.numeric_std.all; 4 | 5 | entity statemanager is 6 | generic 7 | ( 8 | Softmap_SaveState_ADDR : integer; -- 2Mbyte Data for Savestate 9 | Softmap_Rewind_ADDR : integer -- unused 10 | ); 11 | port 12 | ( 13 | clk : in std_logic; 14 | reset : in std_logic; 15 | 16 | rewind_on : in std_logic; 17 | rewind_active : in std_logic; 18 | 19 | savestate_number : in integer; 20 | save : in std_logic; 21 | load : in std_logic; 22 | 23 | sleep_rewind : out std_logic := '0'; 24 | vsync : in std_logic; 25 | 26 | request_savestate : out std_logic := '0'; 27 | request_loadstate : out std_logic := '0'; 28 | request_address : out integer; 29 | request_busy : in std_logic 30 | ); 31 | end entity; 32 | 33 | architecture arch of statemanager is 34 | 35 | constant SAVESTATESIZE : integer := 16#80000#; -- 524288 Dwords = 2Mbyte 36 | constant REWIND_COUNT : integer := 4; 37 | constant TIME_CAPTURE : integer := 10000000; -- 320 ms sim 1000000; 38 | constant TIME_REWIND : integer := 5000000; -- 160 ms sim 1200000; 39 | 40 | signal save_1 : std_logic := '0'; 41 | signal load_1 : std_logic := '0'; 42 | signal save_buffer : std_logic := '0'; 43 | signal load_buffer : std_logic := '0'; 44 | 45 | signal rewind_enabled : std_logic := '0'; 46 | signal rewind_load_next : std_logic := '0'; 47 | 48 | signal timer_rewind : integer range 0 to TIME_CAPTURE := 0; 49 | signal rewind_slow : integer range 0 to TIME_REWIND := 0; 50 | signal savestatecount : integer range 0 to REWIND_COUNT := 0; 51 | signal savestatepos : integer range 0 to REWIND_COUNT - 1 := 0; 52 | 53 | signal vsync_counter : integer range 0 to 2 := 0; 54 | 55 | signal vsync_1 : std_logic; 56 | 57 | begin 58 | 59 | process (clk) 60 | begin 61 | if rising_edge(clk) then 62 | 63 | request_savestate <= '0'; 64 | request_loadstate <= '0'; 65 | rewind_load_next <= '0'; 66 | 67 | vsync_1 <= vsync; 68 | 69 | save_1 <= save; 70 | if (save = '1' and save_1 = '0') then 71 | save_buffer <= '1'; 72 | end if; 73 | 74 | load_1 <= load; 75 | if (load = '1' and load_1 = '0') then 76 | load_buffer <= '1'; 77 | end if; 78 | 79 | if (rewind_on = '0' or reset = '1') then 80 | rewind_enabled <= '0'; 81 | end if; 82 | 83 | if (rewind_active = '0') then 84 | rewind_slow <= 0; 85 | elsif (rewind_slow < TIME_REWIND) then 86 | rewind_slow <= rewind_slow + 1; 87 | end if; 88 | 89 | if (rewind_active = '1') then 90 | timer_rewind <= 0; 91 | elsif (timer_rewind < TIME_CAPTURE) then 92 | timer_rewind <= timer_rewind + 1; 93 | end if; 94 | 95 | if (vsync_counter < 2 and vsync = '1' and vsync_1 = '0') then 96 | vsync_counter <= vsync_counter + 1; 97 | end if; 98 | 99 | sleep_rewind <= '0'; 100 | if (vsync_counter = 2 and rewind_active = '1') then 101 | sleep_rewind <= '1'; 102 | end if; 103 | 104 | if (reset = '0' and request_busy = '0') then 105 | 106 | if (save_buffer = '1') then 107 | request_address <= Softmap_SaveState_ADDR + (savestate_number * SAVESTATESIZE); 108 | request_savestate <= '1'; 109 | save_buffer <= '0'; 110 | elsif (load_buffer = '1') then 111 | request_address <= Softmap_SaveState_ADDR + (savestate_number * SAVESTATESIZE); 112 | request_loadstate <= '1'; 113 | load_buffer <= '0'; 114 | elsif (rewind_enabled = '0' and rewind_on = '1') then 115 | request_address <= Softmap_Rewind_ADDR; 116 | request_savestate <= '1'; 117 | rewind_enabled <= '1'; 118 | timer_rewind <= 0; 119 | savestatecount <= 1; 120 | savestatepos <= 1; 121 | elsif (rewind_enabled = '1' and timer_rewind = TIME_CAPTURE) then 122 | request_address <= Softmap_Rewind_ADDR + (savestatepos * SAVESTATESIZE); 123 | request_savestate <= '1'; 124 | timer_rewind <= 0; 125 | if (savestatecount < REWIND_COUNT) then 126 | savestatecount <= savestatecount + 1; 127 | end if; 128 | if (savestatepos < (REWIND_COUNT - 1)) then 129 | savestatepos <= savestatepos + 1; 130 | else 131 | savestatepos <= 0; 132 | end if; 133 | elsif (rewind_enabled = '1' and rewind_slow = TIME_REWIND) then 134 | if (savestatecount > 1) then 135 | savestatecount <= savestatecount - 1; 136 | if (savestatepos > 0) then 137 | savestatepos <= savestatepos - 1; 138 | else 139 | savestatepos <= REWIND_COUNT - 1; 140 | end if; 141 | rewind_load_next <= '1'; 142 | end if; 143 | rewind_slow <= 0; 144 | elsif (rewind_load_next = '1') then 145 | request_address <= Softmap_Rewind_ADDR + (savestatepos * SAVESTATESIZE); 146 | request_loadstate <= '1'; 147 | vsync_counter <= 0; 148 | end if; 149 | 150 | end if; 151 | 152 | end if; 153 | end process; 154 | 155 | 156 | end architecture; 157 | 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /rtl/t65/T65_Pack.vhd: -------------------------------------------------------------------------------- 1 | -- **** 2 | -- T65(b) core. In an effort to merge and maintain bug fixes .... 3 | -- 4 | -- See list of changes in T65 top file (T65.vhd)... 5 | -- 6 | -- **** 7 | -- 65xx compatible microprocessor core 8 | -- 9 | -- FPGAARCADE SVN: $Id: T65_Pack.vhd 1234 2015-02-28 20:14:50Z wolfgang.scherr $ 10 | -- 11 | -- Copyright (c) 2002...2015 12 | -- Daniel Wallner (jesus opencores org) 13 | -- Mike Johnson (mikej fpgaarcade com) 14 | -- Wolfgang Scherr (WoS pin4 at> 15 | -- Morten Leikvoll () 16 | -- 17 | -- All rights reserved 18 | -- 19 | -- Redistribution and use in source and synthezised forms, with or without 20 | -- modification, are permitted provided that the following conditions are met: 21 | -- 22 | -- Redistributions of source code must retain the above copyright notice, 23 | -- this list of conditions and the following disclaimer. 24 | -- 25 | -- Redistributions in synthesized form must reproduce the above copyright 26 | -- notice, this list of conditions and the following disclaimer in the 27 | -- documentation and/or other materials provided with the distribution. 28 | -- 29 | -- Neither the name of the author nor the names of other contributors may 30 | -- be used to endorse or promote products derived from this software without 31 | -- specific prior written permission. 32 | -- 33 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 34 | -- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 35 | -- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 36 | -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 37 | -- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 38 | -- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 39 | -- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 40 | -- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 41 | -- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 42 | -- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 43 | -- POSSIBILITY OF SUCH DAMAGE. 44 | -- 45 | -- Please report bugs to the author(s), but before you do so, please 46 | -- make sure that this is not a derivative work and that 47 | -- you have the latest version of this file. 48 | -- 49 | -- Limitations : 50 | -- See in T65 top file (T65.vhd)... 51 | 52 | library IEEE; 53 | use IEEE.std_logic_1164.all; 54 | 55 | package T65_Pack is 56 | 57 | constant Flag_C : integer := 0; 58 | constant Flag_Z : integer := 1; 59 | constant Flag_I : integer := 2; 60 | constant Flag_D : integer := 3; 61 | constant Flag_B : integer := 4; 62 | constant Flag_1 : integer := 5; 63 | constant Flag_V : integer := 6; 64 | constant Flag_N : integer := 7; 65 | 66 | subtype T_Lcycle is std_logic_vector(2 downto 0); 67 | constant Cycle_sync :T_Lcycle:="000"; 68 | constant Cycle_1 :T_Lcycle:="001"; 69 | constant Cycle_2 :T_Lcycle:="010"; 70 | constant Cycle_3 :T_Lcycle:="011"; 71 | constant Cycle_4 :T_Lcycle:="100"; 72 | constant Cycle_5 :T_Lcycle:="101"; 73 | constant Cycle_6 :T_Lcycle:="110"; 74 | constant Cycle_7 :T_Lcycle:="111"; 75 | 76 | function CycleNext(c:T_Lcycle) return T_Lcycle; 77 | 78 | type T_Set_BusA_To is 79 | ( 80 | Set_BusA_To_DI, 81 | Set_BusA_To_ABC, 82 | Set_BusA_To_X, 83 | Set_BusA_To_Y, 84 | Set_BusA_To_S, 85 | Set_BusA_To_P, 86 | Set_BusA_To_DA, 87 | Set_BusA_To_DAO, 88 | Set_BusA_To_DAX, 89 | Set_BusA_To_AAX, 90 | Set_BusA_To_DONTCARE 91 | ); 92 | 93 | type T_Set_Addr_To is 94 | ( 95 | Set_Addr_To_PBR, 96 | Set_Addr_To_SP, 97 | Set_Addr_To_ZPG, 98 | Set_Addr_To_BA 99 | ); 100 | 101 | type T_Write_Data is 102 | ( 103 | Write_Data_DL, 104 | Write_Data_ABC, 105 | Write_Data_X, 106 | Write_Data_Y, 107 | Write_Data_S, 108 | Write_Data_P, 109 | Write_Data_PCL, 110 | Write_Data_PCH, 111 | Write_Data_AX, 112 | Write_Data_AXB, 113 | Write_Data_XB, 114 | Write_Data_YB, 115 | Write_Data_DONTCARE 116 | ); 117 | 118 | type T_ALU_OP is 119 | ( 120 | ALU_OP_OR, --"0000" 121 | ALU_OP_AND, --"0001" 122 | ALU_OP_EOR, --"0010" 123 | ALU_OP_ADC, --"0011" 124 | ALU_OP_EQ1, --"0100" EQ1 does not change N,Z flags, EQ2/3 does. 125 | ALU_OP_EQ2, --"0101" Not sure yet whats the difference between EQ2&3. They seem to do the same ALU op 126 | ALU_OP_CMP, --"0110" 127 | ALU_OP_SBC, --"0111" 128 | ALU_OP_ASL, --"1000" 129 | ALU_OP_ROL, --"1001" 130 | ALU_OP_LSR, --"1010" 131 | ALU_OP_ROR, --"1011" 132 | ALU_OP_BIT, --"1100" 133 | -- ALU_OP_EQ3, --"1101" 134 | ALU_OP_DEC, --"1110" 135 | ALU_OP_INC, --"1111" 136 | ALU_OP_ARR, 137 | ALU_OP_ANC, 138 | ALU_OP_SAX, 139 | ALU_OP_XAA 140 | -- ALU_OP_UNDEF--"----"--may be replaced with any? 141 | ); 142 | 143 | type T_t65_dbg is record 144 | I : std_logic_vector(7 downto 0); -- instruction 145 | A : std_logic_vector(7 downto 0); -- A reg 146 | X : std_logic_vector(7 downto 0); -- X reg 147 | Y : std_logic_vector(7 downto 0); -- Y reg 148 | S : std_logic_vector(7 downto 0); -- stack pointer 149 | P : std_logic_vector(7 downto 0); -- processor flags 150 | end record; 151 | 152 | end; 153 | 154 | package body T65_Pack is 155 | 156 | function CycleNext(c:T_Lcycle) return T_Lcycle is 157 | begin 158 | case(c) is 159 | when Cycle_sync=> 160 | return Cycle_1; 161 | when Cycle_1=> 162 | return Cycle_2; 163 | when Cycle_2=> 164 | return Cycle_3; 165 | when Cycle_3=> 166 | return Cycle_4; 167 | when Cycle_4=> 168 | return Cycle_5; 169 | when Cycle_5=> 170 | return Cycle_6; 171 | when Cycle_6=> 172 | return Cycle_7; 173 | when Cycle_7=> 174 | return Cycle_sync; 175 | when others=> 176 | return Cycle_sync; 177 | end case; 178 | end CycleNext; 179 | 180 | end T65_Pack; -------------------------------------------------------------------------------- /rtl/t65/t65.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T65_Pack.vhd ] 2 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T65_ALU.vhd ] 3 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T65_MCode.vhd ] 4 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T65.vhd ] 5 | -------------------------------------------------------------------------------- /rtl/tao.mif: -------------------------------------------------------------------------------- 1 | -- Copyright (C) 2017 Intel Corporation. All rights reserved. 2 | -- Your use of Intel Corporation's design tools, logic functions 3 | -- and other software and tools, and its AMPP partner logic 4 | -- functions, and any output files from any of the foregoing 5 | -- (including device programming or simulation files), and any 6 | -- associated documentation or information are expressly subject 7 | -- to the terms and conditions of the Intel Program License 8 | -- Subscription Agreement, the Intel Quartus Prime License Agreement, 9 | -- the Intel MegaCore Function License Agreement, or other 10 | -- applicable license agreement, including, without limitation, 11 | -- that your use is for the sole purpose of programming logic 12 | -- devices manufactured by Intel and sold by Intel or its 13 | -- authorized distributors. Please refer to the applicable 14 | -- agreement for further details. 15 | 16 | -- Quartus Prime generated Memory Initialization File (.mif) 17 | 18 | WIDTH=24; 19 | DEPTH=64; 20 | 21 | ADDRESS_RADIX=HEX; 22 | DATA_RADIX=BIN; 23 | 24 | CONTENT BEGIN 25 | 00 : 010111110101111101011111; 26 | 01 : 000000000001111110010111; 27 | 02 : 000011110000000010111111; 28 | 03 : 010000110000000010100111; 29 | 04 : 011111110000000001110111; 30 | 05 : 100011110000000000100111; 31 | 06 : 100011110000011100000000; 32 | 07 : 011101110010011100000000; 33 | 08 : 010001110011111100000000; 34 | 09 : 000000000100011100000000; 35 | 0A : 000000000100111100001111; 36 | 0B : 000000000100011100101111; 37 | 0C : 000000000100011101100111; 38 | [0D..0F] : 000000000000000000000000; 39 | 10 : 101011111010111110101111; 40 | 11 : 000000000101011111110111; 41 | 12 : 000111110011111111111111; 42 | 13 : 011001110001111111110111; 43 | 14 : 101011110000011111001111; 44 | 15 : 110101110000000001010111; 45 | 16 : 110111110001011100000000; 46 | 17 : 101111110100011100000000; 47 | 18 : 100001110110011100000000; 48 | 19 : 000101111000011100000000; 49 | 1A : 000000001001011100010111; 50 | 1B : 000000001000011101010111; 51 | 1C : 000000000111111110100111; 52 | 1D : 000101110001011100010111; 53 | [1E..1F] : 000000000000000000000000; 54 | 20 : 111011111110111111101111; 55 | 21 : 001001111001111111111111; 56 | 22 : 010000111000011111111111; 57 | 23 : 100001110110111111111111; 58 | 24 : 110001110101111111111111; 59 | 25 : 111111110101011110011111; 60 | 26 : 111111110110111101001111; 61 | 27 : 111111111000011100000000; 62 | 28 : 110011111010011100000000; 63 | 29 : 011011111100011100000000; 64 | 2A : 000111111100111100101111; 65 | 2B : 000101111100111110010111; 66 | 2C : 000000001011111111100111; 67 | 2D : 010001110100011101000111; 68 | [2E..2F] : 000000000000000000000000; 69 | 30 : 111011111110111111101111; 70 | 31 : 101011111100111111111111; 71 | 32 : 101101111011011111111111; 72 | 33 : 110001111010111111111111; 73 | 34 : 111001111010011111111111; 74 | 35 : 111101111011011111100111; 75 | 36 : 111111111100011111001111; 76 | 37 : 111111111100111110010111; 77 | 38 : 111101111110011110010111; 78 | 39 : 110101111111011110001111; 79 | 3A : 101011111111111110010111; 80 | 3B : 100111111111011111001111; 81 | 3C : 100001111110011111110111; 82 | 3D : 100011111000111110001111; 83 | [3E..3F] : 000000000000000000000000; 84 | END; 85 | -------------------------------------------------------------------------------- /rtl/zapper.sv: -------------------------------------------------------------------------------- 1 | // NES Zapper emulation, by Kitrinx 2 | // Apr, 20 2019 3 | 4 | module zapper ( 5 | input clk, 6 | input reset, 7 | input dpad_up, 8 | input dpad_down, 9 | input dpad_left, 10 | input dpad_right, 11 | input [7:0] dpad_aim_speed, 12 | input [15:0] analog, 13 | input analog_trigger, 14 | input [8:0] cycle, 15 | input [8:0] scanline, 16 | input vde, 17 | input [5:0] color, 18 | output reg [1:0] reticle, 19 | output light, 20 | output trigger 21 | ); 22 | 23 | assign light = ~light_state; 24 | assign trigger = trigger_state; 25 | 26 | wire light_state = light_cnt > 0; 27 | 28 | reg [8:0] light_cnt; // timer for 10-25 scanlines worth of "light" activity. 29 | reg [9:0] pos_x, pos_y; 30 | wire trigger_state = (trigger_cnt > 'd2_100_000); 31 | reg old_msg; 32 | reg [8:0] old_scanline; 33 | reg old_vde; 34 | reg [15:0] old_analog; 35 | reg pressed; 36 | 37 | int trigger_cnt; 38 | 39 | parameter cross_size = 8'd4; 40 | 41 | wire hit_x = ((pos_x >= cycle - cross_size && pos_x <= cycle + cross_size) && scanline == pos_y); 42 | wire hit_y = ((pos_y >= scanline - cross_size && pos_y <= scanline + cross_size) && cycle == pos_x); 43 | 44 | wire is_offscreen = ((pos_x >= 254 || pos_x <= 1) || (pos_y >= 224 || pos_y <= 8)); 45 | wire light_square = ((pos_x >= cycle - 3'd4 && pos_x <= cycle + 3'd4) && (pos_y >= scanline - 3'd4 && pos_y <= scanline + 3'd4)); 46 | 47 | wire [7:0] joy_x = analog[7:0]; 48 | wire [7:0] joy_y = analog[15:8]; 49 | 50 | wire trigger_btn = analog_trigger; 51 | 52 | always @(posedge clk) begin 53 | if (reset) begin 54 | {trigger_cnt, pos_x, pos_y, light_cnt} <= 0; 55 | reticle <= 0; 56 | end else begin 57 | old_scanline <= scanline; 58 | 59 | if (trigger_cnt > 0) trigger_cnt <= trigger_cnt - 1'b1; 60 | 61 | // "Drain" the light from the zapper over time 62 | if (old_scanline != scanline && light_cnt > 0) light_cnt <= light_cnt - 1'b1; 63 | 64 | if (trigger_cnt == 0 && trigger_btn && ~pressed) begin 65 | trigger_cnt <= 'd830000 + 'd2_100_000; 66 | pressed <= 1'b1; 67 | end 68 | 69 | if (~trigger_btn) pressed <= 0; 70 | 71 | old_vde <= vde; 72 | if(~old_vde & vde) begin 73 | old_analog <= analog; 74 | if (old_analog != analog) begin 75 | pos_x <= joy_x; 76 | pos_y <= joy_y; 77 | end else begin 78 | if(dpad_left) begin 79 | if (pos_x >= dpad_aim_speed) pos_x <= pos_x - dpad_aim_speed; 80 | else pos_x <= 0; 81 | end 82 | if(dpad_right) begin 83 | if(pos_x <= 8'd255 - dpad_aim_speed) pos_x <= pos_x + dpad_aim_speed; 84 | else pos_x <= 8'd255; 85 | end 86 | if(dpad_up) begin 87 | if (pos_y >= dpad_aim_speed) pos_y <= pos_y - dpad_aim_speed; 88 | else pos_y <= 0; 89 | end 90 | if(dpad_down) begin 91 | if (pos_y < 8'd240 - dpad_aim_speed) pos_y <= pos_y + dpad_aim_speed; 92 | else pos_y <= 8'd240; 93 | end 94 | end 95 | end 96 | 97 | reticle[0] <= (hit_x || hit_y); 98 | reticle[1] <= is_offscreen; 99 | 100 | // See if we're "pointed" at light 101 | if (light_square && ~is_offscreen) begin 102 | if (color == 'h20 || color == 'h30) 103 | light_cnt <= 'd26; 104 | else if ((color[5:4] == 3 && color < 'h3E) || color == 'h10) 105 | if (light_cnt < 'd20) light_cnt <= 'd20; 106 | else if ((color[5:4] == 2 && color < 'h2E) || color == 'h00) 107 | if (light_cnt < 'd17) light_cnt <= 'd17; 108 | end 109 | end 110 | end 111 | 112 | endmodule 113 | 114 | -------------------------------------------------------------------------------- /target/pocket/core.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "core_top.v"] 2 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "core_bridge_cmd.v"] 3 | set_global_assignment -name SDC_FILE [file join $::quartus(qip_path) "core_constraints.sdc"] 4 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "data_loader.sv"] 5 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "data_unloader.sv"] 6 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "save_state_controller.sv"] 7 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "sound_i2s.sv"] 8 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "sync_fifo.sv"] 9 | 10 | set_global_assignment -name SIGNALTAP_FILE [file join $::quartus(qip_path) "stp1.stp"] 11 | 12 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "mf_audio_pll.qip"] 13 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "mf_pllbase.qip"] 14 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "pll_reconfig.qip"] 15 | -------------------------------------------------------------------------------- /target/pocket/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|*[0].*|divclk \ 12 | ic|mp1|mf_pllbase_inst|altera_pll_i|*[1].*|divclk } \ 13 | -group { ic|mp1|mf_pllbase_inst|altera_pll_i|*[2].*|divclk } \ 14 | -group { ic|mp1|mf_pllbase_inst|altera_pll_i|*[3].*|divclk } \ 15 | -group { ic|audio_mixer|audio_pll|mf_audio_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk \ 16 | ic|audio_mixer|audio_pll|mf_audio_pll_inst|altera_pll_i|general[1].gpll~PLL_OUTPUT_COUNTER|divclk } 17 | 18 | derive_clock_uncertainty 19 | 20 | set_multicycle_path -from {ic|nes|sdram|*} -to [get_clocks {ic|mp1|mf_pllbase_inst|altera_pll_i|*[1].*|divclk}] -start -setup 2 21 | set_multicycle_path -from {ic|nes|sdram|*} -to [get_clocks {ic|mp1|mf_pllbase_inst|altera_pll_i|*[1].*|divclk}] -start -hold 1 22 | 23 | set_multicycle_path -from [get_clocks {ic|mp1|mf_pllbase_inst|altera_pll_i|*[1].*|divclk}] -to {ic|nes|sdram|*} -setup 2 24 | set_multicycle_path -from [get_clocks {ic|mp1|mf_pllbase_inst|altera_pll_i|*[1].*|divclk}] -to {ic|nes|sdram|*} -hold 1 25 | 26 | set_false_path -from {ic|nes|mapper_flags*} 27 | #set_false_path -from {ic|nes|downloading*} 28 | -------------------------------------------------------------------------------- /target/pocket/mf_audio_pll/mf_audio_pll_0002.qip: -------------------------------------------------------------------------------- 1 | set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*mf_audio_pll_0002*|altera_pll:altera_pll_i*|*" 2 | set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*mf_audio_pll_0002*|altera_pll:altera_pll_i*|*" 3 | set_instance_assignment -name PLL_AUTO_RESET OFF -to "*mf_audio_pll_0002*|altera_pll:altera_pll_i*|*" 4 | set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*mf_audio_pll_0002*|altera_pll:altera_pll_i*|*" 5 | -------------------------------------------------------------------------------- /target/pocket/mf_audio_pll/mf_audio_pll_0002.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/10ps 2 | module mf_audio_pll_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 'locked' 17 | output wire locked 18 | ); 19 | 20 | altera_pll #( 21 | .fractional_vco_multiplier("true"), 22 | .reference_clock_frequency("74.25 MHz"), 23 | .operation_mode("direct"), 24 | .number_of_clocks(2), 25 | .output_clock_frequency0("12.288000 MHz"), 26 | .phase_shift0("0 ps"), 27 | .duty_cycle0(50), 28 | .output_clock_frequency1("3.072000 MHz"), 29 | .phase_shift1("0 ps"), 30 | .duty_cycle1(50), 31 | .output_clock_frequency2("0 MHz"), 32 | .phase_shift2("0 ps"), 33 | .duty_cycle2(50), 34 | .output_clock_frequency3("0 MHz"), 35 | .phase_shift3("0 ps"), 36 | .duty_cycle3(50), 37 | .output_clock_frequency4("0 MHz"), 38 | .phase_shift4("0 ps"), 39 | .duty_cycle4(50), 40 | .output_clock_frequency5("0 MHz"), 41 | .phase_shift5("0 ps"), 42 | .duty_cycle5(50), 43 | .output_clock_frequency6("0 MHz"), 44 | .phase_shift6("0 ps"), 45 | .duty_cycle6(50), 46 | .output_clock_frequency7("0 MHz"), 47 | .phase_shift7("0 ps"), 48 | .duty_cycle7(50), 49 | .output_clock_frequency8("0 MHz"), 50 | .phase_shift8("0 ps"), 51 | .duty_cycle8(50), 52 | .output_clock_frequency9("0 MHz"), 53 | .phase_shift9("0 ps"), 54 | .duty_cycle9(50), 55 | .output_clock_frequency10("0 MHz"), 56 | .phase_shift10("0 ps"), 57 | .duty_cycle10(50), 58 | .output_clock_frequency11("0 MHz"), 59 | .phase_shift11("0 ps"), 60 | .duty_cycle11(50), 61 | .output_clock_frequency12("0 MHz"), 62 | .phase_shift12("0 ps"), 63 | .duty_cycle12(50), 64 | .output_clock_frequency13("0 MHz"), 65 | .phase_shift13("0 ps"), 66 | .duty_cycle13(50), 67 | .output_clock_frequency14("0 MHz"), 68 | .phase_shift14("0 ps"), 69 | .duty_cycle14(50), 70 | .output_clock_frequency15("0 MHz"), 71 | .phase_shift15("0 ps"), 72 | .duty_cycle15(50), 73 | .output_clock_frequency16("0 MHz"), 74 | .phase_shift16("0 ps"), 75 | .duty_cycle16(50), 76 | .output_clock_frequency17("0 MHz"), 77 | .phase_shift17("0 ps"), 78 | .duty_cycle17(50), 79 | .pll_type("General"), 80 | .pll_subtype("General") 81 | ) altera_pll_i ( 82 | .rst (rst), 83 | .outclk ({outclk_1, outclk_0}), 84 | .locked (locked), 85 | .fboutclk ( ), 86 | .fbclk (1'b0), 87 | .refclk (refclk) 88 | ); 89 | endmodule 90 | 91 | -------------------------------------------------------------------------------- /target/pocket/mf_pllbase.ppf: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /target/pocket/mf_pllbase/mf_pllbase_0002.qip: -------------------------------------------------------------------------------- 1 | set_instance_assignment -name PLL_COMPENSATION_MODE NORMAL -to "*mf_pllbase_0002*|altera_pll:altera_pll_i*|*" 2 | set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*mf_pllbase_0002*|altera_pll:altera_pll_i*|*" 3 | set_instance_assignment -name PLL_AUTO_RESET ON -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 | -------------------------------------------------------------------------------- /target/pocket/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 'outclk3' 20 | output wire outclk_3, 21 | 22 | // interface 'locked' 23 | output wire locked 24 | ); 25 | 26 | altera_pll #( 27 | .fractional_vco_multiplier("true"), 28 | .reference_clock_frequency("74.25 MHz"), 29 | .operation_mode("normal"), 30 | .number_of_clocks(4), 31 | .output_clock_frequency0("85.908992 MHz"), 32 | .phase_shift0("0 ps"), 33 | .duty_cycle0(50), 34 | .output_clock_frequency1("21.477248 MHz"), 35 | .phase_shift1("0 ps"), 36 | .duty_cycle1(50), 37 | .output_clock_frequency2("5.369312 MHz"), 38 | .phase_shift2("0 ps"), 39 | .duty_cycle2(50), 40 | .output_clock_frequency3("5.369312 MHz"), 41 | .phase_shift3("46561 ps"), 42 | .duty_cycle3(50), 43 | .output_clock_frequency4("0 MHz"), 44 | .phase_shift4("0 ps"), 45 | .duty_cycle4(50), 46 | .output_clock_frequency5("0 MHz"), 47 | .phase_shift5("0 ps"), 48 | .duty_cycle5(50), 49 | .output_clock_frequency6("0 MHz"), 50 | .phase_shift6("0 ps"), 51 | .duty_cycle6(50), 52 | .output_clock_frequency7("0 MHz"), 53 | .phase_shift7("0 ps"), 54 | .duty_cycle7(50), 55 | .output_clock_frequency8("0 MHz"), 56 | .phase_shift8("0 ps"), 57 | .duty_cycle8(50), 58 | .output_clock_frequency9("0 MHz"), 59 | .phase_shift9("0 ps"), 60 | .duty_cycle9(50), 61 | .output_clock_frequency10("0 MHz"), 62 | .phase_shift10("0 ps"), 63 | .duty_cycle10(50), 64 | .output_clock_frequency11("0 MHz"), 65 | .phase_shift11("0 ps"), 66 | .duty_cycle11(50), 67 | .output_clock_frequency12("0 MHz"), 68 | .phase_shift12("0 ps"), 69 | .duty_cycle12(50), 70 | .output_clock_frequency13("0 MHz"), 71 | .phase_shift13("0 ps"), 72 | .duty_cycle13(50), 73 | .output_clock_frequency14("0 MHz"), 74 | .phase_shift14("0 ps"), 75 | .duty_cycle14(50), 76 | .output_clock_frequency15("0 MHz"), 77 | .phase_shift15("0 ps"), 78 | .duty_cycle15(50), 79 | .output_clock_frequency16("0 MHz"), 80 | .phase_shift16("0 ps"), 81 | .duty_cycle16(50), 82 | .output_clock_frequency17("0 MHz"), 83 | .phase_shift17("0 ps"), 84 | .duty_cycle17(50), 85 | .pll_type("General"), 86 | .pll_subtype("General") 87 | ) altera_pll_i ( 88 | .rst (rst), 89 | .outclk ({outclk_3, outclk_2, outclk_1, outclk_0}), 90 | .locked (locked), 91 | .fboutclk ( ), 92 | .fbclk (1'b0), 93 | .refclk (refclk) 94 | ); 95 | endmodule 96 | 97 | -------------------------------------------------------------------------------- /target/pocket/pll_reconfig.ppf: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /target/pocket/pll_reconfig.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_TOOL_NAME "altera_pll_reconfig" 2 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_TOOL_VERSION "21.1" 3 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_TOOL_ENV "mwpim" 4 | set_global_assignment -library "pll_reconfig" -name MISC_FILE [file join $::quartus(qip_path) "pll_reconfig.cmp"] 5 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V" 6 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" 7 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_QSYS_MODE "UNKNOWN" 8 | set_global_assignment -name SYNTHESIS_ONLY_QIP ON 9 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_NAME "cGxsX3JlY29uZmln" 10 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_DISPLAY_NAME "UExMIFJlY29uZmlnIEludGVsIEZQR0EgSVA=" 11 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_REPORT_HIERARCHY "Off" 12 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_INTERNAL "Off" 13 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_AUTHOR "SW50ZWwgQ29ycG9yYXRpb24=" 14 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_VERSION "MjEuMQ==" 15 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_DESCRIPTION "SW50ZWwgUGhhc2UtTG9ja2VkIExvb3AgUmVjb25maWd1cmF0aW9uIEJsb2Nr" 16 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0JZVEVFTkFCTEU=::ZmFsc2U=::QWRkIGJ5dGVlbmFibGUgcG9ydA==" 17 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "QllURUVOQUJMRV9XSURUSA==::NA==::QllURUVOQUJMRV9XSURUSA==" 18 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfQUREUl9XSURUSA==::Ng==::UkVDT05GSUdfQUREUl9XSURUSA==" 19 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfREFUQV9XSURUSA==::MzI=::UkVDT05GSUdfREFUQV9XSURUSA==" 20 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "cmVjb25mX3dpZHRo::NjQ=::cmVjb25mX3dpZHRo" 21 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "V0FJVF9GT1JfTE9DSw==::dHJ1ZQ==::V0FJVF9GT1JfTE9DSw==" 22 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_NAME "YWx0ZXJhX3BsbF9yZWNvbmZpZ190b3A=" 23 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_DISPLAY_NAME "UExMIFJlY29uZmlnIEludGVsIEZQR0EgSVA=" 24 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_REPORT_HIERARCHY "Off" 25 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_INTERNAL "Off" 26 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_AUTHOR "SW50ZWwgQ29ycG9yYXRpb24=" 27 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_VERSION "MjEuMQ==" 28 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_DESCRIPTION "SW50ZWwgUGhhc2UtTG9ja2VkIExvb3AgUmVjb25maWd1cmF0aW9uIEJsb2Nr" 29 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "ZGV2aWNlX2ZhbWlseQ==::Q3ljbG9uZSBW::ZGV2aWNlX2ZhbWlseQ==" 30 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "RU5BQkxFX01JRg==::ZmFsc2U=::RW5hYmxlIE1JRiBTdHJlYW1pbmc=" 31 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0JZVEVFTkFCTEU=::ZmFsc2U=::QWRkIGJ5dGVlbmFibGUgcG9ydA==" 32 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "QllURUVOQUJMRV9XSURUSA==::NA==::QllURUVOQUJMRV9XSURUSA==" 33 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfQUREUl9XSURUSA==::Ng==::UkVDT05GSUdfQUREUl9XSURUSA==" 34 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfREFUQV9XSURUSA==::MzI=::UkVDT05GSUdfREFUQV9XSURUSA==" 35 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "cmVjb25mX3dpZHRo::NjQ=::cmVjb25mX3dpZHRo" 36 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "V0FJVF9GT1JfTE9DSw==::dHJ1ZQ==::V0FJVF9GT1JfTE9DSw==" 37 | 38 | set_global_assignment -library "pll_reconfig" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_reconfig.v"] 39 | set_global_assignment -library "pll_reconfig" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_reconfig/altera_pll_reconfig_top.v"] 40 | set_global_assignment -library "pll_reconfig" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_reconfig/altera_pll_reconfig_core.v"] 41 | set_global_assignment -library "pll_reconfig" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_reconfig/altera_std_synchronizer.v"] 42 | 43 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_TOOL_NAME "altera_pll_reconfig" 44 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_TOOL_VERSION "21.1" 45 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_TOOL_ENV "mwpim" 46 | -------------------------------------------------------------------------------- /target/pocket/pll_reconfig.v: -------------------------------------------------------------------------------- 1 | // megafunction wizard: %PLL Reconfig Intel FPGA IP v21.1% 2 | // GENERATION: XML 3 | // pll_reconfig.v 4 | 5 | // Generated using ACDS version 21.1 850 6 | 7 | `timescale 1 ps / 1 ps 8 | module pll_reconfig #( 9 | parameter ENABLE_BYTEENABLE = 0, 10 | parameter BYTEENABLE_WIDTH = 4, 11 | parameter RECONFIG_ADDR_WIDTH = 6, 12 | parameter RECONFIG_DATA_WIDTH = 32, 13 | parameter reconf_width = 64, 14 | parameter WAIT_FOR_LOCK = 1 15 | ) ( 16 | input wire mgmt_clk, // mgmt_clk.clk 17 | input wire mgmt_reset, // mgmt_reset.reset 18 | output wire mgmt_waitrequest, // mgmt_avalon_slave.waitrequest 19 | input wire mgmt_read, // .read 20 | input wire mgmt_write, // .write 21 | output wire [31:0] mgmt_readdata, // .readdata 22 | input wire [5:0] mgmt_address, // .address 23 | input wire [31:0] mgmt_writedata, // .writedata 24 | output wire [63:0] reconfig_to_pll, // reconfig_to_pll.reconfig_to_pll 25 | input wire [63:0] reconfig_from_pll // reconfig_from_pll.reconfig_from_pll 26 | ); 27 | 28 | altera_pll_reconfig_top #( 29 | .device_family ("Cyclone V"), 30 | .ENABLE_MIF (0), 31 | .MIF_FILE_NAME (""), 32 | .ENABLE_BYTEENABLE (ENABLE_BYTEENABLE), 33 | .BYTEENABLE_WIDTH (BYTEENABLE_WIDTH), 34 | .RECONFIG_ADDR_WIDTH (RECONFIG_ADDR_WIDTH), 35 | .RECONFIG_DATA_WIDTH (RECONFIG_DATA_WIDTH), 36 | .reconf_width (reconf_width), 37 | .WAIT_FOR_LOCK (WAIT_FOR_LOCK) 38 | ) pll_reconfig_inst ( 39 | .mgmt_clk (mgmt_clk), // mgmt_clk.clk 40 | .mgmt_reset (mgmt_reset), // mgmt_reset.reset 41 | .mgmt_waitrequest (mgmt_waitrequest), // mgmt_avalon_slave.waitrequest 42 | .mgmt_read (mgmt_read), // .read 43 | .mgmt_write (mgmt_write), // .write 44 | .mgmt_readdata (mgmt_readdata), // .readdata 45 | .mgmt_address (mgmt_address), // .address 46 | .mgmt_writedata (mgmt_writedata), // .writedata 47 | .reconfig_to_pll (reconfig_to_pll), // reconfig_to_pll.reconfig_to_pll 48 | .reconfig_from_pll (reconfig_from_pll), // reconfig_from_pll.reconfig_from_pll 49 | .mgmt_byteenable (4'b0000) // (terminated) 50 | ); 51 | 52 | endmodule 53 | // Retrieval info: 54 | // 79 | // Retrieval info: 80 | // Retrieval info: 81 | // Retrieval info: 82 | // Retrieval info: 83 | // Retrieval info: 84 | // Retrieval info: 85 | // IPFS_FILES : pll_reconfig.vo 86 | // RELATED_FILES: pll_reconfig.v, altera_pll_reconfig_top.v, altera_pll_reconfig_core.v, altera_std_synchronizer.v 87 | -------------------------------------------------------------------------------- /target/pocket/pll_reconfig/altera_std_synchronizer.v: -------------------------------------------------------------------------------- 1 | // (C) 2001-2022 Intel Corporation. All rights reserved. 2 | // Your use of Intel Corporation's design tools, logic functions and other 3 | // software and tools, and its AMPP partner logic functions, and any output 4 | // files from any of the foregoing (including device programming or simulation 5 | // files), and any associated documentation or information are expressly subject 6 | // to the terms and conditions of the Intel Program License Subscription 7 | // Agreement, Intel FPGA IP License Agreement, or other applicable 8 | // license agreement, including, without limitation, that your use is for the 9 | // sole purpose of programming logic devices manufactured by Intel and sold by 10 | // Intel or its authorized distributors. Please refer to the applicable 11 | // agreement for further details. 12 | 13 | 14 | // $Id: //acds/rel/21.1std/ip/sopc/components/primitives/altera_std_synchronizer/altera_std_synchronizer.v#1 $ 15 | // $Revision: #1 $ 16 | // $Date: 2020/06/22 $ 17 | // $Author: psgswbuild $ 18 | //----------------------------------------------------------------------------- 19 | // 20 | // File: altera_std_synchronizer.v 21 | // 22 | // Abstract: Single bit clock domain crossing synchronizer. 23 | // Composed of two or more flip flops connected in series. 24 | // Random metastable condition is simulated when the 25 | // __ALTERA_STD__METASTABLE_SIM macro is defined. 26 | // Use +define+__ALTERA_STD__METASTABLE_SIM argument 27 | // on the Verilog simulator compiler command line to 28 | // enable this mode. In addition, dfine the macro 29 | // __ALTERA_STD__METASTABLE_SIM_VERBOSE to get console output 30 | // with every metastable event generated in the synchronizer. 31 | // 32 | // Copyright (C) Altera Corporation 2009, All Rights Reserved 33 | //----------------------------------------------------------------------------- 34 | 35 | `timescale 1ns / 1ns 36 | 37 | module altera_std_synchronizer ( 38 | clk, 39 | reset_n, 40 | din, 41 | dout 42 | ); 43 | 44 | parameter depth = 3; // This value must be >= 2 ! 45 | 46 | input clk; 47 | input reset_n; 48 | input din; 49 | output dout; 50 | 51 | // QuartusII synthesis directives: 52 | // 1. Preserve all registers ie. do not touch them. 53 | // 2. Do not merge other flip-flops with synchronizer flip-flops. 54 | // QuartusII TimeQuest directives: 55 | // 1. Identify all flip-flops in this module as members of the synchronizer 56 | // to enable automatic metastability MTBF analysis. 57 | // 2. Cut all timing paths terminating on data input pin of the first flop din_s1. 58 | 59 | (* altera_attribute = {"-name ADV_NETLIST_OPT_ALLOWED NEVER_ALLOW; -name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS; -name DONT_MERGE_REGISTER ON; -name PRESERVE_REGISTER ON; -name SDC_STATEMENT \"set_false_path -to [get_keepers {*altera_std_synchronizer:*|din_s1}]\" "} *) reg din_s1; 60 | 61 | (* altera_attribute = {"-name ADV_NETLIST_OPT_ALLOWED NEVER_ALLOW; -name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS; -name DONT_MERGE_REGISTER ON; -name PRESERVE_REGISTER ON"} *) reg [depth-2:0] dreg; 62 | 63 | //synthesis translate_off 64 | initial begin 65 | if (depth <2) begin 66 | $display("%m: Error: synchronizer length: %0d less than 2.", depth); 67 | end 68 | end 69 | 70 | // the first synchronizer register is either a simple D flop for synthesis 71 | // and non-metastable simulation or a D flop with a method to inject random 72 | // metastable events resulting in random delay of [0,1] cycles 73 | 74 | `ifdef __ALTERA_STD__METASTABLE_SIM 75 | 76 | reg[31:0] RANDOM_SEED = 123456; 77 | wire next_din_s1; 78 | wire dout; 79 | reg din_last; 80 | reg random; 81 | event metastable_event; // hook for debug monitoring 82 | 83 | initial begin 84 | $display("%m: Info: Metastable event injection simulation mode enabled"); 85 | end 86 | 87 | always @(posedge clk) begin 88 | if (reset_n == 0) 89 | random <= $random(RANDOM_SEED); 90 | else 91 | random <= $random; 92 | end 93 | 94 | assign next_din_s1 = (din_last ^ din) ? random : din; 95 | 96 | always @(posedge clk or negedge reset_n) begin 97 | if (reset_n == 0) 98 | din_last <= 1'b0; 99 | else 100 | din_last <= din; 101 | end 102 | 103 | always @(posedge clk or negedge reset_n) begin 104 | if (reset_n == 0) 105 | din_s1 <= 1'b0; 106 | else 107 | din_s1 <= next_din_s1; 108 | end 109 | 110 | `else 111 | 112 | //synthesis translate_on 113 | always @(posedge clk or negedge reset_n) begin 114 | if (reset_n == 0) 115 | din_s1 <= 1'b0; 116 | else 117 | din_s1 <= din; 118 | end 119 | //synthesis translate_off 120 | 121 | `endif 122 | 123 | `ifdef __ALTERA_STD__METASTABLE_SIM_VERBOSE 124 | always @(*) begin 125 | if (reset_n && (din_last != din) && (random != din)) begin 126 | $display("%m: Verbose Info: metastable event @ time %t", $time); 127 | ->metastable_event; 128 | end 129 | end 130 | `endif 131 | 132 | //synthesis translate_on 133 | 134 | // the remaining synchronizer registers form a simple shift register 135 | // of length depth-1 136 | generate 137 | if (depth < 3) begin 138 | always @(posedge clk or negedge reset_n) begin 139 | if (reset_n == 0) 140 | dreg <= {depth-1{1'b0}}; 141 | else 142 | dreg <= din_s1; 143 | end 144 | end else begin 145 | always @(posedge clk or negedge reset_n) begin 146 | if (reset_n == 0) 147 | dreg <= {depth-1{1'b0}}; 148 | else 149 | dreg <= {dreg[depth-3:0], din_s1}; 150 | end 151 | end 152 | endgenerate 153 | 154 | assign dout = dreg[depth-2]; 155 | 156 | endmodule 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /target/pocket/sound_i2s.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 very simple audio i2s bridge to APF, based on their example code 26 | module sound_i2s #( 27 | parameter CHANNEL_WIDTH = 16, 28 | parameter SIGNED_INPUT = 0 29 | ) ( 30 | // input wire clk_74a, 31 | // input wire clk_audio, 32 | input wire audio_sclk, 33 | 34 | // Left and right audio channels. ~~Can be in an arbitrary `clk_audio` domain~~ 35 | input wire [CHANNEL_WIDTH - 1:0] audio_l, 36 | input wire [CHANNEL_WIDTH - 1:0] audio_r, 37 | 38 | // output reg audio_mclk, 39 | output reg audio_lrck, 40 | output reg audio_dac 41 | ); 42 | // 43 | // audio i2s generator 44 | // 45 | 46 | reg audgen_nextsamp; 47 | 48 | // generate MCLK = 12.288mhz with fractional accumulator 49 | // reg [21:0] audgen_accum = 0; 50 | // localparam [20:0] CYCLE_48KHZ = 21'd122880 * 2; 51 | // always @(posedge clk_74a) begin 52 | // audgen_accum <= audgen_accum + CYCLE_48KHZ; 53 | // if (audgen_accum >= 21'd742500) begin 54 | // audio_mclk <= ~audio_mclk; 55 | // audgen_accum <= audgen_accum - 21'd742500 + CYCLE_48KHZ; 56 | // end 57 | // end 58 | 59 | // // generate SCLK = 3.072mhz by dividing MCLK by 4 60 | // reg [1:0] aud_mclk_divider; 61 | // reg prev_audio_mclk; 62 | // wire audgen_sclk = aud_mclk_divider[1] /* synthesis keep*/; 63 | 64 | // always @(posedge clk_74a) begin 65 | // if (audio_mclk && ~prev_audio_mclk) begin 66 | // aud_mclk_divider <= aud_mclk_divider + 1'b1; 67 | // end 68 | 69 | // prev_audio_mclk <= audio_mclk; 70 | // end 71 | 72 | // shift out audio data as I2S 73 | // 32 total bits per channel, but only 16 active bits at the start and then 16 dummy bits 74 | // 75 | // synchronize audio samples coming from the core 76 | 77 | localparam CHANNEL_LEFT_HIGH = 16; 78 | localparam CHANNEL_RIGHT_HIGH = 16 + CHANNEL_LEFT_HIGH; 79 | 80 | // Width of channel with signed component 81 | localparam SIGNED_CHANNEL_WIDTH = SIGNED_INPUT ? CHANNEL_WIDTH : CHANNEL_WIDTH + 1; 82 | 83 | // Can center unsigned in signed interval by flipping high bit 84 | wire [CHANNEL_WIDTH - 1:0] sign_converted_audio_l = { 85 | audio_l[CHANNEL_WIDTH-1:CHANNEL_WIDTH-1], audio_l[CHANNEL_WIDTH-2:0] 86 | }; 87 | 88 | wire [CHANNEL_WIDTH - 1:0] sign_converted_audio_r = { 89 | audio_r[CHANNEL_WIDTH-1:CHANNEL_WIDTH-1], audio_r[CHANNEL_WIDTH-2:0] 90 | }; 91 | 92 | wire [31:0] audgen_sampdata; 93 | 94 | assign audgen_sampdata[CHANNEL_LEFT_HIGH-1:CHANNEL_LEFT_HIGH-CHANNEL_WIDTH] = SIGNED_INPUT ? audio_l : sign_converted_audio_l; 95 | assign audgen_sampdata[CHANNEL_RIGHT_HIGH-1:CHANNEL_RIGHT_HIGH-CHANNEL_WIDTH] = SIGNED_INPUT ? audio_r : sign_converted_audio_r; 96 | 97 | generate 98 | if (15 - SIGNED_CHANNEL_WIDTH > 0) begin 99 | assign audgen_sampdata[31-SIGNED_CHANNEL_WIDTH:16] = 0; 100 | assign audgen_sampdata[15-SIGNED_CHANNEL_WIDTH:0] = 0; 101 | end 102 | endgenerate 103 | 104 | // sync_fifo #( 105 | // .WIDTH(32) 106 | // ) sync_fifo ( 107 | // .clk_write(clk_audio), 108 | // .clk_read (audio_sclk), 109 | 110 | // .write_en(write_en), 111 | // .data(audgen_sampdata), 112 | // .data_s(audgen_sampdata_s) 113 | // ); 114 | 115 | // reg write_en = 0; 116 | // reg [CHANNEL_WIDTH - 1:0] prev_left; 117 | // reg [CHANNEL_WIDTH - 1:0] prev_right; 118 | 119 | // // Mark write when necessary 120 | // always @(posedge clk_audio) begin 121 | // prev_left <= audio_l; 122 | // prev_right <= audio_r; 123 | 124 | // write_en <= 0; 125 | 126 | // if (audio_l != prev_left || audio_r != prev_right) begin 127 | // write_en <= 1; 128 | // end 129 | // end 130 | 131 | // wire [31:0] audgen_sampdata_s; 132 | 133 | reg [31:0] audgen_sampshift; 134 | reg [ 4:0] audio_lrck_cnt; 135 | always @(posedge audio_sclk) begin 136 | // output the next bit 137 | audio_dac <= audgen_sampshift[31]; 138 | 139 | // 48khz * 64 140 | audio_lrck_cnt <= audio_lrck_cnt + 1'b1; 141 | if (audio_lrck_cnt == 31) begin 142 | // switch channels 143 | audio_lrck <= ~audio_lrck; 144 | 145 | // Reload sample shifter 146 | if (~audio_lrck) begin 147 | audgen_sampshift <= audgen_sampdata; 148 | end 149 | end else if (audio_lrck_cnt < 16) begin 150 | // only shift for 16 clocks per channel 151 | audgen_sampshift <= {audgen_sampshift[30:0], 1'b0}; 152 | end 153 | end 154 | 155 | initial begin 156 | // Verify parameters 157 | if (CHANNEL_WIDTH > 16) begin 158 | $error("CHANNEL_WIDTH must be <= 16. Received %d", CHANNEL_WIDTH); 159 | end 160 | 161 | if (SIGNED_INPUT != 0 && SIGNED_INPUT != 1) begin 162 | $error("SIGNED_INPUT must be 0 or 1. Received %d", SIGNED_INPUT); 163 | end 164 | end 165 | endmodule 166 | -------------------------------------------------------------------------------- /target/pocket/sync_fifo.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 | // An easily reusable method for synchronizing multiple bits across clock domains 26 | // Uses a shallow depth (4 entries) FIFO, so make sure to empty it quickly 27 | module sync_fifo #( 28 | parameter WIDTH = 2 29 | ) ( 30 | input wire clk_write, 31 | input wire clk_read, 32 | 33 | input wire write_en, 34 | input wire [WIDTH - 1:0] data, 35 | output reg [WIDTH - 1:0] data_s = 0, 36 | output reg write_en_s = 0 37 | ); 38 | 39 | reg read_req = 0; 40 | wire empty; 41 | 42 | wire [WIDTH - 1:0] fifo_out; 43 | 44 | dcfifo dcfifo_component ( 45 | .data(data), 46 | .rdclk(clk_read), 47 | .rdreq(read_req), 48 | .wrclk(clk_write), 49 | .wrreq(write_en), 50 | .q(fifo_out), 51 | .rdempty(empty), 52 | .aclr(), 53 | .eccstatus(), 54 | .rdfull(), 55 | .rdusedw(), 56 | .wrempty(), 57 | .wrfull(), 58 | .wrusedw() 59 | ); 60 | defparam dcfifo_component.intended_device_family = "Cyclone V", dcfifo_component.lpm_numwords = 4, 61 | dcfifo_component.lpm_showahead = "OFF", dcfifo_component.lpm_type = "dcfifo", 62 | dcfifo_component.lpm_width = WIDTH, dcfifo_component.lpm_widthu = 2, 63 | dcfifo_component.overflow_checking = "ON", dcfifo_component.rdsync_delaypipe = 5, 64 | dcfifo_component.underflow_checking = "ON", dcfifo_component.use_eab = "ON", 65 | dcfifo_component.wrsync_delaypipe = 5; 66 | 67 | reg [1:0] read_state = 0; 68 | 69 | localparam READ_DELAY = 1; 70 | localparam READ_WRITE = 2; 71 | 72 | always @(posedge clk_read) begin 73 | read_req <= 0; 74 | write_en_s <= 0; 75 | 76 | if (~empty) begin 77 | read_state <= READ_DELAY; 78 | read_req <= 1; 79 | end 80 | 81 | case (read_state) 82 | READ_DELAY: begin 83 | read_state <= READ_WRITE; 84 | end 85 | READ_WRITE: begin 86 | read_state <= 0; 87 | 88 | data_s <= fifo_out; 89 | write_en_s <= 1; 90 | end 91 | endcase 92 | end 93 | 94 | endmodule 95 | --------------------------------------------------------------------------------