├── 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 | | Horizontal |
49 | Vertical |
50 |
51 | |
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