├── dist ├── Assets │ └── wonderswan │ │ └── common │ │ └── .gitkeep ├── Cores │ └── agg23.WonderSwan │ │ ├── audio.json │ │ ├── variants.json │ │ ├── video.json │ │ ├── info.txt │ │ ├── core.json │ │ ├── data.json │ │ ├── input.json │ │ └── interact.json └── Platforms │ ├── _images │ └── wonderswan.bin │ └── wonderswan.json ├── .github ├── FUNDING.yml ├── workflows │ └── github-releases-to-discord.yml └── ISSUE_TEMPLATE │ ├── QUESTION.yml │ └── BUG_REPORT.yml ├── src ├── fpga │ ├── core │ │ ├── mf_pllbase_sim.f │ │ ├── mf_pllbase_sim │ │ │ ├── cadence │ │ │ │ ├── hdl.var │ │ │ │ ├── cds.lib │ │ │ │ └── ncsim_setup.sh │ │ │ └── synopsys │ │ │ │ ├── vcsmx │ │ │ │ ├── synopsys_sim.setup │ │ │ │ └── vcsmx_setup.sh │ │ │ │ └── vcs │ │ │ │ └── vcs_setup.sh │ │ ├── mf_pllbase.spd │ │ ├── mf_pllbase │ │ │ ├── mf_pllbase_0002.qip │ │ │ └── mf_pllbase_0002.v │ │ ├── pin_ddio_clk.qip │ │ ├── pin_ddio_clk.ppf │ │ ├── mf_pllbase.sip │ │ ├── core_constraints.sdc │ │ ├── mf_pllbase.ppf │ │ ├── rtl │ │ │ ├── swanbios.vhd │ │ │ ├── swanbioscolor.vhd │ │ │ ├── dummyregs.vhd │ │ │ ├── reg_savestates.vhd │ │ │ ├── ddram.sv │ │ │ ├── joypad.vhd │ │ │ ├── bus_savestates.vhd │ │ │ ├── registerpackage.vhd │ │ │ ├── sound_module1.vhd │ │ │ ├── savestate_ui.sv │ │ │ ├── sound_module5.vhd │ │ │ ├── divider.vhd │ │ │ ├── dpram.vhd │ │ │ ├── sound_module2.vhd │ │ │ ├── IRQ.vhd │ │ │ ├── statemanager.vhd │ │ │ ├── sound_module3.vhd │ │ │ ├── sound_module4.vhd │ │ │ ├── export.vhd │ │ │ └── gpu_bg.vhd │ │ ├── sync_fifo.sv │ │ ├── pin_ddio_clk.v │ │ ├── mf_pllbase.bsf │ │ ├── sound_i2s.sv │ │ ├── data_loader.sv │ │ └── data_unloader.sv │ ├── apf │ │ ├── build_id.mif │ │ ├── mf_datatable.qip │ │ ├── mf_ddio_bidir_12.qip │ │ ├── apf_constraints.sdc │ │ ├── apf.qip │ │ ├── mf_ddio_bidir_12.v │ │ ├── common.v │ │ ├── build_id_gen.tcl │ │ └── io_pad_controller.v │ ├── .gitignore │ └── ap_core.qpf └── support │ └── chip32.asm ├── .gitignore └── README.md /dist/Assets/wonderswan/common/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: agg23 2 | patreon: FPGAzumSpass 3 | -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase_sim.f: -------------------------------------------------------------------------------- 1 | mf_pllbase_sim/mf_pllbase.vo 2 | -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase_sim/cadence/hdl.var: -------------------------------------------------------------------------------- 1 | 2 | DEFINE WORK work 3 | -------------------------------------------------------------------------------- /dist/Cores/agg23.WonderSwan/audio.json: -------------------------------------------------------------------------------- 1 | { 2 | "audio": { 3 | "magic": "APF_VER_1" 4 | } 5 | } -------------------------------------------------------------------------------- /dist/Platforms/_images/wonderswan.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agg23/openfpga-wonderswan/HEAD/dist/Platforms/_images/wonderswan.bin -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.rbf_r 2 | *.rev 3 | *.zip 4 | dist/**/*.bin 5 | src/**/*.bin 6 | src/sim/work/ 7 | src/sim/*.hex 8 | src/sim/*.mem 9 | src/sim/*.bin -------------------------------------------------------------------------------- /dist/Cores/agg23.WonderSwan/variants.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "magic": "APF_VER_1", 4 | "variant_list": [] 5 | } 6 | } -------------------------------------------------------------------------------- /dist/Platforms/wonderswan.json: -------------------------------------------------------------------------------- 1 | { 2 | "platform": { 3 | "category": "Handheld", 4 | "name": "WonderSwan Color", 5 | "year": 2000, 6 | "manufacturer": "Bandai" 7 | } 8 | } -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase.spd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/fpga/apf/build_id.mif: -------------------------------------------------------------------------------- 1 | -- Build ID Memory Initialization File 2 | -- 3 | 4 | DEPTH = 256; 5 | WIDTH = 32; 6 | ADDRESS_RADIX = HEX; 7 | DATA_RADIX = HEX; 8 | 9 | CONTENT 10 | BEGIN 11 | 12 | 0E0 : 20230114; 13 | 0E1 : 00092918; 14 | 0E2 : 1e84d350; 15 | 16 | END; 17 | -------------------------------------------------------------------------------- /src/fpga/apf/mf_datatable.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT" 2 | set_global_assignment -name IP_TOOL_VERSION "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 | -------------------------------------------------------------------------------- /src/fpga/apf/mf_ddio_bidir_12.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "ALTDDIO_BIDIR" 2 | set_global_assignment -name IP_TOOL_VERSION "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 | -------------------------------------------------------------------------------- /src/fpga/.gitignore: -------------------------------------------------------------------------------- 1 | */db/ 2 | */incremental_db/ 3 | */simulation/ 4 | */greybox_tmp/ 5 | incremental_db/ 6 | db/ 7 | output_files/ 8 | PLLJ_PLLSPE_INFO.txt 9 | c5_pin_model_dump.txt 10 | cr_ie_info.json 11 | *.pin 12 | *.pof 13 | *.ptf.* 14 | *.qar 15 | *.qarlog 16 | *.qws 17 | *.rpt 18 | *.smsg 19 | *.sof 20 | *.sopc_builder 21 | *.summary 22 | *.txt 23 | *.bak 24 | *.cmp 25 | *.done 26 | *.xml 27 | *.sld 28 | *.cdf 29 | 30 | -------------------------------------------------------------------------------- /src/fpga/core/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 OFF -to "*mf_pllbase_0002*|altera_pll:altera_pll_i*|*" 4 | set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*mf_pllbase_0002*|altera_pll:altera_pll_i*|*" 5 | -------------------------------------------------------------------------------- /src/fpga/core/pin_ddio_clk.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "ALTDDIO_OUT" 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) "pin_ddio_clk.v"] 5 | set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pin_ddio_clk_inst.v"] 6 | set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pin_ddio_clk.ppf"] 7 | -------------------------------------------------------------------------------- /dist/Cores/agg23.WonderSwan/video.json: -------------------------------------------------------------------------------- 1 | { 2 | "video": { 3 | "magic": "APF_VER_1", 4 | "scaler_modes": [ 5 | { 6 | "width": 224, 7 | "height": 144, 8 | "aspect_w": 14, 9 | "aspect_h": 9, 10 | "rotation": 0, 11 | "mirror": 0 12 | }, 13 | { 14 | "width": 224, 15 | "height": 144, 16 | "aspect_w": 14, 17 | "aspect_h": 9, 18 | "rotation": 270, 19 | "mirror": 0 20 | } 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/fpga/core/pin_ddio_clk.ppf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase.sip: -------------------------------------------------------------------------------- 1 | set_global_assignment -entity "mf_pllbase" -library "lib_mf_pllbase" -name IP_TOOL_NAME "altera_pll" 2 | set_global_assignment -entity "mf_pllbase" -library "lib_mf_pllbase" -name IP_TOOL_VERSION "21.1" 3 | set_global_assignment -entity "mf_pllbase" -library "lib_mf_pllbase" -name IP_TOOL_ENV "mwpim" 4 | set_global_assignment -library "lib_mf_pllbase" -name SPD_FILE [file join $::quartus(sip_path) "mf_pllbase.spd"] 5 | 6 | set_global_assignment -library "lib_mf_pllbase" -name MISC_FILE [file join $::quartus(sip_path) "mf_pllbase_sim/mf_pllbase.vo"] 7 | -------------------------------------------------------------------------------- /dist/Cores/agg23.WonderSwan/info.txt: -------------------------------------------------------------------------------- 1 | Port by agg23. Core by Robert Peip 2 | 3 | WonderSwan, a handheld console by Bandai, had notably better specs than it's competitor, the Game Boy Color. With a 16-bit processor, 8 shades of grey color (later 241 colors), and long battery life, it stands out as a strong contender to Nintendo's dominance. 4 | 5 | Supports: 6 | * Memories 7 | * Fast forward - Runs game at 2.5x speed 8 | * CPU turbo 9 | * Automatic screen orientation 10 | * Flickerblending 11 | 12 | Please report all issues to agg23, as most likely any issues experienced are issues with the port, not the core. -------------------------------------------------------------------------------- /src/fpga/apf/apf_constraints.sdc: -------------------------------------------------------------------------------- 1 | # 2 | # APF constraints 3 | # Do not edit this file. 4 | # 5 | # Add your own constraints in the \core_constraints.sdc in the core directory, which will also be loaded. 6 | 7 | create_clock -name clk_74a -period 13.468 [get_ports clk_74a] 8 | create_clock -name clk_74b -period 13.468 [get_ports clk_74b] 9 | create_clock -name bridge_spiclk -period 13.468 [get_ports bridge_spiclk] 10 | 11 | # autogenerate PLL clock names for use down below 12 | derive_pll_clocks 13 | 14 | 15 | # io constraints go here 16 | # 17 | 18 | 19 | # load in user constraints 20 | read_sdc "core/core_constraints.sdc" -------------------------------------------------------------------------------- /src/fpga/apf/apf.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "apf_top.v"] 2 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "common.v"] 3 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "io_bridge_peripheral.v"] 4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "io_pad_controller.v"] 5 | set_global_assignment -name SDC_FILE [file join $::quartus(qip_path) "apf_constraints.sdc"] 6 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "mf_ddio_bidir_12.qip"] 7 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "mf_datatable.qip"] 8 | -------------------------------------------------------------------------------- /src/fpga/core/core_constraints.sdc: -------------------------------------------------------------------------------- 1 | # 2 | # user core constraints 3 | # 4 | # put your clock groups in here as well as any net assignments 5 | # 6 | 7 | set_clock_groups -asynchronous \ 8 | -group { bridge_spiclk } \ 9 | -group { clk_74a } \ 10 | -group { clk_74b } \ 11 | -group { ic|mp1|mf_pllbase_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk \ 12 | ic|mp1|mf_pllbase_inst|altera_pll_i|general[1].gpll~PLL_OUTPUT_COUNTER|divclk } \ 13 | -group { ic|mp1|mf_pllbase_inst|altera_pll_i|general[2].gpll~PLL_OUTPUT_COUNTER|divclk } \ 14 | -group { ic|mp1|mf_pllbase_inst|altera_pll_i|general[3].gpll~PLL_OUTPUT_COUNTER|divclk } 15 | 16 | derive_clock_uncertainty -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase.ppf: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase_sim/synopsys/vcsmx/synopsys_sim.setup: -------------------------------------------------------------------------------- 1 | 2 | WORK > DEFAULT 3 | DEFAULT: ./libraries/work/ 4 | work: ./libraries/work/ 5 | altera_ver: ./libraries/altera_ver/ 6 | lpm_ver: ./libraries/lpm_ver/ 7 | sgate_ver: ./libraries/sgate_ver/ 8 | altera_mf_ver: ./libraries/altera_mf_ver/ 9 | altera_lnsim_ver: ./libraries/altera_lnsim_ver/ 10 | cyclonev_ver: ./libraries/cyclonev_ver/ 11 | cyclonev_hssi_ver: ./libraries/cyclonev_hssi_ver/ 12 | cyclonev_pcie_hip_ver: ./libraries/cyclonev_pcie_hip_ver/ 13 | LIBRARY_SCAN = TRUE 14 | -------------------------------------------------------------------------------- /.github/workflows/github-releases-to-discord.yml: -------------------------------------------------------------------------------- 1 | on: 2 | release: 3 | types: [published] 4 | 5 | jobs: 6 | github-releases-to-discord: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Github Releases To Discord 10 | uses: kludge-cs/gitcord-release-changelogger@v3.0.0 11 | with: 12 | webhook-url: ${{ secrets.WEBHOOK_URL }} 13 | release-name: ${{ format('WonderSwan Release{0} {1}', ':', github.event.release.name) }} 14 | release-body: ${{ format('# [Get it here]({0}). {1}', github.event.release.html_url, github.event.release.body) }} 15 | avatar-url: "https://cdn.discordapp.com/avatars/160419937825980416/20250cea9ac0e8ce154572c511605d40.png" 16 | username: "agg23" 17 | -------------------------------------------------------------------------------- /.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-wonderswan/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 | -------------------------------------------------------------------------------- /dist/Cores/agg23.WonderSwan/core.json: -------------------------------------------------------------------------------- 1 | { 2 | "core": { 3 | "magic": "APF_VER_1", 4 | "metadata": { 5 | "platform_ids": ["wonderswan"], 6 | "shortname": "WonderSwan", 7 | "description": "WonderSwan and WonderSwan Color by Bandai", 8 | "author": "agg23", 9 | "url": "https://github.com/agg23/openfpga-wonderswan", 10 | "version": "1.0.1", 11 | "date_release": "2023-05-06" 12 | }, 13 | "framework": { 14 | "target_product": "Analogue Pocket", 15 | "version_required": "1.1", 16 | "sleep_supported": true, 17 | "dock": { 18 | "supported": true, 19 | "analog_output": false 20 | }, 21 | "hardware": { 22 | "link_port": false, 23 | "cartridge_adapter": -1 24 | }, 25 | "chip32_vm": "chip32.bin" 26 | }, 27 | "cores": [ 28 | { 29 | "name": "default", 30 | "id": 0, 31 | "filename": "wonderswan.rev" 32 | } 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/fpga/core/rtl/swanbios.vhd: -------------------------------------------------------------------------------- 1 | library IEEE; 2 | use IEEE.std_logic_1164.all; 3 | use IEEE.numeric_std.all; 4 | 5 | entity swanbios is 6 | port 7 | ( 8 | clk : in std_logic; 9 | address : in std_logic_vector(10 downto 0); 10 | data : out std_logic_vector(15 downto 0); 11 | bios_wraddr : in std_logic_vector(10 downto 0); 12 | bios_wrdata : in std_logic_vector(15 downto 0); 13 | bios_wr : in std_logic 14 | ); 15 | end entity; 16 | 17 | architecture arch of swanbios is 18 | 19 | type t_rom is array(0 to 2047) of std_logic_vector(15 downto 0); 20 | signal rom : t_rom; 21 | 22 | begin 23 | 24 | process (clk) 25 | begin 26 | if rising_edge(clk) then 27 | data <= rom(to_integer(unsigned(address))); 28 | end if; 29 | end process; 30 | 31 | process (clk) 32 | begin 33 | if rising_edge(clk) then 34 | if bios_wr = '1' then 35 | rom(to_integer(unsigned(bios_wraddr))) <= bios_wrdata; 36 | end if; 37 | end if; 38 | end process; 39 | 40 | end architecture; 41 | -------------------------------------------------------------------------------- /dist/Cores/agg23.WonderSwan/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": ["ws", "wsc"], 11 | "address": "0x10000000" 12 | }, 13 | { 14 | "name": "B&W BIOS", 15 | "id": 9, 16 | "required": false, 17 | "filename": "bw.rom", 18 | "parameters": "0x0", 19 | "extensions": ["rom"], 20 | "address": "0x30000000" 21 | }, 22 | { 23 | "name": "Color BIOS", 24 | "id": 10, 25 | "required": false, 26 | "filename": "color.rom", 27 | "parameters": "0x0", 28 | "extensions": ["rom"], 29 | "address": "0x30000000" 30 | }, 31 | { 32 | "name": "Save", 33 | "id": 11, 34 | "required": false, 35 | "parameters": "0x84", 36 | "nonvolatile": true, 37 | "extensions": ["sav"], 38 | "address": "0x20000000" 39 | } 40 | ] 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/fpga/core/rtl/swanbioscolor.vhd: -------------------------------------------------------------------------------- 1 | library IEEE; 2 | use IEEE.std_logic_1164.all; 3 | use IEEE.numeric_std.all; 4 | 5 | entity swanbioscolor is 6 | port 7 | ( 8 | clk : in std_logic; 9 | address : in std_logic_vector(11 downto 0); 10 | data : out std_logic_vector(15 downto 0); 11 | bios_wraddr : in std_logic_vector(11 downto 0); 12 | bios_wrdata : in std_logic_vector(15 downto 0); 13 | bios_wr : in std_logic 14 | ); 15 | end entity; 16 | 17 | architecture arch of swanbioscolor is 18 | 19 | type t_rom is array(0 to 4095) of std_logic_vector(15 downto 0); 20 | signal rom : t_rom; 21 | 22 | begin 23 | 24 | process (clk) 25 | begin 26 | if rising_edge(clk) then 27 | data <= rom(to_integer(unsigned(address))); 28 | end if; 29 | end process; 30 | 31 | process (clk) 32 | begin 33 | if rising_edge(clk) then 34 | if bios_wr = '1' then 35 | rom(to_integer(unsigned(bios_wraddr))) <= bios_wrdata; 36 | end if; 37 | end if; 38 | end process; 39 | 40 | end architecture; 41 | -------------------------------------------------------------------------------- /dist/Cores/agg23.WonderSwan/input.json: -------------------------------------------------------------------------------- 1 | { 2 | "input": { 3 | "magic": "APF_VER_1", 4 | "controllers": [ 5 | { 6 | "type": "default", 7 | "mappings": [ 8 | { 9 | "id": 0, 10 | "name": "Horz A/Vert Y2", 11 | "key": "pad_btn_a" 12 | }, 13 | { 14 | "id": 1, 15 | "name": "Horz B/Vert Y3", 16 | "key": "pad_btn_b" 17 | }, 18 | { 19 | "id": 2, 20 | "name": "Horz Y3/Vert Y1", 21 | "key": "pad_btn_x" 22 | }, 23 | { 24 | "id": 3, 25 | "name": "Horz Y4/Vert Y4", 26 | "key": "pad_btn_y" 27 | }, 28 | { 29 | "id": 10, 30 | "name": "Horz Y1/Vert A", 31 | "key": "pad_trig_l" 32 | }, 33 | { 34 | "id": 11, 35 | "name": "Horz Y2/Vert B", 36 | "key": "pad_trig_r" 37 | }, 38 | { 39 | "id": 20, 40 | "name": "Start", 41 | "key": "pad_btn_start" 42 | }, 43 | { 44 | "id": 30, 45 | "name": "Fast Forward", 46 | "key": "pad_btn_select" 47 | } 48 | ] 49 | } 50 | ] 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase_sim/cadence/cds.lib: -------------------------------------------------------------------------------- 1 | 2 | DEFINE std $CDS_ROOT/tools/inca/files/STD/ 3 | DEFINE synopsys $CDS_ROOT/tools/inca/files/SYNOPSYS/ 4 | DEFINE ieee $CDS_ROOT/tools/inca/files/IEEE/ 5 | DEFINE ambit $CDS_ROOT/tools/inca/files/AMBIT/ 6 | DEFINE vital_memory $CDS_ROOT/tools/inca/files/VITAL_MEMORY/ 7 | DEFINE ncutils $CDS_ROOT/tools/inca/files/NCUTILS/ 8 | DEFINE ncinternal $CDS_ROOT/tools/inca/files/NCINTERNAL/ 9 | DEFINE ncmodels $CDS_ROOT/tools/inca/files/NCMODELS/ 10 | DEFINE cds_assertions $CDS_ROOT/tools/inca/files/CDS_ASSERTIONS/ 11 | DEFINE work ./libraries/work/ 12 | DEFINE altera_ver ./libraries/altera_ver/ 13 | DEFINE lpm_ver ./libraries/lpm_ver/ 14 | DEFINE sgate_ver ./libraries/sgate_ver/ 15 | DEFINE altera_mf_ver ./libraries/altera_mf_ver/ 16 | DEFINE altera_lnsim_ver ./libraries/altera_lnsim_ver/ 17 | DEFINE cyclonev_ver ./libraries/cyclonev_ver/ 18 | DEFINE cyclonev_hssi_ver ./libraries/cyclonev_hssi_ver/ 19 | DEFINE cyclonev_pcie_hip_ver ./libraries/cyclonev_pcie_hip_ver/ 20 | -------------------------------------------------------------------------------- /src/fpga/ap_core.qpf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- # 2 | # 3 | # Copyright (C) 2019 Intel Corporation. All rights reserved. 4 | # Your use of Intel Corporation's design tools, logic functions 5 | # and other software and tools, and any partner logic 6 | # functions, and any output files from any of the foregoing 7 | # (including device programming or simulation files), and any 8 | # associated documentation or information are expressly subject 9 | # to the terms and conditions of the Intel Program License 10 | # Subscription Agreement, the Intel Quartus Prime License Agreement, 11 | # the Intel FPGA IP License Agreement, or other applicable license 12 | # agreement, including, without limitation, that your use is for 13 | # the sole purpose of programming logic devices manufactured by 14 | # Intel and sold by Intel or its authorized distributors. Please 15 | # refer to the applicable agreement for further details, at 16 | # https://fpgasoftware.intel.com/eula. 17 | # 18 | # -------------------------------------------------------------------------- # 19 | # 20 | # Quartus Prime 21 | # Version 18.1.1 Build 646 04/11/2019 SJ Lite Edition 22 | # Date created = 21:31:36 January 22, 2020 23 | # 24 | # -------------------------------------------------------------------------- # 25 | 26 | QUARTUS_VERSION = "18.1" 27 | DATE = "21:31:36 January 22, 2020" 28 | 29 | # Revisions 30 | 31 | PROJECT_REVISION = "ap_core" 32 | -------------------------------------------------------------------------------- /src/fpga/core/rtl/dummyregs.vhd: -------------------------------------------------------------------------------- 1 | library IEEE; 2 | use IEEE.std_logic_1164.all; 3 | use IEEE.numeric_std.all; 4 | 5 | use work.pRegisterBus.all; 6 | use work.pReg_swan.all; 7 | 8 | entity dummyregs is 9 | port 10 | ( 11 | clk : in std_logic; 12 | ce : in std_logic; 13 | reset : in std_logic; 14 | 15 | RegBus_Din : in std_logic_vector(BUS_buswidth-1 downto 0); 16 | RegBus_Adr : in std_logic_vector(BUS_busadr-1 downto 0); 17 | RegBus_wren : in std_logic; 18 | RegBus_rst : in std_logic; 19 | RegBus_Dout : out std_logic_vector(BUS_buswidth-1 downto 0) 20 | ); 21 | end entity; 22 | 23 | architecture arch of dummyregs is 24 | 25 | signal SER_DATA : std_logic_vector(REG_SER_DATA .upper downto REG_SER_DATA .lower); 26 | 27 | signal SER_STATUS : std_logic_vector(REG_SER_STATUS.upper downto REG_SER_STATUS.lower); 28 | signal SER_STATUS_read : std_logic_vector(REG_SER_STATUS.upper downto REG_SER_STATUS.lower); 29 | 30 | type t_reg_wired_or is array(0 to 1) of std_logic_vector(7 downto 0); 31 | signal reg_wired_or : t_reg_wired_or; 32 | 33 | begin 34 | 35 | iREG_SER_DATA : entity work.eReg generic map ( REG_SER_DATA ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(0), SER_DATA, SER_DATA ); 36 | iREG_SER_STATUS : entity work.eReg generic map ( REG_SER_STATUS ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(1), SER_STATUS_read, SER_STATUS); 37 | 38 | SER_STATUS_read <= SER_STATUS(7 downto 6) & "000100"; 39 | 40 | process (reg_wired_or) 41 | variable wired_or : std_logic_vector(7 downto 0); 42 | begin 43 | wired_or := reg_wired_or(0); 44 | for i in 1 to (reg_wired_or'length - 1) loop 45 | wired_or := wired_or or reg_wired_or(i); 46 | end loop; 47 | RegBus_Dout <= wired_or; 48 | end process; 49 | 50 | end architecture; 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/fpga/core/rtl/reg_savestates.vhd: -------------------------------------------------------------------------------- 1 | library IEEE; 2 | use IEEE.std_logic_1164.all; 3 | use IEEE.numeric_std.all; 4 | 5 | use work.pBus_savestates.all; 6 | 7 | package pReg_savestates is 8 | 9 | -- ( adr upper lower size default) 10 | 11 | -- cpu 12 | constant REG_SAVESTATE_CPU1 : savestate_type := ( 0, 63, 0, 1, x"0000000000000000"); -- DX_CX_AX_IP 13 | constant REG_SAVESTATE_CPU2 : savestate_type := ( 1, 63, 0, 1, x"0000000020000000"); -- SI_BP_SP_BX 14 | constant REG_SAVESTATE_CPU3 : savestate_type := ( 2, 63, 0, 1, x"0000FFFF00000000"); -- SS_CS_ES_DI 15 | constant REG_SAVESTATE_CPU4 : savestate_type := ( 3, 31, 0, 1, x"00000000F0020000"); -- F_DS 16 | 17 | constant REG_SAVESTATE_IRQ : savestate_type := ( 5, 7, 0, 1, x"0000000000000000"); 18 | 19 | constant REG_SAVESTATE_GPU : savestate_type := ( 7, 15, 0, 1, x"0000000000009EFF"); 20 | 21 | constant REG_SAVESTATE_DMA : savestate_type := ( 11, 59, 0, 1, x"0000000000000000"); 22 | 23 | constant REG_SAVESTATE_SOUND3 : savestate_type := ( 15, 10, 0, 1, x"0000000000000000"); 24 | constant REG_SAVESTATE_SOUND4 : savestate_type := ( 16, 19, 0, 1, x"0000000000000000"); 25 | constant REG_SAVESTATE_SOUNDDMA : savestate_type := ( 17, 59, 0, 1, x"0000000000000000"); 26 | 27 | constant REG_SAVESTATE_EEPROMINT : savestate_type := ( 19, 16, 0, 1, x"0000000000000000"); 28 | constant REG_SAVESTATE_EEPROMEXT : savestate_type := ( 21, 16, 0, 1, x"0000000000000000"); 29 | 30 | constant REG_SAVESTATE_MIXED : savestate_type := ( 23, 0, 0, 1, x"0000000000000000"); 31 | 32 | constant REG_SAVESTATE_TIMER : savestate_type := ( 27, 35, 0, 1, x"0000000000000000"); 33 | 34 | 35 | 36 | 37 | end package; 38 | -------------------------------------------------------------------------------- /.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-wonderswan/issues) before filing a new one! 16 | 17 | - type: input 18 | id: version 19 | attributes: 20 | label: Version (or build number) 21 | placeholder: "1.0.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 | -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase/mf_pllbase_0002.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/10ps 2 | module mf_pllbase_0002( 3 | 4 | // interface 'refclk' 5 | input wire refclk, 6 | 7 | // interface 'reset' 8 | input wire rst, 9 | 10 | // interface 'outclk0' 11 | output wire outclk_0, 12 | 13 | // interface 'outclk1' 14 | output wire outclk_1, 15 | 16 | // interface 'outclk2' 17 | output wire outclk_2, 18 | 19 | // interface '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("110.592000 MHz"), 32 | .phase_shift0("0 ps"), 33 | .duty_cycle0(50), 34 | .output_clock_frequency1("36.864000 MHz"), 35 | .phase_shift1("0 ps"), 36 | .duty_cycle1(50), 37 | .output_clock_frequency2("6.144000 MHz"), 38 | .phase_shift2("0 ps"), 39 | .duty_cycle2(50), 40 | .output_clock_frequency3("6.144000 MHz"), 41 | .phase_shift3("40690 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 | -------------------------------------------------------------------------------- /src/support/chip32.asm: -------------------------------------------------------------------------------- 1 | architecture chip32.vm 2 | output "chip32.bin", create 3 | 4 | // we will put data into here that we're working on. It's the last 1K of the 8K chip32 memory 5 | constant rambuf = 0x1b00 6 | 7 | constant rom_dataslot = 0 8 | constant bw_bios_dataslot = 9 9 | constant color_bios_dataslot = 10 10 | constant save_dataslot = 11 11 | 12 | constant cart_download_addr = 0x0 13 | constant is_color_cart_addr = 0x4 14 | 15 | constant bw_bios_download_addr = 0x8 16 | constant color_bios_download_addr = 0xC 17 | 18 | constant save_download_addr = 0x10 19 | 20 | // Host init command 21 | constant host_init = 0x4002 22 | 23 | macro load_asset(variable ioctl_download_addr, variable dataslot_id, variable error_msg) { 24 | ld r1,#ioctl_download_addr // Set address for write 25 | ld r2,#1 // Downloading start 26 | pmpw r1,r2 // Write ioctl_download = 1 27 | 28 | ld r3,#dataslot_id 29 | ld r14,#error_msg 30 | loadf r3 // Load asset 31 | 32 | if error_msg != 0 { 33 | // Only throw error if an error msg provided 34 | jp nz,print_error_and_exit 35 | } 36 | 37 | // ld r1,#ioctl_download_addr // Set address for write 38 | ld r2,#0 // Downloading end 39 | pmpw r1,r2 // Write ioctl_download = 0 40 | } 41 | 42 | macro load_bios_asset(variable ioctl_download_addr, variable dataslot_id, variable error_msg) { 43 | ld r3,#dataslot_id 44 | ld r14,#error_msg 45 | queryslot r3 // Check if BIOS exists 46 | 47 | jp nz,print_error_and_exit 48 | 49 | load_asset(ioctl_download_addr, dataslot_id, error_msg) 50 | } 51 | 52 | // Error vector (0x0) 53 | jp error_handler 54 | 55 | // Init vector (0x2) 56 | // Choose core 57 | ld r0,#0 58 | core r0 59 | 60 | ld r1,#rom_dataslot // populate data slot 61 | ld r2,#rambuf // get ram buf position 62 | getext r1,r2 63 | ld r1,#ext_wsc 64 | test r1,r2 65 | jp z,set_wsc // Set wsc 66 | 67 | dont_set_wsc: 68 | ld r3,#0 69 | jp start_load 70 | 71 | set_wsc: 72 | ld r3,#1 73 | 74 | start_load: 75 | ld r1,#is_color_cart_addr 76 | pmpw r1,r3 // Write is_color_cart = r3 77 | 78 | // Load cart 79 | load_asset(cart_download_addr, rom_dataslot, rom_err_msg) 80 | 81 | // Load BIOS 82 | load_bios_asset(bw_bios_download_addr, bw_bios_dataslot, bw_bios_err_msg) 83 | load_bios_asset(color_bios_download_addr, color_bios_dataslot, color_bios_err_msg) 84 | 85 | // Load save 86 | load_asset(save_download_addr, save_dataslot, 0) 87 | 88 | // Start core 89 | ld r0,#host_init 90 | host r0,r0 91 | 92 | exit 0 93 | 94 | // Error handling 95 | error_handler: 96 | ld r14,#test_err_msg 97 | 98 | print_error_and_exit: 99 | printf r14 100 | exit 1 101 | 102 | ext_wsc: 103 | db "WSC",0 104 | 105 | test_err_msg: 106 | db "Error",0 107 | 108 | rom_err_msg: 109 | db "Could not load ROM",0 110 | 111 | color_bios_err_msg: 112 | db "No Color BIOS found",0 113 | 114 | bw_bios_err_msg: 115 | db "No B&W BIOS found",0 -------------------------------------------------------------------------------- /src/fpga/core/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 | -------------------------------------------------------------------------------- /src/fpga/core/rtl/joypad.vhd: -------------------------------------------------------------------------------- 1 | library IEEE; 2 | use IEEE.std_logic_1164.all; 3 | use IEEE.numeric_std.all; 4 | 5 | use work.pRegisterBus.all; 6 | use work.pReg_swan.all; 7 | 8 | entity joypad is 9 | port 10 | ( 11 | clk : in std_logic; 12 | 13 | vertical : in std_logic; 14 | 15 | KeyY1 : in std_logic; 16 | KeyY2 : in std_logic; 17 | KeyY3 : in std_logic; 18 | KeyY4 : in std_logic; 19 | KeyX1 : in std_logic; 20 | KeyX2 : in std_logic; 21 | KeyX3 : in std_logic; 22 | KeyX4 : in std_logic; 23 | KeyStart : in std_logic; 24 | KeyA : in std_logic; 25 | KeyB : in std_logic; 26 | 27 | RegBus_Din : in std_logic_vector(BUS_buswidth-1 downto 0); 28 | RegBus_Adr : in std_logic_vector(BUS_busadr-1 downto 0); 29 | RegBus_wren : in std_logic; 30 | RegBus_rst : in std_logic; 31 | RegBus_Dout : out std_logic_vector(BUS_buswidth-1 downto 0) 32 | ); 33 | end entity; 34 | 35 | architecture arch of joypad is 36 | 37 | -- register 38 | signal KEYPAD : std_logic_vector(REG_KEYPAD.upper downto REG_KEYPAD.lower); 39 | signal KEYPAD_read : std_logic_vector(REG_KEYPAD.upper downto REG_KEYPAD.lower); 40 | 41 | begin 42 | 43 | iREG_KEYPAD : entity work.eReg generic map ( REG_KEYPAD ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, RegBus_Dout, KEYPAD_read, KEYPAD); 44 | 45 | process (all) 46 | begin 47 | 48 | KEYPAD_read <= '0' & KEYPAD(6 downto 4) & "0000"; 49 | if (KEYPAD(4) = '1') then 50 | if (vertical = '0') then 51 | if (KeyY1 = '1') then KEYPAD_read(0) <= '1'; end if; 52 | if (KeyY2 = '1') then KEYPAD_read(1) <= '1'; end if; 53 | if (KeyY3 = '1') then KEYPAD_read(2) <= '1'; end if; 54 | if (KeyY4 = '1') then KEYPAD_read(3) <= '1'; end if; 55 | else 56 | if (KeyX4 = '1') then KEYPAD_read(0) <= '1'; end if; 57 | if (KeyX1 = '1') then KEYPAD_read(1) <= '1'; end if; 58 | if (KeyX2 = '1') then KEYPAD_read(2) <= '1'; end if; 59 | if (KeyX3 = '1') then KEYPAD_read(3) <= '1'; end if; 60 | end if; 61 | elsif (KEYPAD(5) = '1') then 62 | if (vertical = '0') then 63 | if (KeyX1 = '1') then KEYPAD_read(0) <= '1'; end if; 64 | if (KeyX2 = '1') then KEYPAD_read(1) <= '1'; end if; 65 | if (KeyX3 = '1') then KEYPAD_read(2) <= '1'; end if; 66 | if (KeyX4 = '1') then KEYPAD_read(3) <= '1'; end if; 67 | else 68 | if (KeyY4 = '1') then KEYPAD_read(0) <= '1'; end if; 69 | if (KeyY1 = '1') then KEYPAD_read(1) <= '1'; end if; 70 | if (KeyY2 = '1') then KEYPAD_read(2) <= '1'; end if; 71 | if (KeyY3 = '1') then KEYPAD_read(3) <= '1'; end if; 72 | end if; 73 | elsif (KEYPAD(6) = '1') then 74 | if (KeyStart = '1') then KEYPAD_read(1) <= '1'; end if; 75 | if (KeyA = '1') then KEYPAD_read(2) <= '1'; end if; 76 | if (KeyB = '1') then KEYPAD_read(3) <= '1'; end if; 77 | end if; 78 | 79 | end process; 80 | 81 | end architecture; 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /src/fpga/core/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 | -------------------------------------------------------------------------------- /src/fpga/core/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 SSBUS_buswidth : integer := 64; 12 | constant SSBUS_busadr : integer := 7; 13 | 14 | type savestate_type is record 15 | Adr : integer range 0 to (2**SSBUS_busadr)-1; 16 | upper : integer range 0 to SSBUS_buswidth-1; 17 | lower : integer range 0 to SSBUS_buswidth-1; 18 | size : integer range 0 to (2**SSBUS_busadr)-1; 19 | defval : std_logic_vector(SSBUS_buswidth-1 downto 0); 20 | end record; 21 | 22 | end package; 23 | 24 | ----------------------------------------------------------------- 25 | --------------- Reg Interface ----------------------------------- 26 | ----------------------------------------------------------------- 27 | 28 | library IEEE; 29 | use IEEE.std_logic_1164.all; 30 | use IEEE.numeric_std.all; 31 | 32 | library work; 33 | use work.pBus_savestates.all; 34 | 35 | entity eReg_SS is 36 | generic 37 | ( 38 | Reg : savestate_type; 39 | index : integer := 0 40 | ); 41 | port 42 | ( 43 | clk : in std_logic; 44 | BUS_Din : in std_logic_vector(SSBUS_buswidth-1 downto 0); 45 | BUS_Adr : in std_logic_vector(SSBUS_busadr-1 downto 0); 46 | BUS_wren : in std_logic; 47 | BUS_rst : in std_logic; 48 | BUS_Dout : out std_logic_vector(SSBUS_buswidth-1 downto 0) := (others => '0'); 49 | Din : in std_logic_vector(Reg.upper downto Reg.lower); 50 | Dout : out std_logic_vector(Reg.upper downto Reg.lower) 51 | ); 52 | end entity; 53 | 54 | architecture arch of eReg_SS is 55 | 56 | signal Dout_buffer : std_logic_vector(Reg.upper downto Reg.lower) := Reg.defval(Reg.upper downto Reg.lower); 57 | 58 | signal AdrI : std_logic_vector(BUS_Adr'left downto 0); 59 | 60 | begin 61 | 62 | AdrI <= std_logic_vector(to_unsigned(Reg.Adr + index, BUS_Adr'length)); 63 | 64 | process (clk) 65 | begin 66 | if rising_edge(clk) then 67 | 68 | if (BUS_rst = '1') then 69 | 70 | Dout_buffer <= Reg.defval(Reg.upper downto Reg.lower); 71 | 72 | else 73 | 74 | if (BUS_Adr = AdrI and BUS_wren = '1') then 75 | for i in Reg.lower to Reg.upper loop 76 | Dout_buffer(i) <= BUS_Din(i); 77 | end loop; 78 | end if; 79 | 80 | end if; 81 | 82 | end if; 83 | end process; 84 | 85 | Dout <= Dout_buffer; 86 | 87 | goutputbit: for i in Reg.lower to Reg.upper generate 88 | BUS_Dout(i) <= Din(i) when BUS_Adr = AdrI else '0'; 89 | end generate; 90 | 91 | glowzero_required: if Reg.lower > 0 generate 92 | glowzero: for i in 0 to Reg.lower - 1 generate 93 | BUS_Dout(i) <= '0'; 94 | end generate; 95 | end generate; 96 | 97 | ghighzero_required: if Reg.upper < SSBUS_buswidth-1 generate 98 | ghighzero: for i in Reg.upper + 1 to SSBUS_buswidth-1 generate 99 | BUS_Dout(i) <= '0'; 100 | end generate; 101 | end generate; 102 | 103 | end architecture; 104 | 105 | 106 | -------------------------------------------------------------------------------- /dist/Cores/agg23.WonderSwan/interact.json: -------------------------------------------------------------------------------- 1 | { 2 | "interact": { 3 | "magic": "APF_VER_1", 4 | "variables": [ 5 | { 6 | "name": "Reset core", 7 | "id": 0, 8 | "type": "action", 9 | "enabled": true, 10 | "address": "0x50", 11 | "value": 1 12 | }, 13 | { 14 | "name": "System Type", 15 | "id": 10, 16 | "type": "list", 17 | "enabled": true, 18 | "persist": true, 19 | "writeonly": true, 20 | "address": "0x100", 21 | "defaultval": 0, 22 | "options": [ 23 | { 24 | "value": 0, 25 | "name": "Auto" 26 | }, 27 | { 28 | "value": 1, 29 | "name": "WonderSwan" 30 | }, 31 | { 32 | "value": 2, 33 | "name": "WonderSwan Color" 34 | }, 35 | { 36 | "value": 3, 37 | "name": "PocketChallenge v2" 38 | } 39 | ] 40 | }, 41 | { 42 | "name": "CPU Turbo", 43 | "id": 14, 44 | "type": "check", 45 | "enabled": true, 46 | "address": "0x110", 47 | "persist": true, 48 | "writeonly": true, 49 | "defaultval": 0, 50 | "value": 1 51 | }, 52 | { 53 | "name": "Video", 54 | "id": 40, 55 | "type": "action", 56 | "enabled": false 57 | }, 58 | { 59 | "name": "Triple Buffer", 60 | "id": 41, 61 | "type": "check", 62 | "enabled": true, 63 | "address": "0x200", 64 | "persist": true, 65 | "writeonly": true, 66 | "defaultval": 1, 67 | "value": 1 68 | }, 69 | { 70 | "name": "Flickerblend", 71 | "id": 42, 72 | "type": "list", 73 | "enabled": true, 74 | "persist": true, 75 | "writeonly": true, 76 | "address": "0x204", 77 | "defaultval": 0, 78 | "options": [ 79 | { 80 | "value": 0, 81 | "name": "Off" 82 | }, 83 | { 84 | "value": 1, 85 | "name": "2 Frames" 86 | }, 87 | { 88 | "value": 2, 89 | "name": "3 Frames" 90 | } 91 | ] 92 | }, 93 | { 94 | "name": "Orientation", 95 | "id": 43, 96 | "type": "list", 97 | "enabled": true, 98 | "persist": true, 99 | "writeonly": true, 100 | "address": "0x208", 101 | "defaultval": 0, 102 | "options": [ 103 | { 104 | "value": 0, 105 | "name": "Auto" 106 | }, 107 | { 108 | "value": 1, 109 | "name": "Horizontal" 110 | }, 111 | { 112 | "value": 2, 113 | "name": "Vertical" 114 | } 115 | ] 116 | }, 117 | { 118 | "name": "Flip Horizontal", 119 | "id": 44, 120 | "type": "check", 121 | "enabled": true, 122 | "address": "0x20C", 123 | "persist": true, 124 | "writeonly": true, 125 | "defaultval": 0, 126 | "value": 1 127 | }, 128 | { 129 | "name": "Sound", 130 | "id": 80, 131 | "type": "action", 132 | "enabled": false 133 | }, 134 | { 135 | "name": "Fast Forward", 136 | "id": 81, 137 | "type": "check", 138 | "enabled": true, 139 | "address": "0x300", 140 | "persist": true, 141 | "writeonly": true, 142 | "defaultval": 1, 143 | "value": 1 144 | } 145 | ], 146 | "messages": [] 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/fpga/core/rtl/registerpackage.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 pRegisterBus is 10 | 11 | constant BUS_buswidth : integer := 8; 12 | constant BUS_busadr : integer := 8; 13 | 14 | type regaccess_type is 15 | ( 16 | readwrite, 17 | readonly, 18 | writeonly, 19 | writeDone -- writeonly, but does send back done, so it is not dead 20 | ); 21 | 22 | type regmap_type is record 23 | Adr : integer range 0 to (2**BUS_busadr)-1; 24 | upper : integer range 0 to BUS_buswidth-1; 25 | lower : integer range 0 to BUS_buswidth-1; 26 | size : integer range 0 to (2**BUS_busadr)-1; 27 | defval : integer; 28 | acccesstype : regaccess_type; 29 | end record; 30 | 31 | end package; 32 | 33 | 34 | ----------------------------------------------------------------- 35 | --------------- Reg Interface ---------------------------------- 36 | ----------------------------------------------------------------- 37 | 38 | library IEEE; 39 | use IEEE.std_logic_1164.all; 40 | use IEEE.numeric_std.all; 41 | 42 | library work; 43 | use work.pRegisterBus.all; 44 | 45 | entity eReg is 46 | generic 47 | ( 48 | Reg : regmap_type; 49 | index : integer := 0 50 | ); 51 | port 52 | ( 53 | clk : in std_logic; 54 | BUS_Din : in std_logic_vector(BUS_buswidth-1 downto 0); 55 | BUS_Adr : in std_logic_vector(BUS_busadr-1 downto 0); 56 | BUS_wren : in std_logic; 57 | BUS_rst : in std_logic; 58 | BUS_Dout : out std_logic_vector(BUS_buswidth-1 downto 0) := (others => '0'); 59 | Din : in std_logic_vector(Reg.upper downto Reg.lower); 60 | Dout : out std_logic_vector(Reg.upper downto Reg.lower); 61 | written : out std_logic := '0' 62 | ); 63 | end entity; 64 | 65 | architecture arch of eReg is 66 | 67 | signal Dout_buffer : std_logic_vector(Reg.upper downto Reg.lower) := std_logic_vector(to_unsigned(Reg.defval,Reg.upper-Reg.lower+1)); 68 | 69 | signal AdrI : std_logic_vector(BUS_Adr'left downto 0); 70 | 71 | begin 72 | 73 | AdrI <= std_logic_vector(to_unsigned(Reg.Adr + index, BUS_Adr'length)); 74 | 75 | process (clk) 76 | begin 77 | if rising_edge(clk) then 78 | 79 | if (BUS_rst = '1') then 80 | 81 | Dout_buffer <= std_logic_vector(to_unsigned(Reg.defval,Reg.upper-Reg.lower+1)); 82 | 83 | else 84 | 85 | if (BUS_Adr = AdrI and BUS_wren = '1') then 86 | for i in Reg.lower to Reg.upper loop 87 | Dout_buffer(i) <= BUS_Din(i); 88 | end loop; 89 | end if; 90 | 91 | end if; 92 | 93 | end if; 94 | end process; 95 | 96 | Dout <= Dout_buffer; 97 | 98 | written <= '1' when (BUS_Adr = AdrI and BUS_wren = '1') else '0'; 99 | 100 | goutputbit: for i in Reg.lower to Reg.upper generate 101 | BUS_Dout(i) <= Din(i) when BUS_Adr = AdrI else '0'; 102 | end generate; 103 | 104 | glowzero_required: if Reg.lower > 0 generate 105 | glowzero: for i in 0 to Reg.lower - 1 generate 106 | BUS_Dout(i) <= '0'; 107 | end generate; 108 | end generate; 109 | 110 | ghighzero_required: if Reg.upper < BUS_buswidth-1 generate 111 | ghighzero: for i in Reg.upper + 1 to BUS_buswidth-1 generate 112 | BUS_Dout(i) <= '0'; 113 | end generate; 114 | end generate; 115 | 116 | end architecture; 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /src/fpga/core/rtl/sound_module1.vhd: -------------------------------------------------------------------------------- 1 | library IEEE; 2 | use IEEE.std_logic_1164.all; 3 | use IEEE.numeric_std.all; 4 | 5 | use work.pRegisterBus.all; 6 | use work.pReg_swan.all; 7 | 8 | entity sound_module1 is 9 | port 10 | ( 11 | clk : in std_logic; 12 | ce : in std_logic; 13 | reset : in std_logic; 14 | 15 | RegBus_Din : in std_logic_vector(BUS_buswidth-1 downto 0); 16 | RegBus_Adr : in std_logic_vector(BUS_busadr-1 downto 0); 17 | RegBus_wren : in std_logic; 18 | RegBus_rst : in std_logic; 19 | RegBus_Dout : out std_logic_vector(BUS_buswidth-1 downto 0); 20 | 21 | sampleRequest : out std_logic := '0'; 22 | sampleposReq : out unsigned(4 downto 0) := (others => '0'); 23 | channelData : in unsigned(3 downto 0); 24 | channelValid : in std_logic; 25 | 26 | soundoutL : out signed(8 downto 0) := (others => '0'); 27 | soundoutR : out signed(8 downto 0) := (others => '0') 28 | ); 29 | end entity; 30 | 31 | architecture arch of sound_module1 is 32 | 33 | -- register 34 | signal SND_CH_PITCH : std_logic_vector(10 downto 0); 35 | signal SND_CH_Vol : std_logic_vector( 7 downto 0); 36 | 37 | type t_reg_wired_or is array(0 to 2) of std_logic_vector(7 downto 0); 38 | signal reg_wired_or : t_reg_wired_or; 39 | 40 | -- internal 41 | signal pitchCount : unsigned(10 downto 0); 42 | signal nextData : unsigned(3 downto 0); 43 | 44 | begin 45 | 46 | iREG_SND_CH_PITCH_L : entity work.eReg generic map ( REG_SND_CH1_PITCH_L ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(0), SND_CH_PITCH( 7 downto 0), SND_CH_PITCH( 7 downto 0)); 47 | iREG_SND_CH_PITCH_H : entity work.eReg generic map ( REG_SND_CH1_PITCH_H ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(1), SND_CH_PITCH(10 downto 8), SND_CH_PITCH(10 downto 8)); 48 | iREG_SND_CH_Vol : entity work.eReg generic map ( REG_SND_CH1_Vol ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(2), SND_CH_Vol , SND_CH_Vol ); 49 | 50 | process (reg_wired_or) 51 | variable wired_or : std_logic_vector(7 downto 0); 52 | begin 53 | wired_or := reg_wired_or(0); 54 | for i in 1 to (reg_wired_or'length - 1) loop 55 | wired_or := wired_or or reg_wired_or(i); 56 | end loop; 57 | RegBus_Dout <= wired_or; 58 | end process; 59 | 60 | process (clk) 61 | variable newPitchCount : unsigned(10 downto 0); 62 | begin 63 | if rising_edge(clk) then 64 | 65 | if (reset = '1') then 66 | 67 | sampleposReq <= (others => '0'); 68 | soundoutL <= (others => '0'); 69 | soundoutR <= (others => '0'); 70 | sampleRequest <= '1'; 71 | 72 | pitchCount <= (others => '0'); 73 | nextData <= (others => '0'); 74 | 75 | elsif (ce = '1') then 76 | 77 | newPitchCount := pitchCount - 1; 78 | pitchCount <= newPitchCount; 79 | if (newPitchCount = unsigned(SND_CH_PITCH)) then 80 | sampleRequest <= '1'; 81 | pitchCount <= (others => '0'); 82 | sampleposReq <= sampleposReq + 1; 83 | soundoutL <= signed('0' & (nextData * unsigned(SND_CH_Vol(7 downto 4)))); 84 | soundoutR <= signed('0' & (nextData * unsigned(SND_CH_Vol(3 downto 0)))); 85 | end if; 86 | 87 | if (channelValid = '1') then 88 | sampleRequest <= '0'; 89 | nextData <= channelData; 90 | end if; 91 | 92 | end if; 93 | 94 | end if; 95 | end process; 96 | 97 | 98 | end architecture; 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /src/fpga/core/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 joyRewind, 13 | input rewindEnable, 14 | input [1:0] status_slot, 15 | input [1:0] OSD_saveload, 16 | output reg ss_save, 17 | output reg ss_load, 18 | output reg ss_info_req, 19 | output reg [7:0] ss_info, 20 | output reg statusUpdate, 21 | output [1:0] selected_slot 22 | ); 23 | 24 | reg [1:0] ss_base = 0; 25 | 26 | reg lastRight = 1'b0; 27 | reg lastLeft = 1'b0; 28 | reg lastDown = 1'b0; 29 | reg lastUp = 1'b0; 30 | 31 | reg [(INFO_TIMEOUT_BITS-1):0] InfoWaitcnt = 0; 32 | 33 | reg slotswitched = 1'b0; 34 | reg [1:0] lastOSDsetting = 2'b0; 35 | 36 | assign selected_slot = ss_base; 37 | 38 | wire pressed = ps2_key[9]; 39 | 40 | always @(posedge clk) begin 41 | reg old_state; 42 | reg alt = 0; 43 | reg [1:0] old_st; 44 | 45 | old_state <= ps2_key[10]; 46 | 47 | lastRight <= joyRight; 48 | lastLeft <= joyLeft; 49 | lastDown <= joyDown; 50 | lastUp <= joyUp; 51 | 52 | slotswitched <= 1'b0; 53 | 54 | ss_save <= 1'b0; 55 | ss_load <= 1'b0; 56 | ss_info_req <= 1'b0; 57 | statusUpdate <= 1'b0; 58 | 59 | lastOSDsetting <= status_slot; 60 | 61 | if(allow_ss) begin 62 | 63 | // keyboard 64 | if(old_state != ps2_key[10]) begin 65 | case(ps2_key[7:0]) 66 | 'h11: alt <= pressed; 67 | 'h05: begin ss_save <= pressed & alt; ss_load <= pressed & ~alt; ss_base <= 0; statusUpdate <= 1'b1; end // F1 68 | 'h06: begin ss_save <= pressed & alt; ss_load <= pressed & ~alt; ss_base <= 1; statusUpdate <= 1'b1; end // F2 69 | 'h04: begin ss_save <= pressed & alt; ss_load <= pressed & ~alt; ss_base <= 2; statusUpdate <= 1'b1; end // F3 70 | 'h0C: begin ss_save <= pressed & alt; ss_load <= pressed & ~alt; ss_base <= 3; statusUpdate <= 1'b1; end // F4 71 | endcase 72 | end 73 | 74 | if (lastOSDsetting != status_slot) begin 75 | ss_base <= status_slot; 76 | statusUpdate <= 1'b1; 77 | end 78 | 79 | // gamepad 80 | if (joySS) begin 81 | // timeout with no button pressed -> help text 82 | InfoWaitcnt <= InfoWaitcnt + 1'b1; 83 | if (InfoWaitcnt[(INFO_TIMEOUT_BITS-1)]) begin 84 | ss_info <= 7'd1; 85 | ss_info_req <= 1'b1; 86 | InfoWaitcnt <= 25'b0; 87 | end 88 | // switch slot 89 | if (joyRight & ~lastRight & ss_base < 3) begin 90 | ss_base <= ss_base + 1'd1; 91 | statusUpdate <= 1'b1; 92 | slotswitched <= 1'b1; 93 | InfoWaitcnt <= 25'b0; 94 | end 95 | if (joyLeft & ~lastLeft & ss_base > 0) begin 96 | ss_base <= ss_base - 1'd1; 97 | statusUpdate <= 1'b1; 98 | slotswitched <= 1'b1; 99 | InfoWaitcnt <= 25'b0; 100 | end 101 | // save and load 102 | if (joyStart & joyDown & ~lastDown) begin 103 | ss_save <= 1'b1; 104 | InfoWaitcnt <= 25'b0; 105 | end 106 | // save and load 107 | if (joyStart & joyUp & ~lastUp) begin 108 | ss_load <= 1'b1; 109 | InfoWaitcnt <= 25'b0; 110 | end 111 | end else begin 112 | InfoWaitcnt <= 25'b0; 113 | end 114 | 115 | // OSD 116 | old_st <= OSD_saveload; 117 | if(old_st[0] ^ OSD_saveload[0]) ss_save <= OSD_saveload[0]; 118 | if(old_st[1] ^ OSD_saveload[1]) ss_load <= OSD_saveload[1]; 119 | 120 | // infotexts 121 | if (slotswitched) begin 122 | ss_info <= 7'd2 + ss_base; 123 | ss_info_req <= 1'b1; 124 | end 125 | 126 | if(ss_load | ss_save) begin 127 | ss_info <= 7'd6 + {ss_base, ss_load}; 128 | ss_info_req <= 1'b1; 129 | end 130 | 131 | // rewind info 132 | if (rewindEnable & joyRewind) begin 133 | ss_info_req <= 1'b1; 134 | ss_info <= 7'd14; 135 | end 136 | 137 | end 138 | end 139 | 140 | endmodule 141 | 142 | -------------------------------------------------------------------------------- /src/fpga/core/rtl/sound_module5.vhd: -------------------------------------------------------------------------------- 1 | library IEEE; 2 | use IEEE.std_logic_1164.all; 3 | use IEEE.numeric_std.all; 4 | 5 | use work.pRegisterBus.all; 6 | use work.pReg_swan.all; 7 | 8 | entity sound_module5 is 9 | port 10 | ( 11 | clk : in std_logic; 12 | ce : in std_logic; 13 | reset : in std_logic; 14 | 15 | soundDMAvalue : in std_logic_vector(7 downto 0); 16 | soundDMAvalid : in std_logic; 17 | 18 | RegBus_Din : in std_logic_vector(BUS_buswidth-1 downto 0); 19 | RegBus_Adr : in std_logic_vector(BUS_busadr-1 downto 0); 20 | RegBus_wren : in std_logic; 21 | RegBus_rst : in std_logic; 22 | RegBus_Dout : out std_logic_vector(BUS_buswidth-1 downto 0); 23 | 24 | soundEnable : out std_logic; 25 | soundoutL : out signed(12 downto 0) := (others => '0'); 26 | soundoutR : out signed(12 downto 0) := (others => '0') 27 | ); 28 | end entity; 29 | 30 | architecture arch of sound_module5 is 31 | 32 | -- register 33 | signal SND_HYPER_CTRL : std_logic_vector(7 downto 0); 34 | signal SND_HYPER_CHAN_CTRL : std_logic_vector(6 downto 0); 35 | signal SND_HYPERVOICE : std_logic_vector(7 downto 0); 36 | 37 | signal SND_HYPERVOICE_written : std_logic; 38 | 39 | type t_reg_wired_or is array(0 to 2) of std_logic_vector(7 downto 0); 40 | signal reg_wired_or : t_reg_wired_or; 41 | 42 | signal sample : unsigned(7 downto 0); 43 | signal volumeMulti : integer range 0 to 8; 44 | 45 | begin 46 | 47 | iREG_SND_HYPER_CTRL : entity work.eReg generic map ( REG_SND_HYPER_CTRL ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(0), SND_HYPER_CTRL , SND_HYPER_CTRL ); 48 | iREG_SND_HYPER_CHAN_CTRL : entity work.eReg generic map ( REG_SND_HYPER_CHAN_CTRL ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(1), SND_HYPER_CHAN_CTRL, SND_HYPER_CHAN_CTRL); 49 | iREG_SND_HYPERVOICE : entity work.eReg generic map ( REG_SND_HYPERVOICE ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(2), SND_HYPERVOICE , SND_HYPERVOICE , SND_HYPERVOICE_written); 50 | 51 | soundEnable <= SND_HYPER_CTRL(7); 52 | 53 | process (reg_wired_or) 54 | variable wired_or : std_logic_vector(7 downto 0); 55 | begin 56 | wired_or := reg_wired_or(0); 57 | for i in 1 to (reg_wired_or'length - 1) loop 58 | wired_or := wired_or or reg_wired_or(i); 59 | end loop; 60 | RegBus_Dout <= wired_or; 61 | end process; 62 | 63 | process (clk) 64 | variable soundvalue : signed(12 downto 0); 65 | begin 66 | if rising_edge(clk) then 67 | 68 | if (reset = '1') then 69 | 70 | soundoutL <= (others => '0'); 71 | soundoutR <= (others => '0'); 72 | sample <= (others => '0'); 73 | 74 | elsif (ce = '1') then 75 | 76 | case (SND_HYPER_CTRL(1 downto 0)) is 77 | when "00" => volumeMulti <= 8; 78 | when "01" => volumeMulti <= 4; 79 | when "10" => volumeMulti <= 2; 80 | when "11" => volumeMulti <= 1; 81 | when others => null; 82 | end case; 83 | 84 | soundvalue := (others => '0'); 85 | case (SND_HYPER_CTRL(3 downto 2)) is 86 | when "00" => soundvalue := to_signed(to_integer(sample) * volumeMulti, 13); 87 | when "01" => soundvalue := to_signed((to_integer(sample) - 16#100#) * volumeMulti, 13); 88 | when "10" => soundvalue := to_signed(to_integer(signed(sample)) * volumeMulti, 13); 89 | when "11" => soundvalue := to_signed(to_integer(sample), 13); 90 | when others => null; 91 | end case; 92 | 93 | if (SND_HYPER_CHAN_CTRL(5) = '1') then soundoutL <= soundvalue; else soundoutL <= (others => '0'); end if; 94 | if (SND_HYPER_CHAN_CTRL(6) = '1') then soundoutR <= soundvalue; else soundoutR <= (others => '0'); end if; 95 | 96 | end if; 97 | 98 | if (SND_HYPERVOICE_written = '1') then sample <= unsigned(SND_HYPERVOICE); end if; 99 | if (soundDMAvalid = '1') then sample <= unsigned(soundDMAvalue); end if; 100 | 101 | end if; 102 | end process; 103 | 104 | 105 | end architecture; 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WonderSwan Color for Analogue Pocket 2 | 3 | Ported from the original core developed by [Robert Piep](https://github.com/RobertPeip) ([Patreon](https://www.patreon.com/FPGAzumSpass)). Core icon provided by [spiritualized1997](https://github.com/spiritualized1997). Latest upstream available at https://github.com/MiSTer-devel/WonderSwan_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 | Download the core by clicking Releases on the right side of this page, then download the `agg23.*.zip` file from the latest release. 15 | 16 | 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. 17 | 18 | ## Usage 19 | 20 | ROMs should be placed in `/Assets/wonderswan/common/` 21 | 22 | You must provide the BIOS files for both the original and WonderSwan Color. The BIOSes should be named `bw.rom` and `color.rom`, and should be placed in `/Assets/wonderswan/common/`. 23 | 24 | WonderSwan 25 | * `bw.rom` 26 | * MD5: 54B915694731CC22E07D3FB8A00EE2DB 27 | 28 | WonderSwan Color 29 | * `color.rom` 30 | * MD5: 880893BD5A7D53FFF826BD76A83D566E 31 | 32 | ## Features 33 | 34 | ### Save States/Sleep + Wake 35 | 36 | Known as "Memories" on the Pocket, this core supports the creation and loading of save states, and by extension, the core also supports Sleep + Wake functionality. Tapping the power button while playing will suspend the game, ready to be resumed when powering the Pocket back on. 37 | 38 | ### Fast Forward 39 | 40 | Hold the `-` button (default) to run the WonderSwan at 2.5x speed. Tapping the button will lock fast forward on, and it will continue fast forwarding until the button is pressed again. 41 | 42 | ### Controls 43 | 44 | The WonderSwan has a lot of buttons for a handheld in an unusual layout. The default button mappings for the Pocket are as close as I can get to the original control layout. 45 | 46 | 47 | 48 | 49 | 50 | 51 |
HorizontalVertical
52 | 53 | | Pocket | WonderSwan | 54 | |---------|------------| 55 | | D-pad | X buttons | 56 | | A | A | 57 | | B | B | 58 | | X | Y3 | 59 | | Y | Y4 | 60 | | L. Trig | Y1 | 61 | | R. Trig | Y2 | 62 | | + | Start | 63 | | - |Fast Forward| 64 | 65 | 66 | 67 | | Pocket | WonderSwan | 68 | |---------|------------| 69 | | D-pad | Y buttons | 70 | | A | X3 | 71 | | B | X4 | 72 | | X | X2 | 73 | | Y | X1 | 74 | | L. Trig | A | 75 | | R. Trig | B | 76 | | + | Start | 77 | | - |Fast Forward| 78 | 79 |
80 | 81 | ### System Settings 82 | 83 | * `System Type` - Choose what type of WonderSwan to boot. Changing this option requires resetting the core 84 | * `CPU Turbo` - Allows the CPU to perform additional processing per frame, which can be used to eliminate some slowdowns. 85 | 86 | ### Video Settings 87 | 88 | The WonderSwan has a native refresh rate of 75.4Hz, but the Analogue Pocket doesn't support higher than ~62Hz (and 60Hz on the Dock). This core provides the option to either run the display directly at 60Hz, introducing tearing, or to triple buffer frames at 60Hz, introducing latency and skipping some frames entirely. 89 | 90 | * `Triple Buffer` - Triple buffer image to prevent tearing. Please note that this does increase latency and will cause frames to be dropped. 91 | * `Flickerblend` - Use a combination of 2 or 3 frames of data to perform blending on flickering UI elements. This will decrease the flickering and resolve the flicker into a lighter grey color. Please note that this enables the frame buffer implicitly. 92 | * `Orientation` - Lock the screen rotation to a particular direction. When set to `Auto`, the core will automatically rotate the display. 93 | * `Flip Horizontal` - Flips the display whenever the WonderSwan would display in horizontal mode. 94 | 95 | ### Sound Settings 96 | 97 | * `Fast Forward` - If enabled, play sound when fast forward is active. -------------------------------------------------------------------------------- /src/fpga/core/pin_ddio_clk.v: -------------------------------------------------------------------------------- 1 | // megafunction wizard: %ALTDDIO_OUT% 2 | // GENERATION: STANDARD 3 | // VERSION: WM1.0 4 | // MODULE: ALTDDIO_OUT 5 | 6 | // ============================================================ 7 | // File Name: pin_ddio_clk.v 8 | // Megafunction Name(s): 9 | // ALTDDIO_OUT 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 pin_ddio_clk ( 41 | datain_h, 42 | datain_l, 43 | outclock, 44 | dataout); 45 | 46 | input [0:0] datain_h; 47 | input [0:0] datain_l; 48 | input outclock; 49 | output [0:0] dataout; 50 | 51 | wire [0:0] sub_wire0; 52 | wire [0:0] dataout = sub_wire0[0:0]; 53 | 54 | altddio_out ALTDDIO_OUT_component ( 55 | .datain_h (datain_h), 56 | .datain_l (datain_l), 57 | .outclock (outclock), 58 | .dataout (sub_wire0), 59 | .aclr (1'b0), 60 | .aset (1'b0), 61 | .oe (1'b1), 62 | .oe_out (), 63 | .outclocken (1'b1), 64 | .sclr (1'b0), 65 | .sset (1'b0)); 66 | defparam 67 | ALTDDIO_OUT_component.extend_oe_disable = "OFF", 68 | ALTDDIO_OUT_component.intended_device_family = "Cyclone V", 69 | ALTDDIO_OUT_component.invert_output = "OFF", 70 | ALTDDIO_OUT_component.lpm_hint = "UNUSED", 71 | ALTDDIO_OUT_component.lpm_type = "altddio_out", 72 | ALTDDIO_OUT_component.oe_reg = "UNREGISTERED", 73 | ALTDDIO_OUT_component.power_up_high = "OFF", 74 | ALTDDIO_OUT_component.width = 1; 75 | 76 | 77 | endmodule 78 | 79 | // ============================================================ 80 | // CNX file retrieval info 81 | // ============================================================ 82 | // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all 83 | // Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone V" 84 | // Retrieval info: CONSTANT: EXTEND_OE_DISABLE STRING "OFF" 85 | // Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone V" 86 | // Retrieval info: CONSTANT: INVERT_OUTPUT STRING "OFF" 87 | // Retrieval info: CONSTANT: LPM_HINT STRING "UNUSED" 88 | // Retrieval info: CONSTANT: LPM_TYPE STRING "altddio_out" 89 | // Retrieval info: CONSTANT: OE_REG STRING "UNREGISTERED" 90 | // Retrieval info: CONSTANT: POWER_UP_HIGH STRING "OFF" 91 | // Retrieval info: CONSTANT: WIDTH NUMERIC "1" 92 | // Retrieval info: USED_PORT: datain_h 0 0 1 0 INPUT NODEFVAL "datain_h[0..0]" 93 | // Retrieval info: CONNECT: @datain_h 0 0 1 0 datain_h 0 0 1 0 94 | // Retrieval info: USED_PORT: datain_l 0 0 1 0 INPUT NODEFVAL "datain_l[0..0]" 95 | // Retrieval info: CONNECT: @datain_l 0 0 1 0 datain_l 0 0 1 0 96 | // Retrieval info: USED_PORT: dataout 0 0 1 0 OUTPUT NODEFVAL "dataout[0..0]" 97 | // Retrieval info: CONNECT: dataout 0 0 1 0 @dataout 0 0 1 0 98 | // Retrieval info: USED_PORT: outclock 0 0 0 0 INPUT_CLK_EXT NODEFVAL "outclock" 99 | // Retrieval info: CONNECT: @outclock 0 0 0 0 outclock 0 0 0 0 100 | // Retrieval info: GEN_FILE: TYPE_NORMAL pin_ddio_clk.v TRUE FALSE 101 | // Retrieval info: GEN_FILE: TYPE_NORMAL pin_ddio_clk.qip TRUE FALSE 102 | // Retrieval info: GEN_FILE: TYPE_NORMAL pin_ddio_clk.bsf FALSE TRUE 103 | // Retrieval info: GEN_FILE: TYPE_NORMAL pin_ddio_clk_inst.v TRUE TRUE 104 | // Retrieval info: GEN_FILE: TYPE_NORMAL pin_ddio_clk_bb.v FALSE TRUE 105 | // Retrieval info: GEN_FILE: TYPE_NORMAL pin_ddio_clk.inc FALSE TRUE 106 | // Retrieval info: GEN_FILE: TYPE_NORMAL pin_ddio_clk.cmp FALSE TRUE 107 | // Retrieval info: GEN_FILE: TYPE_NORMAL pin_ddio_clk.ppf TRUE FALSE 108 | // Retrieval info: LIB_FILE: altera_mf 109 | -------------------------------------------------------------------------------- /src/fpga/core/rtl/divider.vhd: -------------------------------------------------------------------------------- 1 | library IEEE; 2 | use IEEE.std_logic_1164.all; 3 | use IEEE.numeric_std.all; 4 | 5 | entity divider is 6 | port 7 | ( 8 | clk : in std_logic; 9 | start : in std_logic; 10 | done : out std_logic := '0'; 11 | busy : out std_logic := '0'; 12 | dividend : in signed(32 downto 0); 13 | divisor : in signed(32 downto 0); 14 | quotient : out signed(32 downto 0); 15 | remainder : out signed(32 downto 0) 16 | ); 17 | end entity; 18 | 19 | architecture arch of divider is 20 | 21 | constant bits_per_cycle : integer := 1; 22 | 23 | signal dividend_u : unsigned(dividend'length downto 0); 24 | signal divisor_u : unsigned(divisor'length downto 0); 25 | signal quotient_u : unsigned(quotient'length downto 0); 26 | signal Akku : unsigned (divisor'left + 1 downto divisor'right); 27 | signal QPointer : integer range quotient_u'range; 28 | signal done_buffer : std_logic := '0'; 29 | 30 | begin 31 | 32 | process (clk) is 33 | variable XPointer : integer range dividend_u'range; 34 | variable QPointerNew : integer range quotient_u'range; 35 | variable AkkuNew : unsigned (divisor'left + 1 downto divisor'right); 36 | variable Rdy_i : std_logic; 37 | variable Q_bits : std_logic_vector(bits_per_cycle-1 downto 0); 38 | variable Diff : unsigned (AkkuNew'range); 39 | begin 40 | if rising_edge(clk) then 41 | 42 | done_buffer <= '0'; 43 | busy <= '0'; 44 | 45 | -- == Initialize loop =============================================== 46 | if start = '1' then 47 | 48 | busy <= '1'; 49 | 50 | dividend_u <= '0' & unsigned(abs(dividend)); 51 | divisor_u <= '0' & unsigned(abs(divisor)); 52 | 53 | QPointerNew := quotient_u'left; 54 | XPointer := dividend_u'left; 55 | Rdy_i := '0'; 56 | --AkkuNew := (Akku'left downto 1 => '0') & dividend(XPointer); 57 | AkkuNew := (others => '0'); 58 | -- == Repeat for every Digit in Q =================================== 59 | elsif Rdy_i = '0' then 60 | busy <= '1'; 61 | AkkuNew := Akku; 62 | QPointerNew := QPointer; 63 | 64 | for i in 1 to bits_per_cycle loop 65 | 66 | -- Calculate output digit and new Akku --------------------------- 67 | Diff := AkkuNew - divisor_u; 68 | if Diff(Diff'left) = '0' then -- Does Y fit in Akku? 69 | Q_bits(bits_per_cycle-i) := '1'; -- YES: Digit is '1' 70 | AkkuNew := unsigned(shift_left(Diff,1));-- Diff -> Akku 71 | else -- 72 | Q_bits(bits_per_cycle-i) := '0'; -- NO : Digit is '0' 73 | AkkuNew := unsigned(Shift_left(AkkuNew,1));-- Shift Akku 74 | end if; 75 | -- --------------------------------------------------------------- 76 | if XPointer > dividend'right then -- divisor read completely? 77 | XPointer := XPointer - 1; -- NO : Put next digit 78 | AkkuNew(AkkuNew'right) := dividend_u(XPointer); -- in Akku 79 | else 80 | AkkuNew(AkkuNew'right) := '0' ; -- YES: Read Zeros (post point) 81 | end if; 82 | -- --------------------------------------------------------------- 83 | if QPointerNew > quotient'right then -- Has this been the last cycle? 84 | QPointerNew := QPointerNew - 1; -- NO : Prepare next cycle 85 | else -- 86 | Rdy_i := '1'; -- YES: work done 87 | done_buffer <= '1'; 88 | end if; 89 | 90 | end loop; 91 | 92 | quotient_u(QPointer downto QPointer-(bits_per_cycle-1)) <= unsigned(Q_bits); 93 | end if; 94 | 95 | QPointer <= QPointerNew; 96 | Akku <= AkkuNew; 97 | 98 | if ((dividend(dividend'left) xor divisor(divisor'left)) = '1') then 99 | quotient <= -signed(quotient_u(quotient'left downto 0)); 100 | else 101 | quotient <= signed(quotient_u(quotient'left downto 0)); 102 | end if; 103 | if (dividend(dividend'left) = '1') then 104 | remainder <= -signed(AkkuNew(remainder'left + 1 downto remainder'right + 1)); 105 | else 106 | remainder <= signed(AkkuNew(remainder'left + 1 downto remainder'right + 1)); 107 | end if; 108 | 109 | done <= done_buffer; 110 | 111 | end if; 112 | 113 | 114 | 115 | end process; 116 | 117 | 118 | end architecture; 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase.bsf: -------------------------------------------------------------------------------- 1 | /* 2 | WARNING: Do NOT edit the input and output ports in this file in a text 3 | editor if you plan to continue editing the block that represents it in 4 | the Block Editor! File corruption is VERY likely to occur. 5 | */ 6 | /* 7 | Copyright (C) 2022 Intel Corporation. All rights reserved. 8 | Your use of Intel Corporation's design tools, logic functions 9 | and other software and tools, and any partner logic 10 | functions, and any output files from any of the foregoing 11 | (including device programming or simulation files), and any 12 | associated documentation or information are expressly subject 13 | to the terms and conditions of the Intel Program License 14 | Subscription Agreement, the Intel Quartus Prime License Agreement, 15 | the Intel FPGA IP License Agreement, or other applicable license 16 | agreement, including, without limitation, that your use is for 17 | the sole purpose of programming logic devices manufactured by 18 | Intel and sold by Intel or its authorized distributors. Please 19 | refer to the applicable agreement for further details, at 20 | https://fpgasoftware.intel.com/eula. 21 | */ 22 | (header "symbol" (version "1.1")) 23 | (symbol 24 | (rect 0 0 160 264) 25 | (text "mf_pllbase" (rect 48 -1 91 11)(font "Arial" (font_size 10))) 26 | (text "inst" (rect 8 248 20 260)(font "Arial" )) 27 | (port 28 | (pt 0 72) 29 | (input) 30 | (text "refclk" (rect 0 0 22 12)(font "Arial" (font_size 8))) 31 | (text "refclk" (rect 4 61 40 72)(font "Arial" (font_size 8))) 32 | (line (pt 0 72)(pt 48 72)(line_width 1)) 33 | ) 34 | (port 35 | (pt 0 112) 36 | (input) 37 | (text "rst" (rect 0 0 10 12)(font "Arial" (font_size 8))) 38 | (text "rst" (rect 4 101 22 112)(font "Arial" (font_size 8))) 39 | (line (pt 0 112)(pt 48 112)(line_width 1)) 40 | ) 41 | (port 42 | (pt 160 72) 43 | (output) 44 | (text "outclk_0" (rect 0 0 33 12)(font "Arial" (font_size 8))) 45 | (text "outclk_0" (rect 117 61 165 72)(font "Arial" (font_size 8))) 46 | (line (pt 160 72)(pt 112 72)(line_width 1)) 47 | ) 48 | (port 49 | (pt 160 112) 50 | (output) 51 | (text "outclk_1" (rect 0 0 31 12)(font "Arial" (font_size 8))) 52 | (text "outclk_1" (rect 119 101 167 112)(font "Arial" (font_size 8))) 53 | (line (pt 160 112)(pt 112 112)(line_width 1)) 54 | ) 55 | (port 56 | (pt 160 152) 57 | (output) 58 | (text "outclk_2" (rect 0 0 33 12)(font "Arial" (font_size 8))) 59 | (text "outclk_2" (rect 117 141 165 152)(font "Arial" (font_size 8))) 60 | (line (pt 160 152)(pt 112 152)(line_width 1)) 61 | ) 62 | (port 63 | (pt 160 192) 64 | (output) 65 | (text "outclk_3" (rect 0 0 33 12)(font "Arial" (font_size 8))) 66 | (text "outclk_3" (rect 117 181 165 192)(font "Arial" (font_size 8))) 67 | (line (pt 160 192)(pt 112 192)(line_width 1)) 68 | ) 69 | (port 70 | (pt 160 232) 71 | (output) 72 | (text "locked" (rect 0 0 24 12)(font "Arial" (font_size 8))) 73 | (text "locked" (rect 127 221 163 232)(font "Arial" (font_size 8))) 74 | (line (pt 160 232)(pt 112 232)(line_width 1)) 75 | ) 76 | (drawing 77 | (text "refclk" (rect 16 43 68 99)(font "Arial" (color 128 0 0)(font_size 9))) 78 | (text "clk" (rect 53 67 124 144)(font "Arial" (color 0 0 0))) 79 | (text "reset" (rect 19 83 68 179)(font "Arial" (color 128 0 0)(font_size 9))) 80 | (text "reset" (rect 53 107 136 224)(font "Arial" (color 0 0 0))) 81 | (text "outclk0" (rect 113 43 268 99)(font "Arial" (color 128 0 0)(font_size 9))) 82 | (text "clk" (rect 97 67 212 144)(font "Arial" (color 0 0 0))) 83 | (text "outclk1" (rect 113 83 268 179)(font "Arial" (color 128 0 0)(font_size 9))) 84 | (text "clk" (rect 97 107 212 224)(font "Arial" (color 0 0 0))) 85 | (text "outclk2" (rect 113 123 268 259)(font "Arial" (color 128 0 0)(font_size 9))) 86 | (text "clk" (rect 97 147 212 304)(font "Arial" (color 0 0 0))) 87 | (text "outclk3" (rect 113 163 268 339)(font "Arial" (color 128 0 0)(font_size 9))) 88 | (text "clk" (rect 97 187 212 384)(font "Arial" (color 0 0 0))) 89 | (text "locked" (rect 113 203 262 419)(font "Arial" (color 128 0 0)(font_size 9))) 90 | (text "export" (rect 82 227 200 464)(font "Arial" (color 0 0 0))) 91 | (text " altera_pll " (rect 118 248 308 506)(font "Arial" )) 92 | (line (pt 48 32)(pt 112 32)(line_width 1)) 93 | (line (pt 112 32)(pt 112 248)(line_width 1)) 94 | (line (pt 48 248)(pt 112 248)(line_width 1)) 95 | (line (pt 48 32)(pt 48 248)(line_width 1)) 96 | (line (pt 49 52)(pt 49 76)(line_width 1)) 97 | (line (pt 50 52)(pt 50 76)(line_width 1)) 98 | (line (pt 49 92)(pt 49 116)(line_width 1)) 99 | (line (pt 50 92)(pt 50 116)(line_width 1)) 100 | (line (pt 111 52)(pt 111 76)(line_width 1)) 101 | (line (pt 110 52)(pt 110 76)(line_width 1)) 102 | (line (pt 111 92)(pt 111 116)(line_width 1)) 103 | (line (pt 110 92)(pt 110 116)(line_width 1)) 104 | (line (pt 111 132)(pt 111 156)(line_width 1)) 105 | (line (pt 110 132)(pt 110 156)(line_width 1)) 106 | (line (pt 111 172)(pt 111 196)(line_width 1)) 107 | (line (pt 110 172)(pt 110 196)(line_width 1)) 108 | (line (pt 111 212)(pt 111 236)(line_width 1)) 109 | (line (pt 110 212)(pt 110 236)(line_width 1)) 110 | (line (pt 0 0)(pt 160 0)(line_width 1)) 111 | (line (pt 160 0)(pt 160 264)(line_width 1)) 112 | (line (pt 0 264)(pt 160 264)(line_width 1)) 113 | (line (pt 0 0)(pt 0 264)(line_width 1)) 114 | ) 115 | ) 116 | -------------------------------------------------------------------------------- /src/fpga/core/rtl/dpram.vhd: -------------------------------------------------------------------------------- 1 | LIBRARY ieee; 2 | USE ieee.std_logic_1164.all; 3 | 4 | LIBRARY altera_mf; 5 | USE altera_mf.altera_mf_components.all; 6 | 7 | ENTITY dpram IS 8 | generic ( 9 | addr_width : integer := 8; 10 | data_width : integer := 8 11 | ); 12 | PORT 13 | ( 14 | clock_a : IN STD_LOGIC; 15 | clken_a : IN STD_LOGIC := '1'; 16 | address_a : IN STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0); 17 | data_a : IN STD_LOGIC_VECTOR (data_width-1 DOWNTO 0); 18 | wren_a : IN STD_LOGIC := '0'; 19 | q_a : OUT STD_LOGIC_VECTOR (data_width-1 DOWNTO 0); 20 | 21 | clock_b : IN STD_LOGIC; 22 | clken_b : IN STD_LOGIC := '1'; 23 | address_b : IN STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0); 24 | data_b : IN STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0'); 25 | wren_b : IN STD_LOGIC := '0'; 26 | q_b : OUT STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) 27 | ); 28 | END dpram; 29 | 30 | 31 | ARCHITECTURE SYN OF dpram IS 32 | BEGIN 33 | altsyncram_component : altsyncram 34 | GENERIC MAP ( 35 | address_reg_b => "CLOCK1", 36 | clock_enable_input_a => "NORMAL", 37 | clock_enable_input_b => "NORMAL", 38 | clock_enable_output_a => "BYPASS", 39 | clock_enable_output_b => "BYPASS", 40 | indata_reg_b => "CLOCK1", 41 | intended_device_family => "Cyclone V", 42 | lpm_type => "altsyncram", 43 | numwords_a => 2**addr_width, 44 | numwords_b => 2**addr_width, 45 | operation_mode => "BIDIR_DUAL_PORT", 46 | outdata_aclr_a => "NONE", 47 | outdata_aclr_b => "NONE", 48 | outdata_reg_a => "UNREGISTERED", 49 | outdata_reg_b => "UNREGISTERED", 50 | power_up_uninitialized => "FALSE", 51 | read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", 52 | read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ", 53 | widthad_a => addr_width, 54 | widthad_b => addr_width, 55 | width_a => data_width, 56 | width_b => data_width, 57 | width_byteena_a => 1, 58 | width_byteena_b => 1, 59 | wrcontrol_wraddress_reg_b => "CLOCK1" 60 | ) 61 | PORT MAP ( 62 | address_a => address_a, 63 | address_b => address_b, 64 | clock0 => clock_a, 65 | clock1 => clock_b, 66 | clocken0 => clken_a, 67 | clocken1 => clken_b, 68 | data_a => data_a, 69 | data_b => data_b, 70 | wren_a => wren_a, 71 | wren_b => wren_b, 72 | q_a => q_a, 73 | q_b => q_b 74 | ); 75 | 76 | END SYN; 77 | 78 | 79 | -------------------------------------------------------------- 80 | -- Dual port Block RAM different parameters on ports 81 | -------------------------------------------------------------- 82 | LIBRARY ieee; 83 | USE ieee.std_logic_1164.all; 84 | 85 | LIBRARY altera_mf; 86 | USE altera_mf.altera_mf_components.all; 87 | 88 | entity dpram_dif is 89 | generic ( 90 | addr_width_a : integer := 8; 91 | data_width_a : integer := 8; 92 | addr_width_b : integer := 8; 93 | data_width_b : integer := 8; 94 | mem_init_file : string := " " 95 | ); 96 | PORT 97 | ( 98 | clock : in STD_LOGIC; 99 | 100 | address_a : in STD_LOGIC_VECTOR (addr_width_a-1 DOWNTO 0); 101 | data_a : in STD_LOGIC_VECTOR (data_width_a-1 DOWNTO 0) := (others => '0'); 102 | enable_a : in STD_LOGIC := '1'; 103 | wren_a : in STD_LOGIC := '0'; 104 | q_a : out STD_LOGIC_VECTOR (data_width_a-1 DOWNTO 0); 105 | cs_a : in std_logic := '1'; 106 | 107 | address_b : in STD_LOGIC_VECTOR (addr_width_b-1 DOWNTO 0) := (others => '0'); 108 | data_b : in STD_LOGIC_VECTOR (data_width_b-1 DOWNTO 0) := (others => '0'); 109 | enable_b : in STD_LOGIC := '1'; 110 | wren_b : in STD_LOGIC := '0'; 111 | q_b : out STD_LOGIC_VECTOR (data_width_b-1 DOWNTO 0); 112 | cs_b : in std_logic := '1' 113 | ); 114 | end entity; 115 | 116 | 117 | ARCHITECTURE SYN OF dpram_dif IS 118 | 119 | signal q0 : std_logic_vector((data_width_a - 1) downto 0); 120 | signal q1 : std_logic_vector((data_width_b - 1) downto 0); 121 | 122 | signal wren_a_comb : std_logic; 123 | signal wren_b_comb : std_logic; 124 | 125 | BEGIN 126 | q_a<= q0 when cs_a = '1' else (others => '1'); 127 | q_b<= q1 when cs_b = '1' else (others => '1'); 128 | 129 | wren_a_comb <= wren_a and cs_a; 130 | wren_b_comb <= wren_b and cs_b; 131 | 132 | altsyncram_component : altsyncram 133 | GENERIC MAP ( 134 | address_reg_b => "CLOCK1", 135 | clock_enable_input_a => "NORMAL", 136 | clock_enable_input_b => "NORMAL", 137 | clock_enable_output_a => "BYPASS", 138 | clock_enable_output_b => "BYPASS", 139 | indata_reg_b => "CLOCK1", 140 | intended_device_family => "Cyclone V", 141 | lpm_type => "altsyncram", 142 | numwords_a => 2**addr_width_a, 143 | numwords_b => 2**addr_width_b, 144 | operation_mode => "BIDIR_DUAL_PORT", 145 | outdata_aclr_a => "NONE", 146 | outdata_aclr_b => "NONE", 147 | outdata_reg_a => "UNREGISTERED", 148 | outdata_reg_b => "UNREGISTERED", 149 | power_up_uninitialized => "FALSE", 150 | read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", 151 | read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ", 152 | init_file => mem_init_file, 153 | widthad_a => addr_width_a, 154 | widthad_b => addr_width_b, 155 | width_a => data_width_a, 156 | width_b => data_width_b, 157 | width_byteena_a => 1, 158 | width_byteena_b => 1, 159 | wrcontrol_wraddress_reg_b => "CLOCK1" 160 | ) 161 | PORT MAP ( 162 | address_a => address_a, 163 | address_b => address_b, 164 | clock0 => clock, 165 | clock1 => clock, 166 | clocken0 => enable_a, 167 | clocken1 => enable_b, 168 | data_a => data_a, 169 | data_b => data_b, 170 | wren_a => wren_a_comb, 171 | wren_b => wren_b_comb, 172 | q_a => q0, 173 | q_b => q1 174 | ); 175 | 176 | END SYN; 177 | -------------------------------------------------------------------------------- /src/fpga/core/rtl/sound_module2.vhd: -------------------------------------------------------------------------------- 1 | library IEEE; 2 | use IEEE.std_logic_1164.all; 3 | use IEEE.numeric_std.all; 4 | 5 | use work.pRegisterBus.all; 6 | use work.pReg_swan.all; 7 | 8 | entity sound_module2 is 9 | port 10 | ( 11 | clk : in std_logic; 12 | ce : in std_logic; 13 | reset : in std_logic; 14 | 15 | useVoice : in std_logic; 16 | 17 | soundDMAvalue : in std_logic_vector(7 downto 0); 18 | soundDMAvalid : in std_logic; 19 | 20 | SSBus_rst : in std_logic; 21 | 22 | RegBus_Din : in std_logic_vector(BUS_buswidth-1 downto 0); 23 | RegBus_Adr : in std_logic_vector(BUS_busadr-1 downto 0); 24 | RegBus_wren : in std_logic; 25 | RegBus_rst : in std_logic; 26 | RegBus_Dout : out std_logic_vector(BUS_buswidth-1 downto 0); 27 | 28 | sampleRequest : out std_logic := '0'; 29 | sampleposReq : out unsigned(4 downto 0) := (others => '0'); 30 | channelData : in unsigned(3 downto 0); 31 | channelValid : in std_logic; 32 | 33 | soundoutL : out signed(8 downto 0) := (others => '0'); 34 | soundoutR : out signed(8 downto 0) := (others => '0') 35 | ); 36 | end entity; 37 | 38 | architecture arch of sound_module2 is 39 | 40 | -- register 41 | signal SND_CH_PITCH : std_logic_vector(10 downto 0); 42 | signal SND_CH_Vol : std_logic_vector( 7 downto 0); 43 | signal SND_VOICE_CTRL : std_logic_vector( 3 downto 0); 44 | 45 | signal SND_CH_Vol_written : std_logic; 46 | 47 | type t_reg_wired_or is array(0 to 3) of std_logic_vector(7 downto 0); 48 | signal reg_wired_or : t_reg_wired_or; 49 | 50 | -- internal 51 | signal pitchCount : unsigned(10 downto 0); 52 | signal nextData : unsigned(3 downto 0); 53 | 54 | begin 55 | 56 | iREG_SND_CH_PITCH_L : entity work.eReg generic map ( REG_SND_CH2_PITCH_L ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(0), SND_CH_PITCH( 7 downto 0), SND_CH_PITCH( 7 downto 0)); 57 | iREG_SND_CH_PITCH_H : entity work.eReg generic map ( REG_SND_CH2_PITCH_H ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(1), SND_CH_PITCH(10 downto 8), SND_CH_PITCH(10 downto 8)); 58 | iREG_SND_CH_Vol : entity work.eReg generic map ( REG_SND_CH2_Vol ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(2), SND_CH_Vol , open , SND_CH_Vol_written); 59 | iREG_SND_VOICE_CTRL : entity work.eReg generic map ( REG_SND_VOICE_CTRL ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(3), SND_VOICE_CTRL , SND_VOICE_CTRL ); 60 | 61 | process (reg_wired_or) 62 | variable wired_or : std_logic_vector(7 downto 0); 63 | begin 64 | wired_or := reg_wired_or(0); 65 | for i in 1 to (reg_wired_or'length - 1) loop 66 | wired_or := wired_or or reg_wired_or(i); 67 | end loop; 68 | RegBus_Dout <= wired_or; 69 | end process; 70 | 71 | process (clk) 72 | variable newPitchCount : unsigned(10 downto 0); 73 | begin 74 | if rising_edge(clk) then 75 | 76 | if (reset = '1') then 77 | 78 | sampleposReq <= (others => '0'); 79 | soundoutL <= (others => '0'); 80 | soundoutR <= (others => '0'); 81 | sampleRequest <= '1'; 82 | 83 | pitchCount <= (others => '0'); 84 | nextData <= (others => '0'); 85 | 86 | elsif (ce = '1') then 87 | 88 | if (useVoice = '1') then 89 | 90 | soundoutL <= (others => '0'); 91 | if (SND_VOICE_CTRL(2) = '1') then soundoutL(7 downto 0) <= signed(SND_CH_Vol); 92 | elsif (SND_VOICE_CTRL(3) = '1') then soundoutL(6 downto 0) <= signed(SND_CH_Vol(7 downto 1)); 93 | end if; 94 | 95 | soundoutR <= (others => '0'); 96 | if (SND_VOICE_CTRL(0) = '1') then soundoutR(7 downto 0) <= signed(SND_CH_Vol); 97 | elsif (SND_VOICE_CTRL(1) = '1') then soundoutR(6 downto 0) <= signed(SND_CH_Vol(7 downto 1)); 98 | end if; 99 | 100 | else 101 | 102 | newPitchCount := pitchCount - 1; 103 | pitchCount <= newPitchCount; 104 | if (newPitchCount = unsigned(SND_CH_PITCH)) then 105 | sampleRequest <= '1'; 106 | pitchCount <= (others => '0'); 107 | sampleposReq <= sampleposReq + 1; 108 | soundoutL <= signed('0' & (nextData * unsigned(SND_CH_Vol(7 downto 4)))); 109 | soundoutR <= signed('0' & (nextData * unsigned(SND_CH_Vol(3 downto 0)))); 110 | end if; 111 | 112 | if (channelValid = '1') then 113 | sampleRequest <= '0'; 114 | nextData <= channelData; 115 | end if; 116 | 117 | end if; 118 | 119 | end if; 120 | 121 | if (SSBus_rst = '1') then 122 | SND_CH_Vol <= (others => '0'); 123 | else 124 | if (SND_CH_Vol_written = '1') then SND_CH_Vol <= RegBus_Din; end if; 125 | if (soundDMAvalid = '1') then SND_CH_Vol <= soundDMAvalue; end if; 126 | end if; 127 | 128 | end if; 129 | end process; 130 | 131 | 132 | end architecture; 133 | 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /src/fpga/apf/mf_ddio_bidir_12.v: -------------------------------------------------------------------------------- 1 | // megafunction wizard: %ALTDDIO_BIDIR% 2 | // GENERATION: STANDARD 3 | // VERSION: WM1.0 4 | // MODULE: ALTDDIO_BIDIR 5 | 6 | // ============================================================ 7 | // File Name: mf_ddio_bidir_12.v 8 | // Megafunction Name(s): 9 | // ALTDDIO_BIDIR 10 | // 11 | // Simulation Library Files(s): 12 | // 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 | -------------------------------------------------------------------------------- /src/fpga/apf/common.v: -------------------------------------------------------------------------------- 1 | // Software License Agreement 2 | 3 | // The software supplied herewith by Analogue Enterprises Limited (the "Company”), 4 | // the Analogue Pocket Framework (“APF”), is provided and licensed to you, the 5 | // Company's customer, solely for use in designing, testing and creating 6 | // applications for use with Company's Products or Services. The software is 7 | // owned by the Company and/or its licensors, and is protected under applicable 8 | // laws, including, but not limited to, U.S. copyright law. All rights are 9 | // reserved. By using the APF code you are agreeing to the terms of the End User 10 | // License Agreement (“EULA”) located at [https://www.analogue.link/pocket-eula] 11 | // and incorporated herein by reference. To the extent any use of the APF requires 12 | // application of the MIT License or the GNU General Public License and terms of 13 | // this APF Software License Agreement and EULA are inconsistent with such license, 14 | // the applicable terms of the MIT License or the GNU General Public License, as 15 | // applicable, will prevail. 16 | 17 | // THE SOFTWARE IS PROVIDED "AS-IS" AND WE EXPRESSLY DISCLAIM ANY IMPLIED 18 | // WARRANTIES TO THE FULLEST EXTENT PROVIDED BY LAW, INCLUDING BUT NOT LIMITED TO, 19 | // ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR 20 | // NON-INFRINGEMENT. TO THE EXTENT APPLICABLE LAWS PROHIBIT TERMS OF USE FROM 21 | // DISCLAIMING ANY IMPLIED WARRANTY, SUCH IMPLIED WARRANTY SHALL BE LIMITED TO THE 22 | // MINIMUM WARRANTY PERIOD REQUIRED BY LAW, AND IF NO SUCH PERIOD IS REQUIRED, 23 | // THEN THIRTY (30) DAYS FROM FIRST USE OF THE SOFTWARE. WE CANNOT GUARANTEE AND 24 | // DO NOT PROMISE ANY SPECIFIC RESULTS FROM USE OF THE SOFTWARE. WITHOUT LIMITING 25 | // THE FOREGOING, WE DO NOT WARRANT THAT THE SOFTWARE WILL BE UNINTERRUPTED OR 26 | // ERROR-FREE. IN NO EVENT WILL WE BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY 27 | // INDIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, SPECIAL OR PUNITIVE DAMAGES, 28 | // INCLUDING BUT NOT LIMITED TO, LOST PROFITS ARISING OUT OF YOUR USE, OR 29 | // INABILITY TO USE, THE SOFTWARE, EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY 30 | // OF SUCH DAMAGES. UNDER NO CIRCUMSTANCES SHALL OUR LIABILITY TO YOU FOR ANY 31 | // CLAIM OR CAUSE OF ACTION WHATSOEVER, AND REGARDLESS OF THE FORM OF THE ACTION, 32 | // WHETHER ARISING IN CONTRACT, TORT OR OTHERWISE, EXCEED THE AMOUNT PAID BY YOU 33 | // TO US, IF ANY, DURING THE 90 DAY PERIOD IMMEDIATELY PRECEDING THE DATE ON WHICH 34 | // YOU FIRST ASSERT ANY SUCH CLAIM. THE FOREGOING LIMITATIONS SHALL APPLY TO THE 35 | // FULLEST EXTENT PERMITTED BY APPLICABLE LAW. 36 | // 37 | // 2-stage synchronizer 38 | // 39 | module synch_2 #(parameter WIDTH = 1) ( 40 | input wire [WIDTH-1:0] i, // input signal 41 | output reg [WIDTH-1:0] o, // synchronized output 42 | input wire clk, // clock to synchronize on 43 | output wire rise, // one-cycle rising edge pulse 44 | output wire fall // one-cycle falling edge pulse 45 | ); 46 | 47 | reg [WIDTH-1:0] stage_1; 48 | reg [WIDTH-1:0] stage_2; 49 | reg [WIDTH-1:0] stage_3; 50 | 51 | assign rise = (WIDTH == 1) ? (o & ~stage_2) : 1'b0; 52 | assign fall = (WIDTH == 1) ? (~o & stage_2) : 1'b0; 53 | always @(posedge clk) 54 | {stage_2, o, stage_1} <= {o, stage_1, i}; 55 | 56 | endmodule 57 | 58 | 59 | // 60 | // 3-stage synchronizer 61 | // 62 | module synch_3 #(parameter WIDTH = 1) ( 63 | input wire [WIDTH-1:0] i, // input signal 64 | output reg [WIDTH-1:0] o, // synchronized output 65 | input wire clk, // clock to synchronize on 66 | output wire rise, // one-cycle rising edge pulse 67 | output wire fall // one-cycle falling edge pulse 68 | ); 69 | 70 | reg [WIDTH-1:0] stage_1; 71 | reg [WIDTH-1:0] stage_2; 72 | reg [WIDTH-1:0] stage_3; 73 | 74 | assign rise = (WIDTH == 1) ? (o & ~stage_3) : 1'b0; 75 | assign fall = (WIDTH == 1) ? (~o & stage_3) : 1'b0; 76 | always @(posedge clk) 77 | {stage_3, o, stage_2, stage_1} <= {o, stage_2, stage_1, i}; 78 | 79 | endmodule 80 | 81 | 82 | module bram_block_dp #( 83 | parameter DATA = 32, 84 | parameter ADDR = 7 85 | ) ( 86 | input wire a_clk, 87 | input wire a_wr, 88 | input wire [ADDR-1:0] a_addr, 89 | input wire [DATA-1:0] a_din, 90 | output reg [DATA-1:0] a_dout, 91 | 92 | input wire b_clk, 93 | input wire b_wr, 94 | input wire [ADDR-1:0] b_addr, 95 | input wire [DATA-1:0] b_din, 96 | output reg [DATA-1:0] b_dout 97 | ); 98 | 99 | reg [DATA-1:0] mem [(2**ADDR)-1:0]; 100 | 101 | always @(posedge a_clk) begin 102 | if(a_wr) begin 103 | a_dout <= a_din; 104 | mem[a_addr] <= a_din; 105 | end else 106 | a_dout <= mem[a_addr]; 107 | end 108 | 109 | always @(posedge b_clk) begin 110 | if(b_wr) begin 111 | b_dout <= b_din; 112 | mem[b_addr] <= b_din; 113 | end else 114 | b_dout <= mem[b_addr]; 115 | end 116 | 117 | endmodule 118 | 119 | 120 | module bram_block_dp_nonstd #( 121 | parameter DATA = 32, 122 | parameter ADDR = 7, 123 | parameter DEPTH = 128 124 | ) ( 125 | input wire a_clk, 126 | input wire a_wr, 127 | input wire [ADDR-1:0] a_addr, 128 | input wire [DATA-1:0] a_din, 129 | output reg [DATA-1:0] a_dout, 130 | 131 | input wire b_clk, 132 | input wire b_wr, 133 | input wire [ADDR-1:0] b_addr, 134 | input wire [DATA-1:0] b_din, 135 | output reg [DATA-1:0] b_dout 136 | ); 137 | 138 | reg [DATA-1:0] mem [DEPTH-1:0]; 139 | 140 | always @(posedge a_clk) begin 141 | if(a_wr) begin 142 | a_dout <= a_din; 143 | mem[a_addr] <= a_din; 144 | end else 145 | a_dout <= mem[a_addr]; 146 | end 147 | 148 | always @(posedge b_clk) begin 149 | if(b_wr) begin 150 | b_dout <= b_din; 151 | mem[b_addr] <= b_din; 152 | end else 153 | b_dout <= mem[b_addr]; 154 | end 155 | 156 | endmodule 157 | -------------------------------------------------------------------------------- /src/fpga/core/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 = 15, 28 | parameter SIGNED_INPUT = 0 29 | ) ( 30 | input wire clk_74a, 31 | input wire clk_audio, 32 | 33 | // Left and right audio channels. Can be in an arbitrary clock domain 34 | input wire [CHANNEL_WIDTH - 1:0] audio_l, 35 | input wire [CHANNEL_WIDTH - 1:0] audio_r, 36 | 37 | output reg audio_mclk, 38 | output reg audio_lrck, 39 | output reg audio_dac 40 | ); 41 | // 42 | // audio i2s generator 43 | // 44 | 45 | reg audgen_nextsamp; 46 | 47 | // generate MCLK = 12.288mhz with fractional accumulator 48 | reg [21:0] audgen_accum = 0; 49 | localparam [20:0] CYCLE_48KHZ = 21'd122880 * 2; 50 | always @(posedge clk_74a) begin 51 | audgen_accum <= audgen_accum + CYCLE_48KHZ; 52 | if (audgen_accum >= 21'd742500) begin 53 | audio_mclk <= ~audio_mclk; 54 | audgen_accum <= audgen_accum - 21'd742500 + CYCLE_48KHZ; 55 | end 56 | end 57 | 58 | // generate SCLK = 3.072mhz by dividing MCLK by 4 59 | reg [1:0] aud_mclk_divider; 60 | reg prev_audio_mclk; 61 | wire audgen_sclk = aud_mclk_divider[1] /* synthesis keep*/; 62 | 63 | always @(posedge clk_74a) begin 64 | if (audio_mclk && ~prev_audio_mclk) begin 65 | aud_mclk_divider <= aud_mclk_divider + 1'b1; 66 | end 67 | 68 | prev_audio_mclk <= audio_mclk; 69 | end 70 | 71 | // shift out audio data as I2S 72 | // 32 total bits per channel, but only 16 active bits at the start and then 16 dummy bits 73 | // 74 | // synchronize audio samples coming from the core 75 | 76 | localparam CHANNEL_LEFT_HIGH = SIGNED_INPUT ? 16 : 15; 77 | localparam CHANNEL_RIGHT_HIGH = 16 + CHANNEL_LEFT_HIGH; 78 | 79 | // Width of channel with signed component 80 | localparam SIGNED_CHANNEL_WIDTH = SIGNED_INPUT ? CHANNEL_WIDTH : CHANNEL_WIDTH + 1; 81 | 82 | wire [31:0] audgen_sampdata; 83 | 84 | assign audgen_sampdata[CHANNEL_LEFT_HIGH-1:CHANNEL_LEFT_HIGH-CHANNEL_WIDTH] = audio_l; 85 | assign audgen_sampdata[CHANNEL_RIGHT_HIGH-1:CHANNEL_RIGHT_HIGH-CHANNEL_WIDTH] = audio_r; 86 | 87 | generate 88 | if (!SIGNED_INPUT) begin 89 | // If not signed, make sure high bit is 0 90 | assign audgen_sampdata[31] = 0; 91 | assign audgen_sampdata[15] = 0; 92 | end 93 | endgenerate 94 | 95 | generate 96 | if (15 - SIGNED_CHANNEL_WIDTH > 0) begin 97 | assign audgen_sampdata[31-SIGNED_CHANNEL_WIDTH:16] = 0; 98 | assign audgen_sampdata[15-SIGNED_CHANNEL_WIDTH:0] = 0; 99 | end 100 | endgenerate 101 | 102 | sync_fifo #( 103 | .WIDTH(32) 104 | ) sync_fifo ( 105 | .clk_write(clk_audio), 106 | .clk_read (clk_74a), 107 | 108 | .write_en(write_en), 109 | .data(audgen_sampdata), 110 | .data_s(audgen_sampdata_s) 111 | ); 112 | 113 | reg write_en = 0; 114 | reg [CHANNEL_WIDTH - 1:0] prev_left; 115 | reg [CHANNEL_WIDTH - 1:0] prev_right; 116 | 117 | // Mark write when necessary 118 | always @(posedge clk_audio) begin 119 | prev_left <= audio_l; 120 | prev_right <= audio_r; 121 | 122 | write_en <= 0; 123 | 124 | if (audio_l != prev_left || audio_r != prev_right) begin 125 | write_en <= 1; 126 | end 127 | end 128 | 129 | wire [31:0] audgen_sampdata_s; 130 | 131 | reg [31:0] audgen_sampshift; 132 | reg [4:0] audio_lrck_cnt; 133 | reg prev_audgen_sclk; 134 | always @(posedge clk_74a) begin 135 | if (prev_audgen_sclk && ~audgen_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_s; 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 | prev_audgen_sclk <= audgen_sclk; 156 | end 157 | 158 | initial begin 159 | // Verify parameters 160 | if (CHANNEL_WIDTH > 16) begin 161 | $error("CHANNEL_WIDTH must be <= 16. Received %d", CHANNEL_WIDTH); 162 | end 163 | 164 | if (SIGNED_INPUT != 0 && SIGNED_INPUT != 1) begin 165 | $error("SIGNED_INPUT must be 0 or 1. Received %d", SIGNED_INPUT); 166 | end 167 | 168 | if (CHANNEL_WIDTH == 16 && SIGNED_INPUT == 0) begin 169 | $error("Cannot have CHANNEL_WIDTH of 16 and an unsigned input"); 170 | end 171 | end 172 | endmodule 173 | -------------------------------------------------------------------------------- /src/fpga/core/rtl/IRQ.vhd: -------------------------------------------------------------------------------- 1 | library IEEE; 2 | use IEEE.std_logic_1164.all; 3 | use IEEE.numeric_std.all; 4 | 5 | use work.pRegisterBus.all; 6 | use work.pBus_savestates.all; 7 | use work.pReg_savestates.all; 8 | use work.pReg_swan.all; 9 | 10 | entity IRQ is 11 | port 12 | ( 13 | clk : in std_logic; 14 | ce : in std_logic; 15 | reset : in std_logic; 16 | isColor : in std_logic; 17 | 18 | irqrequest : out std_logic; 19 | irqvector : out unsigned(9 downto 0) := (others => '0'); 20 | 21 | IRQ_LineComp : in std_logic; 22 | IRQ_VBlankTmr : in std_logic; 23 | IRQ_VBlank : in std_logic; 24 | IRQ_HBlankTmr : in std_logic; 25 | 26 | RegBus_Din : in std_logic_vector(BUS_buswidth-1 downto 0); 27 | RegBus_Adr : in std_logic_vector(BUS_busadr-1 downto 0); 28 | RegBus_wren : in std_logic; 29 | RegBus_rst : in std_logic; 30 | RegBus_Dout : out std_logic_vector(BUS_buswidth-1 downto 0); 31 | 32 | -- debug 33 | export_irq : out std_logic_vector(7 downto 0); 34 | 35 | -- savestates 36 | SSBus_Din : in std_logic_vector(SSBUS_buswidth-1 downto 0); 37 | SSBus_Adr : in std_logic_vector(SSBUS_busadr-1 downto 0); 38 | SSBus_wren : in std_logic; 39 | SSBus_rst : in std_logic; 40 | SSBus_Dout : out std_logic_vector(SSBUS_buswidth-1 downto 0) 41 | ); 42 | end entity; 43 | 44 | architecture arch of IRQ is 45 | 46 | -- register 47 | signal INT_BASE : std_logic_vector(REG_INT_BASE .upper downto REG_INT_BASE .lower); 48 | signal INT_BASE_back : std_logic_vector(REG_INT_BASE .upper downto REG_INT_BASE .lower); 49 | signal INT_ENABLE : std_logic_vector(REG_INT_ENABLE.upper downto REG_INT_ENABLE.lower); 50 | signal INT_STATUS : std_logic_vector(REG_INT_STATUS.upper downto REG_INT_STATUS.lower); 51 | 52 | signal INT_ENABLE_written : std_logic; 53 | signal INT_ACK_written : std_logic; 54 | 55 | type t_reg_wired_or is array(0 to 3) of std_logic_vector(7 downto 0); 56 | signal reg_wired_or : t_reg_wired_or; 57 | 58 | -- savestates 59 | signal SS_IRQ : std_logic_vector(REG_SAVESTATE_IRQ.upper downto REG_SAVESTATE_IRQ.lower); 60 | signal SS_IRQ_BACK : std_logic_vector(REG_SAVESTATE_IRQ.upper downto REG_SAVESTATE_IRQ.lower); 61 | 62 | begin 63 | 64 | iREG_INT_BASE : entity work.eReg generic map ( REG_INT_BASE ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(0), INT_BASE_back, INT_BASE ); 65 | iREG_INT_ENABLE : entity work.eReg generic map ( REG_INT_ENABLE ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(1), INT_ENABLE , INT_ENABLE, INT_ENABLE_written); 66 | iREG_INT_STATUS : entity work.eReg generic map ( REG_INT_STATUS ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(2), INT_STATUS ); 67 | iREG_INT_ACK : entity work.eReg generic map ( REG_INT_ACK ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(3), x"00" , open , INT_ACK_written); 68 | 69 | INT_BASE_back <= (INT_BASE and x"FE") when isColor = '1' else (INT_BASE and x"F8"); 70 | 71 | process (reg_wired_or) 72 | variable wired_or : std_logic_vector(7 downto 0); 73 | begin 74 | wired_or := reg_wired_or(0); 75 | for i in 1 to (reg_wired_or'length - 1) loop 76 | wired_or := wired_or or reg_wired_or(i); 77 | end loop; 78 | RegBus_Dout <= wired_or; 79 | end process; 80 | 81 | iSS_IRQ : entity work.eReg_SS generic map ( REG_SAVESTATE_IRQ ) port map (clk, SSBUS_Din, SSBUS_Adr, SSBUS_wren, SSBUS_rst, SSBUS_Dout, SS_IRQ_BACK, SS_IRQ); 82 | 83 | irqrequest <= '1' when (INT_STATUS and INT_ENABLE) /= x"00" else '0'; 84 | 85 | export_irq <= INT_STATUS; 86 | 87 | 88 | SS_IRQ_BACK(7 downto 0) <= INT_STATUS; 89 | 90 | process (clk) 91 | begin 92 | if rising_edge(clk) then 93 | if (reset = '1') then 94 | INT_STATUS <= SS_IRQ(7 downto 0); 95 | elsif (ce = '1') then 96 | 97 | -- set 98 | if (IRQ_LineComp = '1' and INT_ENABLE(4) = '1') then INT_STATUS(4) <= '1'; end if; 99 | if (IRQ_VBlankTmr = '1' and INT_ENABLE(5) = '1') then INT_STATUS(5) <= '1'; end if; 100 | if (IRQ_VBlank = '1' and INT_ENABLE(6) = '1') then INT_STATUS(6) <= '1'; end if; 101 | if (IRQ_HBlankTmr = '1' and INT_ENABLE(7) = '1') then INT_STATUS(7) <= '1'; end if; 102 | 103 | -- enable masking 104 | if (INT_ENABLE_written = '1') then 105 | for i in 0 to 7 loop 106 | if (RegBus_Din(i) = '1') then 107 | INT_STATUS(i) <= '0'; 108 | end if; 109 | end loop; 110 | end if; 111 | 112 | -- clear 113 | if (INT_ACK_written = '1') then 114 | if (RegBus_Din(1) = '1') then INT_STATUS(1) <= '0'; end if; 115 | if (RegBus_Din(4) = '1') then INT_STATUS(4) <= '0'; end if; 116 | if (RegBus_Din(5) = '1') then INT_STATUS(5) <= '0'; end if; 117 | if (RegBus_Din(6) = '1') then INT_STATUS(6) <= '0'; end if; 118 | if (RegBus_Din(7) = '1') then INT_STATUS(7) <= '0'; end if; 119 | end if; 120 | 121 | -- pick highest priority 122 | for i in 0 to 7 loop 123 | if (INT_STATUS(i) = '1' and INT_ENABLE(i) = '1') then 124 | irqvector <= to_unsigned(((to_integer(unsigned(INT_BASE_back)) + i) * 4), 10); 125 | end if; 126 | end loop; 127 | 128 | end if; 129 | end if; 130 | end process; 131 | 132 | 133 | 134 | end architecture; 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /src/fpga/core/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; -- count: 1048576 -- 1024 Kbyte Data for Savestate 9 | Softmap_Rewind_ADDR : integer -- count: 1048576*32 -- 32*1024 Kbyte Data for Savestates 10 | ); 11 | port 12 | ( 13 | clk : in std_logic; 14 | ce : in std_logic; 15 | reset : in std_logic; 16 | 17 | rewind_on : in std_logic; 18 | rewind_active : in std_logic; 19 | 20 | savestate_number : in integer; 21 | save : in std_logic; 22 | load : in std_logic; 23 | 24 | sleep_rewind : out std_logic := '0'; 25 | vsync : in std_logic; 26 | system_idle : in std_logic; 27 | 28 | request_savestate : out std_logic := '0'; 29 | request_loadstate : out std_logic := '0'; 30 | request_address : out integer; 31 | request_busy : in std_logic 32 | ); 33 | end entity; 34 | 35 | architecture arch of statemanager is 36 | 37 | constant SAVESTATESIZE : integer := 16#40000#; -- 262144 Dwords = 1024 kbyte 38 | constant REWIND_COUNT : integer := 32; 39 | constant TIME_CAPTURE : integer := 20000000; 40 | constant TIME_REWIND : integer := 10000000; 41 | --constant TIME_CAPTURE : integer := 250000; -- sim 42 | --constant TIME_REWIND : integer := 500000; -- sim 43 | 44 | signal save_1 : std_logic := '0'; 45 | signal load_1 : std_logic := '0'; 46 | signal save_buffer : std_logic := '0'; 47 | signal load_buffer : std_logic := '0'; 48 | 49 | signal rewind_enabled : std_logic := '0'; 50 | signal rewind_load_next : std_logic := '0'; 51 | 52 | signal timer_rewind : integer range 0 to TIME_CAPTURE := 0; 53 | signal rewind_slow : integer range 0 to TIME_REWIND := 0; 54 | signal savestatecount : integer range 0 to REWIND_COUNT := 0; 55 | signal savestatepos : integer range 0 to REWIND_COUNT - 1 := 0; 56 | 57 | signal vsync_counter : integer range 0 to 2 := 0; 58 | 59 | signal vsync_1 : std_logic; 60 | 61 | begin 62 | 63 | process (clk) 64 | begin 65 | if rising_edge(clk) then 66 | 67 | request_savestate <= '0'; 68 | request_loadstate <= '0'; 69 | rewind_load_next <= '0'; 70 | 71 | vsync_1 <= vsync; 72 | 73 | save_1 <= save; 74 | if (save = '1' and save_1 = '0') then 75 | save_buffer <= '1'; 76 | end if; 77 | 78 | load_1 <= load; 79 | if (load = '1' and load_1 = '0') then 80 | load_buffer <= '1'; 81 | end if; 82 | 83 | if (rewind_on = '0' or reset = '1') then 84 | rewind_enabled <= '0'; 85 | end if; 86 | 87 | if (rewind_active = '0') then 88 | rewind_slow <= 0; 89 | elsif (rewind_slow < TIME_REWIND) then 90 | rewind_slow <= rewind_slow + 1; 91 | end if; 92 | 93 | if (rewind_active = '1') then 94 | timer_rewind <= 0; 95 | elsif (timer_rewind < TIME_CAPTURE) then 96 | timer_rewind <= timer_rewind + 1; 97 | end if; 98 | 99 | if (vsync_counter < 2 and vsync = '1' and vsync_1 = '0') then 100 | vsync_counter <= vsync_counter + 1; 101 | end if; 102 | 103 | sleep_rewind <= '0'; 104 | if (vsync_counter = 2 and rewind_active = '1' and system_idle = '1' and ce = '0') then 105 | sleep_rewind <= '1'; 106 | end if; 107 | 108 | if (reset = '0' and request_busy = '0') then 109 | 110 | if (save_buffer = '1') then 111 | request_address <= Softmap_SaveState_ADDR + (savestate_number * SAVESTATESIZE); 112 | request_savestate <= '1'; 113 | save_buffer <= '0'; 114 | elsif (load_buffer = '1') then 115 | request_address <= Softmap_SaveState_ADDR + (savestate_number * SAVESTATESIZE); 116 | request_loadstate <= '1'; 117 | load_buffer <= '0'; 118 | elsif (rewind_enabled = '0' and rewind_on = '1') then 119 | request_address <= Softmap_Rewind_ADDR; 120 | request_savestate <= '1'; 121 | rewind_enabled <= '1'; 122 | timer_rewind <= 0; 123 | savestatecount <= 1; 124 | savestatepos <= 1; 125 | elsif (rewind_enabled = '1' and timer_rewind = TIME_CAPTURE) then 126 | request_address <= Softmap_Rewind_ADDR + (savestatepos * SAVESTATESIZE); 127 | request_savestate <= '1'; 128 | timer_rewind <= 0; 129 | if (savestatecount < REWIND_COUNT) then 130 | savestatecount <= savestatecount + 1; 131 | end if; 132 | if (savestatepos < (REWIND_COUNT - 1)) then 133 | savestatepos <= savestatepos + 1; 134 | else 135 | savestatepos <= 0; 136 | end if; 137 | elsif (rewind_enabled = '1' and rewind_slow = TIME_REWIND) then 138 | if (savestatecount > 1) then 139 | savestatecount <= savestatecount - 1; 140 | if (savestatepos > 0) then 141 | savestatepos <= savestatepos - 1; 142 | else 143 | savestatepos <= REWIND_COUNT - 1; 144 | end if; 145 | rewind_load_next <= '1'; 146 | end if; 147 | rewind_slow <= 0; 148 | elsif (rewind_load_next = '1') then 149 | request_address <= Softmap_Rewind_ADDR + (savestatepos * SAVESTATESIZE); 150 | request_loadstate <= '1'; 151 | vsync_counter <= 0; 152 | end if; 153 | 154 | end if; 155 | 156 | end if; 157 | end process; 158 | 159 | 160 | end architecture; 161 | 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /src/fpga/core/rtl/sound_module3.vhd: -------------------------------------------------------------------------------- 1 | library IEEE; 2 | use IEEE.std_logic_1164.all; 3 | use IEEE.numeric_std.all; 4 | 5 | use work.pRegisterBus.all; 6 | use work.pReg_swan.all; 7 | use work.pBus_savestates.all; 8 | use work.pReg_savestates.all; 9 | 10 | entity sound_module3 is 11 | port 12 | ( 13 | clk : in std_logic; 14 | ce : in std_logic; 15 | reset : in std_logic; 16 | 17 | useSweep : in std_logic; 18 | 19 | RegBus_Din : in std_logic_vector(BUS_buswidth-1 downto 0); 20 | RegBus_Adr : in std_logic_vector(BUS_busadr-1 downto 0); 21 | RegBus_wren : in std_logic; 22 | RegBus_rst : in std_logic; 23 | RegBus_Dout : out std_logic_vector(BUS_buswidth-1 downto 0); 24 | 25 | sampleRequest : out std_logic := '0'; 26 | sampleposReq : out unsigned(4 downto 0) := (others => '0'); 27 | channelData : in unsigned(3 downto 0); 28 | channelValid : in std_logic; 29 | 30 | soundoutL : out signed(8 downto 0) := (others => '0'); 31 | soundoutR : out signed(8 downto 0) := (others => '0'); 32 | 33 | -- savestates 34 | SSBUS_Din : in std_logic_vector(SSBUS_buswidth-1 downto 0); 35 | SSBUS_Adr : in std_logic_vector(SSBUS_busadr-1 downto 0); 36 | SSBUS_wren : in std_logic; 37 | SSBUS_rst : in std_logic; 38 | SSBUS_Dout : out std_logic_vector(SSBUS_buswidth-1 downto 0) 39 | ); 40 | end entity; 41 | 42 | architecture arch of sound_module3 is 43 | 44 | -- register 45 | signal SND_CH_PITCH : std_logic_vector(10 downto 0); 46 | signal SND_CH_Vol : std_logic_vector( 7 downto 0); 47 | signal SND_SWEEP_VALUE : std_logic_vector( 7 downto 0); 48 | signal SND_SWEEP_TIME : std_logic_vector( 4 downto 0); 49 | 50 | signal pitchWriteL : std_logic; 51 | signal pitchWriteH : std_logic; 52 | 53 | type t_reg_wired_or is array(0 to 4) of std_logic_vector(7 downto 0); 54 | signal reg_wired_or : t_reg_wired_or; 55 | 56 | -- internal 57 | signal pitchCount : unsigned(10 downto 0); 58 | signal nextData : unsigned(3 downto 0); 59 | signal sweepslow : integer range 0 to 8191; 60 | signal sweepCounter : unsigned(4 downto 0); 61 | 62 | -- savestates 63 | signal SS_SOUND3 : std_logic_vector(REG_SAVESTATE_SOUND3.upper downto REG_SAVESTATE_SOUND3.lower); 64 | signal SS_SOUND3_BACK : std_logic_vector(REG_SAVESTATE_SOUND3.upper downto REG_SAVESTATE_SOUND3.lower); 65 | 66 | begin 67 | 68 | iREG_SND_CH_PITCH_L : entity work.eReg generic map ( REG_SND_CH3_PITCH_L ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(0), SND_CH_PITCH( 7 downto 0), open , pitchWriteL); 69 | iREG_SND_CH_PITCH_H : entity work.eReg generic map ( REG_SND_CH3_PITCH_H ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(1), SND_CH_PITCH(10 downto 8), open , pitchWriteH); 70 | iREG_SND_CH_Vol : entity work.eReg generic map ( REG_SND_CH3_Vol ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(2), SND_CH_Vol , SND_CH_Vol ); 71 | iREG_SND_SWEEP_VALUE : entity work.eReg generic map ( REG_SND_SWEEP_VALUE ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(3), SND_SWEEP_VALUE , SND_SWEEP_VALUE ); 72 | iREG_SND_SWEEP_TIME : entity work.eReg generic map ( REG_SND_SWEEP_TIME ) port map (clk, RegBus_Din, RegBus_Adr, RegBus_wren, RegBus_rst, reg_wired_or(4), SND_SWEEP_TIME , SND_SWEEP_TIME ); 73 | 74 | process (reg_wired_or) 75 | variable wired_or : std_logic_vector(7 downto 0); 76 | begin 77 | wired_or := reg_wired_or(0); 78 | for i in 1 to (reg_wired_or'length - 1) loop 79 | wired_or := wired_or or reg_wired_or(i); 80 | end loop; 81 | RegBus_Dout <= wired_or; 82 | end process; 83 | 84 | -- savestates 85 | iSS_SOUND3 : entity work.eReg_SS generic map ( REG_SAVESTATE_SOUND3 ) port map (clk, SSBUS_Din, SSBUS_Adr, SSBUS_wren, SSBUS_rst, SSBUS_Dout, SS_SOUND3_BACK, SS_SOUND3 ); 86 | 87 | SS_SOUND3_BACK <= SND_CH_PITCH; 88 | 89 | process (clk) 90 | variable newPitchCount : unsigned(10 downto 0); 91 | begin 92 | if rising_edge(clk) then 93 | 94 | if (reset = '1') then 95 | 96 | SND_CH_PITCH <= SS_SOUND3; 97 | 98 | sampleposReq <= (others => '0'); 99 | soundoutL <= (others => '0'); 100 | soundoutR <= (others => '0'); 101 | sampleRequest <= '1'; 102 | 103 | pitchCount <= (others => '0'); 104 | nextData <= (others => '0'); 105 | sweepslow <= 0; 106 | sweepCounter <= (others => '0'); 107 | 108 | elsif (ce = '1') then 109 | 110 | newPitchCount := pitchCount - 1; 111 | pitchCount <= newPitchCount; 112 | if (newPitchCount = unsigned(SND_CH_PITCH)) then 113 | sampleRequest <= '1'; 114 | pitchCount <= (others => '0'); 115 | sampleposReq <= sampleposReq + 1; 116 | soundoutL <= signed('0' & (nextData * unsigned(SND_CH_Vol(7 downto 4)))); 117 | soundoutR <= signed('0' & (nextData * unsigned(SND_CH_Vol(3 downto 0)))); 118 | end if; 119 | 120 | if (channelValid = '1') then 121 | sampleRequest <= '0'; 122 | nextData <= channelData; 123 | end if; 124 | 125 | -- sweep 126 | if (sweepslow = 8191) then 127 | sweepslow <= 0; 128 | if (useSweep = '1' and sweepCounter = 0) then 129 | sweepCounter <= unsigned(SND_SWEEP_TIME); 130 | SND_CH_PITCH <= std_logic_vector(to_unsigned(to_integer(unsigned(SND_CH_PITCH)) + to_integer(signed(SND_SWEEP_VALUE)), 11)); 131 | else 132 | sweepCounter <= sweepCounter - 1; 133 | end if; 134 | else 135 | sweepslow <= sweepslow + 1; 136 | end if; 137 | 138 | -- writing pitch from reg interface 139 | if (pitchWriteL = '1') then SND_CH_PITCH( 7 downto 0) <= RegBus_Din; end if; 140 | if (pitchWriteH = '1') then SND_CH_PITCH(10 downto 8) <= RegBus_Din(2 downto 0); end if; 141 | 142 | end if; 143 | 144 | end if; 145 | end process; 146 | 147 | 148 | end architecture; 149 | 150 | 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /src/fpga/core/mf_pllbase_sim/synopsys/vcs/vcs_setup.sh: -------------------------------------------------------------------------------- 1 | 2 | # (C) 2001-2022 Altera Corporation. All rights reserved. 3 | # Your use of Altera Corporation's design tools, logic functions and 4 | # other software and tools, and its AMPP partner logic functions, and 5 | # any output files any of the foregoing (including device programming 6 | # or simulation files), and any associated documentation or information 7 | # are expressly subject to the terms and conditions of the Altera 8 | # Program License Subscription Agreement, Altera MegaCore Function 9 | # License Agreement, or other applicable license agreement, including, 10 | # without limitation, that your use is for the sole purpose of 11 | # programming logic devices manufactured by Altera and sold by Altera 12 | # or its authorized distributors. Please refer to the applicable 13 | # agreement for further details. 14 | 15 | # ACDS 21.1 850 win32 2022.10.10.16:26:47 16 | 17 | # ---------------------------------------- 18 | # vcs - auto-generated simulation script 19 | 20 | # ---------------------------------------- 21 | # This script provides commands to simulate the following IP detected in 22 | # your Quartus project: 23 | # mf_pllbase 24 | # 25 | # Altera recommends that you source this Quartus-generated IP simulation 26 | # script from your own customized top-level script, and avoid editing this 27 | # generated script. 28 | # 29 | # To write a top-level shell script that compiles Altera simulation libraries 30 | # and the Quartus-generated IP in your project, along with your design and 31 | # testbench files, follow the guidelines below. 32 | # 33 | # 1) Copy the shell script text from the TOP-LEVEL TEMPLATE section 34 | # below into a new file, e.g. named "vcs_sim.sh". 35 | # 36 | # 2) Copy the text from the DESIGN FILE LIST & OPTIONS TEMPLATE section into 37 | # a separate file, e.g. named "filelist.f". 38 | # 39 | # ---------------------------------------- 40 | # # TOP-LEVEL TEMPLATE - BEGIN 41 | # # 42 | # # TOP_LEVEL_NAME is used in the Quartus-generated IP simulation script to 43 | # # set the top-level simulation or testbench module/entity name. 44 | # # 45 | # # QSYS_SIMDIR is used in the Quartus-generated IP simulation script to 46 | # # construct paths to the files required to simulate the IP in your Quartus 47 | # # project. By default, the IP script assumes that you are launching the 48 | # # simulator from the IP script location. If launching from another 49 | # # location, set QSYS_SIMDIR to the output directory you specified when you 50 | # # generated the IP script, relative to the directory from which you launch 51 | # # the simulator. 52 | # # 53 | # # Source the Quartus-generated IP simulation script and do the following: 54 | # # - Compile the Quartus EDA simulation library and IP simulation files. 55 | # # - Specify TOP_LEVEL_NAME and QSYS_SIMDIR. 56 | # # - Compile the design and top-level simulation module/entity using 57 | # # information specified in "filelist.f". 58 | # # - Override the default USER_DEFINED_SIM_OPTIONS. For example, to run 59 | # # until $finish(), set to an empty string: USER_DEFINED_SIM_OPTIONS="". 60 | # # - Run the simulation. 61 | # # 62 | # source