├── .github
└── FUNDING.yml
├── .gitignore
├── LICENSE
├── README.md
├── SNES.aseprite
├── build.ps1
├── docs
└── PLL Reconfig.md
├── gateware.json
├── generate.tcl
├── pkg
├── Assets
│ └── snes
│ │ └── common
│ │ └── .gitkeep
├── Cores
│ └── agg23.SNES
│ │ ├── audio.json
│ │ ├── core.json
│ │ ├── data.json
│ │ ├── icon.bin
│ │ ├── info.txt
│ │ ├── input.json
│ │ ├── interact.json
│ │ ├── loader.bin
│ │ ├── snes_custom.rev
│ │ ├── snes_main.rev
│ │ ├── snes_pal.rev
│ │ ├── snes_spc.rev
│ │ ├── variants.json
│ │ └── video.json
└── Platforms
│ ├── _images
│ └── snes.bin
│ └── snes.json
├── platform
└── pocket
│ ├── apf.qip
│ ├── apf_constraints.sdc
│ ├── apf_top.v
│ ├── build_cdf.tcl
│ ├── build_id_gen.tcl
│ ├── common.v
│ ├── io_bridge_peripheral.v
│ ├── io_pad_controller.v
│ ├── mf_datatable.qip
│ ├── mf_datatable.v
│ ├── mf_ddio_bidir_12.qip
│ ├── mf_ddio_bidir_12.v
│ └── pocket.tcl
├── projects
├── snes_pocket.qip
├── snes_pocket.qpf
├── snes_pocket.qsf
└── snes_pocket.sdc
├── rtl
├── 65C816
│ ├── 65C816.qip
│ ├── ALU.vhd
│ ├── AddSubBCD.vhd
│ ├── AddrGen.vhd
│ ├── BCDAdder.vhd
│ ├── MCode.vhd
│ ├── P65816_pkg.vhd
│ └── P65C816.vhd
├── CEGen.vhd
├── CPU.vhd
├── DSP.vhd
├── DSP_PKG.vhd
├── PPU.vhd
├── PPU_PKG.vhd
├── SMP.vhd
├── SNES.vhd
├── SPC700
│ ├── ALU.vhd
│ ├── AddSub.vhd
│ ├── AddrGen.vhd
│ ├── BCDAdj.vhd
│ ├── MCode.vhd
│ ├── MulDiv.vhd
│ ├── SPC700.qip
│ ├── SPC700.vhd
│ └── SPC700_pkg.vhd
├── SWRAM.vhd
├── bram.vhd
├── cheatcodes.sv
├── chip
│ ├── BSX
│ │ ├── BSXMap.vhd
│ │ ├── BSX_BS.vhd
│ │ ├── BSX_DP.vhd
│ │ ├── BSX_MCC.vhd
│ │ └── bsx121-124.mif
│ ├── CX4
│ │ ├── CX4.vhd
│ │ ├── CX4Map.vhd
│ │ ├── cx4cache.vhd
│ │ └── drom.mif
│ ├── DSP
│ │ ├── DSP_LHRomMap.vhd
│ │ ├── DSPn.vhd
│ │ ├── OBC1.vhd
│ │ ├── dsp11b23410_d.mif
│ │ └── dsp11b23410_p.mif
│ ├── GSU
│ │ ├── GSU.vhd
│ │ ├── GSUMap.vhd
│ │ └── GSU_PKG.vhd
│ ├── MSU1
│ │ ├── MSU.sv
│ │ ├── msu_audio.v
│ │ ├── msu_data_store.sv
│ │ └── msu_fifo.v
│ ├── RTC4513.vhd
│ ├── SA1
│ │ ├── SA1.vhd
│ │ ├── SA1DIV.vhd
│ │ ├── SA1MULT.vhd
│ │ └── SA1Map.vhd
│ ├── SDD1
│ │ ├── Decoder.vhd
│ │ ├── InputMgr.vhd
│ │ ├── SDD1.vhd
│ │ └── SDD1Map.vhd
│ ├── SPC7110
│ │ ├── SPC7110.vhd
│ │ ├── SPC7110Map.vhd
│ │ ├── SPC7110_DEC.vhd
│ │ ├── SPC7110_DEC_PKG.vhd
│ │ ├── SPC7110_FIFO.vhd
│ │ └── SPC7110_MULDIV.vhd
│ ├── SRTC.vhd
│ └── chip.qip
├── hps_ext.v
├── ioport.sv
├── lightgun.sv
├── main.v
├── miracle.sv
├── mister_top
│ ├── SNES.sv
│ ├── rom_parser.sv
│ ├── rom_parser_tb.sv
│ └── scanline_filler.sv
├── sdram.sv
└── snes.qip
├── support
├── check_header.asm
├── loader.asm
├── loader.bin
├── test.bin
├── test_data.json
└── util.asm
└── target
└── pocket
├── core.qip
├── core_bridge_cmd.v
├── core_constraints.sdc
├── core_top.sv
├── data_loader.sv
├── data_unloader.sv
├── mf_pllbase.ppf
├── mf_pllbase.qip
├── mf_pllbase.v
├── mf_pllbase
├── mf_pllbase.mif
├── mf_pllbase_0002.qip
└── mf_pllbase_0002.v
├── mf_pllbase_pal.ppf
├── mf_pllbase_pal.qip
├── mf_pllbase_pal.v
├── mf_pllbase_pal
├── mf_pllbase_pal_0002.qip
└── mf_pllbase_pal_0002.v
├── pll_reconfig.ppf
├── pll_reconfig.qip
├── pll_reconfig.v
├── pll_reconfig
├── altera_pll_reconfig_core.v
├── altera_pll_reconfig_top.v
└── altera_std_synchronizer.v
├── psram.sv
├── save_state_controller.sv
├── sound_i2s.sv
├── stp1.stp
└── sync_fifo.sv
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: agg23
2 | patreon: srg320
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.rbf_r
2 | *.zip
3 | dist/**/*.rev
4 | dist/**/*.bin
5 | src/**/*.bin
6 | src/sim/work/
7 | src/sim/*.hex
8 | src/sim/*.mem
9 | src/sim/*.bin
10 |
11 | # Quartus directories and files
12 | db
13 | greybox_tmp
14 | hps_isw_handoff
15 | incremental_db
16 | output_files
17 | PLLJ_PLLSPE_INFO.txt
18 | simulation
19 | vip
20 | .qsys_edit
21 | *_netlist
22 | *_sim
23 | *.bak
24 | *.bsf
25 | *.cdf
26 | *.cmp
27 | *.csv
28 | *.done
29 | *.f
30 | *.pin
31 | *.pof
32 | *.ptf.*
33 | *.qar
34 | *.qarlog
35 | *.qdf
36 | *.qws
37 | *.rbf
38 | *.rpt
39 | *.sip
40 | *.sld
41 | *.smsg
42 | *.sof
43 | *.sopc_builder
44 | *.sopcinfo
45 | *.spd
46 | *.summary
47 | *.txt
48 | *.xml
49 | *~
50 | **/.DS_Store
51 | build_id.mif
52 | build_id.v
53 | c5_pin_model_dump.txt
54 | cr_ie_info.json
55 | # Gateman directories and files
56 | !.gateman/*
57 | !gateware.json
58 | !/pkg/*
59 | /pkg/**/*.rom
60 | /pkg/**/*.zip
61 | /staging/*
62 | /release/*
63 | # Editor directories and files
64 | .idea
65 | *.suo
66 | *.ntvs*
67 | *.njsproj
68 | *.sln
69 | *.sw?
70 | # Pocket directories and files
71 | !info.txt
72 | # ROMS Checklist
73 | !checklist.sha1
74 | !checklist.md5
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SNES for Analogue Pocket
2 |
3 | Ported from the original core developed by [srg320](https://github.com/srg320) ([Patreon](https://www.patreon.com/srg320)). Latest upstream available at https://github.com/MiSTer-devel/SNES_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 | > [!WARNING]
8 | >
9 | > Savestates/Memories/Sleep not supported
10 | >
11 | > Savestates/Memories/Sleep are not supported by any FPGA SNES core. Not this one, not the MiSTer core it's ported from, not the Analogue Super NT one.
12 | >
13 | > **Support for savestates will _not_ be coming** to any of these cores. Do not ask. If you would like to learn more, see [issue #59](https://github.com/agg23/openfpga-SNES/issues/59) and [this discussion on the MiSTer forums](https://misterfpga.org/viewtopic.php?t=4944).
14 |
15 | ## Installation
16 |
17 | ### Easy mode
18 |
19 | 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
20 |
21 | ### Manual mode
22 | 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.
23 |
24 | ## Usage
25 |
26 | ROMs should be placed in `/Assets/snes/common`. Both headered and unheadered ROMs are now supported.
27 |
28 | ## Features
29 |
30 | ### Dock Support
31 |
32 | Core supports four players/controllers via the Analogue Dock. To enable four player mode, turn on `Use Multitap` setting.
33 |
34 | ### Expansion Chips
35 |
36 | All original expansion chips supported by MiSTer are also supported on the Pocket. The full list is:
37 |
38 | * SA-1 (Super Mario RPG)
39 | * Super FX/GSU-1/2 (Star Fox)
40 | * DSP (Super Mario Kart)
41 | * CX4 (Mega Man X 2)
42 | * S-DD1 (Star Ocean)
43 | * SPC7110 (Far East of Eden)
44 | * ST1010 (F1 Roc 2)
45 | * BSX (Satellaview)
46 |
47 | The Super Game Boy, ST011 (Hayazashi Nidan Morita Shougi), and ST018 (Hayazashi Nidan Morita Shougi 2) are not supported in the MiSTer core, and therefore are not supported here. Additionally, the homebrew MSU expansion chip is not currently supported.
48 |
49 | #### BSX
50 |
51 | BSX ROMs must be patched to run without BIOS. The BSX BIOS is not currently supported
52 |
53 | ### Savestates/Memories/Sleep
54 |
55 | > **Warning**: Not supported
56 |
57 | Savestates/Memories/Sleep are not supported by any FPGA SNES core. Not this one, not the MiSTer core it's ported from, not the Analogue Super NT one.
58 |
59 | **Support for savestates will _not_ be coming** to any of these cores. Do not ask. If you would like to learn more, see [issue #59](https://github.com/agg23/openfpga-SNES/issues/59) and [this discussion on the MiSTer forums](https://misterfpga.org/viewtopic.php?t=4944).
60 |
61 | ### Video
62 |
63 | * `Square Pixels` - The internal resolution of the SNES is a 8:7 pixel aspect ratio (wide pixels), which roughly corresponds to what users would see on 4:3 display aspect ratio CRTs. Some games are designed to be displayed at 8:7 PAR (the core's default), and others at 1:1 PAR (square pixels). The `Square Pixels` option is provided to switch to a 1:1 pixel aspect ratio
64 | * `Pseudo Transparency` - Enable blending of adjacent pixels, used in some games to simulate transparency
65 |
66 | ### Turbo
67 |
68 | * `CPU Turbo` - Applies a speed increase to the main SNES CPU. **NOTE:** This has different compatibility with different games. See the [MiSTer list of games](https://github.com/MiSTer-devel/SNES_MiSTer/blob/master/SNES_Turbo.md) that this feature works with
69 | * `SuperFX Turbo` - Applies a speed increase to the GSU (SuperFX) chip. Can be used in addition to the `CPU Turbo` option in games like Star Fox to maintain a higher frame rate.
70 |
71 | ### Controller Options
72 |
73 | There are several options provided for selecting which type of controller the core will emulate.
74 |
75 | * `Gamepad` - The standard SNES controller used with most games.
76 | * `Super Scope` - The Super Scope lightgun that's used with most lightgun games. See Lightguns for more details.
77 | * `Justifier` - The Justifier lightgun that's used with Lethal Enforcers. See Lightguns for more details.
78 | * `Mouse` - The SNES mouse that's used with Mario Paint and several other games. See SNES Mouse for more details.
79 |
80 | ### Lightguns
81 |
82 | Core supports virtual lightguns by selecting the `Super Scope` or `Justifier` options under `Controller Options`. Most lightgun games user the Super Scope but Lethal Enforcers uses the Justifier. The crosshair can be controlled with the D-Pad or left joystick, using the A button to fire and the B button to reload. D-Pad aim sensitivity can be adjusted with the `D-Pad Aim Speed` setting.
83 |
84 | **NOTE:** Joystick support for aiming only appears to work when a controller is paired over Bluetooth and not connected to the Analogue Dock directly by USB.
85 |
86 | ### SNES Mouse
87 |
88 | Core supports a virtual SNES mouse by selecting `Mouse` under `Controller Options`. The mouse can be moved with the D-Pad or left joystick and left and right clicks can be performed by pressing the A and B buttons respectively. Mouse D-Pad movement sensitivity can be adjusted with the `D-Pad Aim Speed` setting.
89 |
90 | **NOTE:** The dock firmware doesn't currently support a USB mouse.
--------------------------------------------------------------------------------
/SNES.aseprite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agg23/openfpga-SNES/05f0587891754e885647915ed42faa52604fc1d5/SNES.aseprite
--------------------------------------------------------------------------------
/build.ps1:
--------------------------------------------------------------------------------
1 | if (($args.count -ne 1) -or ($args[0] -eq "")) {
2 | Write-Output "Expected build type arg"
3 | exit 1
4 | }
5 |
6 | $build_type = $args[0]
7 |
8 | quartus_sh -t generate.tcl $build_type
9 |
10 | $exitcode = $LASTEXITCODE
11 | if ($exitcode -ne 0) {
12 | Write-Output "Build failed with $exitcode"
13 | exit $exitcode
14 | }
15 |
16 | $output_file = "snes_main.rev"
17 |
18 | if (($build_type -eq "ntsc") -or ($build_type -eq "none")) {
19 | $output_file = "snes_main.rev"
20 | } elseif (($build_type -eq "pal") -or ($build_type -eq "none_pal")) {
21 | $output_file = "snes_pal.rev"
22 | } elseif ($build_type -eq "ntsc_spc") {
23 | $output_file = "snes_spc.rev"
24 | }
25 |
26 | C:\Users\adam\code\pocket-text\tools\reverse.exe C:\Users\adam\code\fpga\openFPGA\ports\snes\projects\output_files\snes_pocket.rbf "C:\Users\adam\code\fpga\openFPGA\ports\snes\pkg\Cores\agg23.SNES\$output_file";
--------------------------------------------------------------------------------
/docs/PLL Reconfig.md:
--------------------------------------------------------------------------------
1 | # C Counter
2 |
3 | ## C0
4 |
5 | NTSC:
6 | Lo: 3
7 | Hi: 4
8 | Bypass: false
9 | Odd div: true
10 |
11 | 0x020403
12 |
13 | PAL:
14 | Lo: 4
15 | Hi: 4
16 | Bypass: false
17 | Odd div: false
18 |
19 | 0x000404
20 |
21 | ## C1
22 |
23 | NTSC:
24 | Lo: 14
25 | Hi: 14
26 | Bypass: false
27 | Odd div: false
28 |
29 | 0x040E0E
30 |
31 | PAL:
32 | Lo: 16
33 | Hi: 16
34 | Bypass: false
35 | Odd div: false
36 |
37 | 0x041010
38 |
39 | ## C2
40 |
41 | NTSC:
42 | Lo: 28
43 | Hi: 28
44 | Bypass: false
45 | Odd div: false
46 |
47 | 0x081C1C
48 |
49 | PAL:
50 | Lo: 32
51 | Hi: 32
52 | Bypass: false
53 | Odd div: false
54 |
55 | 0x082020
56 |
57 | ## C3
58 |
59 | NTSC:
60 | Lo: 28
61 | Hi: 28
62 | Bypass: false
63 | Odd div: false
64 |
65 | 0x0C1C1C
66 |
67 | PAL:
68 | Lo: 32
69 | Hi: 32
70 | Bypass: false
71 | Odd div: false
72 |
73 | 0x0C2020
74 |
75 | # M Counter
76 |
77 | NTSC:
78 | Lo: 4
79 | Hi: 4
80 | Bypass: false
81 | Odd div: false
82 |
83 | 0x00404
84 |
85 | PAL:
86 | Lo: 4
87 | Hi: 5
88 | Bypass: false
89 | Odd div: true
90 |
91 | 0x20504
92 |
93 | # Fractional division
94 |
95 | NTSC: 425937894
96 | PAL: 737741702
--------------------------------------------------------------------------------
/gateware.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "snes",
3 | "displayName": "snes",
4 | "description": "Super Nintendo and Super Famicom. Nintendo's second major home console",
5 | "author": "agg23",
6 | "version": "0.4.4",
7 | "license": "GPL-3.0-or-later",
8 | "repository": "https://github.com/agg23/openFPGA-SNES",
9 | "keywords": [
10 | "ecosystem:gateman"
11 | ],
12 | "scripts": {
13 | "verilator": "echo \"Error: no simulation specified\" && exit 1",
14 | "build:pocket": "pwsh build.ps1",
15 | "program:pocket": "quartus_pgm -m jtag -c 1 -o \"p;projects/output_files/nes_pocket.sof@1\""
16 | },
17 | "platforms": {
18 | "pocket": "1.3.0"
19 | },
20 | "modules": {}
21 | }
--------------------------------------------------------------------------------
/generate.tcl:
--------------------------------------------------------------------------------
1 | # Run with quartus_sh -t generate.tcl
2 |
3 | # Load Quartus II Tcl Project package
4 | package require ::quartus::project
5 |
6 | # Required for compilation
7 | package require ::quartus::flow
8 |
9 | if { $argc != 1 } {
10 | puts "Exactly 1 argument required"
11 | exit
12 | }
13 |
14 | project_open projects/snes_pocket.qpf
15 |
16 | if { [lindex $argv 0] == "ntsc" } {
17 | puts "NTSC"
18 | set_parameter -name PAL_PLL -entity core_top '0
19 |
20 | set_parameter -name USE_CX4 -entity MAIN_SNES '1
21 | set_parameter -name USE_SDD1 -entity MAIN_SNES '0
22 | set_parameter -name USE_GSU -entity MAIN_SNES '1
23 | set_parameter -name USE_SA1 -entity MAIN_SNES '1
24 | set_parameter -name USE_DSPn -entity MAIN_SNES '1
25 | set_parameter -name USE_SPC7110 -entity MAIN_SNES '0
26 | set_parameter -name USE_BSX -entity MAIN_SNES '0
27 | set_parameter -name USE_MSU -entity MAIN_SNES '0
28 | } elseif { [lindex $argv 0] == "pal" } {
29 | puts "PAL"
30 | set_parameter -name PAL_PLL -entity core_top '1
31 |
32 | set_parameter -name USE_CX4 -entity MAIN_SNES '1
33 | set_parameter -name USE_SDD1 -entity MAIN_SNES '0
34 | set_parameter -name USE_GSU -entity MAIN_SNES '1
35 | set_parameter -name USE_SA1 -entity MAIN_SNES '1
36 | set_parameter -name USE_DSPn -entity MAIN_SNES '1
37 | set_parameter -name USE_SPC7110 -entity MAIN_SNES '0
38 | set_parameter -name USE_BSX -entity MAIN_SNES '0
39 | set_parameter -name USE_MSU -entity MAIN_SNES '0
40 | } elseif { [lindex $argv 0] == "ntsc_spc" } {
41 | puts "NTSC SPC"
42 | set_parameter -name PAL_PLL -entity core_top '0
43 |
44 | set_parameter -name USE_CX4 -entity MAIN_SNES '0
45 | set_parameter -name USE_SDD1 -entity MAIN_SNES '1
46 | set_parameter -name USE_GSU -entity MAIN_SNES '0
47 | set_parameter -name USE_SA1 -entity MAIN_SNES '0
48 | set_parameter -name USE_DSPn -entity MAIN_SNES '0
49 | set_parameter -name USE_SPC7110 -entity MAIN_SNES '1
50 | set_parameter -name USE_BSX -entity MAIN_SNES '1
51 | set_parameter -name USE_MSU -entity MAIN_SNES '0
52 | } elseif { [lindex $argv 0] == "none" } {
53 | puts "NONE"
54 | set_parameter -name PAL_PLL -entity core_top '0
55 |
56 | set_parameter -name USE_CX4 -entity MAIN_SNES '0
57 | set_parameter -name USE_SDD1 -entity MAIN_SNES '0
58 | set_parameter -name USE_GSU -entity MAIN_SNES '0
59 | set_parameter -name USE_SA1 -entity MAIN_SNES '0
60 | set_parameter -name USE_DSPn -entity MAIN_SNES '0
61 | set_parameter -name USE_SPC7110 -entity MAIN_SNES '0
62 | set_parameter -name USE_BSX -entity MAIN_SNES '0
63 | set_parameter -name USE_MSU -entity MAIN_SNES '0
64 | } elseif { [lindex $argv 0] == "none_pal" } {
65 | puts "NONE PAL"
66 | set_parameter -name PAL_PLL -entity core_top '1
67 |
68 | set_parameter -name USE_CX4 -entity MAIN_SNES '0
69 | set_parameter -name USE_SDD1 -entity MAIN_SNES '0
70 | set_parameter -name USE_GSU -entity MAIN_SNES '0
71 | set_parameter -name USE_SA1 -entity MAIN_SNES '0
72 | set_parameter -name USE_DSPn -entity MAIN_SNES '0
73 | set_parameter -name USE_SPC7110 -entity MAIN_SNES '0
74 | set_parameter -name USE_BSX -entity MAIN_SNES '0
75 | set_parameter -name USE_MSU -entity MAIN_SNES '0
76 | } else {
77 | puts "Unknown bitstream type [lindex $argv 0]"
78 | project_close
79 | exit
80 | }
81 |
82 | execute_flow -compile
83 |
84 | project_close
--------------------------------------------------------------------------------
/pkg/Assets/snes/common/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agg23/openfpga-SNES/05f0587891754e885647915ed42faa52604fc1d5/pkg/Assets/snes/common/.gitkeep
--------------------------------------------------------------------------------
/pkg/Cores/agg23.SNES/audio.json:
--------------------------------------------------------------------------------
1 | {
2 | "audio": {
3 | "magic": "APF_VER_1"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/pkg/Cores/agg23.SNES/core.json:
--------------------------------------------------------------------------------
1 | {
2 | "core": {
3 | "magic": "APF_VER_1",
4 | "metadata": {
5 | "platform_ids": [
6 | "snes"
7 | ],
8 | "shortname": "SNES",
9 | "description": "Super Nintendo and Super Famicom. Nintendo's second major home console",
10 | "author": "agg23",
11 | "url": "https://github.com/agg23/openfpga-snes",
12 | "version": "0.4.4",
13 | "date_release": "2024-09-16"
14 | },
15 | "framework": {
16 | "target_product": "Analogue Pocket",
17 | "version_required": "1.1",
18 | "sleep_supported": false,
19 | "dock": {
20 | "supported": true,
21 | "analog_output": false
22 | },
23 | "hardware": {
24 | "link_port": false,
25 | "cartridge_adapter": -1
26 | },
27 | "chip32_vm": "loader.bin"
28 | },
29 | "cores": [
30 | {
31 | "name": "main",
32 | "id": 0,
33 | "filename": "snes_main.rev"
34 | },
35 | {
36 | "name": "SPCSDD1",
37 | "id": 1,
38 | "filename": "snes_spc.rev"
39 | },
40 | {
41 | "name": "PAL",
42 | "id": 2,
43 | "filename": "snes_pal.rev"
44 | }
45 | ]
46 | }
47 | }
--------------------------------------------------------------------------------
/pkg/Cores/agg23.SNES/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": ["smc", "sfc", "bs"],
11 | "address": "0x10000000"
12 | },
13 | {
14 | "name": "Save",
15 | "id": 10,
16 | "required": false,
17 | "parameters": "0x84",
18 | "nonvolatile": true,
19 | "extensions": ["sav", "srm"],
20 | "address": "0x20000000",
21 | "size_maximum": "0x20000"
22 | }
23 | ]
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/pkg/Cores/agg23.SNES/icon.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agg23/openfpga-SNES/05f0587891754e885647915ed42faa52604fc1d5/pkg/Cores/agg23.SNES/icon.bin
--------------------------------------------------------------------------------
/pkg/Cores/agg23.SNES/info.txt:
--------------------------------------------------------------------------------
1 | Port by agg23. Core by srg320.
2 |
3 | Super Nintendo Entertainment System (SNES), referred to as the Super Famicom (SFC) in Japan was the second home console produced by Nintendo. A 16-bit console that remains hugely popular to this day due to its expansive library and impressive enhancement chips.
4 |
5 | Core supports 4 controllers (when connected to the Dock), and the SA-1, Super FX (GSU), DSP, CX4, S-DD1, SPC7110, and BSX expansion chips. Please report all issues to agg23, as most likely any issues experienced are issues with the port, not the core.
--------------------------------------------------------------------------------
/pkg/Cores/agg23.SNES/input.json:
--------------------------------------------------------------------------------
1 | {
2 | "input": {
3 | "magic": "APF_VER_1",
4 | "controllers": [
5 | {
6 | "type": "default",
7 | "mappings": [
8 | {
9 | "id": 0,
10 | "name": "A Button",
11 | "key": "pad_btn_a"
12 | },
13 | {
14 | "id": 1,
15 | "name": "B Button",
16 | "key": "pad_btn_b"
17 | },
18 | {
19 | "id": 2,
20 | "name": "X Button",
21 | "key": "pad_btn_x"
22 | },
23 | {
24 | "id": 3,
25 | "name": "Y Button",
26 | "key": "pad_btn_y"
27 | },
28 | {
29 | "id": 10,
30 | "name": "Left Trigger",
31 | "key": "pad_trig_l"
32 | },
33 | {
34 | "id": 11,
35 | "name": "Right Trigger",
36 | "key": "pad_trig_r"
37 | },
38 | {
39 | "id": 20,
40 | "name": "Start",
41 | "key": "pad_btn_start"
42 | },
43 | {
44 | "id": 21,
45 | "name": "Select",
46 | "key": "pad_btn_select"
47 | }
48 | ]
49 | }
50 | ]
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/pkg/Cores/agg23.SNES/interact.json:
--------------------------------------------------------------------------------
1 | {
2 | "interact": {
3 | "magic": "APF_VER_1",
4 | "variables": [
5 | {
6 | "name": "Reset Core",
7 | "id": 10,
8 | "type": "action",
9 | "enabled": true,
10 | "address": "0x50",
11 | "value": 1
12 | },
13 | {
14 | "name": "CPU Turbo",
15 | "id": 15,
16 | "type": "check",
17 | "enabled": true,
18 | "address": "0x80",
19 | "persist": true,
20 | "writeonly": true,
21 | "defaultval": 0,
22 | "value": 1
23 | },
24 | {
25 | "name": "SuperFX Turbo",
26 | "id": 16,
27 | "type": "check",
28 | "enabled": true,
29 | "address": "0x84",
30 | "persist": true,
31 | "writeonly": true,
32 | "defaultval": 0,
33 | "value": 1
34 | },
35 | {
36 | "name": "Use Multitap",
37 | "id": 20,
38 | "type": "check",
39 | "enabled": true,
40 | "address": "0x100",
41 | "persist": true,
42 | "writeonly": true,
43 | "defaultval": 0,
44 | "value": 1
45 | },
46 | {
47 | "name": "Controller Options",
48 | "id": 30,
49 | "type": "list",
50 | "enabled": true,
51 | "address": "0x104",
52 | "persist": true,
53 | "writeonly": true,
54 | "defaultval": 0,
55 | "options": [
56 | {
57 | "name": "Gamepad",
58 | "value": 0
59 | },
60 | {
61 | "name": "Super Scope",
62 | "value": 1
63 | },
64 | {
65 | "name": "Justifier",
66 | "value": 3
67 | },
68 | {
69 | "name": "Mouse",
70 | "value": 4
71 | }
72 | ]
73 | },
74 | {
75 | "name": "D-Pad Aim Speed",
76 | "id": 34,
77 | "type": "slider_u32",
78 | "enabled": true,
79 | "address": "0x108",
80 | "persist": true,
81 | "writeonly": true,
82 | "defaultval": 3,
83 | "graphical": {
84 | "signed": false,
85 | "min": 1,
86 | "max": 10,
87 | "adjust_small": 1,
88 | "adjust_large": 4
89 | }
90 | },
91 | {
92 | "name": "Joy Deadzone",
93 | "id": 35,
94 | "type": "slider_u32",
95 | "enabled": true,
96 | "address": "0x0000010C",
97 | "persist": true,
98 | "writeonly": true,
99 | "defaultval": 0,
100 | "graphical": {
101 | "signed": false,
102 | "min": 0,
103 | "max": 64,
104 | "adjust_small": 1,
105 | "adjust_large": 10
106 | }
107 | },
108 | {
109 | "name": "Square Pixels",
110 | "id": 42,
111 | "type": "check",
112 | "enabled": true,
113 | "address": "0x200",
114 | "persist": true,
115 | "writeonly": true,
116 | "defaultval": 0,
117 | "value": 1
118 | },
119 | {
120 | "name": "Pseudo Transparency",
121 | "id": 41,
122 | "type": "check",
123 | "enabled": true,
124 | "address": "0x204",
125 | "persist": true,
126 | "writeonly": true,
127 | "defaultval": 1,
128 | "value": 1
129 | }
130 | ],
131 | "messages": []
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/pkg/Cores/agg23.SNES/loader.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agg23/openfpga-SNES/05f0587891754e885647915ed42faa52604fc1d5/pkg/Cores/agg23.SNES/loader.bin
--------------------------------------------------------------------------------
/pkg/Cores/agg23.SNES/snes_custom.rev:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agg23/openfpga-SNES/05f0587891754e885647915ed42faa52604fc1d5/pkg/Cores/agg23.SNES/snes_custom.rev
--------------------------------------------------------------------------------
/pkg/Cores/agg23.SNES/snes_main.rev:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agg23/openfpga-SNES/05f0587891754e885647915ed42faa52604fc1d5/pkg/Cores/agg23.SNES/snes_main.rev
--------------------------------------------------------------------------------
/pkg/Cores/agg23.SNES/snes_pal.rev:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agg23/openfpga-SNES/05f0587891754e885647915ed42faa52604fc1d5/pkg/Cores/agg23.SNES/snes_pal.rev
--------------------------------------------------------------------------------
/pkg/Cores/agg23.SNES/snes_spc.rev:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agg23/openfpga-SNES/05f0587891754e885647915ed42faa52604fc1d5/pkg/Cores/agg23.SNES/snes_spc.rev
--------------------------------------------------------------------------------
/pkg/Cores/agg23.SNES/variants.json:
--------------------------------------------------------------------------------
1 | {
2 | "variants": {
3 | "magic": "APF_VER_1",
4 | "variant_list": []
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/pkg/Cores/agg23.SNES/video.json:
--------------------------------------------------------------------------------
1 | {
2 | "video": {
3 | "magic": "APF_VER_1",
4 | "scaler_modes": [
5 | {
6 | "width": 512,
7 | "height": 224,
8 | "aspect_w": 64,
9 | "aspect_h": 49,
10 | "rotation": 0,
11 | "mirror": 0
12 | },
13 | {
14 | "width": 512,
15 | "height": 224,
16 | "aspect_w": 8,
17 | "aspect_h": 7,
18 | "rotation": 0,
19 | "mirror": 0
20 | },
21 | {
22 | "width": 512,
23 | "height": 240,
24 | "aspect_w": 128,
25 | "aspect_h": 105,
26 | "rotation": 0,
27 | "mirror": 0
28 | },
29 | {
30 | "width": 512,
31 | "height": 240,
32 | "aspect_w": 16,
33 | "aspect_h": 15,
34 | "rotation": 0,
35 | "mirror": 0
36 | }
37 | ],
38 | "display_modes": [
39 | {
40 | "id": "0x10"
41 | },
42 | {
43 | "id": "0x20"
44 | },
45 | {
46 | "id": "0x30"
47 | },
48 | {
49 | "id": "0x40"
50 | },
51 | {
52 | "id": "0xE0"
53 | },
54 | {
55 | "id": "0xE1"
56 | }
57 | ]
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/pkg/Platforms/_images/snes.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agg23/openfpga-SNES/05f0587891754e885647915ed42faa52604fc1d5/pkg/Platforms/_images/snes.bin
--------------------------------------------------------------------------------
/pkg/Platforms/snes.json:
--------------------------------------------------------------------------------
1 | {
2 | "platform": {
3 | "category": "Console",
4 | "name": "SNES",
5 | "manufacturer": "Nintendo",
6 | "year": 1990
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/platform/pocket/apf.qip:
--------------------------------------------------------------------------------
1 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "apf_top.v"]
2 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "common.v"]
3 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "io_bridge_peripheral.v"]
4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "io_pad_controller.v"]
5 | set_global_assignment -name SDC_FILE [file join $::quartus(qip_path) "apf_constraints.sdc"]
6 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "mf_ddio_bidir_12.qip"]
7 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "mf_datatable.qip"]
8 |
--------------------------------------------------------------------------------
/platform/pocket/apf_constraints.sdc:
--------------------------------------------------------------------------------
1 | #
2 | # APF constraints
3 | # Do not edit this file.
4 | #
5 | # Add your own constraints in the \core_constraints.sdc in the core directory, which will also be loaded.
6 |
7 | create_clock -name clk_74a -period 13.468 [get_ports clk_74a]
8 | create_clock -name clk_74b -period 13.468 [get_ports clk_74b]
9 | create_clock -name bridge_spiclk -period 13.468 [get_ports bridge_spiclk]
10 |
11 | # autogenerate PLL clock names for use down below
12 | derive_pll_clocks
13 |
--------------------------------------------------------------------------------
/platform/pocket/build_cdf.tcl:
--------------------------------------------------------------------------------
1 | # ==============================================================================
2 | # SPDX-License-Identifier: CC0-1.0
3 | # SPDX-FileType: SOURCE
4 | # SPDX-FileCopyrightText: (c) 2022, OpenGateware authors and contributors
5 | # ==============================================================================
6 | # @file: build_cd.h
7 | # @brief: Generate a JTAG Chain Description File.
8 | # Create a .cdf file to be used with Quartus Prime Programmer
9 | # ==============================================================================
10 | proc createChainDescriptionFile {revision device outpath project_name} {
11 | set outputFileName "$project_name.cdf"
12 | set outputFile [open $outputFileName "w"]
13 |
14 | puts $outputFile "JedecChain;"
15 | puts $outputFile " FileRevision(JESD32A);"
16 | puts $outputFile " DefaultMfr(6E);"
17 | puts $outputFile ""
18 | puts $outputFile " P ActionCode(Cfg)"
19 | puts $outputFile " Device PartName($device) Path(\"$outpath/\") File(\"$revision.sof\") MfrSpec(OpMask(1));"
20 | puts $outputFile "ChainEnd;"
21 | puts $outputFile ""
22 | puts $outputFile "AlteraBegin;"
23 | puts $outputFile " ChainType(JTAG);"
24 | puts $outputFile "AlteraEnd;"
25 | }
26 |
27 | set project_name [lindex $quartus(args) 1]
28 | set revision [lindex $quartus(args) 2]
29 |
30 | if {[project_exists $project_name]} {
31 | if {[string equal "" $revision]} {
32 | project_open $project_name -revision [get_current_revision $project_name]
33 | } else {
34 | project_open $project_name -revision $revision
35 | }
36 | } else {
37 | post_message -type error "Project $project_name does not exist"
38 | exit
39 | }
40 |
41 | set device [get_global_assignment -name DEVICE]
42 | set outpath [get_global_assignment -name PROJECT_OUTPUT_DIRECTORY]
43 |
44 | if [is_project_open] {
45 | project_close
46 | }
47 |
48 | createChainDescriptionFile $revision $device $outpath $project_name
49 |
--------------------------------------------------------------------------------
/platform/pocket/common.v:
--------------------------------------------------------------------------------
1 | // Software License Agreement
2 |
3 | // The software supplied herewith by Analogue Enterprises Limited (the "Company”),
4 | // the Analogue Pocket Framework (“APF”), is provided and licensed to you, the
5 | // Company's customer, solely for use in designing, testing and creating
6 | // applications for use with Company's Products or Services. The software is
7 | // owned by the Company and/or its licensors, and is protected under applicable
8 | // laws, including, but not limited to, U.S. copyright law. All rights are
9 | // reserved. By using the APF code you are agreeing to the terms of the End User
10 | // License Agreement (“EULA”) located at [https://www.analogue.link/pocket-eula]
11 | // and incorporated herein by reference. To the extent any use of the APF requires
12 | // application of the MIT License or the GNU General Public License and terms of
13 | // this APF Software License Agreement and EULA are inconsistent with such license,
14 | // the applicable terms of the MIT License or the GNU General Public License, as
15 | // applicable, will prevail.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS-IS" AND WE EXPRESSLY DISCLAIM ANY IMPLIED
18 | // WARRANTIES TO THE FULLEST EXTENT PROVIDED BY LAW, INCLUDING BUT NOT LIMITED TO,
19 | // ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR
20 | // NON-INFRINGEMENT. TO THE EXTENT APPLICABLE LAWS PROHIBIT TERMS OF USE FROM
21 | // DISCLAIMING ANY IMPLIED WARRANTY, SUCH IMPLIED WARRANTY SHALL BE LIMITED TO THE
22 | // MINIMUM WARRANTY PERIOD REQUIRED BY LAW, AND IF NO SUCH PERIOD IS REQUIRED,
23 | // THEN THIRTY (30) DAYS FROM FIRST USE OF THE SOFTWARE. WE CANNOT GUARANTEE AND
24 | // DO NOT PROMISE ANY SPECIFIC RESULTS FROM USE OF THE SOFTWARE. WITHOUT LIMITING
25 | // THE FOREGOING, WE DO NOT WARRANT THAT THE SOFTWARE WILL BE UNINTERRUPTED OR
26 | // ERROR-FREE. IN NO EVENT WILL WE BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
27 | // INDIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, SPECIAL OR PUNITIVE DAMAGES,
28 | // INCLUDING BUT NOT LIMITED TO, LOST PROFITS ARISING OUT OF YOUR USE, OR
29 | // INABILITY TO USE, THE SOFTWARE, EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY
30 | // OF SUCH DAMAGES. UNDER NO CIRCUMSTANCES SHALL OUR LIABILITY TO YOU FOR ANY
31 | // CLAIM OR CAUSE OF ACTION WHATSOEVER, AND REGARDLESS OF THE FORM OF THE ACTION,
32 | // WHETHER ARISING IN CONTRACT, TORT OR OTHERWISE, EXCEED THE AMOUNT PAID BY YOU
33 | // TO US, IF ANY, DURING THE 90 DAY PERIOD IMMEDIATELY PRECEDING THE DATE ON WHICH
34 | // YOU FIRST ASSERT ANY SUCH CLAIM. THE FOREGOING LIMITATIONS SHALL APPLY TO THE
35 | // FULLEST EXTENT PERMITTED BY APPLICABLE LAW.
36 | //
37 | // 2-stage synchronizer
38 | //
39 | module synch_2 #(parameter WIDTH = 1) (
40 | input wire [WIDTH-1:0] i, // input signal
41 | output reg [WIDTH-1:0] o, // synchronized output
42 | input wire clk, // clock to synchronize on
43 | output wire rise, // one-cycle rising edge pulse
44 | output wire fall // one-cycle falling edge pulse
45 | );
46 |
47 | reg [WIDTH-1:0] stage_1;
48 | reg [WIDTH-1:0] stage_2;
49 | reg [WIDTH-1:0] stage_3;
50 |
51 | assign rise = (WIDTH == 1) ? (o & ~stage_2) : 1'b0;
52 | assign fall = (WIDTH == 1) ? (~o & stage_2) : 1'b0;
53 | always @(posedge clk)
54 | {stage_2, o, stage_1} <= {o, stage_1, i};
55 |
56 | endmodule
57 |
58 |
59 | //
60 | // 3-stage synchronizer
61 | //
62 | module synch_3 #(parameter WIDTH = 1) (
63 | input wire [WIDTH-1:0] i, // input signal
64 | output reg [WIDTH-1:0] o, // synchronized output
65 | input wire clk, // clock to synchronize on
66 | output wire rise, // one-cycle rising edge pulse
67 | output wire fall // one-cycle falling edge pulse
68 | );
69 |
70 | reg [WIDTH-1:0] stage_1;
71 | reg [WIDTH-1:0] stage_2;
72 | reg [WIDTH-1:0] stage_3;
73 |
74 | assign rise = (WIDTH == 1) ? (o & ~stage_3) : 1'b0;
75 | assign fall = (WIDTH == 1) ? (~o & stage_3) : 1'b0;
76 | always @(posedge clk)
77 | {stage_3, o, stage_2, stage_1} <= {o, stage_2, stage_1, i};
78 |
79 | endmodule
80 |
81 |
82 | module bram_block_dp #(
83 | parameter DATA = 32,
84 | parameter ADDR = 7
85 | ) (
86 | input wire a_clk,
87 | input wire a_wr,
88 | input wire [ADDR-1:0] a_addr,
89 | input wire [DATA-1:0] a_din,
90 | output reg [DATA-1:0] a_dout,
91 |
92 | input wire b_clk,
93 | input wire b_wr,
94 | input wire [ADDR-1:0] b_addr,
95 | input wire [DATA-1:0] b_din,
96 | output reg [DATA-1:0] b_dout
97 | );
98 |
99 | reg [DATA-1:0] mem [(2**ADDR)-1:0];
100 |
101 | always @(posedge a_clk) begin
102 | if(a_wr) begin
103 | a_dout <= a_din;
104 | mem[a_addr] <= a_din;
105 | end else
106 | a_dout <= mem[a_addr];
107 | end
108 |
109 | always @(posedge b_clk) begin
110 | if(b_wr) begin
111 | b_dout <= b_din;
112 | mem[b_addr] <= b_din;
113 | end else
114 | b_dout <= mem[b_addr];
115 | end
116 |
117 | endmodule
118 |
119 |
120 | module bram_block_dp_nonstd #(
121 | parameter DATA = 32,
122 | parameter ADDR = 7,
123 | parameter DEPTH = 128
124 | ) (
125 | input wire a_clk,
126 | input wire a_wr,
127 | input wire [ADDR-1:0] a_addr,
128 | input wire [DATA-1:0] a_din,
129 | output reg [DATA-1:0] a_dout,
130 |
131 | input wire b_clk,
132 | input wire b_wr,
133 | input wire [ADDR-1:0] b_addr,
134 | input wire [DATA-1:0] b_din,
135 | output reg [DATA-1:0] b_dout
136 | );
137 |
138 | reg [DATA-1:0] mem [DEPTH-1:0];
139 |
140 | always @(posedge a_clk) begin
141 | if(a_wr) begin
142 | a_dout <= a_din;
143 | mem[a_addr] <= a_din;
144 | end else
145 | a_dout <= mem[a_addr];
146 | end
147 |
148 | always @(posedge b_clk) begin
149 | if(b_wr) begin
150 | b_dout <= b_din;
151 | mem[b_addr] <= b_din;
152 | end else
153 | b_dout <= mem[b_addr];
154 | end
155 |
156 | endmodule
157 |
--------------------------------------------------------------------------------
/platform/pocket/mf_datatable.qip:
--------------------------------------------------------------------------------
1 | set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT"
2 | set_global_assignment -name IP_TOOL_VERSION "18.1"
3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}"
4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "mf_datatable.v"]
5 |
--------------------------------------------------------------------------------
/platform/pocket/mf_ddio_bidir_12.qip:
--------------------------------------------------------------------------------
1 | set_global_assignment -name IP_TOOL_NAME "ALTDDIO_BIDIR"
2 | set_global_assignment -name IP_TOOL_VERSION "18.1"
3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}"
4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "mf_ddio_bidir_12.v"]
5 | set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "mf_ddio_bidir_12.ppf"]
6 |
--------------------------------------------------------------------------------
/platform/pocket/mf_ddio_bidir_12.v:
--------------------------------------------------------------------------------
1 | // megafunction wizard: %ALTDDIO_BIDIR%
2 | // GENERATION: STANDARD
3 | // VERSION: WM1.0
4 | // MODULE: ALTDDIO_BIDIR
5 |
6 | // ============================================================
7 | // File Name: mf_ddio_bidir_12.v
8 | // Megafunction Name(s):
9 | // ALTDDIO_BIDIR
10 | //
11 | // Simulation Library Files(s):
12 | // altera_mf
13 | // ============================================================
14 | // ************************************************************
15 | // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
16 | //
17 | // 18.1.1 Build 646 04/11/2019 SJ Lite Edition
18 | // ************************************************************
19 |
20 |
21 | //Copyright (C) 2019 Intel Corporation. All rights reserved.
22 | //Your use of Intel Corporation's design tools, logic functions
23 | //and other software and tools, and any partner logic
24 | //functions, and any output files from any of the foregoing
25 | //(including device programming or simulation files), and any
26 | //associated documentation or information are expressly subject
27 | //to the terms and conditions of the Intel Program License
28 | //Subscription Agreement, the Intel Quartus Prime License Agreement,
29 | //the Intel FPGA IP License Agreement, or other applicable license
30 | //agreement, including, without limitation, that your use is for
31 | //the sole purpose of programming logic devices manufactured by
32 | //Intel and sold by Intel or its authorized distributors. Please
33 | //refer to the applicable agreement for further details, at
34 | //https://fpgasoftware.intel.com/eula.
35 |
36 |
37 | // synopsys translate_off
38 | `timescale 1 ps / 1 ps
39 | // synopsys translate_on
40 | module mf_ddio_bidir_12 (
41 | datain_h,
42 | datain_l,
43 | inclock,
44 | oe,
45 | outclock,
46 | dataout_h,
47 | dataout_l,
48 | padio);
49 |
50 | input [11:0] datain_h;
51 | input [11:0] datain_l;
52 | input inclock;
53 | input oe;
54 | input outclock;
55 | output [11:0] dataout_h;
56 | output [11:0] dataout_l;
57 | inout [11:0] padio;
58 |
59 | wire [11:0] sub_wire0;
60 | wire [11:0] sub_wire1;
61 | wire [11:0] dataout_h = sub_wire0[11:0];
62 | wire [11:0] dataout_l = sub_wire1[11:0];
63 |
64 | altddio_bidir ALTDDIO_BIDIR_component (
65 | .datain_h (datain_h),
66 | .datain_l (datain_l),
67 | .inclock (inclock),
68 | .oe (oe),
69 | .outclock (outclock),
70 | .padio (padio),
71 | .dataout_h (sub_wire0),
72 | .dataout_l (sub_wire1),
73 | .aclr (1'b0),
74 | .aset (1'b0),
75 | .combout (),
76 | .dqsundelayedout (),
77 | .inclocken (1'b1),
78 | .oe_out (),
79 | .outclocken (1'b1),
80 | .sclr (1'b0),
81 | .sset (1'b0));
82 | defparam
83 | ALTDDIO_BIDIR_component.extend_oe_disable = "OFF",
84 | ALTDDIO_BIDIR_component.implement_input_in_lcell = "OFF",
85 | ALTDDIO_BIDIR_component.intended_device_family = "Cyclone V",
86 | ALTDDIO_BIDIR_component.invert_output = "OFF",
87 | ALTDDIO_BIDIR_component.lpm_hint = "UNUSED",
88 | ALTDDIO_BIDIR_component.lpm_type = "altddio_bidir",
89 | ALTDDIO_BIDIR_component.oe_reg = "UNREGISTERED",
90 | ALTDDIO_BIDIR_component.power_up_high = "OFF",
91 | ALTDDIO_BIDIR_component.width = 12;
92 |
93 |
94 | endmodule
95 |
96 | // ============================================================
97 | // CNX file retrieval info
98 | // ============================================================
99 | // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
100 | // Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone V"
101 | // Retrieval info: CONSTANT: EXTEND_OE_DISABLE STRING "OFF"
102 | // Retrieval info: CONSTANT: IMPLEMENT_INPUT_IN_LCELL STRING "OFF"
103 | // Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone V"
104 | // Retrieval info: CONSTANT: INVERT_OUTPUT STRING "OFF"
105 | // Retrieval info: CONSTANT: LPM_HINT STRING "UNUSED"
106 | // Retrieval info: CONSTANT: LPM_TYPE STRING "altddio_bidir"
107 | // Retrieval info: CONSTANT: OE_REG STRING "UNREGISTERED"
108 | // Retrieval info: CONSTANT: POWER_UP_HIGH STRING "OFF"
109 | // Retrieval info: CONSTANT: WIDTH NUMERIC "12"
110 | // Retrieval info: USED_PORT: datain_h 0 0 12 0 INPUT NODEFVAL "datain_h[11..0]"
111 | // Retrieval info: CONNECT: @datain_h 0 0 12 0 datain_h 0 0 12 0
112 | // Retrieval info: USED_PORT: datain_l 0 0 12 0 INPUT NODEFVAL "datain_l[11..0]"
113 | // Retrieval info: CONNECT: @datain_l 0 0 12 0 datain_l 0 0 12 0
114 | // Retrieval info: USED_PORT: dataout_h 0 0 12 0 OUTPUT NODEFVAL "dataout_h[11..0]"
115 | // Retrieval info: CONNECT: dataout_h 0 0 12 0 @dataout_h 0 0 12 0
116 | // Retrieval info: USED_PORT: dataout_l 0 0 12 0 OUTPUT NODEFVAL "dataout_l[11..0]"
117 | // Retrieval info: CONNECT: dataout_l 0 0 12 0 @dataout_l 0 0 12 0
118 | // Retrieval info: USED_PORT: inclock 0 0 0 0 INPUT_CLK_EXT NODEFVAL "inclock"
119 | // Retrieval info: CONNECT: @inclock 0 0 0 0 inclock 0 0 0 0
120 | // Retrieval info: USED_PORT: oe 0 0 0 0 INPUT NODEFVAL "oe"
121 | // Retrieval info: CONNECT: @oe 0 0 0 0 oe 0 0 0 0
122 | // Retrieval info: USED_PORT: outclock 0 0 0 0 INPUT_CLK_EXT NODEFVAL "outclock"
123 | // Retrieval info: CONNECT: @outclock 0 0 0 0 outclock 0 0 0 0
124 | // Retrieval info: USED_PORT: padio 0 0 12 0 BIDIR NODEFVAL "padio[11..0]"
125 | // Retrieval info: CONNECT: padio 0 0 12 0 @padio 0 0 12 0
126 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.v TRUE FALSE
127 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.qip TRUE FALSE
128 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.bsf FALSE TRUE
129 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12_inst.v FALSE TRUE
130 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12_bb.v FALSE TRUE
131 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.inc FALSE TRUE
132 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.cmp FALSE TRUE
133 | // Retrieval info: GEN_FILE: TYPE_NORMAL mf_ddio_bidir_12.ppf TRUE FALSE
134 | // Retrieval info: LIB_FILE: altera_mf
135 |
--------------------------------------------------------------------------------
/projects/snes_pocket.qip:
--------------------------------------------------------------------------------
1 | # ==============================================================================
2 | # Quartus Prime Platform Specific Modules File
3 | # Generated by OpenGateware - Gateman CLI v0.1.0
4 | # ==============================================================================
5 | # A single file that contains paths to platform specific third-party modules.
6 | # Quartus will use this file but won't edit it.
7 | # You need to edit it manually to add/remove files here.
8 | # ==============================================================================
9 |
10 |
--------------------------------------------------------------------------------
/projects/snes_pocket.qpf:
--------------------------------------------------------------------------------
1 | # ==============================================================================
2 | # Quartus Prime Project File
3 | # Generated by OpenGateware - Gateman CLI v0.1.0
4 | # ==============================================================================
5 |
6 | QUARTUS_VERSION = "18.1"
7 | DATE = "16:33:14 September 23, 2023"
8 |
9 | # Revisions
10 |
11 | PROJECT_REVISION = "snes_pocket"
12 |
--------------------------------------------------------------------------------
/projects/snes_pocket.qsf:
--------------------------------------------------------------------------------
1 | # ==============================================================================
2 | # Quartus Prime Settings File
3 | # Generated by OpenGateware - Gateman CLI v0.1.0
4 | # ==============================================================================
5 | # WARNING: DO NOT ADD FILES TO THE PROJECT VIA THE QUARTUS IDE!
6 | # Add them manually to nes_pocket.qip or Quartus will overwrite this file.
7 | # ==============================================================================
8 |
9 | # ==============================================================================
10 | # Project-Wide Assignments
11 | # ==============================================================================
12 | set_global_assignment -name ORIGINAL_QUARTUS_VERSION 18.1.1
13 | set_global_assignment -name LAST_QUARTUS_VERSION "21.1.1 Lite Edition"
14 | set_global_assignment -name TOP_LEVEL_ENTITY apf_top
15 | set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
16 | set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
17 | set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
18 | set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
19 |
20 | # ==============================================================================
21 | # Compiler Assignments
22 | # ==============================================================================
23 | set_global_assignment -name OPTIMIZATION_MODE "HIGH PERFORMANCE EFFORT"
24 | set_global_assignment -name SAVE_DISK_SPACE OFF
25 | set_global_assignment -name SEED 1
26 | set_global_assignment -name SMART_RECOMPILE ON
27 |
28 | # ==============================================================================
29 | # Analysis & Synthesis Assignments
30 | # ==============================================================================
31 | set_global_assignment -name ADV_NETLIST_OPT_SYNTH_WYSIWYG_REMAP ON
32 | set_global_assignment -name MUX_RESTRUCTURE OFF
33 | set_global_assignment -name OPTIMIZATION_TECHNIQUE SPEED
34 | set_global_assignment -name PRE_MAPPING_RESYNTHESIS ON
35 | set_global_assignment -name SAFE_STATE_MACHINE ON
36 | set_global_assignment -name SYNTH_PROTECT_SDC_CONSTRAINT ON
37 |
38 | # ==============================================================================
39 | # Fitter Assignments
40 | # ==============================================================================
41 | set_global_assignment -name ACTIVE_SERIAL_CLOCK FREQ_100MHZ
42 | set_global_assignment -name CRC_ERROR_OPEN_DRAIN ON
43 | set_global_assignment -name ECO_OPTIMIZE_TIMING ON
44 | set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 256
45 | set_global_assignment -name FITTER_EFFORT "AUTO FIT"
46 | set_global_assignment -name PERIPHERY_TO_CORE_PLACEMENT_AND_ROUTING_OPTIMIZATION ON
47 | set_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING ON
48 | set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC ON
49 | set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON
50 | set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON
51 | set_global_assignment -name ROUTER_CLOCKING_TOPOLOGY_ANALYSIS ON
52 | set_global_assignment -name ROUTER_LCELL_INSERTION_AND_LOGIC_DUPLICATION ON
53 | set_global_assignment -name STRATIXV_CONFIGURATION_SCHEME "PASSIVE SERIAL"
54 |
55 | # ==============================================================================
56 | # Platform/Core Assignments
57 | # ==============================================================================
58 | source ../platform/pocket/pocket.tcl
59 | set_global_assignment -name QIP_FILE snes_pocket.qip
60 | set_global_assignment -name SDC_FILE snes_pocket.sdc
61 | set_global_assignment -name QIP_FILE ../rtl/snes.qip
62 |
63 | # Default values
64 | set_parameter -name USE_CX4 '0 -entity MAIN_SNES
65 | set_parameter -name USE_SDD1 '0 -entity MAIN_SNES
66 | set_parameter -name USE_GSU '0 -entity MAIN_SNES
67 | set_parameter -name USE_SA1 '0 -entity MAIN_SNES
68 | set_parameter -name USE_DSPn '0 -entity MAIN_SNES
69 | set_parameter -name USE_SPC7110 '0 -entity MAIN_SNES
70 | set_parameter -name USE_BSX '0 -entity MAIN_SNES
71 | set_parameter -name USE_MSU '0 -entity MAIN_SNES
72 | set_parameter -name PAL_PLL '0 -entity core_top
73 |
74 | # ==============================================================================
75 |
76 |
77 | set_global_assignment -name FITTER_AGGRESSIVE_ROUTABILITY_OPTIMIZATION ALWAYS
78 | set_global_assignment -name ALM_REGISTER_PACKING_EFFORT LOW
79 | set_global_assignment -name NUM_PARALLEL_PROCESSORS 4
80 | set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
--------------------------------------------------------------------------------
/projects/snes_pocket.sdc:
--------------------------------------------------------------------------------
1 | # ==============================================================================
2 | # Quartus Prime Synopsys Design Constraint File
3 | # Generated by OpenGateware - Gateman CLI v0.1.0
4 | # ==============================================================================
5 | # pocket SDC settings
6 | # Users are recommended to modify this file to match users logic.
7 | # Put your clock groups in here as well as any net assignments.
8 | # ==============================================================================
9 |
10 | # ==============================================================================
11 | # Time Information
12 | # ==============================================================================
13 |
14 | # ==============================================================================
15 | # Create Clock
16 | # ==============================================================================
17 |
18 | # ==============================================================================
19 | # Create Generated Clock
20 | # ==============================================================================
21 |
22 | # ==============================================================================
23 | # Set Clock Latency
24 | # ==============================================================================
25 |
26 | # ==============================================================================
27 | # Set Clock Uncertainty
28 | # ==============================================================================
29 |
30 | # ==============================================================================
31 | # Set Input Delay
32 | # ==============================================================================
33 |
34 | # ==============================================================================
35 | # Set Output Delay
36 | # ==============================================================================
37 |
38 | # ==============================================================================
39 | # Set Clock Groups
40 | # ==============================================================================
41 |
42 | # ==============================================================================
43 | # Set False Path
44 | # ==============================================================================
45 |
46 | # ==============================================================================
47 | # Set Multicycle Path
48 | # ==============================================================================
49 |
50 | # ==============================================================================
51 | # Set Maximum Delay
52 | # ==============================================================================
53 |
54 | # ==============================================================================
55 | # Set Minimum Delay
56 | # ==============================================================================
57 |
58 | # ==============================================================================
59 | # Set Input Transition
60 | # ==============================================================================
61 |
62 |
--------------------------------------------------------------------------------
/rtl/65C816/65C816.qip:
--------------------------------------------------------------------------------
1 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) P65816_pkg.vhd ]
2 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) AddrGen.vhd ]
3 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) BCDAdder.vhd ]
4 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) AddSubBCD.vhd ]
5 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) ALU.vhd ]
6 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) MCode.vhd ]
7 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) P65C816.vhd ]
8 |
--------------------------------------------------------------------------------
/rtl/65C816/ALU.vhd:
--------------------------------------------------------------------------------
1 | library IEEE;
2 | use IEEE.std_logic_1164.all;
3 | use ieee.numeric_std.all;
4 | library work;
5 | use work.P65816_pkg.all;
6 |
7 | entity ALU is
8 | port(
9 | L : in std_logic_vector(15 downto 0);
10 | R : in std_logic_vector(15 downto 0);
11 | CTRL : in ALUCtrl_r;
12 | w16 : in std_logic;
13 | BCD : in std_logic;
14 | CI : in std_logic;
15 | VI : in std_logic;
16 | SI : in std_logic;
17 | CO : out std_logic;
18 | VO : out std_logic;
19 | SO : out std_logic;
20 | ZO : out std_logic;
21 | RES : out std_logic_vector(15 downto 0);
22 | IntR : out std_logic_vector(15 downto 0)
23 | );
24 | end ALU;
25 |
26 | architecture rtl of ALU is
27 |
28 | signal IntR16 : std_logic_vector(15 downto 0);
29 | signal IntR8 : std_logic_vector(7 downto 0);
30 | signal CR8, CR16, CR, ZR : std_logic;
31 | signal CIIn, ADDIn, BCDIn: std_logic;
32 |
33 | signal AddR : std_logic_vector(15 downto 0);
34 | signal AddCO, AddVO : std_logic;
35 | signal Result16 : std_logic_vector(15 downto 0);
36 | signal Result8 : std_logic_vector(7 downto 0);
37 |
38 | begin
39 |
40 | process(CTRL, CI, R)
41 | begin
42 | CR8 <= CI;
43 | CR16 <= CI;
44 | case CTRL.fstOp is
45 | when "000" =>
46 | CR8 <= R(7);
47 | CR16 <= R(15);
48 | IntR8 <= R(6 downto 0) & "0";
49 | IntR16 <= R(14 downto 0) & "0";
50 | when "001"=>
51 | CR8 <= R(7);
52 | CR16 <= R(15);
53 | IntR8 <= R(6 downto 0) & CI;
54 | IntR16 <= R(14 downto 0) & CI;
55 | when "010" =>
56 | CR8 <= R(0);
57 | CR16 <= R(0);
58 | IntR8 <= "0" & R(7 downto 1);
59 | IntR16 <= "0" & R(15 downto 1);
60 | when "011" =>
61 | CR8 <= R(0);
62 | CR16 <= R(0);
63 | IntR8 <= CI & R(7 downto 1);
64 | IntR16 <= CI & R(15 downto 1);
65 | when "100" =>
66 | IntR8 <= R(7 downto 0);
67 | IntR16 <= R;
68 | when "101" =>
69 | IntR8 <= R(15 downto 8);
70 | IntR16 <= R(7 downto 0) & R(15 downto 8);
71 | when "110" =>
72 | IntR8 <= std_logic_vector(unsigned(R(7 downto 0)) - 1); -- INC/DEC
73 | IntR16 <= std_logic_vector(unsigned(R) - 1); -- INC/DEC
74 | when "111" =>
75 | IntR8 <= std_logic_vector(unsigned(R(7 downto 0)) + 1); -- INC/DEC
76 | IntR16 <= std_logic_vector(unsigned(R) + 1); -- INC/DEC
77 | when others => null;
78 | end case;
79 | end process;
80 |
81 | CR <= CR8 when w16 = '0' else CR16;
82 |
83 | CIIn <= CR or not CTRL.secOp(0);
84 | ADDIn <= not CTRL.secOp(2);
85 | BCDIn <= BCD and CTRL.secOp(0);
86 |
87 | AddSub: entity work.AddSubBCD
88 | port map (
89 | A => L,
90 | B => R,
91 | CI => CIIn,
92 | ADD => ADDIn,
93 | BCD => BCDIn,
94 | w16 => w16,
95 | S => AddR,
96 | CO => AddCO,
97 | VO => AddVO
98 | );
99 |
100 | process(CTRL, w16, CR, IntR8, IntR16, L, AddCO, AddR)
101 | variable temp8 : std_logic_vector(7 downto 0);
102 | variable temp16 : std_logic_vector(15 downto 0);
103 | begin
104 | ZR <= '0';
105 | case CTRL.secOp is
106 | when "000" =>
107 | CO <= CR;
108 | Result8 <= L(7 downto 0) or IntR8;
109 | Result16 <= L or IntR16;
110 | when "001"=>
111 | CO <= CR;
112 | Result8 <= L(7 downto 0) and IntR8;
113 | Result16 <= L and IntR16;
114 | when "010" =>
115 | CO <= CR;
116 | Result8 <= L(7 downto 0) xor IntR8;
117 | Result16 <= L xor IntR16;
118 | when "011" | "110" | "111" =>
119 | CO <= AddCO;
120 | Result8 <= AddR(7 downto 0);
121 | Result16 <= AddR;
122 | when "100" =>
123 | CO <= CR;
124 | Result8 <= IntR8;
125 | Result16 <= IntR16;
126 | when "101" => --TRB,TSB
127 | CO <= CR;
128 | if CTRL.fc = '0' then
129 | Result8 <= IntR8 and (not L(7 downto 0));
130 | Result16 <= IntR16 and (not L);
131 | else
132 | Result8 <= IntR8 or L(7 downto 0);
133 | Result16 <= IntR16 or L;
134 | end if;
135 |
136 | temp8 := IntR8 and L(7 downto 0);
137 | temp16 := IntR16 and L;
138 | if (temp8 = x"00" and w16 = '0') or
139 | (temp16 = x"0000" and w16 = '1') then
140 | ZR <= '1';
141 | end if;
142 | when others => null;
143 | end case;
144 | end process;
145 |
146 | process(CTRL, w16, VI, SI, IntR8, IntR16, Result8, Result16, AddVO)
147 | begin
148 | VO <= VI;
149 | if w16 = '0' then
150 | SO <= Result8(7);
151 | else
152 | SO <= Result16(15);
153 | end if;
154 | case CTRL.secOp is
155 | when "001" =>
156 | if CTRL.fc = '1' then
157 | if w16 = '0' then
158 | VO <= IntR8(6); -- Set V to 6th bit for BIT
159 | SO <= IntR8(7);
160 | else
161 | VO <= IntR16(14); -- Set V to 14th bit for BIT
162 | SO <= IntR16(15);
163 | end if;
164 | end if;
165 | when "011" =>
166 | VO <= AddVO; -- ADC always sets V.
167 | when "101" => --TRB,TSB
168 | SO <= SI;
169 | when "111" =>
170 | if CTRL.fc = '1' then
171 | VO <= AddVO; -- Only SBC sets V.
172 | end if;
173 | when others => null;
174 | end case;
175 | end process;
176 |
177 |
178 | ZO <= ZR when CTRL.secOp = "101" else
179 | '1' when (w16 = '0' and Result8 = x"00") or (w16 = '1' and Result16 = x"0000") else
180 | '0';
181 |
182 | RES <= x"00"&Result8 when w16 = '0' else Result16;
183 | IntR <= x"00"&IntR8 when w16 = '0' else IntR16;
184 |
185 | end rtl;
--------------------------------------------------------------------------------
/rtl/65C816/AddSubBCD.vhd:
--------------------------------------------------------------------------------
1 | library IEEE;
2 | use IEEE.std_logic_1164.all;
3 | use ieee.numeric_std.all;
4 | library work;
5 | use work.P65816_pkg.all;
6 |
7 | entity AddSubBCD is
8 | port(
9 | A : in std_logic_vector(15 downto 0);
10 | B : in std_logic_vector(15 downto 0);
11 | CI : in std_logic;
12 | ADD : in std_logic;
13 | BCD : in std_logic;
14 | w16 : in std_logic;
15 | S : out std_logic_vector(15 downto 0);
16 | CO : out std_logic;
17 | VO : out std_logic
18 | );
19 | end AddSubBCD;
20 |
21 | architecture rtl of AddSubBCD is
22 |
23 | signal VO1, VO3 : std_logic;
24 | signal CO0, CO1, CO2, CO3 : std_logic;
25 |
26 | begin
27 |
28 | add0 : entity work.BCDAdder
29 | port map (
30 | A => A(3 downto 0),
31 | B => B(3 downto 0),
32 | CI => CI,
33 |
34 | S => S(3 downto 0),
35 | CO => CO0,
36 |
37 | ADD => ADD,
38 | BCD => BCD
39 | );
40 |
41 | add1 : entity work.BCDAdder
42 | port map (
43 | A => A(7 downto 4),
44 | B => B(7 downto 4),
45 | CI => CO0,
46 |
47 | S => S(7 downto 4),
48 | CO => CO1,
49 | VO => VO1,
50 |
51 | ADD => ADD,
52 | BCD => BCD
53 | );
54 |
55 | add2 : entity work.BCDAdder
56 | port map (
57 | A => A(11 downto 8),
58 | B => B(11 downto 8),
59 | CI => CO1,
60 |
61 | S => S(11 downto 8),
62 | CO => CO2,
63 |
64 | ADD => ADD,
65 | BCD => BCD
66 | );
67 |
68 | add3 : entity work.BCDAdder
69 | port map (
70 | A => A(15 downto 12),
71 | B => B(15 downto 12),
72 | CI => CO2,
73 |
74 | S => S(15 downto 12),
75 | CO => CO3,
76 | VO => VO3,
77 |
78 | ADD => ADD,
79 | BCD => BCD
80 | );
81 |
82 |
83 | VO <= VO1 when w16 = '0' else VO3;
84 | CO <= CO1 when w16 = '0' else CO3;
85 |
86 | end rtl;
--------------------------------------------------------------------------------
/rtl/65C816/BCDAdder.vhd:
--------------------------------------------------------------------------------
1 | library IEEE;
2 | use IEEE.STD_LOGIC_1164.ALL;
3 | library STD;
4 | use IEEE.NUMERIC_STD.ALL;
5 | library work;
6 |
7 | entity bit_adder is
8 | port(
9 | A : in std_logic;
10 | B : in std_logic;
11 | CI : in std_logic;
12 | S : out std_logic;
13 | CO : out std_logic
14 | );
15 | end bit_adder;
16 |
17 | architecture rtl of bit_adder is
18 |
19 | begin
20 |
21 | S <= (not A and not B and CI) or
22 | (not A and B and not CI) or
23 | ( A and not B and not CI) or
24 | ( A and B and CI);
25 |
26 | CO <= (not A and B and CI) or
27 | ( A and not B and CI) or
28 | ( A and B and not CI) or
29 | ( A and B and CI);
30 |
31 | end rtl;
32 |
33 |
34 |
35 | library IEEE;
36 | use IEEE.STD_LOGIC_1164.ALL;
37 | library STD;
38 | use IEEE.NUMERIC_STD.ALL;
39 | library work;
40 |
41 | entity adder4 is
42 | port(
43 | A : in std_logic_vector(3 downto 0);
44 | B : in std_logic_vector(3 downto 0);
45 | CI : in std_logic;
46 | S : out std_logic_vector(3 downto 0);
47 | CO : out std_logic
48 | );
49 | end adder4;
50 |
51 | architecture rtl of adder4 is
52 |
53 | component bit_adder is
54 | port(
55 | A : in std_logic;
56 | B : in std_logic;
57 | CI : in std_logic;
58 | S : out std_logic;
59 | CO : out std_logic
60 | );
61 | end component;
62 |
63 | signal CO0, CO1, CO2 : std_logic;
64 |
65 | begin
66 |
67 | b_add0: bit_adder port map (A(0), B(0), CI, S(0), CO0);
68 | b_add1: bit_adder port map (A(1), B(1), CO0, S(1), CO1);
69 | b_add2: bit_adder port map (A(2), B(2), CO1, S(2), CO2);
70 | b_add3: bit_adder port map (A(3), B(3), CO2, S(3), CO);
71 |
72 | end rtl;
73 |
74 |
75 | library IEEE;
76 | use IEEE.STD_LOGIC_1164.ALL;
77 | library STD;
78 | use IEEE.NUMERIC_STD.ALL;
79 | library work;
80 |
81 | entity BCDAdder is
82 | port(
83 | A : in std_logic_vector(3 downto 0);
84 | B : in std_logic_vector(3 downto 0);
85 | CI : in std_logic;
86 |
87 | S : out std_logic_vector(3 downto 0);
88 | CO : out std_logic;
89 | VO : out std_logic;
90 |
91 | ADD : in std_logic;
92 | BCD : in std_logic
93 | );
94 | end BCDAdder;
95 |
96 | architecture rtl of BCDAdder is
97 |
98 | signal B2 : std_logic_vector(3 downto 0);
99 | signal BIN_S : std_logic_vector(3 downto 0);
100 | signal BIN_CO : std_logic;
101 | signal BCD_B : std_logic_vector(3 downto 0);
102 | signal BCD_CO : std_logic;
103 |
104 | begin
105 |
106 | B2 <= B xor (3 downto 0 => not ADD);
107 |
108 | bin_adder : entity work.adder4
109 | port map(
110 | A => A,
111 | B => B2,
112 | CI => CI,
113 | S => BIN_S,
114 | CO => BIN_CO
115 | );
116 |
117 |
118 | BCD_CO <= (((BIN_S(3) and BIN_S(2)) or (BIN_S(3) and BIN_S(1))) and ADD) or (not (BIN_CO xor ADD));
119 | BCD_B <= not ADD & ((BCD_CO and BCD) xor not ADD) & ((BCD_CO and BCD) xor not ADD) & not ADD;
120 |
121 | bcd_corr_adder : entity work.adder4
122 | port map(
123 | A => BIN_S,
124 | B => BCD_B,
125 | CI => not ADD,
126 | S => S
127 | );
128 |
129 | CO <= BIN_CO when BCD = '0' else BCD_CO xor not ADD;
130 | VO <= (not (A(3) xor B2(3))) and (A(3) xor BIN_S(3));
131 |
132 | end rtl;
133 |
--------------------------------------------------------------------------------
/rtl/65C816/P65816_pkg.vhd:
--------------------------------------------------------------------------------
1 | library IEEE;
2 | use IEEE.std_logic_1164.all;
3 | use ieee.numeric_std.all;
4 |
5 | package P65816_pkg is
6 |
7 | type MicroInst_r is record
8 | stateCtrl : std_logic_vector(2 downto 0);
9 | addrBus : std_logic_vector(2 downto 0);
10 | addrInc : std_logic_vector(1 downto 0);
11 | loadP : std_logic_vector(2 downto 0);
12 | loadT : std_logic_vector(1 downto 0);
13 | muxCtrl : std_logic_vector(1 downto 0);
14 | addrCtrl : std_logic_vector(7 downto 0);
15 | loadPC : std_logic_vector(2 downto 0);
16 | loadSP : std_logic_vector(2 downto 0);
17 | regAXY : std_logic_vector(2 downto 0);
18 | loadDKB : std_logic_vector(1 downto 0);
19 | busCtrl : std_logic_vector(5 downto 0);
20 | ALUCtrl : std_logic_vector(4 downto 0);
21 | byteSel : std_logic_vector(1 downto 0);
22 | outBus : std_logic_vector(2 downto 0);
23 | va : std_logic_vector(1 downto 0);
24 | end record;
25 |
26 | type ALUCtrl_r is record
27 | fstOp : std_logic_vector(2 downto 0);
28 | secOp : std_logic_vector(2 downto 0);
29 | fc : std_logic;
30 | w16 : std_logic;
31 | end record;
32 |
33 | type MCode_r is record
34 | ALU_CTRL : ALUCtrl_r;
35 | STATE_CTRL : std_logic_vector(2 downto 0);
36 | ADDR_BUS : std_logic_vector(2 downto 0);
37 | ADDR_INC : std_logic_vector(1 downto 0);
38 | IND_CTRL : std_logic_vector(1 downto 0);
39 | ADDR_CTRL : std_logic_vector(7 downto 0);
40 | LOAD_PC : std_logic_vector(2 downto 0);
41 | LOAD_SP : std_logic_vector(2 downto 0);
42 | LOAD_AXY : std_logic_vector(2 downto 0);
43 | LOAD_P : std_logic_vector(2 downto 0);
44 | LOAD_T : std_logic_vector(1 downto 0);
45 | LOAD_DKB : std_logic_vector(1 downto 0);
46 | BUS_CTRL : std_logic_vector(5 downto 0);
47 | BYTE_SEL : std_logic_vector(1 downto 0);
48 | OUT_BUS : std_logic_vector(2 downto 0);
49 | VA : std_logic_vector(1 downto 0);
50 | end record;
51 |
52 | type addrIncTab_t is array(0 to 3) of unsigned(15 downto 0);
53 | constant INC_TAB: addrIncTab_t := (x"0000", x"0001", x"0002", x"0003");
54 |
55 | end P65816_pkg;
56 |
57 | package body P65816_pkg is
58 |
59 |
60 | end package body P65816_pkg;
61 |
--------------------------------------------------------------------------------
/rtl/CEGen.vhd:
--------------------------------------------------------------------------------
1 | LIBRARY ieee;
2 | USE ieee.std_logic_1164.all;
3 |
4 | ENTITY CEGen IS
5 | PORT
6 | (
7 | CLK : in STD_LOGIC;
8 | RST_N : in STD_LOGIC;
9 |
10 | IN_CLK : in integer;
11 | OUT_CLK : in integer;
12 |
13 | CE : out STD_LOGIC
14 | );
15 | END CEGen;
16 |
17 | ARCHITECTURE SYN OF CEGen IS
18 | BEGIN
19 | process( RST_N, CLK )
20 | variable CLK_SUM : integer;
21 | begin
22 | if RST_N = '0' then
23 | CLK_SUM := 0;
24 | CE <= '0';
25 | elsif falling_edge(CLK) then
26 | CE <= '0';
27 | CLK_SUM := CLK_SUM + OUT_CLK;
28 | if CLK_SUM >= IN_CLK then
29 | CLK_SUM := CLK_SUM - IN_CLK;
30 | CE <= '1';
31 | end if;
32 | end if;
33 | end process;
34 | END SYN;
35 |
--------------------------------------------------------------------------------
/rtl/SPC700/ALU.vhd:
--------------------------------------------------------------------------------
1 | library IEEE;
2 | use IEEE.std_logic_1164.all;
3 | use ieee.numeric_std.all;
4 | library work;
5 | use work.SPC700_pkg.all;
6 |
7 | entity SPC700_ALU is
8 | port(
9 | CLK : in std_logic;
10 | RST_N : in std_logic;
11 | EN : in std_logic;
12 | L : in std_logic_vector(7 downto 0);
13 | R : in std_logic_vector(7 downto 0);
14 | CTRL : in ALUCtrl_r;
15 | CI : in std_logic;
16 | VI : in std_logic;
17 | SI : in std_logic;
18 | ZI : in std_logic;
19 | HI : in std_logic;
20 | DivZI : in std_logic;
21 | DivVI : in std_logic;
22 | DivHI : in std_logic;
23 | DivSI : in std_logic;
24 | CO : out std_logic;
25 | VO : out std_logic;
26 | SO : out std_logic;
27 | ZO : out std_logic;
28 | HO : out std_logic;
29 | RES : out std_logic_vector(7 downto 0)
30 | );
31 | end SPC700_ALU;
32 |
33 | architecture rtl of SPC700_ALU is
34 |
35 | signal tIntR : std_logic_vector(7 downto 0);
36 | signal CR, COut, HOut, VOut, SOut, tZ, SaveC : std_logic;
37 | signal CIIn, ADDIn: std_logic;
38 |
39 | signal AddR, BCDR : std_logic_vector(7 downto 0);
40 | signal AddCO, AddVO, AddHO : std_logic;
41 | signal BCDCO : std_logic;
42 | signal tResult : std_logic_vector(7 downto 0);
43 |
44 | begin
45 |
46 | process(CTRL, CI, R)
47 | begin
48 | CR <= CI;
49 | case CTRL.fstOp is
50 | when "000" =>
51 | CR <= R(7);
52 | tIntR <= R(6 downto 0) & "0";
53 | when "001"=>
54 | CR <= R(7);
55 | tIntR <= R(6 downto 0) & CI;
56 | when "010" =>
57 | CR <= R(0);
58 | tIntR <= "0" & R(7 downto 1);
59 | when "011" =>
60 | CR <= R(0);
61 | tIntR <= CI & R(7 downto 1);
62 | when "100" =>
63 | tIntR <= x"00";
64 | when "101" => --INC,DEC
65 | tIntR <= x"01";
66 | when "110" =>
67 | tIntR <= R;
68 | when "111" =>
69 | tIntR <= not R;
70 | when others => null;
71 | end case;
72 | end process;
73 |
74 | process(CLK, RST_N)
75 | begin
76 | if RST_N = '0' then
77 | SaveC <= '0';
78 | elsif rising_edge(CLK) then
79 | if EN = '1' then
80 | if CTRL.secOp(3) = '1' then
81 | SaveC <= AddCO;
82 | end if;
83 | end if;
84 | end if;
85 | end process;
86 |
87 | CIIn <= SaveC when CTRL.intC = '1' else
88 | CI when CTRL.secOp(0) = '0' else
89 | CTRL.secOp(1);
90 |
91 | ADDIn <= not CTRL.secOp(1);
92 |
93 | AddSub: entity work.SPC700_AddSub
94 | port map (
95 | A => L,
96 | B => tIntR,
97 | CI => CIIn,
98 | ADD => ADDIn,
99 | S => AddR,
100 | CO => AddCO,
101 | VO => AddVO,
102 | HO => AddHO
103 | );
104 |
105 | BCD: entity work.SPC700_BCDAdj
106 | port map (
107 | A => L,
108 | ADD => CTRL.secOp(0),
109 | CI => CI,
110 | HI => HI,
111 | R => BCDR,
112 | CO => BCDCO
113 | );
114 |
115 | process(CTRL, CR, tIntR, L, AddCO, AddHO, BCDCO, AddR, BCDR, DivHI)
116 | begin
117 | HOut <= '0';
118 | COut <= CR;
119 | case CTRL.secOp is
120 | when "0000" =>
121 | tResult <= L or tIntR;
122 | when "0001"=>
123 | tResult <= L and tIntR;
124 | when "0010" =>
125 | tResult <= L xor tIntR;
126 | when "0011" =>
127 | tResult <= tIntR;
128 | when "0100" => --TCLR1
129 | tResult <= tIntR and (not L);
130 | when "0101" => --TSET1
131 | tResult <= tIntR or L;
132 | when "0110" => --XCN
133 | tResult <= tIntR(3 downto 0) & tIntR(7 downto 4);
134 | when "1000" | "1010" | "1001" | "1011" => --ADC,SBC, ADD,SUB
135 | tResult <= AddR;
136 | COut <= AddCO;
137 | HOut <= AddHO;
138 | when "1100" | "1101" => --DAA,DAS
139 | tResult <= BCDR;
140 | COut <= BCDCO;
141 | when "1110" => --MUL
142 | tResult <= tIntR;
143 | when "1111" => --DIV
144 | tResult <= tIntR;
145 | HOut <= DivHI;
146 | when others =>
147 | tResult <= x"00";
148 | end case;
149 | end process;
150 |
151 | process(CTRL, VI, AddVO, DivVI)
152 | begin
153 | VOut <= VI;
154 | case CTRL.secOp is
155 | when "1000" | "1001" => --ADC,ADD
156 | VOut <= AddVO;
157 | when "1010" | "1011" => --SBC,SUB
158 | VOut <= AddVO;
159 | when "1111" => --DIV
160 | VOut <= DivVI;
161 | when others => null;
162 | end case;
163 | end process;
164 |
165 | process(CTRL, SI, tResult, DivSI)
166 | begin
167 | SOut <= SI;
168 | case CTRL.secOp is
169 | when "1110" => --MUL
170 | SOut <= DivSI;
171 | when "1111" => --DIV
172 | SOut <= DivSI;
173 | when others =>
174 | SOut <= tResult(7);
175 | end case;
176 | end process;
177 |
178 | tZ <= DivZI when CTRL.secOp(3 downto 1) = "111" else
179 | '1' when tResult = x"00" else '0';
180 | ZO <= ZI and tZ when CTRL.w = '1' else tZ;
181 | CO <= COut when CTRL.chgCO = '1' else CI;
182 | VO <= VOut when CTRL.chgVO = '1' else VI;
183 | HO <= HOut when CTRL.chgHO = '1' else HI;
184 | SO <= SOut;
185 |
186 | RES <= tResult;
187 |
188 | end rtl;
--------------------------------------------------------------------------------
/rtl/SPC700/AddSub.vhd:
--------------------------------------------------------------------------------
1 | library IEEE;
2 | use IEEE.std_logic_1164.all;
3 | use ieee.numeric_std.all;
4 | library work;
5 | use work.SPC700_pkg.all;
6 |
7 | entity SPC700_AddSub is
8 | port(
9 | A : in std_logic_vector(7 downto 0);
10 | B : in std_logic_vector(7 downto 0);
11 | CI : in std_logic;
12 | ADD : in std_logic;
13 | S : out std_logic_vector(7 downto 0);
14 | CO : out std_logic;
15 | VO : out std_logic;
16 | HO : out std_logic
17 | );
18 | end SPC700_AddSub;
19 |
20 | architecture rtl of SPC700_AddSub is
21 |
22 | signal tempB : std_logic_vector(7 downto 0);
23 | signal res : unsigned(7 downto 0);
24 | signal C7 : std_logic;
25 |
26 | begin
27 |
28 | tempB <= B when ADD = '1' else B xor x"FF";
29 |
30 | process(A, tempB, CI, ADD)
31 | variable temp0, temp1 : unsigned(4 downto 0);
32 | begin
33 | temp0 := ('0' & unsigned(A(3 downto 0))) + ('0' & unsigned(tempB(3 downto 0))) + ("0000" & CI);
34 | temp1 := ('0' & unsigned(A(7 downto 4))) + ('0' & unsigned(tempB(7 downto 4))) + ("0000" & temp0(4));
35 |
36 | res <= temp1(3 downto 0) & temp0(3 downto 0);
37 | C7 <= temp1(4);
38 | end process;
39 |
40 | S <= std_logic_vector(res);
41 | VO <= (not (A(7) xor tempB(7))) and (A(7) xor res(7));
42 | HO <= (A(4) xor B(4) xor res(4)) xor not ADD;
43 | CO <= C7;
44 |
45 | end rtl;
--------------------------------------------------------------------------------
/rtl/SPC700/AddrGen.vhd:
--------------------------------------------------------------------------------
1 | library IEEE;
2 | use IEEE.std_logic_1164.all;
3 | use ieee.numeric_std.all;
4 | library work;
5 | use work.SPC700_pkg.all;
6 |
7 | entity SPC700_AddrGen is
8 | port(
9 | CLK : in std_logic;
10 | RST_N : in std_logic;
11 | EN : in std_logic;
12 | ADDR_CTRL : in std_logic_vector(5 downto 0);
13 | LOAD_PC : in std_logic_vector(2 downto 0);
14 | GotInterrupt : in std_logic;
15 | D_IN : in std_logic_vector(7 downto 0);
16 | X : in std_logic_vector(7 downto 0);
17 | Y : in std_logic_vector(7 downto 0);
18 | S : in std_logic_vector(7 downto 0);
19 | T : in std_logic_vector(7 downto 0);
20 | P : in std_logic;
21 | PC : out std_logic_vector(15 downto 0);
22 | AX : out std_logic_vector(15 downto 0);
23 | ALCarry : out std_logic;
24 |
25 | REG_DAT : in std_logic_vector(15 downto 0);
26 | REG_SET : in std_logic
27 | );
28 | end SPC700_AddrGen;
29 |
30 | architecture rtl of SPC700_AddrGen is
31 |
32 | signal AL, AH : std_logic_vector(7 downto 0);
33 | signal SavedCarry : std_logic;
34 |
35 | signal NewAL, NewAH : std_logic_vector(8 downto 0);
36 | signal NewAHWithCarry : std_logic_vector(7 downto 0);
37 | signal NextAX : std_logic_vector(15 downto 0);
38 |
39 | signal DR : std_logic_vector(7 downto 0);
40 | signal PCr: std_logic_vector(15 downto 0);
41 | signal NextPC, NewPCWithOffset: std_logic_vector(15 downto 0);
42 |
43 | signal ALCtrl : std_logic_vector(1 downto 0);
44 | signal AHCtrl : std_logic_vector(1 downto 0);
45 | signal MuxCtrl : std_logic_vector(1 downto 0);
46 |
47 | begin
48 |
49 | ALCtrl <= ADDR_CTRL(5 downto 4);
50 | AHCtrl <= ADDR_CTRL(3 downto 2);
51 | MuxCtrl <= ADDR_CTRL(1 downto 0);
52 |
53 | NewPCWithOffset <= std_logic_vector(unsigned(PCr) + unsigned((7 downto 0 => DR(7)) & DR));
54 |
55 | process(LOAD_PC, PCr, D_IN, DR, NewPCWithOffset, AL, AH, GotInterrupt)
56 | begin
57 | case LOAD_PC is
58 | when "000" =>
59 | NextPC <= PCr;
60 | when "001" =>
61 | if GotInterrupt = '0' then
62 | NextPC <= std_logic_vector(unsigned(PCr) + 1);
63 | else
64 | NextPC <= PCr;
65 | end if;
66 | when "010"=>
67 | NextPC <= D_IN & DR;
68 | when "011" =>
69 | NextPC <= NewPCWithOffset;
70 | when "100" =>
71 | NextPC <= AH & AL;
72 | when "101" =>
73 | NextPC <= x"FF" & AL;
74 | when others =>
75 | NextPC <= PCr;
76 | end case;
77 | end process;
78 |
79 | process(CLK, RST_N)
80 | begin
81 | if RST_N = '0' then
82 | PCr <= (others=>'0');
83 | DR <= (others=>'0');
84 | elsif rising_edge(CLK) then
85 | if REG_SET = '1' then
86 | PCr <= REG_DAT;
87 | elsif EN = '0' then
88 |
89 | else
90 | DR <= D_IN;
91 | PCr <= NextPC;
92 | end if;
93 | end if;
94 | end process;
95 |
96 |
97 | process(MuxCtrl, AL, X, Y, DR)
98 | begin
99 | case MuxCtrl is
100 | when "00" =>
101 | NewAL <= std_logic_vector(unsigned("0" & AL) + unsigned("0" & X));
102 | when "01" =>
103 | NewAL <= std_logic_vector(unsigned("0" & AL) + unsigned("0" & Y));
104 | when "10"=>
105 | NewAL <= "0" & DR;
106 | when "11" =>
107 | NewAL <= std_logic_vector(unsigned("0" & DR) + unsigned("0" & Y));
108 | when others => null;
109 | end case;
110 | end process;
111 |
112 | NewAHWithCarry <= std_logic_vector(unsigned(AH) + ("0000000"&SavedCarry));
113 | NextAX <= std_logic_vector((unsigned(AH) & unsigned(AL)) + 1);
114 |
115 | process(CLK, RST_N)
116 | begin
117 | if RST_N = '0' then
118 | AL <= (others=>'0');
119 | AH <= (others=>'0');
120 | SavedCarry <= '0';
121 | elsif rising_edge(CLK) then
122 | if EN = '1' then
123 | case ALCtrl is
124 | when "00" => SavedCarry <= '0';
125 | when "01" => AL <= NewAL(7 downto 0); SavedCarry <= NewAL(8);
126 | when "10" =>
127 | case MuxCtrl is
128 | when "00" => AL <= D_IN;
129 | when "01" => AL <= X;
130 | when "10" => AL <= Y;
131 | when others => null;
132 | end case;
133 | SavedCarry <= '0';
134 | when "11" => AL <= std_logic_vector(NextAX(7 downto 0)); SavedCarry <= '0';
135 | when others => null;
136 | end case;
137 |
138 | case AHCtrl is
139 | when "00" => null;
140 | when "01" => AH <= "0000000"&P;
141 | when "10" => AH <= D_IN;
142 | when "11" =>
143 | if ALCtrl /= "11" then
144 | AH <= NewAHWithCarry;
145 | else
146 | AH <= std_logic_vector(NextAX(15 downto 8));
147 | end if;
148 | when others => null;
149 | end case;
150 |
151 | end if;
152 | end if;
153 | end process;
154 |
155 | ALCarry <= NewAL(8);
156 | AX <= AH & AL;
157 | PC <= PCr;
158 |
159 | end rtl;
--------------------------------------------------------------------------------
/rtl/SPC700/BCDAdj.vhd:
--------------------------------------------------------------------------------
1 | library IEEE;
2 | use IEEE.std_logic_1164.all;
3 | use ieee.numeric_std.all;
4 | library work;
5 | use work.SPC700_pkg.all;
6 |
7 | entity SPC700_BCDAdj is
8 | port(
9 | A : in std_logic_vector(7 downto 0);
10 | ADD : in std_logic;
11 | CI : in std_logic;
12 | HI : in std_logic;
13 | R : out std_logic_vector(7 downto 0);
14 | CO : out std_logic
15 | );
16 | end SPC700_BCDAdj;
17 |
18 | architecture rtl of SPC700_BCDAdj is
19 |
20 | signal res : unsigned(7 downto 0);
21 | signal tempC : std_logic;
22 |
23 | begin
24 |
25 | process(A, CI, HI, ADD)
26 | variable temp0, temp1 : unsigned(7 downto 0);
27 | begin
28 | temp0 := unsigned(A);
29 | tempC <= CI;
30 |
31 | temp1 := temp0;
32 | if CI = not ADD or temp0 > x"99" then
33 | if ADD = '0' then
34 | temp1 := temp0 + x"60";
35 | else
36 | temp1 := temp0 - x"60";
37 | end if;
38 | tempC <= not ADD;
39 | end if;
40 |
41 | res <= temp1;
42 | if HI = not ADD or temp1(3 downto 0) > x"9" then
43 | if ADD = '0' then
44 | res <= temp1 + x"06";
45 | else
46 | res <= temp1 - x"06";
47 | end if;
48 | end if;
49 | end process;
50 |
51 | R <= std_logic_vector(res);
52 | CO <= tempC;
53 |
54 | end rtl;
--------------------------------------------------------------------------------
/rtl/SPC700/MulDiv.vhd:
--------------------------------------------------------------------------------
1 | library IEEE;
2 | use IEEE.std_logic_1164.all;
3 | use ieee.numeric_std.all;
4 | library work;
5 | use work.SPC700_pkg.all;
6 |
7 |
8 | entity MulDiv is
9 | port(
10 | CLK : in std_logic;
11 | RST_N : in std_logic;
12 | EN : in std_logic;
13 | CTRL : in ALUCtrl_r;
14 | A : in std_logic_vector(7 downto 0);
15 | X : in std_logic_vector(7 downto 0);
16 | Y : in std_logic_vector(7 downto 0);
17 | RES : out std_logic_vector(15 downto 0);
18 | ZO : out std_logic;
19 | VO : out std_logic;
20 | HO : out std_logic;
21 | SO : out std_logic
22 | );
23 | end MulDiv;
24 |
25 | architecture rtl of MulDiv is
26 |
27 | signal tResult : std_logic_vector(15 downto 0);
28 | signal tV, tZ, tS : std_logic;
29 | signal mulRes, mulTemp : unsigned(15 downto 0);
30 | signal mulA : unsigned(15 downto 0);
31 | signal mulY : unsigned(7 downto 0);
32 | signal divt : unsigned(15 downto 0);
33 | signal quotient : unsigned(8 downto 0);
34 | signal remainder : unsigned(15 downto 0);
35 |
36 | begin
37 |
38 | process(CLK, RST_N)
39 | begin
40 | if RST_N = '0' then
41 | mulA <= (others=>'0');
42 | mulY <= (others=>'0');
43 | mulRes <= (others=>'0');
44 | divt <= (others=>'0');
45 | remainder <= (others=>'0');
46 | quotient <= (others=>'0');
47 | elsif rising_edge(CLK) then
48 | if EN = '1' then
49 | if CTRL.secOp = "1110" then
50 | mulRes <= mulTemp;
51 | mulA <= mulA(14 downto 0) & "0";
52 | mulY <= "0" & mulY(7 downto 1);
53 | elsif CTRL.secOp = "1111" then
54 | if remainder >= divt then
55 | remainder <= remainder - divt;
56 | quotient <= quotient(7 downto 0) & "1";
57 | else
58 | quotient <= quotient(7 downto 0) & "0";
59 | end if;
60 | divt <= "0" & divt(15 downto 1);
61 | else
62 | mulA <= unsigned("00000000" & A);
63 | mulY <= unsigned(Y);
64 | mulRes <= (others=>'0');
65 | divt <= unsigned(X & "00000000");
66 | remainder <= unsigned(Y & A);
67 | quotient <= (others=>'0');
68 | end if;
69 | end if;
70 | end if;
71 | end process;
72 |
73 | process(CTRL, mulA, mulY, mulRes, mulTemp, quotient, remainder)
74 | begin
75 | mulTemp <= (others=>'0');
76 | if CTRL.secOp = "1110" then
77 | if mulY(0) = '1' then
78 | mulTemp <= mulRes + mulA;
79 | else
80 | mulTemp <= mulRes;
81 | end if;
82 | tResult <= std_logic_vector(mulTemp);
83 | if mulTemp(15 downto 8) = 0 then
84 | tZ <= '1';
85 | else
86 | tZ <= '0';
87 | end if;
88 | tV <= '0';
89 | tS <= mulTemp(15);
90 | elsif CTRL.secOp = "1111" then
91 | tResult <= std_logic_vector(remainder(7 downto 0) & quotient(7 downto 0));
92 | if quotient(7 downto 0) = 0 then
93 | tZ <= '1';
94 | else
95 | tZ <= '0';
96 | end if;
97 | tV <= quotient(8);
98 | tS <= quotient(7);
99 | else
100 | tResult <= (others=>'0');
101 | tZ <= '0';
102 | tV <= '0';
103 | tS <= '0';
104 | end if;
105 | end process;
106 |
107 | RES <= tResult;
108 | ZO <= tZ;
109 | VO <= tV;
110 | SO <= tS;
111 | HO <= '1' when Y(3 downto 0) >= X(3 downto 0) else '0';
112 |
113 | end rtl;
--------------------------------------------------------------------------------
/rtl/SPC700/SPC700.qip:
--------------------------------------------------------------------------------
1 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) SPC700_pkg.vhd ]
2 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) AddrGen.vhd ]
3 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) AddSub.vhd ]
4 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) ALU.vhd ]
5 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) BCDAdj.vhd ]
6 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) MCode.vhd ]
7 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) MulDiv.vhd ]
8 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) SPC700.vhd ]
9 |
--------------------------------------------------------------------------------
/rtl/SPC700/SPC700_pkg.vhd:
--------------------------------------------------------------------------------
1 | library IEEE;
2 | use IEEE.Std_Logic_1164.all;
3 |
4 | package SPC700_pkg is
5 |
6 | type MicroInst_r is record
7 | stateCtrl : std_logic_vector(1 downto 0);
8 | addrBus : std_logic_vector(1 downto 0);
9 | addrCtrl : std_logic_vector(5 downto 0);
10 | regMode : std_logic_vector(4 downto 0);
11 | regAXY : std_logic_vector(1 downto 0);
12 | busCtrl : std_logic_vector(5 downto 0);
13 | ALUCtrl : std_logic_vector(5 downto 0);
14 | outBus : std_logic_vector(2 downto 0);
15 | end record;
16 |
17 | type ALUCtrl_r is record
18 | fstOp : std_logic_vector(2 downto 0);
19 | secOp : std_logic_vector(3 downto 0);
20 | chgVO : std_logic;
21 | chgHO : std_logic;
22 | intC : std_logic;
23 | chgCO : std_logic;
24 | w : std_logic;
25 | end record;
26 |
27 | type RegCtrl_r is record
28 | loadPC : std_logic_vector(2 downto 0);
29 | loadSP : std_logic_vector(1 downto 0);
30 | loadP : std_logic_vector(2 downto 0);
31 | loadT : std_logic_vector(1 downto 0);
32 | end record;
33 |
34 | type MCode_r is record
35 | ALU_CTRL : ALUCtrl_r;
36 | STATE_CTRL : std_logic_vector(1 downto 0);
37 | ADDR_BUS : std_logic_vector(1 downto 0);
38 | ADDR_CTRL : std_logic_vector(5 downto 0);
39 | LOAD_PC : std_logic_vector(2 downto 0);
40 | LOAD_SP : std_logic_vector(1 downto 0);
41 | LOAD_AXY : std_logic_vector(1 downto 0);
42 | LOAD_P : std_logic_vector(2 downto 0);
43 | LOAD_T : std_logic_vector(1 downto 0);
44 | BUS_CTRL : std_logic_vector(5 downto 0);
45 | OUT_BUS : std_logic_vector(2 downto 0);
46 | end record;
47 |
48 | end SPC700_pkg;
49 |
50 | package body SPC700_pkg is
51 |
52 |
53 | end package body SPC700_pkg;
54 |
--------------------------------------------------------------------------------
/rtl/SWRAM.vhd:
--------------------------------------------------------------------------------
1 | library IEEE;
2 | use IEEE.STD_LOGIC_1164.ALL;
3 | library STD;
4 | use IEEE.NUMERIC_STD.ALL;
5 |
6 | entity SWRAM is
7 | port(
8 | CLK : in std_logic;
9 | SYSCLK_CE : in std_logic;
10 | RST_N : in std_logic;
11 | ENABLE : in std_logic;
12 |
13 | CA : in std_logic_vector(23 downto 0);
14 | CPURD_N : in std_logic;
15 | CPUWR_N : in std_logic;
16 | RAMSEL_N : in std_logic;
17 |
18 | PA : in std_logic_vector(7 downto 0);
19 | PARD_N : in std_logic;
20 | PAWR_N : in std_logic;
21 |
22 | DI : in std_logic_vector(7 downto 0);
23 | DO : out std_logic_vector(7 downto 0);
24 |
25 | RAM_A : out std_logic_vector(16 downto 0);
26 | RAM_D : out std_logic_vector(7 downto 0);
27 | RAM_Q : in std_logic_vector(7 downto 0);
28 | RAM_WE_N : out std_logic;
29 | RAM_CE_N : out std_logic;
30 | RAM_OE_N : out std_logic
31 | );
32 | end SWRAM;
33 |
34 | architecture rtl of SWRAM is
35 |
36 | signal WMADD : std_logic_vector(23 downto 0);
37 |
38 | begin
39 |
40 | process( RST_N, CLK )
41 | begin
42 | if RST_N = '0' then
43 | WMADD <= (others => '0');
44 | elsif rising_edge(CLK) then
45 | if ENABLE = '1' and SYSCLK_CE = '1' then
46 | if PAWR_N = '0' then
47 | case PA is
48 | when x"80" =>
49 | if RAMSEL_N = '1' then --check if DMA use WRAM in ABUS
50 | WMADD <= std_logic_vector(unsigned(WMADD) + 1);
51 | end if;
52 | when x"81" =>
53 | WMADD(7 downto 0) <= DI;
54 | when x"82" =>
55 | WMADD(15 downto 8) <= DI;
56 | when x"83" =>
57 | WMADD(23 downto 16) <= DI;
58 | when others => null;
59 | end case;
60 | elsif PARD_N = '0' then
61 | case PA is
62 | when x"80" =>
63 | if RAMSEL_N = '1' then --check if DMA use WRAM in ABUS
64 | WMADD <= std_logic_vector(unsigned(WMADD) + 1);
65 | end if;
66 | when others => null;
67 | end case;
68 | end if;
69 | end if;
70 | end if;
71 | end process;
72 |
73 | DO <= RAM_Q;
74 | RAM_D <= x"FF" when PA = x"80" and RAMSEL_N = '0' else DI;
75 |
76 | RAM_A <= CA(16 downto 0) when RAMSEL_N = '0' else
77 | WMADD(16 downto 0);
78 |
79 | RAM_CE_N <= '0' when ENABLE = '0' else
80 | '0' when RAMSEL_N = '0' else
81 | '0' when PA = x"80" else
82 | '1';
83 |
84 | RAM_OE_N <= '0' when ENABLE = '0' else
85 | '0' when RAMSEL_N = '0' and CPURD_N = '0' else
86 | '0' when PA = x"80" and PARD_N = '0' and RAMSEL_N = '1' else
87 | '1';
88 |
89 | RAM_WE_N <= '1' when ENABLE = '0' else
90 | '0' when RAMSEL_N = '0' and CPUWR_N = '0' else
91 | '0' when PA = x"80" and PAWR_N = '0' and RAMSEL_N = '1' else
92 | '1';
93 |
94 | end rtl;
95 |
96 |
--------------------------------------------------------------------------------
/rtl/cheatcodes.sv:
--------------------------------------------------------------------------------
1 | // Cheat Code handling by Kitrinx
2 | // Apr 21, 2019
3 |
4 | // Code layout:
5 | // {clock bit, code flags, 32'b address, 32'b compare, 32'b replace}
6 | // 128 127:96 95:64 63:32 31:0
7 | // Integer values are in BIG endian byte order, so it up to the loader
8 | // or generator of the code to re-arrange them correctly.
9 |
10 | module CODES(
11 | input clk, // Best to not make it too high speed for timing reasons
12 | input reset, // This should only be triggered when a new rom is loaded or before new codes load, not warm reset
13 | input enable,
14 | output available,
15 | input [ADDR_WIDTH - 1:0] addr_in,
16 | input [DATA_WIDTH - 1:0] data_in,
17 | input [128:0] code,
18 | output genie_ovr,
19 | output [DATA_WIDTH - 1:0] genie_data
20 | );
21 |
22 | parameter ADDR_WIDTH = 16; // Not more than 32
23 | parameter DATA_WIDTH = 8; // Not more than 32
24 | parameter MAX_CODES = 32;
25 |
26 | localparam INDEX_SIZE = $clog2(MAX_CODES-1); // Number of bits for index, must accomodate MAX_CODES
27 |
28 | localparam DATA_S = DATA_WIDTH - 1;
29 | localparam COMP_S = DATA_S + DATA_WIDTH;
30 | localparam ADDR_S = COMP_S + ADDR_WIDTH;
31 | localparam COMP_F_S = ADDR_S + 1;
32 | localparam ENA_F_S = COMP_F_S + 1;
33 | localparam CODE_WIDTH = ENA_F_S + 1;
34 |
35 | reg [ENA_F_S:0] codes[MAX_CODES];
36 |
37 | wire [ADDR_WIDTH-1: 0] code_addr = code[64+:ADDR_WIDTH];
38 | wire [DATA_WIDTH-1: 0] code_compare = code[32+:DATA_WIDTH];
39 | wire [DATA_WIDTH-1: 0] code_data = code[0+:DATA_WIDTH];
40 | wire code_comp_f = code[96];
41 |
42 | wire [COMP_F_S:0] code_trimmed = {code_comp_f, code_addr, code_compare, code_data};
43 |
44 | // If MAX_INDEX is changes, these need to be made larger
45 | wire [INDEX_SIZE-1:0] index, dup_index;
46 | reg [INDEX_SIZE:0] next_index;
47 | wire found_dup;
48 |
49 | assign index = found_dup ? dup_index : next_index[INDEX_SIZE-1:0];
50 |
51 | // See if the code exists already, so it can be disabled if loaded again
52 | always_comb begin
53 | int x;
54 | dup_index = 0;
55 | found_dup = 0;
56 |
57 | for (x = 0; x < MAX_CODES; x = x + 1) begin
58 | if (codes[x][ADDR_S-:ADDR_WIDTH] == code_addr) begin
59 | dup_index = x[INDEX_SIZE-1:0];
60 | found_dup = 1;
61 | end
62 | end
63 | end
64 |
65 | assign available = |next_index;
66 |
67 | reg code_change;
68 | always_ff @(posedge clk) begin
69 | int x;
70 | if (reset) begin
71 | next_index <= 0;
72 | code_change <= 0;
73 | for (x = 0; x < MAX_CODES; x = x + 1) codes[x] <= '0;
74 | end else begin
75 | code_change <= code[128];
76 | if (code[128] && ~code_change && (found_dup || next_index < MAX_CODES)) begin // detect posedge
77 | // replace it enabled if it has the same address, otherwise, add a new code
78 | codes[index] <= {1'b1, code_trimmed};
79 | if (~found_dup) next_index <= next_index + 1'b1;
80 | end
81 | end
82 | end
83 |
84 | always_comb begin
85 | int x;
86 | genie_ovr = 0;
87 | genie_data = '0;
88 |
89 | if (enable) begin
90 | for (x = 0; x < MAX_CODES; x = x + 1) begin
91 | if (codes[x][ENA_F_S] && codes[x][ADDR_S-:ADDR_WIDTH] == addr_in) begin
92 | if (!codes[x][COMP_F_S] || (codes[x][COMP_S-:DATA_WIDTH] == data_in)) begin
93 | genie_ovr = 1;
94 | genie_data = codes[x][DATA_S-:DATA_WIDTH];
95 | end
96 | end
97 | end
98 | end
99 | end
100 |
101 | endmodule
102 |
--------------------------------------------------------------------------------
/rtl/chip/BSX/BSX_DP.vhd:
--------------------------------------------------------------------------------
1 | library IEEE;
2 | use IEEE.STD_LOGIC_1164.ALL;
3 | library STD;
4 | use IEEE.NUMERIC_STD.ALL;
5 | library work;
6 |
7 | entity DATAPAK is
8 | port(
9 | CLK : in std_logic;
10 | RST_N : in std_logic;
11 | ENABLE : in std_logic;
12 |
13 | A : in std_logic_vector(19 downto 0);
14 | DI : in std_logic_vector(7 downto 0);
15 | DO : out std_logic_vector(7 downto 0);
16 | CE_N : in std_logic;
17 | RD_N : in std_logic;
18 | WR_N : in std_logic;
19 | SYSCLKF_CE : in std_logic;
20 | SYSCLKR_CE : in std_logic;
21 |
22 | MEM_ADDR : out std_logic_vector(19 downto 0);
23 | MEM_DI : in std_logic_vector(7 downto 0);
24 | MEM_DO : out std_logic_vector(7 downto 0);
25 | MEM_RD : out std_logic;
26 | MEM_WR : out std_logic
27 | );
28 | end DATAPAK;
29 |
30 | architecture rtl of DATAPAK is
31 |
32 | signal IO_REG : std_logic_vector(13 downto 0);
33 | signal PREV_COM : std_logic_vector(7 downto 0);
34 | signal CSR : std_logic;
35 | signal ESR : std_logic;
36 | signal VEN : std_logic;
37 | signal BYTE_WRITE : std_logic;
38 |
39 | type FlashStates_t is (
40 | FS_IDLE,
41 | FS_READ,
42 | FS_WRITE,
43 | FS_ERASE
44 | );
45 | signal FS : FlashStates_t;
46 | signal WRITE_ADDR : std_logic_vector(19 downto 0);
47 | signal WRITE_DATA : std_logic_vector(7 downto 0);
48 | signal READ_DATA : std_logic_vector(7 downto 0);
49 | signal WRITE_PEND : std_logic;
50 | signal PAGE_ERASE_PEND : std_logic;
51 | signal CHIP_ERASE_PEND : std_logic;
52 |
53 | begin
54 |
55 | process( RST_N, CLK)
56 | begin
57 | if RST_N = '0' then
58 | CSR <= '0';
59 | ESR <= '0';
60 | VEN <= '0';
61 | BYTE_WRITE <= '0';
62 | PREV_COM <= (others => '0');
63 | FS <= FS_IDLE;
64 | WRITE_PEND <= '0';
65 | PAGE_ERASE_PEND <= '0';
66 | CHIP_ERASE_PEND <= '0';
67 | elsif rising_edge(CLK) then
68 | if ENABLE = '1' then
69 | if CE_N = '0' and WR_N = '0' and SYSCLKF_CE = '1' then
70 | if BYTE_WRITE = '1' then --Data write
71 | if WRITE_PEND = '0' then
72 | WRITE_ADDR <= A;
73 | WRITE_DATA <= DI;
74 | WRITE_PEND <= '1';
75 | BYTE_WRITE <= '0';
76 | end if;
77 | else --Command write
78 | PREV_COM <= DI;
79 | case DI is
80 | when x"00" | x"FF" => --Reset
81 | CSR <= '0';
82 | ESR <= '0';
83 | VEN <= '0';
84 | when x"10" | x"40" => --Byte write
85 | BYTE_WRITE <= '1';
86 | when x"70" => --CSR enable
87 | CSR <= '1';
88 | when x"71" => --ESR enable
89 | ESR <= '1';
90 | when x"75" => --Vendor Info enable
91 | VEN <= '1';
92 | when x"D0" => --Double Byte Commands
93 | case PREV_COM is
94 | when x"20" => --Page erase
95 | if PAGE_ERASE_PEND = '0' then
96 | WRITE_ADDR <= A(19 downto 16)&x"0000";
97 | WRITE_DATA <= x"FF";
98 | PAGE_ERASE_PEND <= '1';
99 | end if;
100 | when x"A7" => --Chip erase
101 | if CHIP_ERASE_PEND = '0' then
102 | WRITE_ADDR <= (others => '0');
103 | WRITE_DATA <= x"FF";
104 | CHIP_ERASE_PEND <= '1';
105 | end if;
106 | when others => null;
107 | end case;
108 | when others => null;
109 | end case;
110 | end if;
111 | elsif CE_N = '0' and RD_N = '0' and SYSCLKF_CE = '1' then
112 | if ESR = '1' and (A(15 downto 0) = x"0002" or A(15 downto 0) = x"0004") then
113 |
114 | elsif CSR = '1' then
115 | CSR <= '0';
116 | end if;
117 | end if;
118 |
119 | if SYSCLKR_CE = '1' then
120 | READ_DATA <= MEM_DI;
121 | end if;
122 |
123 | if SYSCLKF_CE = '1' then
124 | case FS is
125 | when FS_IDLE =>
126 | if WRITE_PEND = '1' then
127 | FS <= FS_READ;
128 | elsif PAGE_ERASE_PEND = '1' or CHIP_ERASE_PEND = '1' then
129 | FS <= FS_ERASE;
130 | end if;
131 |
132 | when FS_READ =>
133 | WRITE_DATA <= WRITE_DATA and READ_DATA;
134 | FS <= FS_WRITE;
135 |
136 | when FS_WRITE =>
137 | WRITE_PEND <= '0';
138 | FS <= FS_IDLE;
139 |
140 | when FS_ERASE =>
141 | WRITE_ADDR <= std_logic_vector( unsigned(WRITE_ADDR) + 1 );
142 | if WRITE_ADDR(15 downto 0) = x"FFFF" and (WRITE_ADDR(19 downto 16) = x"F" or CHIP_ERASE_PEND = '0') then
143 | PAGE_ERASE_PEND <= '0';
144 | CHIP_ERASE_PEND <= '0';
145 | FS <= FS_IDLE;
146 | end if;
147 |
148 | when others => null;
149 | end case;
150 | end if;
151 | end if;
152 | end if;
153 | end process;
154 |
155 | MEM_ADDR <= WRITE_ADDR;
156 | MEM_DO <= WRITE_DATA;
157 | MEM_RD <= '1' when FS = FS_READ else '0';
158 | MEM_WR <= '1' when FS = FS_WRITE or FS = FS_ERASE else '0';
159 |
160 |
161 | process( RST_N, CLK)
162 | begin
163 | if RST_N = '0' then
164 | DO <= (others => '0');
165 | elsif rising_edge(CLK) then
166 | if ESR = '1' and A(15 downto 0) = x"0002" then
167 | DO <= x"C0";
168 | elsif ESR = '1' and A(15 downto 0) = x"0004" then
169 | DO <= not CHIP_ERASE_PEND & "0000010";
170 | elsif CSR = '1' then
171 | DO <= not (WRITE_PEND or PAGE_ERASE_PEND) & "0000000";
172 | elsif VEN = '1' and A(14 downto 8) = "1111111" then
173 | case A(7 downto 0) is
174 | when x"00" => DO <= x"4D";
175 | when x"01" => DO <= x"00";
176 | when x"02" => DO <= x"50";
177 | when x"03" => DO <= x"00";
178 | when x"04" => DO <= x"00";
179 | when x"05" => DO <= x"00";
180 | when x"06" => DO <= x"1A";
181 | when x"07" => DO <= x"00";
182 | when others =>DO <= x"00";
183 | end case;
184 | else
185 | DO <= MEM_DI;
186 | end if;
187 | end if;
188 | end process;
189 |
190 | end rtl;
--------------------------------------------------------------------------------
/rtl/chip/BSX/BSX_MCC.vhd:
--------------------------------------------------------------------------------
1 | library IEEE;
2 | use IEEE.STD_LOGIC_1164.ALL;
3 | library STD;
4 | use IEEE.NUMERIC_STD.ALL;
5 | library work;
6 |
7 | entity MCC is
8 | port(
9 | CLK : in std_logic;
10 | RST_N : in std_logic;
11 | ENABLE : in std_logic;
12 |
13 | CA : in std_logic_vector(23 downto 12);
14 | DI7 : in std_logic;
15 | DO7 : out std_logic;
16 | RD_N : in std_logic;
17 | WR_N : in std_logic;
18 | SYSCLKF_CE : in std_logic;
19 |
20 | BIOS_CE_N : out std_logic;
21 | SRAM_CE_N : out std_logic;
22 |
23 | ADDR : out std_logic_vector(19 downto 15);
24 | PSRAM_CE_N : out std_logic;
25 | EXTMEM_CE_N : out std_logic;
26 | DPAK_CE_N : out std_logic;
27 | DPAK_WR_N : out std_logic;
28 |
29 | IOPORT_CE_N : out std_logic
30 | );
31 | end MCC;
32 |
33 | architecture rtl of MCC is
34 |
35 | signal IO_REG : std_logic_vector(13 downto 2);
36 | signal REG : std_logic_vector(13 downto 2);
37 | signal ENIRQ : std_logic;
38 | signal MAP_MODE : std_logic;
39 | signal PSRAM_ON : std_logic_vector(1 downto 0);
40 | signal PSRAM_MAP : std_logic_vector(1 downto 0);
41 | signal BIOS_ON : std_logic_vector(1 downto 0);
42 | signal EXT_ON : std_logic_vector(1 downto 0);
43 | signal EXT_MAP : std_logic;
44 | signal EN_DPAK_WR : std_logic;
45 | signal EN_EXT_WR : std_logic;
46 | signal IO_SEL : std_logic;
47 | signal ROM_AREA : std_logic;
48 |
49 | begin
50 |
51 | IO_SEL <= '1' when CA(23 downto 20) = x"0" and CA(15 downto 12) = x"5" else '0'; -- 00:5XXX-0F:5XXX
52 | IOPORT_CE_N <= not IO_SEL;
53 |
54 | process( RST_N, CLK)
55 | begin
56 | if RST_N = '0' then
57 | IO_REG <= "001011111011";
58 | ENIRQ <= '0';
59 | MAP_MODE <= '1';
60 | PSRAM_ON <= "01";
61 | PSRAM_MAP <= "11";
62 | BIOS_ON <= "11";
63 | EXT_ON <= "01";
64 | EXT_MAP <= '1';
65 | EN_DPAK_WR <= '0';
66 | EN_EXT_WR <= '0';
67 | elsif rising_edge(CLK) then
68 | if ENABLE = '1' then
69 | if IO_SEL = '1' and WR_N = '0' and SYSCLKF_CE = '1' then
70 | case CA(19 downto 16) is
71 | when x"0" =>
72 | when x"1" => ENIRQ <= DI7;
73 | when x"2" => IO_REG(2) <= DI7;
74 | when x"3" => IO_REG(3) <= DI7;
75 | when x"4" => IO_REG(4) <= DI7;
76 | when x"5" => IO_REG(5) <= DI7;
77 | when x"6" => IO_REG(6) <= DI7;
78 | when x"7" => IO_REG(7) <= DI7;
79 | when x"8" => IO_REG(8) <= DI7;
80 | when x"9" => IO_REG(9) <= DI7;
81 | when x"A" => IO_REG(10) <= DI7;
82 | when x"B" => IO_REG(11) <= DI7;
83 | when x"C" => IO_REG(12) <= DI7;
84 | when x"D" => IO_REG(13) <= DI7;
85 | when x"E" =>
86 | MAP_MODE <= IO_REG(2);
87 | PSRAM_ON <= IO_REG(4 downto 3);
88 | PSRAM_MAP <= IO_REG(6 downto 5);
89 | BIOS_ON <= IO_REG(8 downto 7);
90 | EXT_ON <= IO_REG(10 downto 9);
91 | EXT_MAP <= IO_REG(11);
92 | EN_DPAK_WR <= IO_REG(12);
93 | EN_EXT_WR <= IO_REG(13);
94 | when others => null;
95 | end case;
96 | end if;
97 | end if;
98 | end if;
99 | end process;
100 |
101 | process( RST_N, CLK)
102 | begin
103 | if RST_N = '0' then
104 | DO7 <= '0';
105 | elsif rising_edge(CLK) then
106 | if IO_SEL = '1' then
107 | case CA(19 downto 16) is
108 | when x"0" => DO7 <= '0';
109 | when x"1" => DO7 <= ENIRQ;
110 | when x"2" => DO7 <= MAP_MODE;
111 | when x"3" => DO7 <= PSRAM_ON(0);
112 | when x"4" => DO7 <= PSRAM_ON(1);
113 | when x"5" => DO7 <= PSRAM_MAP(1);
114 | when x"6" => DO7 <= PSRAM_MAP(1);
115 | when x"7" => DO7 <= BIOS_ON(0);
116 | when x"8" => DO7 <= BIOS_ON(1);
117 | when x"9" => DO7 <= EXT_ON(0);
118 | when x"A" => DO7 <= EXT_ON(1);
119 | when x"B" => DO7 <= EXT_MAP;
120 | when x"C" => DO7 <= EN_DPAK_WR;
121 | when x"D" => DO7 <= EN_EXT_WR;
122 | when others => DO7 <= '0';
123 | end case;
124 | else
125 | DO7 <= '0';
126 | end if;
127 | end if;
128 | end process;
129 |
130 | ROM_AREA <= '0' when CA(23 downto 17) = "0111111" or (CA(22) = '0' and CA(15) = '0') else '1';
131 |
132 | process( CA, ROM_AREA, MAP_MODE, PSRAM_ON, PSRAM_MAP, BIOS_ON, EXT_ON, EXT_MAP )
133 | begin
134 | BIOS_CE_N <= '1';
135 | PSRAM_CE_N <= '1';
136 | EXTMEM_CE_N <= '1';
137 | DPAK_CE_N <= '1';
138 |
139 | if MAP_MODE = '0' then
140 | if ((not CA(23) and BIOS_ON(0)) = '1' or (CA(23) and BIOS_ON(1)) = '1') and CA(22) = '0' then
141 | BIOS_CE_N <= not ROM_AREA;
142 | elsif ((not CA(23) and PSRAM_ON(0)) = '1' or (CA(23) and PSRAM_ON(1)) = '1') and CA(22 downto 21) = PSRAM_MAP then
143 | PSRAM_CE_N <= not ROM_AREA;
144 | elsif ((not CA(23) and EXT_ON(0)) = '1' or (CA(23) and EXT_ON(1)) = '1') and CA(22) = EXT_MAP and CA(21) = '0' then
145 | EXTMEM_CE_N <= not ROM_AREA;
146 | else
147 | DPAK_CE_N <= not ROM_AREA;
148 | end if;
149 |
150 | if ((not CA(23) and PSRAM_ON(0)) = '1' or (CA(23) and PSRAM_ON(1)) = '1') and CA(22 downto 20) = "111" and CA(15) = '0' then --70-7D:0000-7FFF,F0-FF:0000-7FFF
151 | PSRAM_CE_N <= not ROM_AREA;
152 | end if;
153 | else
154 | if ((not CA(23) and BIOS_ON(0)) = '1' or (CA(23) and BIOS_ON(1)) = '1') and CA(22) = '0' then
155 | BIOS_CE_N <= not ROM_AREA;
156 | elsif ((not CA(23) and PSRAM_ON(0)) = '1' or (CA(23) and PSRAM_ON(1)) = '1') and CA(21 downto 20) = PSRAM_MAP and CA(19) = '0' then
157 | PSRAM_CE_N <= not ROM_AREA;
158 | elsif ((not CA(23) and EXT_ON(0)) = '1' or (CA(23) and EXT_ON(1)) = '1') and CA(21) = EXT_MAP and CA(20) = '0' then
159 | EXTMEM_CE_N <= not ROM_AREA;
160 | else
161 | DPAK_CE_N <= not ROM_AREA;
162 | end if;
163 |
164 | if CA(22 downto 21) = "01" and CA(15 downto 12) = x"6" then --20-3F:6000-6FFF,A0-BF:6000-6FFF
165 | PSRAM_CE_N <= '0';
166 | end if;
167 | end if;
168 |
169 | if ((not CA(23) and PSRAM_ON(0)) = '1' or (CA(23) and PSRAM_ON(1)) = '1') and CA(23 downto 19) = "00010" and CA(15 downto 12) = x"5" then --10-17:5000-5FFF
170 | SRAM_CE_N <= '0';
171 | else
172 | SRAM_CE_N <= '1';
173 | end if;
174 | end process;
175 |
176 | DPAK_WR_N <= WR_N or not EN_DPAK_WR;
177 |
178 | process( CA, MAP_MODE )
179 | begin
180 | if MAP_MODE = '0' then
181 | ADDR <= CA(20 downto 16);--LoROM
182 | else
183 | ADDR <= CA(19 downto 15);--HiROM
184 | end if;
185 | end process;
186 |
187 | end rtl;
--------------------------------------------------------------------------------
/rtl/chip/CX4/CX4Map.vhd:
--------------------------------------------------------------------------------
1 | library STD;
2 | use STD.TEXTIO.ALL;
3 | library IEEE;
4 | use IEEE.STD_LOGIC_1164.ALL;
5 | use IEEE.NUMERIC_STD.ALL;
6 | use IEEE.STD_LOGIC_UNSIGNED.ALL;
7 | use IEEE.STD_LOGIC_TEXTIO.all;
8 |
9 | entity CX4Map is
10 | port(
11 | MCLK : in std_logic;
12 | RST_N : in std_logic;
13 | ENABLE : in std_logic := '1';
14 |
15 | CA : in std_logic_vector(23 downto 0);
16 | DI : in std_logic_vector(7 downto 0);
17 | DO : out std_logic_vector(7 downto 0);
18 | CPURD_N : in std_logic;
19 | CPUWR_N : in std_logic;
20 |
21 | PA : in std_logic_vector(7 downto 0);
22 | PARD_N : in std_logic;
23 | PAWR_N : in std_logic;
24 |
25 | ROMSEL_N : in std_logic;
26 | RAMSEL_N : in std_logic;
27 |
28 | SYSCLKF_CE : in std_logic;
29 | SYSCLKR_CE : in std_logic;
30 | REFRESH : in std_logic;
31 |
32 | IRQ_N : out std_logic;
33 |
34 | ROM_ADDR : out std_logic_vector(22 downto 0);
35 | ROM_Q : in std_logic_vector(15 downto 0);
36 | ROM_CE_N : out std_logic;
37 | ROM_OE_N : out std_logic;
38 | ROM_WORD : out std_logic;
39 |
40 | BSRAM_ADDR : out std_logic_vector(19 downto 0);
41 | BSRAM_D : out std_logic_vector(7 downto 0);
42 | BSRAM_Q : in std_logic_vector(7 downto 0);
43 | BSRAM_CE_N : out std_logic;
44 | BSRAM_OE_N : out std_logic;
45 | BSRAM_WE_N : out std_logic;
46 |
47 | MAP_ACTIVE : out std_logic;
48 | MAP_CTRL : in std_logic_vector(7 downto 0);
49 | ROM_MASK : in std_logic_vector(23 downto 0);
50 | BSRAM_MASK : in std_logic_vector(23 downto 0)
51 | );
52 | end CX4Map;
53 |
54 | architecture rtl of CX4Map is
55 |
56 | signal CX4_A : std_logic_vector(23 downto 0);
57 | signal CX4_DI : std_logic_vector(7 downto 0);
58 | signal SRAM_CE_N, ROM_CE1_N, ROM_CE2_N : std_logic;
59 | signal CART_ADDR : std_logic_vector(21 downto 0);
60 | signal BRAM_ADDR : std_logic_vector(19 downto 0);
61 | signal CX4_CE : std_logic;
62 | signal MAP_SEL : std_logic;
63 | begin
64 |
65 | MAP_SEL <= '1' when MAP_CTRL(7 downto 4) = X"4" else '0';
66 | MAP_ACTIVE <= MAP_SEL;
67 |
68 | CEGen : entity work.CEGen
69 | port map(
70 | CLK => MCLK,
71 | RST_N => RST_N,
72 | IN_CLK => 2147727,
73 | OUT_CLK => 2000000,
74 | CE => CX4_CE
75 | );
76 |
77 | CX4 : entity work.CX4
78 | port map(
79 | CLK => MCLK,
80 | CE => CX4_CE,
81 | RST_N => RST_N and MAP_SEL,
82 | ENABLE => ENABLE,
83 |
84 | ADDR => CA,
85 | DO => DO,
86 | DI => DI,
87 | RD_N => CPURD_N,
88 | WR_N => CPUWR_N,
89 |
90 | SYSCLKF_CE => SYSCLKF_CE,
91 | SYSCLKR_CE => SYSCLKR_CE,
92 |
93 | IRQ_N => IRQ_N,
94 |
95 | BUS_A => CX4_A,
96 | BUS_DI => CX4_DI,
97 | BUS_DO => BSRAM_D,
98 | BUS_OE_N => BSRAM_OE_N,
99 | BUS_WE_N => BSRAM_WE_N,
100 | ROM_CE1_N => ROM_CE1_N,
101 | ROM_CE2_N => ROM_CE2_N,
102 | SRAM_CE_N => SRAM_CE_N,
103 |
104 | BUS_RD_N => ROM_OE_N,
105 |
106 | MAPPER => MAP_CTRL(0)
107 | );
108 |
109 | CART_ADDR <= CX4_A(22) & not ROM_CE2_N & CX4_A(20 downto 16) & CX4_A(14 downto 0);
110 | BRAM_ADDR <= CX4_A(20 downto 16) & CX4_A(14 downto 0);
111 |
112 | ROM_ADDR <= CART_ADDR and ROM_MASK(22 downto 0);
113 | ROM_CE_N <= ROM_CE1_N and ROM_CE2_N;
114 | ROM_WORD <= '0';
115 |
116 | BSRAM_ADDR <= BRAM_ADDR and BSRAM_MASK(19 downto 0);
117 | BSRAM_CE_N <= SRAM_CE_N;
118 |
119 | CX4_DI <= BSRAM_Q when SRAM_CE_N = '0' else ROM_Q(7 downto 0);
120 |
121 | end rtl;
122 |
--------------------------------------------------------------------------------
/rtl/chip/DSP/OBC1.vhd:
--------------------------------------------------------------------------------
1 | library IEEE;
2 | use IEEE.STD_LOGIC_1164.ALL;
3 | library STD;
4 | use IEEE.NUMERIC_STD.ALL;
5 |
6 |
7 | entity OBC1 is
8 | port(
9 | CLK : in std_logic;
10 | RST_N : in std_logic;
11 | ENABLE : in std_logic;
12 |
13 | CA : in std_logic_vector(23 downto 0);
14 | DI : in std_logic_vector(7 downto 0);
15 | CPURD_N : in std_logic;
16 | CPUWR_N : in std_logic;
17 |
18 | SYSCLKF_CE : in std_logic;
19 |
20 | CS : in std_logic;
21 |
22 | SRAM_A : out std_logic_vector(12 downto 0);
23 | SRAM_DI : in std_logic_vector(7 downto 0);
24 | SRAM_DO : out std_logic_vector(7 downto 0)
25 | );
26 | end OBC1;
27 |
28 | architecture rtl of OBC1 is
29 |
30 | signal BASE : std_logic;
31 | signal INDEX : std_logic_vector(6 downto 0);
32 |
33 | signal SRAM_ADDR : std_logic_vector(12 downto 0);
34 |
35 | begin
36 |
37 | process( RST_N, CLK)
38 | begin
39 | if RST_N = '0' then
40 | INDEX <= (others => '0');
41 | BASE <= '0';
42 | elsif rising_edge(CLK) then
43 | if ENABLE = '1' and SYSCLKF_CE = '1' then
44 | if CPUWR_N = '0' and CS = '1' and CA(15 downto 4) = x"7FF" then
45 | case CA(3 downto 0) is
46 | when x"5" =>
47 | BASE<= DI(0);
48 | when x"6" =>
49 | INDEX <= DI(6 downto 0);
50 | when others => null;
51 | end case;
52 | end if;
53 | end if;
54 | end if;
55 | end process;
56 |
57 | process( CA, BASE, INDEX )
58 | begin
59 | if CA(12 downto 3) = "1111111110" then --7FF0-7FF7
60 | case CA(3 downto 0) is
61 | when x"0" | x"1" | x"2" | x"3" =>
62 | SRAM_ADDR <= "11" & not BASE & "0" & INDEX & CA(1 downto 0);
63 | when x"4" =>
64 | SRAM_ADDR <= "11" & not BASE & "1" & "0000" & INDEX(6 downto 2);
65 | when others =>
66 | SRAM_ADDR <= CA(12 downto 0);
67 | end case;
68 | else
69 | SRAM_ADDR <= CA(12 downto 0);
70 | end if;
71 | end process;
72 | SRAM_A <= SRAM_ADDR;
73 |
74 | process( CA, DI, INDEX, SRAM_DI)
75 | begin
76 | if CA(12 downto 0) = "1111111110100" then --7FF4
77 | case INDEX(1 downto 0) is
78 | when "00" =>
79 | SRAM_DO <= SRAM_DI(7 downto 2) & DI(1 downto 0);
80 | when "01" =>
81 | SRAM_DO <= SRAM_DI(7 downto 4) & DI(1 downto 0) & SRAM_DI(1 downto 0);
82 | when "10" =>
83 | SRAM_DO <= SRAM_DI(7 downto 6) & DI(1 downto 0) & SRAM_DI(3 downto 0);
84 | when others =>
85 | SRAM_DO <= DI(1 downto 0) & SRAM_DI(5 downto 0);
86 | end case;
87 | else
88 | SRAM_DO <= DI;
89 | end if;
90 | end process;
91 |
92 | end rtl;
93 |
--------------------------------------------------------------------------------
/rtl/chip/GSU/GSUMap.vhd:
--------------------------------------------------------------------------------
1 | library STD;
2 | use STD.TEXTIO.ALL;
3 | library IEEE;
4 | use IEEE.STD_LOGIC_1164.ALL;
5 | use IEEE.NUMERIC_STD.ALL;
6 | use IEEE.STD_LOGIC_UNSIGNED.ALL;
7 | use IEEE.STD_LOGIC_TEXTIO.all;
8 |
9 | entity GSUMap is
10 | port(
11 | MCLK : in std_logic;
12 | RST_N : in std_logic;
13 | ENABLE : in std_logic := '1';
14 |
15 | CA : in std_logic_vector(23 downto 0);
16 | DI : in std_logic_vector(7 downto 0);
17 | DO : out std_logic_vector(7 downto 0);
18 | CPURD_N : in std_logic;
19 | CPUWR_N : in std_logic;
20 |
21 | PA : in std_logic_vector(7 downto 0);
22 | PARD_N : in std_logic;
23 | PAWR_N : in std_logic;
24 |
25 | ROMSEL_N : in std_logic;
26 | RAMSEL_N : in std_logic;
27 |
28 | SYSCLKF_CE : in std_logic;
29 | SYSCLKR_CE : in std_logic;
30 | REFRESH : in std_logic;
31 |
32 | IRQ_N : out std_logic;
33 |
34 | ROM_ADDR : out std_logic_vector(22 downto 0);
35 | ROM_Q : in std_logic_vector(15 downto 0);
36 | ROM_CE_N : out std_logic;
37 | ROM_OE_N : out std_logic;
38 | ROM_WORD : out std_logic;
39 |
40 | BSRAM_ADDR : out std_logic_vector(19 downto 0);
41 | BSRAM_D : out std_logic_vector(7 downto 0);
42 | BSRAM_Q : in std_logic_vector(7 downto 0);
43 | BSRAM_CE_N : out std_logic;
44 | BSRAM_OE_N : out std_logic;
45 | BSRAM_WE_N : out std_logic;
46 |
47 | MAP_ACTIVE : out std_logic;
48 | MAP_CTRL : in std_logic_vector(7 downto 0);
49 | ROM_MASK : in std_logic_vector(23 downto 0);
50 | BSRAM_MASK : in std_logic_vector(23 downto 0);
51 |
52 | TURBO : in std_logic
53 | );
54 | end GSUMap;
55 |
56 | architecture rtl of GSUMap is
57 |
58 | signal ROM_A : std_logic_vector(20 downto 0);
59 | signal RAM_A : std_logic_vector(16 downto 0);
60 | signal RAM_WE_N : std_logic;
61 | signal MAP_SEL : std_logic;
62 |
63 | begin
64 |
65 | MAP_SEL <= '1' when MAP_CTRL(7 downto 4) = X"7" else '0';
66 | MAP_ACTIVE <= MAP_SEL;
67 |
68 | GSU : entity work.GSU
69 | port map(
70 | CLK => MCLK,
71 | RST_N => RST_N and MAP_SEL,
72 | ENABLE => ENABLE,
73 |
74 | ADDR => CA,
75 | DO => DO,
76 | DI => DI,
77 | RD_N => CPURD_N,
78 | WR_N => CPUWR_N,
79 |
80 | SYSCLKF_CE => SYSCLKF_CE,
81 | SYSCLKR_CE => SYSCLKR_CE,
82 |
83 | IRQ_N => IRQ_N,
84 |
85 | ROM_A => ROM_A,
86 | ROM_DI => ROM_Q(7 downto 0),
87 | ROM_RD_N => ROM_OE_N,
88 |
89 | RAM_A => RAM_A,
90 | RAM_DI => BSRAM_Q,
91 | RAM_DO => BSRAM_D,
92 | RAM_WE_N => RAM_WE_N,
93 | RAM_CE_N => BSRAM_CE_N,
94 |
95 | TURBO => TURBO
96 | );
97 |
98 | ROM_ADDR <= ("00" & ROM_A) and ROM_MASK(22 downto 0);
99 | ROM_CE_N <= '0';
100 | ROM_WORD <= '0';
101 |
102 | BSRAM_ADDR <= "0000" & RAM_A(15 downto 0);
103 | BSRAM_OE_N <= not RAM_WE_N;
104 | BSRAM_WE_N <= RAM_WE_N;
105 |
106 | end rtl;
--------------------------------------------------------------------------------
/rtl/chip/MSU1/MSU.sv:
--------------------------------------------------------------------------------
1 | // This module is responsible for exposing MSU registers to the SNES for it to control
2 |
3 | module MSU
4 | (
5 | input CLK,
6 | input RST_N,
7 | input ENABLE,
8 |
9 | input RD_N,
10 | input WR_N,
11 | input SYSCLKF_CE,
12 |
13 | input [23:0] ADDR,
14 | input [7:0] DIN,
15 | output reg [7:0] DOUT,
16 | output MSU_SEL,
17 |
18 | output reg [15:0] track_num,
19 | output track_request,
20 | input track_mounting,
21 |
22 | // Audio player control
23 | output reg [7:0] volume,
24 | input status_track_missing,
25 | output reg status_audio_repeat,
26 | output reg status_audio_playing,
27 | input audio_stop,
28 |
29 | // Data track read
30 | output reg [31:0] data_addr,
31 | input [7:0] data,
32 | input data_ack,
33 | output reg data_seek,
34 | output reg data_req
35 | );
36 |
37 |
38 | // Read 'registers'
39 | // MSU_STATUS - $2000
40 | // Status bits
41 | localparam [2:0] status_revision = 3'b001;
42 | wire [7:0] MSU_STATUS = {
43 | status_data_busy,
44 | status_audio_busy,
45 | status_audio_repeat,
46 | status_audio_playing,
47 | status_track_missing,
48 | status_revision
49 | };
50 |
51 | // Write registers
52 | reg [31:0] MSU_SEEK; // $2000 - $2003
53 | reg [15:0] MSU_TRACK; // $2004 - $2005
54 |
55 | // banks 00-3F and 80-BF, address 2000-2007
56 | assign MSU_SEL = ENABLE && !ADDR[22] && (ADDR[15:4] == 'h200) && !ADDR[3];
57 |
58 | wire status_audio_busy = track_request;
59 |
60 | reg data_ack_1 = 1'b0;
61 | reg status_data_busy = 1'b0;
62 | reg track_mounting_old = 0;
63 |
64 | reg data_rd_old;
65 | wire data_rd = MSU_SEL && !RD_N && ADDR[2:0] == 1 && !status_data_busy;
66 |
67 | always @(posedge CLK) begin
68 | if (~RST_N) begin
69 | MSU_SEEK <= 0;
70 | data_addr <= 0;
71 | MSU_TRACK <= 0;
72 | track_num <= 0;
73 | track_request <= 0;
74 | volume <= 0;
75 | status_audio_playing <= 0;
76 | status_audio_repeat <= 0;
77 | status_data_busy <= 0;
78 | track_mounting_old <= 0;
79 | data_req <= 0;
80 | data_seek <= 0;
81 | end
82 | else begin
83 | // Reset our request trigger for pulsing
84 | data_req <= 0;
85 |
86 | // Falling edge of data busy
87 | data_ack_1 <= data_ack;
88 | if (!data_ack_1 && data_ack) begin
89 | status_data_busy <= 0;
90 | data_seek <= 0;
91 | end
92 |
93 | // Falling edge of track mounting
94 | track_mounting_old <= track_mounting;
95 | if (track_mounting_old && !track_mounting) track_request <= 0;
96 |
97 | if (audio_stop) status_audio_playing <= 0;
98 |
99 | // Register writes
100 | if (MSU_SEL & SYSCLKF_CE & ~WR_N) begin
101 | case (ADDR[2:0])
102 | 0: MSU_SEEK[7:0] <= DIN; // Data seek address. MSU_SEEK, LSB byte
103 | 1: MSU_SEEK[15:8] <= DIN; // Data seek address. MSU_SEEK.
104 | 2: MSU_SEEK[23:16] <= DIN; // Data seek address. MSU_SEEK.
105 | 3: begin
106 | MSU_SEEK[31:24] <= DIN; // Data seek address. MSU_SEEK, MSB byte
107 | data_addr <= {DIN, MSU_SEEK[23:0]};
108 | data_seek <= 1;
109 | status_data_busy <= 1;
110 | end
111 |
112 | 4: MSU_TRACK[7:0] <= DIN; // MSU_Track LSB
113 | 5: begin
114 | MSU_TRACK[15:8] <= DIN; // MSU_Track MSB
115 | track_num <= {DIN, MSU_TRACK[7:0]};
116 | track_request <= 1;
117 | end
118 |
119 | 6: volume <= DIN; // MSU Audio Volume
120 |
121 | // MSU Audio state control
122 | 7: begin
123 | status_audio_repeat <= DIN[1];
124 | status_audio_playing <= DIN[0];
125 | end
126 | endcase
127 | end
128 |
129 | // Advance data pointer after read
130 | data_rd_old <= data_rd;
131 | if (data_rd_old & ~data_rd) begin
132 | data_addr <= data_addr + 1;
133 | data_req <= 1'b1;
134 | end
135 |
136 | case (ADDR[2:0])
137 | 0: DOUT <= MSU_STATUS;
138 | 1: DOUT <= data;
139 | 2: DOUT <= "S";
140 | 3: DOUT <= "-";
141 | 4: DOUT <= "M";
142 | 5: DOUT <= "S";
143 | 6: DOUT <= "U";
144 | 7: DOUT <= "1";
145 | endcase
146 | end
147 | end
148 |
149 | endmodule
150 |
--------------------------------------------------------------------------------
/rtl/chip/MSU1/msu_data_store.sv:
--------------------------------------------------------------------------------
1 | //
2 | // msu_data_store.v
3 | // Copyright (c) 2022 Alexey Melnikov
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 | module msu_data_store
22 | (
23 | input DDRAM_CLK,
24 |
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 | input clk_sys,
36 | input [31:0] base_addr,
37 |
38 | input rd_next,
39 | input rd_seek,
40 | output reg rd_seek_done,
41 | input [31:0] rd_addr,
42 | output [7:0] rd_dout
43 | );
44 |
45 | assign DDRAM_BURSTCNT = ram_burst;
46 | assign DDRAM_BE = 8'hFF;
47 | assign DDRAM_ADDR = ram_address;
48 | assign DDRAM_RD = ram_read;
49 | assign DDRAM_DIN = 0;
50 | assign DDRAM_WE = 0;
51 |
52 | wire [28:0] ph_addr = base_addr[31:3] + rd_addr[31:3];
53 | wire [28:0] ph_addr_curr = ph_addr + ((ph_addr >= 'h4400000) ? 29'h100000 : 29'h0);
54 | wire [28:0] ph_addr_next = ph_addr + ((ph_addr >= 'h43FFFFF) ? 29'h100001 : 29'h1);
55 |
56 | assign rd_dout = ram_q[{rd_addr[2:0], 3'b000} +:8];
57 |
58 | reg [7:0] ram_burst;
59 | reg [63:0] ram_q, next_q;
60 | reg [63:0] ram_data;
61 | reg [28:0] ram_address, cache_addr;
62 | reg ram_read = 0;
63 |
64 | reg [1:0] state = 0;
65 |
66 | always @(posedge DDRAM_CLK) begin
67 | reg old_seek;
68 | reg old_rd;
69 |
70 | if(~rd_seek) old_seek <= 0;
71 |
72 | if(!DDRAM_BUSY) begin
73 |
74 | ram_read <= 0;
75 | old_rd <= rd_next;
76 |
77 | case(state)
78 | 0: if(~old_seek & rd_seek) begin
79 | old_seek <= 1;
80 | rd_seek_done<= 0;
81 | ram_address <= ph_addr_curr;
82 | cache_addr <= ph_addr_next; // seek to 'h21FFFFF8 will return wrong second dword
83 | ram_read <= 1;
84 | ram_burst <= 2;
85 | state <= 1;
86 | end
87 | else if(~old_rd & rd_next) begin
88 | if(cache_addr == ph_addr_curr) begin
89 | ram_q <= next_q;
90 | ram_address <= ph_addr_next;
91 | cache_addr <= ph_addr_next;
92 | ram_read <= 1;
93 | ram_burst <= 1;
94 | state <= 2;
95 | end
96 | end
97 |
98 | 1: if(DDRAM_DOUT_READY) begin
99 | ram_q <= DDRAM_DOUT;
100 | state <= 2;
101 | end
102 |
103 | 2: if(DDRAM_DOUT_READY) begin
104 | next_q <= DDRAM_DOUT;
105 | state <= 0;
106 | rd_seek_done <= 1;
107 | end
108 | endcase
109 | end
110 | end
111 |
112 | endmodule
113 |
--------------------------------------------------------------------------------
/rtl/chip/MSU1/msu_fifo.v:
--------------------------------------------------------------------------------
1 |
2 | module msu_fifo #(parameter WIDTH, DEPTH)
3 | (
4 | input aclr,
5 |
6 | input wrclk,
7 | input wrreq,
8 | input [WIDTH-1:0] data,
9 | output wrfull,
10 | output [DEPTH-1:0] wrusedw,
11 |
12 | input rdclk,
13 | input rdreq,
14 | output [WIDTH-1:0] q,
15 | output rdempty,
16 | output [DEPTH-1:0] rdusedw
17 | );
18 |
19 | dcfifo dcfifo_component
20 | (
21 | .aclr (aclr),
22 | .data (data),
23 | .rdclk (rdclk),
24 | .rdreq (rdreq),
25 | .wrclk (wrclk),
26 | .wrreq (wrreq),
27 | .q (q),
28 | .rdempty (rdempty),
29 | .wrfull (wrfull),
30 | .wrusedw (wrusedw),
31 | .eccstatus (),
32 | .rdfull (),
33 | .rdusedw (rdusedw),
34 | .wrempty ()
35 | );
36 | defparam
37 | dcfifo_component.intended_device_family = "Cyclone V",
38 | dcfifo_component.lpm_numwords = 2**DEPTH,
39 | dcfifo_component.lpm_showahead = "ON",
40 | dcfifo_component.lpm_type = "dcfifo",
41 | dcfifo_component.lpm_width = WIDTH,
42 | dcfifo_component.lpm_widthu = DEPTH,
43 | dcfifo_component.overflow_checking = "ON",
44 | dcfifo_component.rdsync_delaypipe = 4,
45 | dcfifo_component.read_aclr_synch = "OFF",
46 | dcfifo_component.underflow_checking = "ON",
47 | dcfifo_component.use_eab = "ON",
48 | dcfifo_component.write_aclr_synch = "OFF",
49 | dcfifo_component.wrsync_delaypipe = 4;
50 |
51 | endmodule
52 |
--------------------------------------------------------------------------------
/rtl/chip/SA1/SA1DIV.vhd:
--------------------------------------------------------------------------------
1 | -- megafunction wizard: %LPM_DIVIDE%
2 | -- GENERATION: STANDARD
3 | -- VERSION: WM1.0
4 | -- MODULE: LPM_DIVIDE
5 |
6 | -- ============================================================
7 | -- File Name: SA1DIV.vhd
8 | -- Megafunction Name(s):
9 | -- LPM_DIVIDE
10 | --
11 | -- Simulation Library Files(s):
12 | -- lpm
13 | -- ============================================================
14 | -- ************************************************************
15 | -- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
16 | --
17 | -- 13.1.4 Build 182 03/12/2014 SJ Full Version
18 | -- ************************************************************
19 |
20 |
21 | --Copyright (C) 1991-2014 Altera Corporation
22 | --Your use of Altera Corporation's design tools, logic functions
23 | --and other software and tools, and its AMPP 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 Altera Program License
28 | --Subscription Agreement, Altera MegaCore Function License
29 | --Agreement, or other applicable license agreement, including,
30 | --without limitation, that your use is for the sole purpose of
31 | --programming logic devices manufactured by Altera and sold by
32 | --Altera or its authorized distributors. Please refer to the
33 | --applicable agreement for further details.
34 |
35 |
36 | LIBRARY ieee;
37 | USE ieee.std_logic_1164.all;
38 |
39 | LIBRARY lpm;
40 | USE lpm.all;
41 |
42 | ENTITY SA1DIV IS
43 | PORT
44 | (
45 | clock : IN STD_LOGIC ;
46 | denom : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
47 | numer : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
48 | quotient : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
49 | remain : OUT STD_LOGIC_VECTOR (15 DOWNTO 0)
50 | );
51 | END SA1DIV;
52 |
53 |
54 | ARCHITECTURE SYN OF sa1div IS
55 |
56 | SIGNAL sub_wire0 : STD_LOGIC_VECTOR (15 DOWNTO 0);
57 | SIGNAL sub_wire1 : STD_LOGIC_VECTOR (15 DOWNTO 0);
58 |
59 |
60 |
61 | COMPONENT lpm_divide
62 | GENERIC (
63 | lpm_drepresentation : STRING;
64 | lpm_hint : STRING;
65 | lpm_nrepresentation : STRING;
66 | lpm_pipeline : NATURAL;
67 | lpm_type : STRING;
68 | lpm_widthd : NATURAL;
69 | lpm_widthn : NATURAL
70 | );
71 | PORT (
72 | clock : IN STD_LOGIC ;
73 | remain : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
74 | denom : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
75 | numer : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
76 | quotient : OUT STD_LOGIC_VECTOR (15 DOWNTO 0)
77 | );
78 | END COMPONENT;
79 |
80 | BEGIN
81 | remain <= sub_wire0(15 DOWNTO 0);
82 | quotient <= sub_wire1(15 DOWNTO 0);
83 |
84 | LPM_DIVIDE_component : LPM_DIVIDE
85 | GENERIC MAP (
86 | lpm_drepresentation => "UNSIGNED",
87 | lpm_hint => "LPM_REMAINDERPOSITIVE=TRUE",
88 | lpm_nrepresentation => "SIGNED",
89 | lpm_pipeline => 6,
90 | lpm_type => "LPM_DIVIDE",
91 | lpm_widthd => 16,
92 | lpm_widthn => 16
93 | )
94 | PORT MAP (
95 | clock => clock,
96 | denom => denom,
97 | numer => numer,
98 | remain => sub_wire0,
99 | quotient => sub_wire1
100 | );
101 |
102 |
103 |
104 | END SYN;
105 |
106 | -- ============================================================
107 | -- CNX file retrieval info
108 | -- ============================================================
109 | -- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
110 | -- Retrieval info: PRIVATE: PRIVATE_LPM_REMAINDERPOSITIVE STRING "TRUE"
111 | -- Retrieval info: PRIVATE: PRIVATE_MAXIMIZE_SPEED NUMERIC "-1"
112 | -- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
113 | -- Retrieval info: PRIVATE: USING_PIPELINE NUMERIC "1"
114 | -- Retrieval info: PRIVATE: VERSION_NUMBER NUMERIC "2"
115 | -- Retrieval info: PRIVATE: new_diagram STRING "1"
116 | -- Retrieval info: LIBRARY: lpm lpm.lpm_components.all
117 | -- Retrieval info: CONSTANT: LPM_DREPRESENTATION STRING "UNSIGNED"
118 | -- Retrieval info: CONSTANT: LPM_HINT STRING "LPM_REMAINDERPOSITIVE=TRUE"
119 | -- Retrieval info: CONSTANT: LPM_NREPRESENTATION STRING "SIGNED"
120 | -- Retrieval info: CONSTANT: LPM_PIPELINE NUMERIC "6"
121 | -- Retrieval info: CONSTANT: LPM_TYPE STRING "LPM_DIVIDE"
122 | -- Retrieval info: CONSTANT: LPM_WIDTHD NUMERIC "16"
123 | -- Retrieval info: CONSTANT: LPM_WIDTHN NUMERIC "16"
124 | -- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL "clock"
125 | -- Retrieval info: USED_PORT: denom 0 0 16 0 INPUT NODEFVAL "denom[15..0]"
126 | -- Retrieval info: USED_PORT: numer 0 0 16 0 INPUT NODEFVAL "numer[15..0]"
127 | -- Retrieval info: USED_PORT: quotient 0 0 16 0 OUTPUT NODEFVAL "quotient[15..0]"
128 | -- Retrieval info: USED_PORT: remain 0 0 16 0 OUTPUT NODEFVAL "remain[15..0]"
129 | -- Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0
130 | -- Retrieval info: CONNECT: @denom 0 0 16 0 denom 0 0 16 0
131 | -- Retrieval info: CONNECT: @numer 0 0 16 0 numer 0 0 16 0
132 | -- Retrieval info: CONNECT: quotient 0 0 16 0 @quotient 0 0 16 0
133 | -- Retrieval info: CONNECT: remain 0 0 16 0 @remain 0 0 16 0
134 | -- Retrieval info: GEN_FILE: TYPE_NORMAL SA1DIV.vhd TRUE
135 | -- Retrieval info: GEN_FILE: TYPE_NORMAL SA1DIV.inc FALSE
136 | -- Retrieval info: GEN_FILE: TYPE_NORMAL SA1DIV.cmp FALSE
137 | -- Retrieval info: GEN_FILE: TYPE_NORMAL SA1DIV.bsf FALSE
138 | -- Retrieval info: GEN_FILE: TYPE_NORMAL SA1DIV_inst.vhd FALSE
139 | -- Retrieval info: LIB_FILE: lpm
140 |
--------------------------------------------------------------------------------
/rtl/chip/SA1/SA1MULT.vhd:
--------------------------------------------------------------------------------
1 | -- megafunction wizard: %LPM_MULT%
2 | -- GENERATION: STANDARD
3 | -- VERSION: WM1.0
4 | -- MODULE: lpm_mult
5 |
6 | -- ============================================================
7 | -- File Name: SA1MULT.vhd
8 | -- Megafunction Name(s):
9 | -- lpm_mult
10 | --
11 | -- Simulation Library Files(s):
12 | -- lpm
13 | -- ============================================================
14 | -- ************************************************************
15 | -- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
16 | --
17 | -- 11.1 Build 216 11/23/2011 SP 1 SJ Full Version
18 | -- ************************************************************
19 |
20 |
21 | --Copyright (C) 1991-2011 Altera Corporation
22 | --Your use of Altera Corporation's design tools, logic functions
23 | --and other software and tools, and its AMPP 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 Altera Program License
28 | --Subscription Agreement, Altera MegaCore Function License
29 | --Agreement, or other applicable license agreement, including,
30 | --without limitation, that your use is for the sole purpose of
31 | --programming logic devices manufactured by Altera and sold by
32 | --Altera or its authorized distributors. Please refer to the
33 | --applicable agreement for further details.
34 |
35 |
36 | LIBRARY ieee;
37 | USE ieee.std_logic_1164.all;
38 |
39 | LIBRARY lpm;
40 | USE lpm.all;
41 |
42 | ENTITY SA1MULT IS
43 | PORT
44 | (
45 | dataa : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
46 | datab : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
47 | result : OUT STD_LOGIC_VECTOR (31 DOWNTO 0)
48 | );
49 | END SA1MULT;
50 |
51 |
52 | ARCHITECTURE SYN OF sa1mult IS
53 |
54 | SIGNAL sub_wire0 : STD_LOGIC_VECTOR (31 DOWNTO 0);
55 |
56 |
57 |
58 | COMPONENT lpm_mult
59 | GENERIC (
60 | lpm_hint : STRING;
61 | lpm_representation : STRING;
62 | lpm_type : STRING;
63 | lpm_widtha : NATURAL;
64 | lpm_widthb : NATURAL;
65 | lpm_widthp : NATURAL
66 | );
67 | PORT (
68 | dataa : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
69 | datab : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
70 | result : OUT STD_LOGIC_VECTOR (31 DOWNTO 0)
71 | );
72 | END COMPONENT;
73 |
74 | BEGIN
75 | result <= sub_wire0(31 DOWNTO 0);
76 |
77 | lpm_mult_component : lpm_mult
78 | GENERIC MAP (
79 | lpm_hint => "MAXIMIZE_SPEED=5",
80 | lpm_representation => "SIGNED",
81 | lpm_type => "LPM_MULT",
82 | lpm_widtha => 16,
83 | lpm_widthb => 16,
84 | lpm_widthp => 32
85 | )
86 | PORT MAP (
87 | dataa => dataa,
88 | datab => datab,
89 | result => sub_wire0
90 | );
91 |
92 |
93 |
94 | END SYN;
95 |
96 | -- ============================================================
97 | -- CNX file retrieval info
98 | -- ============================================================
99 | -- Retrieval info: PRIVATE: AutoSizeResult NUMERIC "1"
100 | -- Retrieval info: PRIVATE: B_isConstant NUMERIC "0"
101 | -- Retrieval info: PRIVATE: ConstantB NUMERIC "0"
102 | -- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
103 | -- Retrieval info: PRIVATE: LPM_PIPELINE NUMERIC "0"
104 | -- Retrieval info: PRIVATE: Latency NUMERIC "0"
105 | -- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
106 | -- Retrieval info: PRIVATE: SignedMult NUMERIC "1"
107 | -- Retrieval info: PRIVATE: USE_MULT NUMERIC "1"
108 | -- Retrieval info: PRIVATE: ValidConstant NUMERIC "0"
109 | -- Retrieval info: PRIVATE: WidthA NUMERIC "16"
110 | -- Retrieval info: PRIVATE: WidthB NUMERIC "16"
111 | -- Retrieval info: PRIVATE: WidthP NUMERIC "32"
112 | -- Retrieval info: PRIVATE: aclr NUMERIC "0"
113 | -- Retrieval info: PRIVATE: clken NUMERIC "0"
114 | -- Retrieval info: PRIVATE: new_diagram STRING "1"
115 | -- Retrieval info: PRIVATE: optimize NUMERIC "0"
116 | -- Retrieval info: LIBRARY: lpm lpm.lpm_components.all
117 | -- Retrieval info: CONSTANT: LPM_HINT STRING "MAXIMIZE_SPEED=5"
118 | -- Retrieval info: CONSTANT: LPM_REPRESENTATION STRING "SIGNED"
119 | -- Retrieval info: CONSTANT: LPM_TYPE STRING "LPM_MULT"
120 | -- Retrieval info: CONSTANT: LPM_WIDTHA NUMERIC "16"
121 | -- Retrieval info: CONSTANT: LPM_WIDTHB NUMERIC "16"
122 | -- Retrieval info: CONSTANT: LPM_WIDTHP NUMERIC "32"
123 | -- Retrieval info: USED_PORT: dataa 0 0 16 0 INPUT NODEFVAL "dataa[15..0]"
124 | -- Retrieval info: USED_PORT: datab 0 0 16 0 INPUT NODEFVAL "datab[15..0]"
125 | -- Retrieval info: USED_PORT: result 0 0 32 0 OUTPUT NODEFVAL "result[31..0]"
126 | -- Retrieval info: CONNECT: @dataa 0 0 16 0 dataa 0 0 16 0
127 | -- Retrieval info: CONNECT: @datab 0 0 16 0 datab 0 0 16 0
128 | -- Retrieval info: CONNECT: result 0 0 32 0 @result 0 0 32 0
129 | -- Retrieval info: GEN_FILE: TYPE_NORMAL SA1MULT.vhd TRUE
130 | -- Retrieval info: GEN_FILE: TYPE_NORMAL SA1MULT.inc FALSE
131 | -- Retrieval info: GEN_FILE: TYPE_NORMAL SA1MULT.cmp FALSE
132 | -- Retrieval info: GEN_FILE: TYPE_NORMAL SA1MULT.bsf FALSE
133 | -- Retrieval info: GEN_FILE: TYPE_NORMAL SA1MULT_inst.vhd FALSE
134 | -- Retrieval info: LIB_FILE: lpm
135 |
--------------------------------------------------------------------------------
/rtl/chip/SA1/SA1Map.vhd:
--------------------------------------------------------------------------------
1 | library STD;
2 | use STD.TEXTIO.ALL;
3 | library IEEE;
4 | use IEEE.STD_LOGIC_1164.ALL;
5 | use IEEE.NUMERIC_STD.ALL;
6 | use IEEE.STD_LOGIC_UNSIGNED.ALL;
7 | use IEEE.STD_LOGIC_TEXTIO.all;
8 |
9 | entity SA1Map is
10 | port(
11 | MCLK : in std_logic;
12 | RST_N : in std_logic;
13 | ENABLE : in std_logic := '1';
14 |
15 | CA : in std_logic_vector(23 downto 0);
16 | DI : in std_logic_vector(7 downto 0);
17 | DO : out std_logic_vector(7 downto 0);
18 | CPURD_N : in std_logic;
19 | CPUWR_N : in std_logic;
20 |
21 | PA : in std_logic_vector(7 downto 0);
22 | PARD_N : in std_logic;
23 | PAWR_N : in std_logic;
24 |
25 | ROMSEL_N : in std_logic;
26 | RAMSEL_N : in std_logic;
27 |
28 | SYSCLKF_CE : in std_logic;
29 | SYSCLKR_CE : in std_logic;
30 |
31 | REFRESH : in std_logic;
32 |
33 | PAL : in std_logic;
34 |
35 | IRQ_N : out std_logic;
36 |
37 | ROM_ADDR : out std_logic_vector(22 downto 0);
38 | ROM_Q : in std_logic_vector(15 downto 0);
39 | ROM_CE_N : out std_logic;
40 | ROM_OE_N : out std_logic;
41 | ROM_WORD : out std_logic;
42 |
43 | BSRAM_ADDR : out std_logic_vector(19 downto 0);
44 | BSRAM_D : out std_logic_vector(7 downto 0);
45 | BSRAM_Q : in std_logic_vector(7 downto 0);
46 | BSRAM_CE_N : out std_logic;
47 | BSRAM_OE_N : out std_logic;
48 | BSRAM_WE_N : out std_logic;
49 |
50 | MAP_ACTIVE : out std_logic;
51 | MAP_CTRL : in std_logic_vector(7 downto 0);
52 | ROM_MASK : in std_logic_vector(23 downto 0);
53 | BSRAM_MASK : in std_logic_vector(23 downto 0)
54 | );
55 | end SA1Map;
56 |
57 | architecture rtl of SA1Map is
58 |
59 | signal ROM_A : std_logic_vector(22 downto 0);
60 | signal BWRAM_A : std_logic_vector(17 downto 0);
61 | signal MAP_SEL : std_logic;
62 |
63 | begin
64 |
65 | MAP_SEL <= '1' when MAP_CTRL(7 downto 4) = X"6" else '0';
66 | MAP_ACTIVE <= MAP_SEL;
67 |
68 | SA1 : entity work.SA1
69 | port map(
70 | CLK => MCLK,
71 | RST_N => RST_N and MAP_SEL,
72 | ENABLE => ENABLE,
73 |
74 | SNES_A => CA,
75 | SNES_DO => DO,
76 | SNES_DI => DI,
77 | SNES_RD_N => CPURD_N,
78 | SNES_WR_N => CPUWR_N,
79 |
80 | SYSCLKF_CE => SYSCLKF_CE,
81 | SYSCLKR_CE => SYSCLKR_CE,
82 |
83 | REFRESH => REFRESH,
84 |
85 | PAL => PAL,
86 |
87 | ROM_A => ROM_A,
88 | ROM_DI => ROM_Q,
89 | ROM_RD_N => ROM_OE_N,
90 |
91 | BWRAM_A => BWRAM_A,
92 | BWRAM_DI => BSRAM_Q,
93 | BWRAM_DO => BSRAM_D,
94 | BWRAM_OE_N => BSRAM_OE_N,
95 | BWRAM_WE_N => BSRAM_WE_N,
96 |
97 | IRQ_N => IRQ_N
98 | );
99 |
100 | ROM_ADDR <= ROM_A and ROM_MASK(22 downto 0);
101 | ROM_CE_N <= '0';
102 | ROM_WORD <= '1';
103 |
104 | BSRAM_ADDR <= ("00" & BWRAM_A) and BSRAM_MASK(19 downto 0);
105 | BSRAM_CE_N <= '0';
106 |
107 | end rtl;
--------------------------------------------------------------------------------
/rtl/chip/SDD1/InputMgr.vhd:
--------------------------------------------------------------------------------
1 | library IEEE;
2 | use IEEE.STD_LOGIC_1164.ALL;
3 | use IEEE.STD_LOGIC_ARITH.ALL;
4 | use IEEE.STD_LOGIC_UNSIGNED.ALL;
5 |
6 | entity InputMgr is
7 | port(
8 | RST_N : in std_logic;
9 | CLK : in std_logic;
10 | ENABLE : in std_logic;
11 |
12 | INIT_ADDR : in std_logic_vector(23 downto 0);
13 |
14 | INIT : in std_logic;
15 | DATA_REQ : in std_logic;
16 |
17 | ROM_ADDR : out std_logic_vector(23 downto 0);
18 | ROM_DATA : in std_logic_vector(15 downto 0);
19 |
20 | ROM_RD : in std_logic;
21 |
22 | OUT_DATA : out std_logic_vector(15 downto 0);
23 | HEADER : out std_logic_vector(3 downto 0);
24 |
25 | INIT_DONE : out std_logic
26 | );
27 | end InputMgr;
28 |
29 | architecture rtl of InputMgr is
30 |
31 | signal LOAD_ADDR : std_logic_vector(23 downto 0);
32 | signal CURR_DATA, NEXT_DATA : std_logic_vector(15 downto 0);
33 | signal BYTE_LOAD : std_logic;
34 | signal INIT_CNT : std_logic_vector(1 downto 0);
35 | signal WAIT_ACCESS: std_logic_vector(1 downto 0);
36 | signal TINIT_DONE : std_logic;
37 |
38 | type DataBuf_t is array(0 to 3) of std_logic_vector(15 downto 0);
39 | signal DATA_BUF: DataBuf_t;
40 | attribute ramstyle : string;
41 | attribute ramstyle of DATA_BUF : signal is "logic";
42 | signal WR_POS : std_logic_vector(1 downto 0);
43 | signal RD_POS : std_logic_vector(1 downto 0);
44 | begin
45 |
46 | process( RST_N, CLK)
47 | variable READ_REQ : std_logic;
48 | variable WRITE_REQ : std_logic;
49 | begin
50 | if RST_N = '0' then
51 | HEADER <= (others => '0');
52 | CURR_DATA <= (others => '0');
53 | NEXT_DATA <= (others => '0');
54 | LOAD_ADDR <= (others => '0');
55 | INIT_CNT <= (others => '0');
56 | BYTE_LOAD <= '0';
57 | TINIT_DONE <= '0';
58 | WAIT_ACCESS <= (others => '1');
59 | WR_POS <= (others => '0');
60 | RD_POS <= (others => '0');
61 | elsif rising_edge(CLK) then
62 | if ENABLE = '1' then
63 | if DATA_REQ = '1' and BYTE_LOAD = '1' then
64 | READ_REQ := '1';
65 | else
66 | READ_REQ := '0';
67 | end if;
68 |
69 | if ROM_RD = '1' and (WR_POS + 1 /= RD_POS) then
70 | WAIT_ACCESS <= (others => '0');
71 | elsif WAIT_ACCESS < 3 then
72 | WAIT_ACCESS <= WAIT_ACCESS + 1;
73 | end if;
74 |
75 | if WAIT_ACCESS = 1 then
76 | WRITE_REQ := '1';
77 | else
78 | WRITE_REQ := '0';
79 | end if;
80 |
81 | if INIT = '1' then
82 | LOAD_ADDR <= INIT_ADDR;
83 | INIT_CNT <= (others => '0');
84 | TINIT_DONE <= '0';
85 | WAIT_ACCESS <= (others => '1');
86 | WR_POS <= (others => '0');
87 | RD_POS <= (others => '0');
88 | else
89 | if TINIT_DONE = '0' and (WR_POS + 1 = RD_POS) then
90 | TINIT_DONE <= '1';
91 | end if;
92 |
93 | if INIT_CNT < 3 and WRITE_REQ = '1' then
94 | if INIT_CNT = 0 then
95 | if LOAD_ADDR(0) = '0' then
96 | CURR_DATA <= ROM_DATA(7 downto 0) & ROM_DATA(15 downto 8);
97 | HEADER <= ROM_DATA(7 downto 4);
98 | LOAD_ADDR <= LOAD_ADDR + 2;
99 | else
100 | CURR_DATA(15 downto 8) <= ROM_DATA(15 downto 8);
101 | HEADER <= ROM_DATA(15 downto 12);
102 | LOAD_ADDR <= LOAD_ADDR + 1;
103 | end if;
104 | BYTE_LOAD <= LOAD_ADDR(0);
105 | elsif INIT_CNT = 1 then
106 | if BYTE_LOAD = '1' then
107 | CURR_DATA(7 downto 0) <= ROM_DATA(7 downto 0);
108 | end if;
109 | NEXT_DATA <= ROM_DATA;
110 | LOAD_ADDR <= LOAD_ADDR + 2;
111 | end if;
112 | INIT_CNT <= INIT_CNT + 1;
113 |
114 | else
115 | if DATA_REQ = '1' then
116 | BYTE_LOAD <= not BYTE_LOAD;
117 | if BYTE_LOAD = '0' then
118 | CURR_DATA <= CURR_DATA(7 downto 0) & NEXT_DATA(7 downto 0);
119 | else
120 | CURR_DATA <= CURR_DATA(7 downto 0) & NEXT_DATA(15 downto 8);
121 | end if;
122 | end if;
123 |
124 | if READ_REQ = '1' then
125 | NEXT_DATA <= DATA_BUF(conv_integer(RD_POS));
126 | if RD_POS /= WR_POS then
127 | RD_POS <= RD_POS + 1;
128 | end if;
129 | end if;
130 |
131 | if WRITE_REQ = '1' then
132 | DATA_BUF(conv_integer(WR_POS)) <= ROM_DATA;
133 | LOAD_ADDR <= LOAD_ADDR + 2;
134 | WR_POS <= WR_POS + 1;
135 | end if;
136 |
137 | end if;
138 | end if;
139 | end if;
140 | end if;
141 | end process;
142 |
143 | ROM_ADDR <= LOAD_ADDR;
144 | OUT_DATA <= CURR_DATA;
145 | INIT_DONE <= TINIT_DONE;
146 |
147 | end rtl;
148 |
--------------------------------------------------------------------------------
/rtl/chip/SDD1/SDD1Map.vhd:
--------------------------------------------------------------------------------
1 | library STD;
2 | use STD.TEXTIO.ALL;
3 | library IEEE;
4 | use IEEE.STD_LOGIC_1164.ALL;
5 | use IEEE.NUMERIC_STD.ALL;
6 | use IEEE.STD_LOGIC_UNSIGNED.ALL;
7 | use IEEE.STD_LOGIC_TEXTIO.all;
8 |
9 | entity SDD1Map is
10 | port(
11 | MCLK : in std_logic;
12 | RST_N : in std_logic;
13 | ENABLE : in std_logic := '1';
14 |
15 | CA : in std_logic_vector(23 downto 0);
16 | DI : in std_logic_vector(7 downto 0);
17 | DO : out std_logic_vector(7 downto 0);
18 | CPURD_N : in std_logic;
19 | CPUWR_N : in std_logic;
20 |
21 | PA : in std_logic_vector(7 downto 0);
22 | PARD_N : in std_logic;
23 | PAWR_N : in std_logic;
24 |
25 | ROMSEL_N : in std_logic;
26 | RAMSEL_N : in std_logic;
27 |
28 | SYSCLKF_CE : in std_logic;
29 | SYSCLKR_CE : in std_logic;
30 | REFRESH : in std_logic;
31 |
32 | IRQ_N : out std_logic;
33 |
34 | ROM_ADDR : out std_logic_vector(22 downto 0);
35 | ROM_Q : in std_logic_vector(15 downto 0);
36 | ROM_CE_N : out std_logic;
37 | ROM_OE_N : out std_logic;
38 | ROM_WORD : out std_logic;
39 |
40 | BSRAM_ADDR : out std_logic_vector(19 downto 0);
41 | BSRAM_D : out std_logic_vector(7 downto 0);
42 | BSRAM_Q : in std_logic_vector(7 downto 0);
43 | BSRAM_CE_N : out std_logic;
44 | BSRAM_OE_N : out std_logic;
45 | BSRAM_WE_N : out std_logic;
46 |
47 | MAP_ACTIVE : out std_logic;
48 | MAP_CTRL : in std_logic_vector(7 downto 0);
49 | ROM_MASK : in std_logic_vector(23 downto 0);
50 | BSRAM_MASK : in std_logic_vector(23 downto 0)
51 | );
52 | end SDD1Map;
53 |
54 | architecture rtl of SDD1Map is
55 |
56 | signal SDD1_ROM_A : std_logic_vector(23 downto 0);
57 | signal BSRAM_CS_N : std_logic;
58 | signal SDD1_DO : std_logic_vector(7 downto 0);
59 | signal MAP_SEL : std_logic;
60 | begin
61 |
62 | MAP_SEL <= '1' when MAP_CTRL(7 downto 4) = X"5" else '0';
63 | MAP_ACTIVE <= MAP_SEL;
64 |
65 | -- SDD1
66 | SDD1 : entity work.SDD1
67 | port map(
68 | RST_N => RST_N and MAP_SEL,
69 | CLK => MCLK,
70 | ENABLE => ENABLE,
71 |
72 | CA => CA,
73 | CPURD_N => CPURD_N,
74 | CPUWR_N => CPUWR_N,
75 | DO => SDD1_DO,
76 | DI => DI,
77 | ROMSEL_N => ROMSEL_N,
78 |
79 | SYSCLKF_CE => SYSCLKF_CE,
80 | SYSCLKR_CE => SYSCLKR_CE,
81 |
82 | ROM_A => SDD1_ROM_A,
83 | ROM_DO => ROM_Q,
84 | ROM_RD_N => ROM_OE_N
85 | );
86 |
87 | ROM_ADDR <= SDD1_ROM_A(22 downto 0) and ROM_MASK(22 downto 0);
88 | ROM_CE_N <= '0';
89 | ROM_WORD <= '1';
90 |
91 | BSRAM_CS_N <= '0' when CA(23 downto 18) = x"7" & "00" or (CA(22) = '0' and CA(15 downto 13) = "011") else '1';
92 | BSRAM_ADDR <= ("0" & CA(19 downto 16) & CA(14 downto 0)) and BSRAM_MASK(19 downto 0);
93 | BSRAM_CE_N <= BSRAM_CS_N;
94 | BSRAM_OE_N <= CPURD_N;
95 | BSRAM_WE_N <= CPUWR_N;
96 | BSRAM_D <= DI;
97 |
98 | DO <= BSRAM_Q when BSRAM_CS_N = '0' else SDD1_DO;
99 |
100 | IRQ_N <= '1';
101 |
102 | end rtl;
103 |
--------------------------------------------------------------------------------
/rtl/chip/SPC7110/SPC7110Map.vhd:
--------------------------------------------------------------------------------
1 | library STD;
2 | use STD.TEXTIO.ALL;
3 | library IEEE;
4 | use IEEE.STD_LOGIC_1164.ALL;
5 | use IEEE.NUMERIC_STD.ALL;
6 | use IEEE.STD_LOGIC_UNSIGNED.ALL;
7 | use IEEE.STD_LOGIC_TEXTIO.all;
8 |
9 | entity SPC7110Map is
10 | port(
11 | MCLK : in std_logic;
12 | RST_N : in std_logic;
13 | ENABLE : in std_logic := '1';
14 |
15 | CA : in std_logic_vector(23 downto 0);
16 | DI : in std_logic_vector(7 downto 0);
17 | DO : out std_logic_vector(7 downto 0);
18 | CPURD_N : in std_logic;
19 | CPUWR_N : in std_logic;
20 |
21 | PA : in std_logic_vector(7 downto 0);
22 | PARD_N : in std_logic;
23 | PAWR_N : in std_logic;
24 |
25 | ROMSEL_N : in std_logic;
26 | RAMSEL_N : in std_logic;
27 |
28 | SYSCLKF_CE : in std_logic;
29 | SYSCLKR_CE : in std_logic;
30 | REFRESH : in std_logic;
31 |
32 | IRQ_N : out std_logic;
33 |
34 | ROM_ADDR : out std_logic_vector(22 downto 0);
35 | ROM_Q : in std_logic_vector(15 downto 0);
36 | ROM_CE_N : out std_logic;
37 | ROM_OE_N : out std_logic;
38 | ROM_WORD : out std_logic;
39 |
40 | BSRAM_ADDR : out std_logic_vector(19 downto 0);
41 | BSRAM_D : out std_logic_vector(7 downto 0);
42 | BSRAM_Q : in std_logic_vector(7 downto 0);
43 | BSRAM_CE_N : out std_logic;
44 | BSRAM_OE_N : out std_logic;
45 | BSRAM_WE_N : out std_logic;
46 |
47 | MAP_ACTIVE : out std_logic;
48 | MAP_CTRL : in std_logic_vector(7 downto 0);
49 | ROM_MASK : in std_logic_vector(23 downto 0);
50 | BSRAM_MASK : in std_logic_vector(23 downto 0);
51 |
52 | EXT_RTC : in std_logic_vector(64 downto 0)
53 | );
54 | end SPC7110Map;
55 |
56 | architecture rtl of SPC7110Map is
57 |
58 | signal PROM_OE_N : std_logic;
59 |
60 | signal SPC7110_DROM_A : std_logic_vector(22 downto 0);
61 | signal SPC7110_DROM_DO : std_logic_vector(7 downto 0);
62 | signal SPC7110_DROM_OE_N : std_logic;
63 | signal SPC7110_DROM_RDY : std_logic;
64 | signal SNES_DROM_A : std_logic_vector(22 downto 0);
65 | signal SNES_DROM_OE_N : std_logic;
66 |
67 | signal SRAM_CE_N : std_logic;
68 |
69 | signal RTC_DI : std_logic_vector(3 downto 0);
70 | signal RTC_DO : std_logic_vector(3 downto 0);
71 | signal RTC_CE : std_logic;
72 | signal RTC_CK : std_logic;
73 |
74 | signal SPC7110_DO : std_logic_vector(7 downto 0);
75 | signal SNES_ROM_ACTIVE : std_logic;
76 | signal SPC7110_DROM_ACTIVE : std_logic;
77 | signal ROM_RD : std_logic;
78 | signal ROM_RD_LATE : std_logic;
79 |
80 | signal MAP_SEL : std_logic;
81 |
82 | begin
83 |
84 | MAP_SEL <= '1' when MAP_CTRL(7 downto 4) = X"D" else '0';
85 | MAP_ACTIVE <= MAP_SEL;
86 |
87 | SPC7110 : entity work.SPC7110
88 | port map(
89 | RST_N => RST_N and MAP_SEL,
90 | CLK => MCLK,
91 | ENABLE => ENABLE,
92 |
93 | CA => CA,
94 | DO => SPC7110_DO,
95 | DI => DI,
96 | CPURD_N => CPURD_N,
97 | CPUWR_N => CPUWR_N,
98 |
99 | SYSCLKF_CE => SYSCLKF_CE,
100 | SYSCLKR_CE => SYSCLKR_CE,
101 |
102 | DROM_A => SPC7110_DROM_A,
103 | DROM_OE_N => SPC7110_DROM_OE_N,
104 | DROM_DO => ROM_Q(7 downto 0),
105 | DROM_RDY => SPC7110_DROM_RDY,
106 |
107 | PROM_OE_N => PROM_OE_N,
108 | SNES_DROM_A => SNES_DROM_A,
109 | SNES_DROM_OE_N => SNES_DROM_OE_N,
110 | SRAM_CE_N => SRAM_CE_N,
111 |
112 | RTC_DO => RTC_DI,
113 | RTC_DI => RTC_DO,
114 | RTC_CE => RTC_CE,
115 | RTC_CK => RTC_CK
116 | );
117 |
118 | RTC : entity work.RTC4513
119 | port map(
120 | CLK => MCLK,
121 | ENABLE => ENABLE,
122 |
123 | DO => RTC_DO,
124 | DI => RTC_DI,
125 | CE => RTC_CE,
126 | CK => RTC_CK,
127 |
128 | EXT_RTC => EXT_RTC
129 | );
130 |
131 |
132 | process(MCLK, RST_N)
133 | begin
134 | if RST_N = '0' then
135 | SNES_ROM_ACTIVE <= '0';
136 | SPC7110_DROM_ACTIVE <= '0';
137 | SPC7110_DROM_RDY <= '0';
138 | ROM_RD_LATE <= '0';
139 | elsif rising_edge(MCLK) then
140 | if SYSCLKF_CE = '1' then
141 | SPC7110_DROM_ACTIVE <= not SPC7110_DROM_OE_N;
142 | SNES_ROM_ACTIVE <= '0';
143 | elsif SYSCLKR_CE = '1' then
144 | SPC7110_DROM_ACTIVE <= '0';
145 | SNES_ROM_ACTIVE <= '1';
146 | end if;
147 |
148 | ROM_RD_LATE <= ROM_RD; --waiting for 2 cycles of reading sdram
149 |
150 | SPC7110_DROM_RDY <= '0';
151 | if SPC7110_DROM_RDY = '0' and ROM_RD_LATE = '1' and SPC7110_DROM_ACTIVE = '1' then
152 | SPC7110_DROM_RDY <= '1';
153 | end if;
154 | end if;
155 | end process;
156 |
157 | process(MCLK, RST_N)
158 | begin
159 | if RST_N = '0' then
160 | ROM_RD <= '0';
161 | elsif rising_edge(MCLK) then
162 | ROM_RD <= '0';
163 | if SYSCLKR_CE = '1' or SYSCLKF_CE = '1' then
164 | ROM_RD <= '1';
165 | end if;
166 | end if;
167 | end process;
168 |
169 | -- SYSCLK |___|---|
170 | -- 0 - slot for SPC7110 for DROM access if need, else same SNES access (for sdram refresh)
171 | -- 1 - slot for SNES for PROM/DROM access, first 1 MByte - PROM, rest - DROM
172 | process(CA, SPC7110_DROM_A, SNES_DROM_A, SPC7110_DROM_ACTIVE, SNES_DROM_OE_N, SNES_ROM_ACTIVE)
173 | begin
174 | if SNES_ROM_ACTIVE = '0' then
175 | if SPC7110_DROM_ACTIVE = '1' then
176 | ROM_ADDR <= std_logic_vector(unsigned(SPC7110_DROM_A(22 downto 20)) + "001") & SPC7110_DROM_A(19 downto 0);
177 | else
178 | ROM_ADDR <= (not CA(23) and CA(22)) & (not CA(23) and CA(22)) & "0" & CA(19 downto 0);
179 | end if;
180 | else
181 | if SNES_DROM_OE_N = '0' then
182 | ROM_ADDR <= std_logic_vector(unsigned(SNES_DROM_A(22 downto 20)) + "001") & SNES_DROM_A(19 downto 0);
183 | else
184 | ROM_ADDR <= (not CA(23) and CA(22)) & (not CA(23) and CA(22)) & "0" & CA(19 downto 0);
185 | end if;
186 | end if;
187 | end process;
188 | ROM_CE_N <= '0';
189 | ROM_OE_N <= not ROM_RD;
190 | ROM_WORD <= '0';
191 |
192 | BSRAM_ADDR <= ("0000000" & CA(12 downto 0)) and BSRAM_MASK(19 downto 0);
193 | BSRAM_D <= DI;
194 | BSRAM_CE_N <= SRAM_CE_N;
195 | BSRAM_OE_N <= CPURD_N;
196 | BSRAM_WE_N <= CPUWR_N;
197 |
198 | DO <= ROM_Q(7 downto 0) when PROM_OE_N = '0' or SNES_DROM_OE_N = '0' else
199 | BSRAM_Q when SRAM_CE_N = '0' else
200 | SPC7110_DO;
201 |
202 | IRQ_N <= '1';
203 |
204 | end rtl;
205 |
--------------------------------------------------------------------------------
/rtl/chip/SRTC.vhd:
--------------------------------------------------------------------------------
1 | library IEEE;
2 | use IEEE.STD_LOGIC_1164.ALL;
3 | library STD;
4 | use IEEE.NUMERIC_STD.ALL;
5 |
6 | entity SRTC is
7 | port(
8 | CLK : in std_logic;
9 |
10 | A0 : in std_logic;
11 | DI : in std_logic_vector(7 downto 0);
12 | DO : out std_logic_vector(7 downto 0);
13 | CS : in std_logic;
14 | CPURD_N : in std_logic;
15 | CPUWR_N : in std_logic;
16 |
17 | SYSCLKF_CE : in std_logic;
18 |
19 | EXT_RTC : in std_logic_vector(64 downto 0)
20 | );
21 | end SRTC;
22 |
23 | architecture rtl of SRTC is
24 |
25 | type regs_t is array(0 to 12) of std_logic_vector(3 downto 0);
26 | signal REGS : regs_t;
27 |
28 | signal INDEX : integer range 0 to 15 := 15;
29 | signal MODE : integer range 0 to 3 := 0;
30 |
31 | signal SEC_DIV : integer := 0;
32 | signal SEC_TICK : std_logic := '0';
33 | signal LAST_RTC64 : std_logic := '0';
34 |
35 | type LastDayOfMonth_t is array(0 to 12) of std_logic_vector(7 downto 0);
36 | constant DAYS_TBL : LastDayOfMonth_t := (
37 | x"31",--not use
38 | x"31",--01
39 | x"28",--02
40 | x"31",--03
41 | x"30",--04
42 | x"31",--05
43 | x"30",--06
44 | x"31",--07
45 | x"31",--08
46 | x"30",--09
47 | x"31",--10
48 | x"30",--11
49 | x"31" --12
50 | );
51 |
52 | begin
53 |
54 | process( CLK)
55 | begin
56 | if rising_edge(CLK) then
57 | SEC_TICK <= '0';
58 |
59 | SEC_DIV <= SEC_DIV + 1;
60 | if SEC_DIV = 21477270-1 then
61 | SEC_DIV <= 0;
62 | SEC_TICK <= '1';
63 | end if;
64 | end if;
65 | end process;
66 |
67 | process( CLK)
68 | variable DAY_OF_MONTH_L : std_logic_vector(3 downto 0);
69 | variable DAY_OF_MONTH_H : std_logic_vector(3 downto 0);
70 | begin
71 | if rising_edge(CLK) then
72 | DAY_OF_MONTH_H := DAYS_TBL(to_integer(unsigned(REGS(8))))(7 downto 4);
73 | DAY_OF_MONTH_L := DAYS_TBL(to_integer(unsigned(REGS(8))))(3 downto 0);
74 |
75 | if SEC_TICK = '1' then
76 | REGS(0) <= std_logic_vector( unsigned(REGS(0)) + 1 ); --sec low inc
77 | if REGS(0) = x"9" then
78 | REGS(0) <= (others => '0');
79 | REGS(1) <= std_logic_vector( unsigned(REGS(1)) + 1 ); --sec high inc
80 | if REGS(1) = x"5" then
81 | REGS(1) <= (others => '0');
82 | REGS(2) <= std_logic_vector( unsigned(REGS(2)) + 1 ); --min low inc
83 | if REGS(2) = x"9" then
84 | REGS(2) <= (others => '0');
85 | REGS(3) <= std_logic_vector( unsigned(REGS(3)) + 1 ); --min high inc
86 | if REGS(3) = x"5" then
87 | REGS(3) <= (others => '0');
88 | REGS(4) <= std_logic_vector( unsigned(REGS(4)) + 1 ); --hour low inc
89 | if REGS(4) = x"9" and REGS(5) <= x"2" then
90 | REGS(4) <= (others => '0');
91 | REGS(5) <= std_logic_vector( unsigned(REGS(5)) + 1 ); --hour high inc
92 | elsif REGS(4) = x"3" and REGS(5) = x"2" then
93 | REGS(4) <= (others => '0');
94 | REGS(5) <= (others => '0');
95 | REGS(6) <= std_logic_vector( unsigned(REGS(6)) + 1 ); --day low inc
96 | if REGS(6) = x"9" and REGS(7)(1 downto 0) <= x"2" then
97 | REGS(6) <= (others => '0');
98 | REGS(7) <= std_logic_vector( unsigned(REGS(7)) + 1 ); --day high inc
99 | elsif REGS(6) = DAY_OF_MONTH_L and REGS(7) = DAY_OF_MONTH_H then
100 | REGS(6) <= x"1";
101 | REGS(7) <= (others => '0');
102 | REGS(8) <= std_logic_vector( unsigned(REGS(8)) + 1 ); --month inc
103 | if REGS(8) = x"C" then
104 | REGS(8) <= x"1";
105 | REGS(9) <= std_logic_vector( unsigned(REGS(9)) + 1 ); --year low inc
106 | if REGS(9) = x"9" then
107 | REGS(9) <= (others => '0');
108 | REGS(10) <= std_logic_vector( unsigned(REGS(10)) + 1 ); --year high inc
109 | if REGS(10) = x"9" then
110 | REGS(10) <= (others => '0');
111 | REGS(11) <= std_logic_vector( unsigned(REGS(11)) + 1 ); --century inc
112 | if REGS(11) = x"C" then
113 | REGS(11) <= (others => '0');
114 | end if;
115 | end if;
116 | end if;
117 | end if;
118 | end if;
119 | REGS(12) <= std_logic_vector( unsigned(REGS(12)) + 1 ); --weeks inc
120 | if REGS(12) = x"6" then
121 | REGS(12) <= (others => '0');
122 | end if;
123 | end if;
124 | end if;
125 | end if;
126 | end if;
127 | end if;
128 | end if;
129 |
130 | if EXT_RTC(64) /= LAST_RTC64 then
131 | LAST_RTC64 <= EXT_RTC(64);
132 | REGS(0) <= EXT_RTC(3 downto 0);
133 | REGS(1) <= EXT_RTC(7 downto 4);
134 | REGS(2) <= EXT_RTC(11 downto 8);
135 | REGS(3) <= EXT_RTC(15 downto 12);
136 | REGS(4) <= EXT_RTC(19 downto 16);
137 | REGS(5) <= EXT_RTC(23 downto 20);
138 | REGS(6) <= EXT_RTC(27 downto 24);
139 | REGS(7) <= EXT_RTC(31 downto 28);
140 | if EXT_RTC(36) = '0' then
141 | REGS(8) <= EXT_RTC(35 downto 32);
142 | else
143 | REGS(8) <= std_logic_vector( unsigned(EXT_RTC(35 downto 32)) + 10 );
144 | end if;
145 | REGS(9) <= EXT_RTC(43 downto 40);
146 | REGS(10) <= EXT_RTC(47 downto 44);
147 | REGS(11) <= x"A";
148 | REGS(12) <= EXT_RTC(51 downto 48);
149 | end if;
150 |
151 | if CS = '1' and SYSCLKF_CE = '1' then
152 | if CPUWR_N = '0' and A0 = '1' then
153 | if DI(3 downto 0) = x"D" then
154 | INDEX <= 15;
155 | MODE <= 0;
156 | elsif DI(3 downto 0) = x"E" then
157 | MODE <= 1;
158 | else
159 | if MODE = 1 then
160 | case DI(3 downto 0) is
161 | when x"0" =>
162 | MODE <= 2;
163 | INDEX <= 0;
164 | when others =>
165 | MODE <= 3;
166 | end case;
167 | elsif MODE = 2 then
168 | if INDEX < 12 then
169 | REGS(INDEX) <= DI(3 downto 0);
170 | INDEX <= INDEX + 1;
171 | end if;
172 | end if;
173 | end if;
174 | end if;
175 |
176 | if CPURD_N = '0' and A0 = '0' then
177 | if MODE = 0 then
178 | if INDEX = 13 then
179 | INDEX <= 15;
180 | else
181 | INDEX <= INDEX + 1;
182 | end if;
183 | end if;
184 | end if;
185 | end if;
186 | end if;
187 | end process;
188 |
189 | DO <= x"0" & REGS(INDEX) when INDEX <= 12 else x"0F";
190 |
191 | end rtl;
192 |
--------------------------------------------------------------------------------
/rtl/chip/chip.qip:
--------------------------------------------------------------------------------
1 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) CX4/CX4.vhd ]
2 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) CX4/cx4cache.vhd ]
3 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) CX4/CX4Map.vhd ]
4 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) DSP/DSPn.vhd ]
5 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) DSP/DSP_LHRomMap.vhd ]
6 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) DSP/OBC1.vhd ]
7 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) SDD1/InputMgr.vhd ]
8 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) SDD1/Decoder.vhd ]
9 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) SDD1/SDD1.vhd ]
10 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) SDD1/SDD1Map.vhd ]
11 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) GSU/GSU.vhd ]
12 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) GSU/GSU_PKG.vhd ]
13 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) GSU/GSUMap.vhd ]
14 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) SA1/SA1.vhd ]
15 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) SA1/SA1DIV.vhd ]
16 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) SA1/SA1MULT.vhd ]
17 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) SA1/SA1Map.vhd ]
18 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) SPC7110/SPC7110.vhd ]
19 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) SPC7110/SPC7110_DEC.vhd ]
20 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) SPC7110/SPC7110_DEC_PKG.vhd ]
21 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) SPC7110/SPC7110_FIFO.vhd ]
22 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) SPC7110/SPC7110_MULDIV.vhd ]
23 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) SPC7110/SPC7110Map.vhd ]
24 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) BSX/BSX_MCC.vhd ]
25 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) BSX/BSX_DP.vhd ]
26 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) BSX/BSX_BS.vhd ]
27 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) BSX/BSXMap.vhd ]
28 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) MSU1/MSU.sv ]
29 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) MSU1/msu_audio.v ]
30 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) MSU1/msu_fifo.v ]
31 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) MSU1/msu_data_store.sv ]
32 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) RTC4513.vhd ]
33 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) SRTC.vhd ]
34 |
--------------------------------------------------------------------------------
/rtl/hps_ext.v:
--------------------------------------------------------------------------------
1 | //
2 | // hps_ext for Mega CD
3 | //
4 | // Copyright (c) 2020 Alexey Melnikov
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 | module hps_ext
22 | (
23 | input reset,
24 | input clk_sys,
25 | inout [35:0] EXT_BUS,
26 |
27 | output reg msu_enable,
28 |
29 | input [15:0] msu_track_num,
30 | input msu_track_request,
31 | output reg msu_track_mounting,
32 | output reg msu_track_missing,
33 |
34 | output reg [31:0] msu_audio_size,
35 | output reg msu_audio_ack,
36 | input msu_audio_req,
37 | input msu_audio_seek,
38 | input [21:0] msu_audio_sector,
39 | input msu_audio_download,
40 |
41 | output reg [31:0] msu_data_base
42 | );
43 |
44 | assign EXT_BUS[15:0] = io_dout;
45 | wire [15:0] io_din = EXT_BUS[31:16];
46 | assign EXT_BUS[32] = dout_en;
47 | wire io_strobe = EXT_BUS[33];
48 | wire io_enable = EXT_BUS[34];
49 |
50 | localparam EXT_CMD_MIN = CD_GET;
51 | localparam EXT_CMD_MAX = CD_SET;
52 |
53 | localparam CD_GET = 'h34;
54 | localparam CD_SET = 'h35;
55 |
56 | reg [15:0] io_dout;
57 | reg dout_en = 0;
58 | reg [9:0] byte_cnt;
59 |
60 | always@(posedge clk_sys) begin
61 | reg [15:0] cmd;
62 | reg [7:0] cd_req = 0;
63 |
64 | cd_get <= 0;
65 | if(cd_put) cd_req <= cd_req + 1'd1;
66 |
67 | if(~io_enable) begin
68 | dout_en <= 0;
69 | io_dout <= 0;
70 | byte_cnt <= 0;
71 | if(cmd == 'h35) cd_get <= 1;
72 | end
73 | else if(io_strobe) begin
74 |
75 | io_dout <= 0;
76 | if(~&byte_cnt) byte_cnt <= byte_cnt + 1'd1;
77 |
78 | if(byte_cnt == 0) begin
79 | cmd <= io_din;
80 | dout_en <= (io_din >= EXT_CMD_MIN && io_din <= EXT_CMD_MAX);
81 | if(io_din == CD_GET) io_dout <= cd_req;
82 | end else begin
83 | case(cmd)
84 | CD_GET:
85 | if(!byte_cnt[9:3]) begin
86 | case(byte_cnt[2:0])
87 | 1: io_dout <= cd_in[15:0];
88 | 2: io_dout <= cd_in[31:16];
89 | 3: io_dout <= cd_in[47:32];
90 | endcase
91 | end
92 |
93 | CD_SET:
94 | if(!byte_cnt[9:3]) begin
95 | case(byte_cnt[2:0])
96 | 1: cd_out[15:0] <= io_din;
97 | 2: cd_out[31:16] <= io_din;
98 | 3: cd_out[47:32] <= io_din;
99 | endcase
100 | end
101 | endcase
102 | end
103 | end
104 | end
105 |
106 | reg [47:0] cd_in;
107 | reg [47:0] cd_out;
108 | reg cd_put, cd_get;
109 |
110 | always @(posedge clk_sys) begin
111 | reg reset_old = 0;
112 | reg msu_audio_req_old = 0;
113 | reg msu_audio_seek_old = 0;
114 | reg msu_track_request_old = 0;
115 | reg msu_audio_download_old = 0;
116 |
117 | cd_put <= 0;
118 |
119 | reset_old <= reset;
120 | if (reset) begin
121 | msu_track_missing <= 0;
122 | msu_track_mounting <= 0;
123 | msu_audio_ack <= 0;
124 | if (!reset_old) begin
125 | cd_in <= 8'hFF;
126 | cd_put <= 1;
127 | end
128 | end
129 |
130 | msu_audio_download_old <= msu_audio_download;
131 | if (!msu_audio_download && msu_audio_download_old) begin
132 | msu_audio_ack <= 0;
133 | end
134 | if (msu_audio_download && !msu_audio_download_old) begin
135 | msu_audio_ack <= 1;
136 | end
137 |
138 | // Outgoing messaging
139 | // Sectors
140 | msu_audio_req_old <= msu_audio_req;
141 | if (!msu_track_request && !msu_audio_req_old && msu_audio_req) begin
142 | cd_in <= 'h34;
143 | cd_put <= 1;
144 | end
145 |
146 | // Jump to a sector
147 | msu_audio_seek_old <= msu_audio_seek;
148 | if (!msu_track_request && !msu_audio_seek_old && msu_audio_seek) begin
149 | cd_in <= { msu_audio_sector, 16'h36 };
150 | cd_put <= 1;
151 | end
152 |
153 | // Track requests
154 | msu_track_request_old <= msu_track_request;
155 | if (!msu_track_request_old && msu_track_request) begin
156 | cd_in <= { msu_track_num, 16'h35 };
157 | cd_put <= 1;
158 | msu_track_missing <= 0;
159 | msu_track_mounting <= 1;
160 | end
161 |
162 | if (cd_get) begin
163 | case(cd_out[3:0])
164 | 1: msu_enable <= cd_out[15];
165 | 2: {msu_audio_size, msu_track_missing, msu_track_mounting, msu_audio_ack} <= {cd_out[47:16], !cd_out[47:16], 2'b00};
166 | 3: msu_data_base <= cd_out[47:16];
167 | endcase
168 | end
169 | end
170 |
171 | endmodule
172 |
--------------------------------------------------------------------------------
/rtl/ioport.sv:
--------------------------------------------------------------------------------
1 |
2 | module ioport
3 | (
4 | input CLK,
5 |
6 | input MULTITAP,
7 |
8 | input PORT_LATCH,
9 | input PORT_CLK,
10 | input PORT_P6,
11 | output [1:0] PORT_DO,
12 |
13 | input [11:0] JOYSTICK1,
14 | input [11:0] JOYSTICK2,
15 | input [11:0] JOYSTICK3,
16 | input [11:0] JOYSTICK4,
17 |
18 | input [7:0] JOY_X,
19 | input [7:0] JOY_Y,
20 |
21 | input [7:0] DPAD_AIM_SPEED,
22 |
23 | input MOUSE_EN
24 | );
25 |
26 | assign PORT_DO = {(JOY_LATCH1[15] & ~PORT_LATCH) | ~MULTITAP, MOUSE_EN ? MS_LATCH[31] : JOY_LATCH0[15]};
27 |
28 | wire [11:0] JOYSTICK[4] = '{JOYSTICK1,JOYSTICK2,JOYSTICK3,JOYSTICK4};
29 |
30 | wire JOYn = ~PORT_P6 & MULTITAP;
31 |
32 | wire [15:0] JOY0 = {JOYSTICK[{JOYn,1'b0}][5], JOYSTICK[{JOYn,1'b0}][7],
33 | JOYSTICK[{JOYn,1'b0}][10], JOYSTICK[{JOYn,1'b0}][11],
34 | JOYSTICK[{JOYn,1'b0}][3], JOYSTICK[{JOYn,1'b0}][2],
35 | JOYSTICK[{JOYn,1'b0}][1], JOYSTICK[{JOYn,1'b0}][0],
36 | JOYSTICK[{JOYn,1'b0}][4], JOYSTICK[{JOYn,1'b0}][6],
37 | JOYSTICK[{JOYn,1'b0}][8], JOYSTICK[{JOYn,1'b0}][9], 4'b0000};
38 |
39 | wire [15:0] JOY1 = {JOYSTICK[{JOYn,1'b1}][5], JOYSTICK[{JOYn,1'b1}][7],
40 | JOYSTICK[{JOYn,1'b1}][10], JOYSTICK[{JOYn,1'b1}][11],
41 | JOYSTICK[{JOYn,1'b1}][3], JOYSTICK[{JOYn,1'b1}][2],
42 | JOYSTICK[{JOYn,1'b1}][1], JOYSTICK[{JOYn,1'b1}][0],
43 | JOYSTICK[{JOYn,1'b1}][4], JOYSTICK[{JOYn,1'b1}][6],
44 | JOYSTICK[{JOYn,1'b1}][8], JOYSTICK[{JOYn,1'b1}][9], 4'b0000};
45 |
46 | // Gamepads
47 | reg [15:0] JOY_LATCH0;
48 | always @(posedge CLK) begin
49 | reg old_clk, old_n;
50 | old_clk <= PORT_CLK;
51 | old_n <= JOYn;
52 | if(PORT_LATCH | (~old_n & JOYn)) JOY_LATCH0 <= ~JOY0;
53 | else if (~old_clk & PORT_CLK) JOY_LATCH0 <= JOY_LATCH0 << 1;
54 | end
55 |
56 | reg [15:0] JOY_LATCH1;
57 | always @(posedge CLK) begin
58 | reg old_clk, old_n;
59 | old_clk <= PORT_CLK;
60 | old_n <= JOYn;
61 | if(PORT_LATCH | (~old_n & JOYn)) JOY_LATCH1 <= ~JOY1;
62 | else if (~old_clk & PORT_CLK) JOY_LATCH1 <= JOY_LATCH1 << 1;
63 | end
64 |
65 | // Mouse
66 | wire dpad_mouse_sdy = JOYSTICK1[3];
67 | wire dpad_mouse_sdx = JOYSTICK1[1];
68 | wire [6:0] dpad_mouse_dy = JOYSTICK1[3] | JOYSTICK1[2] ? DPAD_AIM_SPEED[6:0] : 7'd0;
69 | wire [6:0] dpad_mouse_dx = JOYSTICK1[0] | JOYSTICK1[1] ? DPAD_AIM_SPEED[6:0] : 7'd0;
70 | wire joy_mouse_sdy = ~JOY_Y[7];
71 | wire joy_mouse_sdx = ~JOY_X[7];
72 | wire [6:0] joy_mouse_dy = joy_mouse_sdy ? (8'd128-JOY_Y) >> 4 : (JOY_Y[6:0]) >> 4;
73 | wire [6:0] joy_mouse_dx = joy_mouse_sdx ? (8'd128-JOY_X) >> 4 : (JOY_X[6:0]) >> 4;
74 | wire mouse_left = JOYSTICK1[5];
75 | wire mouse_right = JOYSTICK1[4];
76 |
77 | reg joystick_detected = 0;
78 | reg [1:0] speed = 0;
79 | reg [31:0] MS_LATCH;
80 | always @(posedge CLK) begin
81 | reg old_stb, old_clk, old_latch;
82 | reg sdx,sdy;
83 |
84 | old_clk <= PORT_CLK;
85 | old_latch <= PORT_LATCH;
86 |
87 | if (JOY_Y || JOY_X)
88 | joystick_detected <= 1'b1;
89 |
90 | if(old_latch & ~PORT_LATCH) begin
91 | if(joystick_detected && (joy_mouse_dy + joy_mouse_dx > 0)) begin
92 | MS_LATCH <= ~{8'h00, mouse_left, mouse_right, speed, 4'b0001, joy_mouse_sdy, joy_mouse_dy, joy_mouse_sdx, joy_mouse_dx};
93 | end else begin
94 | MS_LATCH <= ~{8'h00, mouse_left, mouse_right, speed, 4'b0001, dpad_mouse_sdy, dpad_mouse_dy, dpad_mouse_sdx, dpad_mouse_dx};
95 | end
96 | end
97 |
98 | if(~old_clk & PORT_CLK) begin
99 | if(PORT_LATCH) begin
100 | speed <= speed + 1'd1;
101 | if(speed == 2) speed <= 0;
102 | end
103 | else MS_LATCH <= MS_LATCH << 1;
104 | end
105 | end
106 |
107 | endmodule
108 |
--------------------------------------------------------------------------------
/rtl/lightgun.sv:
--------------------------------------------------------------------------------
1 |
2 | module lightgun
3 | (
4 | input CLK,
5 | input RESET,
6 |
7 | //input [24:0] MOUSE,
8 | //input MOUSE_XY,
9 |
10 | input [7:0] JOY_X,JOY_Y,
11 | input F,C,T,P,
12 |
13 | input UP,
14 | input DOWN,
15 | input LEFT,
16 | input RIGHT,
17 | input [7:0] DPAD_AIM_SPEED,
18 |
19 | input HDE,VDE,
20 | input CLKPIX,
21 |
22 | output [2:0] TARGET,
23 | input SIZE,
24 | input GUN_TYPE,
25 |
26 | input PORT_LATCH,
27 | input PORT_CLK,
28 | output PORT_P6,
29 | output [1:0] PORT_DO
30 | );
31 |
32 | parameter CROSS_SZ = 8'd4;
33 |
34 | assign PORT_DO = {1'b1, GUN_TYPE ? JUSTIFIER_LATCH[31] : JOY_LATCH0[7]};
35 | assign TARGET = {{2{~Ttr & ~offscreen & draw}}, Ttr & ~offscreen & draw};
36 |
37 | reg Ttr; // 0 - one-shot fire. 1 - continous fire.
38 | reg Fb = 0, Pb = 0;
39 |
40 | reg [2:0] reload_pend;
41 | reg [2:0] reload;
42 |
43 | reg [7:0] JOY_LATCH0;
44 | reg [31:0] JUSTIFIER_LATCH;
45 | always @(posedge CLK) begin
46 | reg old_clk, old_f, old_p, old_t, old_latch;
47 | old_clk <= PORT_CLK;
48 |
49 | old_latch <= PORT_LATCH;
50 | if(old_latch & ~PORT_LATCH) begin
51 | Pb <= 0;
52 | if(~Ttr) Fb <= 0;
53 | end
54 |
55 | old_t <= T;
56 | if(~old_t & T) Ttr <=~Ttr;
57 | if(RESET) Ttr <= 1;
58 |
59 | old_f <= F;
60 | if(~old_f & F) Fb <= 1;
61 | if(old_f & ~F) Fb <= 0;
62 |
63 | old_p <= P;
64 | if(~old_p & P) Pb <= 1;
65 |
66 | if(PORT_LATCH) begin
67 | JOY_LATCH0 <= ~{Fb,C,Ttr,Pb,2'b00,offscreen,1'b0};
68 | JUSTIFIER_LATCH <= ~{24'b000000000000111001010101, reload ? 1'b1 : (reload_pend ? 1'b0 : F), 1'b0, P, 1'b0, 4'b1000};
69 | end
70 | else if (~old_clk & PORT_CLK) begin
71 | JOY_LATCH0 <= JOY_LATCH0 << 1;
72 | JUSTIFIER_LATCH <= JUSTIFIER_LATCH << 1;
73 | end
74 | end
75 |
76 | reg [8:0] lg_x, lg_y, x, y;
77 |
78 | wire [9:0] new_x = {lg_x[8],lg_x};// + {{2{MOUSE[4]}},MOUSE[15:8]};
79 | wire [9:0] new_y = {lg_y[8],lg_y};// - {{2{MOUSE[5]}},MOUSE[23:16]};
80 |
81 | reg [7:0] old_joy_x;
82 | reg [7:0] old_joy_y;
83 | reg [8:0] j_x;
84 | reg [8:0] j_y;
85 |
86 | reg offscreen = 0, draw = 0;
87 | reg [21:0] port_p6_sr;
88 | always @(posedge CLK) begin
89 | reg old_pix, old_hde, old_vde, old_ms;
90 | reg [8:0] hcnt, vcnt;
91 | reg [8:0] vtotal;
92 | reg [15:0] hde_d;
93 | reg [8:0] xm,xp,ym,yp;
94 | reg reload_pressed;
95 | reg [16:0] jy1,jy2;
96 |
97 | jy1 <= {8'd0, j_y} * vtotal;
98 | jy2 <= jy1;
99 |
100 | /*old_ms <= MOUSE[24];
101 | if(MOUSE_XY) begin
102 | if(old_ms ^ MOUSE[24]) begin
103 | if(new_x[9]) lg_x <= 0;
104 | else if(new_x[8]) lg_x <= 255;
105 | else lg_x <= new_x[8:0];
106 |
107 | if(new_y[9]) lg_y <= 0;
108 | else if(new_y > vtotal) lg_y <= vtotal;
109 | else lg_y <= new_y[8:0];
110 | end
111 | end
112 | else begin*/
113 | lg_x <= j_x;
114 | lg_y <= jy2[16:8];
115 | if(jy2[16:8] > vtotal) lg_y <= vtotal;
116 | //end
117 |
118 | old_pix <= CLKPIX;
119 | if(~old_pix & CLKPIX) begin
120 | hde_d <= {hde_d[14:0],HDE};
121 | old_hde <= hde_d[15];
122 | if(~&hcnt) hcnt <= hcnt + 1'd1;
123 | if(~old_hde & ~HDE) hcnt <= 0;
124 | if(old_hde & ~hde_d[15]) begin
125 | if(~VDE) begin
126 | vcnt <= 0;
127 | if(vcnt) vtotal <= vcnt - 1'd1;
128 | end
129 | else if(~&vcnt) vcnt <= vcnt + 1'd1;
130 | end
131 |
132 | old_vde <= VDE;
133 | if(~old_vde & VDE) begin
134 |
135 | old_joy_x <= JOY_X;
136 | old_joy_y <= JOY_Y;
137 | if(old_joy_x != JOY_X || old_joy_y != JOY_Y) begin
138 | j_x <= JOY_X[7:0];
139 | j_y <= JOY_Y[7:0];
140 | end else begin
141 | if(LEFT) begin
142 | if (j_x >= DPAD_AIM_SPEED) j_x <= j_x - DPAD_AIM_SPEED;
143 | else j_x <= 0;
144 | end
145 | if(RIGHT) begin
146 | if(lg_x <= 8'd255 - DPAD_AIM_SPEED) j_x <= j_x + DPAD_AIM_SPEED;
147 | else j_x <= 8'd255;
148 | end
149 | if(UP) begin
150 | if (j_y >= DPAD_AIM_SPEED) j_y <= j_y - DPAD_AIM_SPEED;
151 | else j_y <= 0;
152 | end
153 | if(DOWN) begin
154 | if (j_y < vtotal - DPAD_AIM_SPEED) j_y <= j_y + DPAD_AIM_SPEED;
155 | else j_y <= vtotal;
156 | end
157 | end
158 |
159 | x <= lg_x;
160 | y <= lg_y;
161 | xm <= lg_x - CROSS_SZ;
162 | xp <= lg_x + CROSS_SZ;
163 | ym <= lg_y - CROSS_SZ;
164 | yp <= lg_y + CROSS_SZ;
165 | offscreen <= !lg_y[7:1] || lg_y >= (vtotal-1'd1) || !lg_x[7:1] || &lg_x[7:1] || reload_pend || reload;
166 |
167 | if(reload_pend && !reload) begin
168 | reload_pend <= reload_pend - 3'd1;
169 | if (reload_pend == 3'd1) reload <= 3'd5;
170 | end
171 | else if (reload) reload <= reload - 3'd1;
172 | end
173 |
174 | port_p6_sr <= {port_p6_sr[20:0], ~(HDE && VDE && x == hcnt && y == vcnt) || offscreen };
175 | end
176 |
177 | reload_pressed <= C;
178 | if (GUN_TYPE && C && ~reload_pressed) reload_pend <= 3'd5;
179 |
180 | PORT_P6 <= port_p6_sr[21];
181 | draw <= (((SIZE || ($signed(hcnt) >= $signed(xm) && hcnt <= xp)) && y == vcnt) ||
182 | ((SIZE || ($signed(vcnt) >= $signed(ym) && vcnt <= yp)) && x == hcnt));
183 | end
184 |
185 | endmodule
186 |
--------------------------------------------------------------------------------
/rtl/mister_top/rom_parser_tb.sv:
--------------------------------------------------------------------------------
1 | `timescale 1 ns / 10 ps // time-unit = 1 ns, precision = 10 ps
2 |
3 | module rom_parser_tb;
4 | reg clk_74a = 0;
5 |
6 | localparam period = 20;
7 | localparam half_period = period / 2;
8 |
9 | reg [31:0] rom_file_size;
10 |
11 | reg [24:0] addr;
12 | reg [15:0] data;
13 | reg downloading;
14 |
15 | wire [2:0] parsed_rom_type;
16 |
17 | rom_parser rom_parser (
18 | .clk_mem(clk_74a),
19 |
20 | .rom_file_size(rom_file_size),
21 |
22 | .addr(addr),
23 | .data(data),
24 | .downloading(downloading),
25 |
26 | .parsed_rom_type(parsed_rom_type)
27 | );
28 |
29 | always begin
30 | #half_period clk_74a = ~clk_74a;
31 | end
32 |
33 | integer fd;
34 | integer value;
35 |
36 | reg div;
37 |
38 | initial begin
39 | fd = $fopen("Super Mario Kart.smc", "rb");
40 | rom_file_size = 'h100000;
41 | downloading = 1;
42 |
43 | if (!fd) begin
44 | $error("Could not open file");
45 | end
46 |
47 | addr = 0;
48 |
49 | value = $fgetc(fd);
50 | div = 1;
51 | data[7:0] = value;
52 |
53 | while (value != -1) begin
54 | value = $fgetc(fd);
55 |
56 | if (div) begin
57 | data[15:8] = value;
58 |
59 | // Send data
60 | #period;
61 |
62 | addr += 2;
63 | end else begin
64 | data[7:0] = value;
65 | end
66 |
67 | div = ~div;
68 | end
69 |
70 | #period;
71 |
72 | downloading = 0;
73 |
74 | #(10 * period);
75 |
76 | $stop;
77 | end
78 |
79 | endmodule
80 |
--------------------------------------------------------------------------------
/rtl/mister_top/scanline_filler.sv:
--------------------------------------------------------------------------------
1 | module scanline_filler #(
2 | parameter int SNAP_COUNT = 1,
3 | parameter int SNAP_POINTS[SNAP_COUNT] = '{240},
4 | parameter int HSYNC_DELAY = 6
5 | ) (
6 | input wire clk,
7 |
8 | input wire hsync_in,
9 | input wire vsync_in,
10 |
11 | input wire vblank_in,
12 | input wire hblank_in,
13 |
14 | input wire [23:0] rgb_in,
15 |
16 | output reg hsync,
17 | output wire vsync,
18 |
19 | output reg de,
20 | output reg [23:0] rgb,
21 | output wire [7:0] snap_index,
22 | output wire [8:0] snap_point
23 | );
24 | reg prev_de = 0;
25 | reg prev_hsync = 0;
26 | reg prev_vsync = 0;
27 | reg [2:0] hs_delay = 0;
28 |
29 | reg [8:0] output_line_count = 0;
30 | reg [8:0] visible_line_count = 0;
31 | // reg [9:0] clks_since_hsync_count = 0;
32 | // reg [8:0] black_pixel_count = 0;
33 |
34 | reg drawing_line = 0 /* synthesis noprune */;
35 | reg drawing_black = 0 /* synthesis noprune */;
36 |
37 | wire extended_vblank = vblank_in && ~(output_line_count < snap_point && output_line_count > 0) /* synthesis keep */;
38 | wire de_blanks = ~(hblank_in || extended_vblank);
39 |
40 | always @(posedge clk) begin
41 | prev_hsync <= hsync_in;
42 | prev_vsync <= vsync_in;
43 | prev_de <= de_blanks;
44 |
45 | hsync <= 0;
46 | de <= 0;
47 | rgb <= 0;
48 | // clks_since_hsync_count <= clks_since_hsync_count + 1;
49 |
50 | if (vsync_in && ~prev_vsync) begin
51 | // Reset line count on start of vsync
52 | output_line_count <= 0;
53 | visible_line_count <= 0;
54 | end
55 |
56 | if (de_blanks && ~prev_de) begin
57 | // We're drawing on this line
58 | drawing_line <= 1;
59 | drawing_black <= 0;
60 | end
61 | // else if (output_line_count < snap_point && ~drawing_line &&
62 | // clks_since_hsync_count > CLKS_UNTIL_BLANK_LINE[9:0] &&
63 | // black_pixel_count < horizontal_width) begin
64 | // // No data to render for this line, but we haven't met the snap point, so fill black
65 | // de <= 1;
66 | // rgb <= 0;
67 | // black_pixel_count <= black_pixel_count + 1;
68 | // drawing_black <= 1;
69 | // end
70 |
71 | if (de_blanks) begin
72 | de <= 1;
73 | if (vblank_in) begin
74 | // Extended blanking
75 | rgb <= 0;
76 | drawing_black <= 1;
77 | end else begin
78 | // Normal pixels
79 | rgb <= rgb_in;
80 | end
81 | end else if (~de_blanks && prev_de) begin
82 | // Falling edge of drawing
83 | output_line_count <= output_line_count + 1;
84 | if (~drawing_black) begin
85 | // If we drew black this line, it's not visible
86 | visible_line_count <= visible_line_count + 1;
87 | end
88 | end
89 |
90 | // Move hsync to not collide with vsync
91 | // ------------
92 | if (hs_delay > 0) begin
93 | hs_delay <= hs_delay - 1;
94 | end
95 |
96 | if (hs_delay == 1) begin
97 | hsync <= 1;
98 | // clks_since_hsync_count <= 0;
99 | // black_pixel_count <= 0;
100 | // drawing_black <= 0;
101 | drawing_line <= 0;
102 | end
103 |
104 | if (hsync_in && ~prev_hsync) begin
105 | if (HSYNC_DELAY <= 1) begin
106 | hsync <= 1;
107 | // clks_since_hsync_count <= 0;
108 | // black_pixel_count <= 0;
109 | // drawing_black <= 0;
110 | drawing_line <= 0;
111 | end else begin
112 | hs_delay <= HSYNC_DELAY[2:0];
113 | end
114 | end
115 | end
116 |
117 | always @(posedge clk) begin
118 | for (int i = 0; i < SNAP_COUNT; i = i + 1) begin
119 | if (visible_line_count <= SNAP_POINTS[i][8:0]) begin
120 | snap_index <= i[7:0];
121 | snap_point <= SNAP_POINTS[i][8:0];
122 | end
123 | end
124 |
125 | end
126 |
127 | assign vsync = vsync_in && ~prev_vsync;
128 |
129 | endmodule
130 |
--------------------------------------------------------------------------------
/rtl/snes.qip:
--------------------------------------------------------------------------------
1 | # ==============================================================================
2 | # RTL
3 | # ==============================================================================
4 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "mister_top/SNES.sv"]
5 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "mister_top/rom_parser.sv"]
6 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "mister_top/scanline_filler.sv"]
7 | set_global_assignment -name MIF_FILE [file join $::quartus(qip_path) "chip/DSP/dsp11b23410_p.mif"]
8 | set_global_assignment -name MIF_FILE [file join $::quartus(qip_path) "chip/DSP/dsp11b23410_d.mif"]
9 | set_global_assignment -name MIF_FILE [file join $::quartus(qip_path) "chip/CX4/drom.mif"]
10 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "SPC700/SPC700.qip"]
11 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "65C816/65C816.qip"]
12 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SWRAM.vhd"]
13 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SNES.vhd"]
14 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "SMP.vhd"]
15 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "sdram.sv"]
16 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "PPU_PKG.vhd"]
17 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "PPU.vhd"]
18 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "miracle.sv"]
19 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "main.v"]
20 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "lightgun.sv"]
21 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "ioport.sv"]
22 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "hps_ext.v"]
23 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "DSP_PKG.vhd"]
24 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "DSP.vhd"]
25 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "CPU.vhd"]
26 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "cheatcodes.sv"]
27 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "CEGen.vhd"]
28 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "bram.vhd"]
29 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "chip/chip.qip"]
30 |
31 | # ==============================================================================
32 | # MODULES
33 | # ==============================================================================
34 |
35 |
--------------------------------------------------------------------------------
/support/loader.asm:
--------------------------------------------------------------------------------
1 | architecture chip32.vm
2 | output "loader.bin", create
3 |
4 | constant DEBUG = 0
5 |
6 | constant rom_dataslot = 0
7 | constant save_dataslot = 10
8 |
9 | // Host init command
10 | constant host_init = 0x4002
11 |
12 | // Addresses
13 | constant rom_file_size = 0x1000
14 | constant header_offset_addr = 0x1004
15 |
16 | constant lorom_header_seek = 0x007FBD
17 | constant hirom_header_seek = 0x00FFBD
18 | constant exhirom_header_seek = 0x40FFBD
19 |
20 | constant lorom_output = 0x1A00
21 | constant hirom_output = 0x1A10
22 | constant exhirom_output = 0x1A20
23 |
24 | constant romsz_addr = 0x1800
25 |
26 | // Error vector (0x0)
27 | jp error_handler
28 |
29 | // Init vector (0x2)
30 | jp start
31 |
32 | /// Includes ///
33 | include "util.asm"
34 | align(2)
35 |
36 | include "check_header.asm"
37 | align(2)
38 |
39 | start:
40 | ld r1,#rom_dataslot // populate data slot
41 | open r1,r2
42 |
43 | ld.l (rom_file_size),r2
44 | and r2,#0x200 // AND with 0x200, which implies SMC header
45 | jp z, no_header // If empty, no header
46 | log_string("File has header")
47 | jp store_header
48 |
49 | no_header:
50 | log_string("File doesn't have header")
51 |
52 | store_header:
53 | ld.w (header_offset_addr),r2 // Store header offset
54 |
55 | // Calculate romsz
56 | ld r1,#15
57 | ld r2,#0x1000000 // Max ROM size
58 | ld.l r3,(rom_file_size) // ROM file size
59 | ld.w r4,(header_offset_addr) // Header offset
60 | sub r3,r4 // Remove header offset from size for calculation
61 |
62 | rom_size_loop:
63 | cmp r1,#0
64 | jp z, finished_rom_size // If romsz == 0
65 | cmp r2,r3
66 | jp c, finished_rom_size // If size > r2
67 | asl r3,#1 // Else shift size left 1
68 | sub r1,#1 // Subtract 1 from rom size
69 | jp rom_size_loop
70 |
71 | finished_rom_size:
72 | ld.b (romsz_addr),r1
73 | log_string("Calculated ROM size:")
74 | hex.b r1
75 |
76 | check_header(lorom_header_seek, lorom_output)
77 |
78 | // Check headers at 0xFFBD
79 | ld.l r2,(rom_file_size)
80 | cmp r2,#0xFFFF
81 | jp c, finished_checking_headers // If ROM is smaller than 0xFFFF
82 | check_header(hirom_header_seek, hirom_output)
83 |
84 | // Check headers at 0x40FFBD
85 | ld.l r2,(rom_file_size)
86 | ld r3,#0x40
87 | asl r3,#16 // Shift left 16 times
88 | or r3,#0xFFFF // We now have 0x40FFFF in r3
89 | cmp r2,r3
90 | jp c, finished_checking_headers // If ROM is smaller than 0x40FFFF
91 |
92 | check_header(exhirom_header_seek, exhirom_output)
93 |
94 | // All headers checked, compare scores
95 | finished_checking_headers:
96 | close // Close file since we won't be seeking anymore
97 |
98 | ld.b r1,(lorom_output) // Get LoROM score
99 | ld.b r2,(hirom_output) // Get HiROM score
100 | ld.b r3,(exhirom_output) // Get ExHiROM score
101 | jp z,compare_scores // If ExHiROM has a score
102 | add r3,#4 // Add 4 to score to give weight if ExHiROM exists
103 |
104 | compare_scores:
105 | cmp r1,r2 // r1 - r2
106 | jp c, check_hirom_score // Jp if hirom >= lorom
107 | cmp r1,r3 // Else lorom >= hirom, so r1 - r3
108 | jp c, check_hirom_score // jp if exhirom >= lorom
109 |
110 | // LoROM has the highest core
111 | log_string("Choosing LoROM")
112 | ld.b r1,(lorom_output + 1) // Get LoROM chip type
113 | ld.b r2,(lorom_output + 2) // Get RAMSZ
114 | ld.b r3,(lorom_output + 3) // Get PAL
115 | jp set_core
116 |
117 | check_hirom_score:
118 | cmp r2,r3
119 | jp c, score_exhi // jp if exhirom >= hirom
120 |
121 | log_string("Choosing HiROM")
122 | ld.b r1,(hirom_output + 1) // Get HiROM chip type
123 | or r1,#1 // OR 1 to chip_type to mark HiROM
124 | ld.b r2,(hirom_output + 2) // Get RAMSZ
125 | ld.b r3,(hirom_output + 3) // Get PAL
126 |
127 | jp set_core
128 |
129 | score_exhi:
130 | log_string("Choosing ExHiROM")
131 | ld.b r1,(exhirom_output + 1) // Get ExHiROM chip type
132 | or r1,#2 // OR 2 to chip_type to mark ExHiROM
133 | ld.b r2,(exhirom_output + 2) // Get RAMSZ
134 | ld.b r3,(exhirom_output + 3) // Get PAL
135 |
136 | // Set core
137 | set_core:
138 | log_string("Setting core")
139 | ld r4,r1 // Copy chip type to r4
140 | and r4,#0xF0 // Get only the high nibble
141 |
142 | ld r8,#0
143 | core r8 // Default to the main core
144 |
145 | cmp r4,#0xD0 // Check if SPC7110
146 | jp nz, bit_sdd1
147 | log_string("Using SPC7110")
148 | jp expansion_core // It's SPC7110
149 |
150 | bit_sdd1:
151 | cmp r4,#0x50 // Check if SDD1
152 | jp nz, bit_bsx
153 | log_string("Using SDD1")
154 | jp expansion_core // It's SDD1
155 |
156 | bit_bsx:
157 | cmp r4,#0x30 // Check if BSX
158 | jp nz, check_pal
159 | log_string("Using BSX")
160 | // It's BSX
161 |
162 | expansion_core:
163 | ld r8,#1
164 | core r8 // Boot SPC7110/SDD1/BSX core
165 | jp send_chip
166 |
167 | check_pal:
168 | cmp r3,#1 // Check if PAL
169 | jp nz, send_chip
170 | // It's PAL
171 | ld r8,#2
172 | core r8
173 |
174 | send_chip:
175 | log_string("Sending chip type")
176 | ld r8,#8
177 | pmpw r8,r1
178 |
179 | log_string("Sending ROM size")
180 | ld.b r7,(romsz_addr)
181 | ld r8,#4 // Load address of ROM size
182 | pmpw r8,r7 // Send ROM size to FPGA
183 |
184 | log_string("Sending RAMSZ")
185 | ld r8,#0xC
186 | pmpw r8,r2
187 |
188 | log_string("Sending PAL")
189 | ld r8,#0x10
190 | pmpw r8,r3
191 |
192 | log_string("Booting")
193 | ld r1,#0 // Set address for write
194 | ld r2,#1 // Downloading start
195 | pmpw r1,r2 // Write ioctl_download = 1
196 |
197 | ld r1,#rom_dataslot
198 | ld.w r2,(header_offset_addr) // Get header offset
199 | adjfo r1,r2 // Offset by header offset
200 | loadf r1 // Load ROM
201 |
202 | ld r1,#0 // Set address for write
203 | ld r2,#0 // Downloading end
204 | pmpw r1,r2 // Write ioctl_download = 0
205 |
206 | // Load save
207 | ld r1,#0 // Set address for write
208 | ld r2,#1 // Downloading start
209 | pmpw r1,r2 // Write ioctl_download = 1
210 |
211 | ld r1,#save_dataslot
212 | loadf r1 // Load Save
213 |
214 | ld r1,#0 // Set address for write
215 | ld r2,#0 // Downloading end
216 | pmpw r1,r2 // Write ioctl_download = 0
217 |
218 | // Start core
219 | ld r0,#host_init
220 | host r0,r0
221 |
222 | exit 0
223 |
224 | error_handler:
225 | ld r14,#test_err_msg
226 |
227 | print:
228 | printf r14
229 | exit 1
230 |
231 | test_err_msg:
232 | db "Error",0
233 | align(2)
234 |
--------------------------------------------------------------------------------
/support/loader.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agg23/openfpga-SNES/05f0587891754e885647915ed42faa52604fc1d5/support/loader.bin
--------------------------------------------------------------------------------
/support/test.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agg23/openfpga-SNES/05f0587891754e885647915ed42faa52604fc1d5/support/test.bin
--------------------------------------------------------------------------------
/support/test_data.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "magic": "APF_VER_1",
4 | "data_slots": [
5 | {
6 | "name": "SMC",
7 | "id": 0,
8 | "filename": "C:/Users/adam/Downloads/SNES/Super Mario World (U) [!].smc",
9 | "required": true,
10 | "parameters": "0x109",
11 | "extensions": ["smc", "sfc"],
12 | "address": "0x10000000"
13 | },
14 | {
15 | "name": "SMC",
16 | "id": 0,
17 | "filename": "C:/Users/adam/Downloads/SNES/Super Mario World With Header.smc",
18 | "required": true,
19 | "parameters": "0x109",
20 | "extensions": ["smc", "sfc"],
21 | "address": "0x10000000"
22 | },
23 | {
24 | "name": "SMC",
25 | "id": 0,
26 | "filename": "C:/Users/adam/Downloads/SNES/Super Mario World 2 - Yoshi's Island.smc",
27 | "required": true,
28 | "parameters": "0x109",
29 | "extensions": ["smc", "sfc"],
30 | "address": "0x10000000"
31 | },
32 | {
33 | "name": "SMC",
34 | "id": 0,
35 | "filename": "C:/Users/adam/Downloads/SNES/Pilotwings (U) [!].smc",
36 | "required": true,
37 | "parameters": "0x109",
38 | "extensions": ["smc", "sfc"],
39 | "address": "0x10000000"
40 | },
41 | {
42 | "name": "SMC",
43 | "id": 0,
44 | "filename": "C:/Users/adam/Downloads/SNES/Asterix (Europe) (En,Fr,De,Es).sfc",
45 | "required": true,
46 | "parameters": "0x109",
47 | "extensions": ["smc", "sfc"],
48 | "address": "0x10000000"
49 | },
50 | {
51 | "name": "SMC",
52 | "id": 0,
53 | "filename": "C:/Users/adam/Downloads/SNES/Super Mario Kart.smc",
54 | "required": true,
55 | "parameters": "0x109",
56 | "extensions": ["smc", "sfc"],
57 | "address": "0x10000000"
58 | },
59 | {
60 | "name": "SMC",
61 | "id": 0,
62 | "filename": "C:/Users/adam/Downloads/SNES/Tales of Phantasia.smc",
63 | "required": true,
64 | "parameters": "0x109",
65 | "extensions": ["smc", "sfc"],
66 | "address": "0x10000000"
67 | },
68 | {
69 | "name": "SMC",
70 | "id": 0,
71 | "filename": "C:/Users/adam/Downloads/SNES/Star Ocean (J) [!].smc",
72 | "required": true,
73 | "parameters": "0x109",
74 | "extensions": ["smc", "sfc"],
75 | "address": "0x10000000"
76 | },
77 | {
78 | "name": "SMC",
79 | "id": 0,
80 | "filename": "C:/Users/adam/Downloads/SNES/Far East of Eden Zero (J).smc",
81 | "required": true,
82 | "parameters": "0x109",
83 | "extensions": ["smc", "sfc"],
84 | "address": "0x10000000"
85 | },
86 | {
87 | "name": "SMC",
88 | "id": 0,
89 | "filename": "C:/Users/adam/Downloads/SNES/SDD1/Star Ocean Eng Patched.sfc",
90 | "required": true,
91 | "parameters": "0x109",
92 | "extensions": ["smc", "sfc"],
93 | "address": "0x10000000"
94 | }
95 | ]
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/support/util.asm:
--------------------------------------------------------------------------------
1 | /// Util Functions ///
2 |
3 | // Seek function
4 | // Input: location - r1
5 | // Clobbers Z
6 | macro seek() {
7 | seek r1
8 | jp z, seek_end
9 |
10 | // Failed to seek
11 | ld r14,#seek_err
12 | printf r14
13 | hex.l r1
14 | exit 1
15 |
16 | seek_end:
17 | }
18 |
19 | // Read function
20 | // Input: length - r1
21 | // Input: ouput memory address - r2
22 | // Clobbers Z
23 | macro read() {
24 | read r2,r1
25 | jp z, read_end
26 |
27 | // Failed to read
28 | ld r14,#read_err
29 | printf r14
30 | hex.l r1
31 | exit 1
32 |
33 | read_end:
34 | }
35 |
36 | macro align(size) {
37 | while (pc() % {size}) {
38 | db 0
39 | }
40 | }
41 |
42 | macro log_string(value) {
43 | if DEBUG {
44 | ld r15,#+
45 | printf r15
46 | jp ++
47 |
48 | +;
49 | db {value},0
50 | align(2)
51 | +;
52 | }
53 | }
54 |
55 | macro log_hex(value) {
56 | if DEBUG {
57 | ld r15,#{value}
58 | hex.l r15
59 | }
60 | }
61 |
62 | macro log_dec(value) {
63 | if DEBUG {
64 | ld r15,#{value}
65 | dec.l r15
66 | }
67 | }
68 |
69 | /// Messages ///
70 |
71 | seek_err:
72 | db "Seek fail 0x",0
73 |
74 | read_err:
75 | db "Read fail length 0x",0
76 |
--------------------------------------------------------------------------------
/target/pocket/core.qip:
--------------------------------------------------------------------------------
1 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "core_top.sv"]
2 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "core_bridge_cmd.v"]
3 | set_global_assignment -name SDC_FILE [file join $::quartus(qip_path) "core_constraints.sdc"]
4 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "data_loader.sv"]
5 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "data_unloader.sv"]
6 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "psram.sv"]
7 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "save_state_controller.sv"]
8 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "sound_i2s.sv"]
9 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "sync_fifo.sv"]
10 |
11 | set_global_assignment -name SIGNALTAP_FILE [file join $::quartus(qip_path) "stp1.stp"]
12 |
13 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "mf_pllbase.qip"]
14 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "mf_pllbase_pal.qip"]
15 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) "pll_reconfig.qip"]
16 |
--------------------------------------------------------------------------------
/target/pocket/core_constraints.sdc:
--------------------------------------------------------------------------------
1 | #
2 | # user core constraints
3 | #
4 | # put your clock groups in here as well as any net assignments
5 | #
6 |
7 | set_clock_groups -asynchronous \
8 | -group { bridge_spiclk } \
9 | -group { clk_74a } \
10 | -group { clk_74b } \
11 | -group { ic|mp1|mf_pllbase_inst|altera_pll_i|*[0].*|divclk \
12 | ic|mp1|mf_pllbase_inst|altera_pll_i|*[1].*|divclk } \
13 | -group { ic|mp1|mf_pllbase_inst|altera_pll_i|*[2].*|divclk } \
14 | -group { ic|mp1|mf_pllbase_inst|altera_pll_i|*[3].*|divclk } \
15 | -group { ic|audio_mixer|audio_pll|mf_audio_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk \
16 | ic|audio_mixer|audio_pll|mf_audio_pll_inst|altera_pll_i|general[1].gpll~PLL_OUTPUT_COUNTER|divclk }
17 |
18 | derive_clock_uncertainty
19 |
20 | set_multicycle_path -from {ic|nes|sdram|*} -to [get_clocks {ic|mp1|mf_pllbase_inst|altera_pll_i|*[1].*|divclk}] -start -setup 2
21 | set_multicycle_path -from {ic|nes|sdram|*} -to [get_clocks {ic|mp1|mf_pllbase_inst|altera_pll_i|*[1].*|divclk}] -start -hold 1
22 |
23 | set_multicycle_path -from [get_clocks {ic|mp1|mf_pllbase_inst|altera_pll_i|*[1].*|divclk}] -to {ic|nes|sdram|*} -setup 2
24 | set_multicycle_path -from [get_clocks {ic|mp1|mf_pllbase_inst|altera_pll_i|*[1].*|divclk}] -to {ic|nes|sdram|*} -hold 1
25 |
26 | set_false_path -from {ic|nes|mapper_flags*}
27 | #set_false_path -from {ic|nes|downloading*}
28 |
--------------------------------------------------------------------------------
/target/pocket/mf_pllbase.ppf:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/target/pocket/mf_pllbase/mf_pllbase_0002.qip:
--------------------------------------------------------------------------------
1 | set_instance_assignment -name PLL_COMPENSATION_MODE NORMAL -to "*mf_pllbase_0002*|altera_pll:altera_pll_i*|*"
2 | set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*mf_pllbase_0002*|altera_pll:altera_pll_i*|*"
3 | set_instance_assignment -name PLL_AUTO_RESET 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 |
--------------------------------------------------------------------------------
/target/pocket/mf_pllbase/mf_pllbase_0002.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns/10ps
2 | module mf_pllbase_0002(
3 |
4 | // interface 'refclk'
5 | input wire refclk,
6 |
7 | // interface 'reset'
8 | input wire rst,
9 |
10 | // interface 'outclk0'
11 | output wire outclk_0,
12 |
13 | // interface 'outclk1'
14 | output wire outclk_1,
15 |
16 | // interface 'outclk2'
17 | output wire outclk_2,
18 |
19 | // interface 'outclk3'
20 | output wire outclk_3,
21 |
22 | // interface 'locked'
23 | output wire locked
24 | );
25 |
26 | altera_pll #(
27 | .fractional_vco_multiplier("true"),
28 | .reference_clock_frequency("74.25 MHz"),
29 | .operation_mode("normal"),
30 | .number_of_clocks(4),
31 | .output_clock_frequency0("85.909080 MHz"),
32 | .phase_shift0("0 ps"),
33 | .duty_cycle0(50),
34 | .output_clock_frequency1("21.477270 MHz"),
35 | .phase_shift1("0 ps"),
36 | .duty_cycle1(50),
37 | .output_clock_frequency2("10.738635 MHz"),
38 | .phase_shift2("0 ps"),
39 | .duty_cycle2(50),
40 | .output_clock_frequency3("10.738635 MHz"),
41 | .phase_shift3("23280 ps"),
42 | .duty_cycle3(50),
43 | .output_clock_frequency4("0 MHz"),
44 | .phase_shift4("0 ps"),
45 | .duty_cycle4(50),
46 | .output_clock_frequency5("0 MHz"),
47 | .phase_shift5("0 ps"),
48 | .duty_cycle5(50),
49 | .output_clock_frequency6("0 MHz"),
50 | .phase_shift6("0 ps"),
51 | .duty_cycle6(50),
52 | .output_clock_frequency7("0 MHz"),
53 | .phase_shift7("0 ps"),
54 | .duty_cycle7(50),
55 | .output_clock_frequency8("0 MHz"),
56 | .phase_shift8("0 ps"),
57 | .duty_cycle8(50),
58 | .output_clock_frequency9("0 MHz"),
59 | .phase_shift9("0 ps"),
60 | .duty_cycle9(50),
61 | .output_clock_frequency10("0 MHz"),
62 | .phase_shift10("0 ps"),
63 | .duty_cycle10(50),
64 | .output_clock_frequency11("0 MHz"),
65 | .phase_shift11("0 ps"),
66 | .duty_cycle11(50),
67 | .output_clock_frequency12("0 MHz"),
68 | .phase_shift12("0 ps"),
69 | .duty_cycle12(50),
70 | .output_clock_frequency13("0 MHz"),
71 | .phase_shift13("0 ps"),
72 | .duty_cycle13(50),
73 | .output_clock_frequency14("0 MHz"),
74 | .phase_shift14("0 ps"),
75 | .duty_cycle14(50),
76 | .output_clock_frequency15("0 MHz"),
77 | .phase_shift15("0 ps"),
78 | .duty_cycle15(50),
79 | .output_clock_frequency16("0 MHz"),
80 | .phase_shift16("0 ps"),
81 | .duty_cycle16(50),
82 | .output_clock_frequency17("0 MHz"),
83 | .phase_shift17("0 ps"),
84 | .duty_cycle17(50),
85 | .pll_type("General"),
86 | .pll_subtype("General")
87 | ) altera_pll_i (
88 | .rst (rst),
89 | .outclk ({outclk_3, outclk_2, outclk_1, outclk_0}),
90 | .locked (locked),
91 | .fboutclk ( ),
92 | .fbclk (1'b0),
93 | .refclk (refclk)
94 | );
95 | endmodule
96 |
97 |
--------------------------------------------------------------------------------
/target/pocket/mf_pllbase_pal.ppf:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/target/pocket/mf_pllbase_pal/mf_pllbase_pal_0002.qip:
--------------------------------------------------------------------------------
1 | set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*mf_pllbase_pal_0002*|altera_pll:altera_pll_i*|*"
2 | set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*mf_pllbase_pal_0002*|altera_pll:altera_pll_i*|*"
3 | set_instance_assignment -name PLL_AUTO_RESET OFF -to "*mf_pllbase_pal_0002*|altera_pll:altera_pll_i*|*"
4 | set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*mf_pllbase_pal_0002*|altera_pll:altera_pll_i*|*"
5 |
--------------------------------------------------------------------------------
/target/pocket/mf_pllbase_pal/mf_pllbase_pal_0002.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns/10ps
2 | module mf_pllbase_pal_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("direct"),
30 | .number_of_clocks(4),
31 | .output_clock_frequency0("85.125480 MHz"),
32 | .phase_shift0("0 ps"),
33 | .duty_cycle0(50),
34 | .output_clock_frequency1("21.281370 MHz"),
35 | .phase_shift1("0 ps"),
36 | .duty_cycle1(50),
37 | .output_clock_frequency2("10.640685 MHz"),
38 | .phase_shift2("0 ps"),
39 | .duty_cycle2(50),
40 | .output_clock_frequency3("10.640685 MHz"),
41 | .phase_shift3("23495 ps"),
42 | .duty_cycle3(50),
43 | .output_clock_frequency4("0 MHz"),
44 | .phase_shift4("0 ps"),
45 | .duty_cycle4(50),
46 | .output_clock_frequency5("0 MHz"),
47 | .phase_shift5("0 ps"),
48 | .duty_cycle5(50),
49 | .output_clock_frequency6("0 MHz"),
50 | .phase_shift6("0 ps"),
51 | .duty_cycle6(50),
52 | .output_clock_frequency7("0 MHz"),
53 | .phase_shift7("0 ps"),
54 | .duty_cycle7(50),
55 | .output_clock_frequency8("0 MHz"),
56 | .phase_shift8("0 ps"),
57 | .duty_cycle8(50),
58 | .output_clock_frequency9("0 MHz"),
59 | .phase_shift9("0 ps"),
60 | .duty_cycle9(50),
61 | .output_clock_frequency10("0 MHz"),
62 | .phase_shift10("0 ps"),
63 | .duty_cycle10(50),
64 | .output_clock_frequency11("0 MHz"),
65 | .phase_shift11("0 ps"),
66 | .duty_cycle11(50),
67 | .output_clock_frequency12("0 MHz"),
68 | .phase_shift12("0 ps"),
69 | .duty_cycle12(50),
70 | .output_clock_frequency13("0 MHz"),
71 | .phase_shift13("0 ps"),
72 | .duty_cycle13(50),
73 | .output_clock_frequency14("0 MHz"),
74 | .phase_shift14("0 ps"),
75 | .duty_cycle14(50),
76 | .output_clock_frequency15("0 MHz"),
77 | .phase_shift15("0 ps"),
78 | .duty_cycle15(50),
79 | .output_clock_frequency16("0 MHz"),
80 | .phase_shift16("0 ps"),
81 | .duty_cycle16(50),
82 | .output_clock_frequency17("0 MHz"),
83 | .phase_shift17("0 ps"),
84 | .duty_cycle17(50),
85 | .pll_type("General"),
86 | .pll_subtype("General")
87 | ) altera_pll_i (
88 | .rst (rst),
89 | .outclk ({outclk_3, outclk_2, outclk_1, outclk_0}),
90 | .locked (locked),
91 | .fboutclk ( ),
92 | .fbclk (1'b0),
93 | .refclk (refclk)
94 | );
95 | endmodule
96 |
97 |
--------------------------------------------------------------------------------
/target/pocket/pll_reconfig.ppf:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/target/pocket/pll_reconfig.qip:
--------------------------------------------------------------------------------
1 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_TOOL_NAME "altera_pll_reconfig"
2 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_TOOL_VERSION "21.1"
3 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_TOOL_ENV "mwpim"
4 | set_global_assignment -library "pll_reconfig" -name MISC_FILE [file join $::quartus(qip_path) "pll_reconfig.cmp"]
5 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V"
6 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}"
7 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_QSYS_MODE "UNKNOWN"
8 | set_global_assignment -name SYNTHESIS_ONLY_QIP ON
9 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_NAME "cGxsX3JlY29uZmln"
10 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_DISPLAY_NAME "UExMIFJlY29uZmlnIEludGVsIEZQR0EgSVA="
11 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_REPORT_HIERARCHY "Off"
12 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_INTERNAL "Off"
13 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_AUTHOR "SW50ZWwgQ29ycG9yYXRpb24="
14 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_VERSION "MjEuMQ=="
15 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_DESCRIPTION "SW50ZWwgUGhhc2UtTG9ja2VkIExvb3AgUmVjb25maWd1cmF0aW9uIEJsb2Nr"
16 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0JZVEVFTkFCTEU=::ZmFsc2U=::QWRkIGJ5dGVlbmFibGUgcG9ydA=="
17 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "QllURUVOQUJMRV9XSURUSA==::NA==::QllURUVOQUJMRV9XSURUSA=="
18 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfQUREUl9XSURUSA==::Ng==::UkVDT05GSUdfQUREUl9XSURUSA=="
19 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfREFUQV9XSURUSA==::MzI=::UkVDT05GSUdfREFUQV9XSURUSA=="
20 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "cmVjb25mX3dpZHRo::NjQ=::cmVjb25mX3dpZHRo"
21 | set_global_assignment -entity "pll_reconfig" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "V0FJVF9GT1JfTE9DSw==::dHJ1ZQ==::V0FJVF9GT1JfTE9DSw=="
22 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_NAME "YWx0ZXJhX3BsbF9yZWNvbmZpZ190b3A="
23 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_DISPLAY_NAME "UExMIFJlY29uZmlnIEludGVsIEZQR0EgSVA="
24 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_REPORT_HIERARCHY "Off"
25 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_INTERNAL "Off"
26 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_AUTHOR "SW50ZWwgQ29ycG9yYXRpb24="
27 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_VERSION "MjEuMQ=="
28 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_DESCRIPTION "SW50ZWwgUGhhc2UtTG9ja2VkIExvb3AgUmVjb25maWd1cmF0aW9uIEJsb2Nr"
29 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "ZGV2aWNlX2ZhbWlseQ==::Q3ljbG9uZSBW::ZGV2aWNlX2ZhbWlseQ=="
30 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "RU5BQkxFX01JRg==::ZmFsc2U=::RW5hYmxlIE1JRiBTdHJlYW1pbmc="
31 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0JZVEVFTkFCTEU=::ZmFsc2U=::QWRkIGJ5dGVlbmFibGUgcG9ydA=="
32 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "QllURUVOQUJMRV9XSURUSA==::NA==::QllURUVOQUJMRV9XSURUSA=="
33 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfQUREUl9XSURUSA==::Ng==::UkVDT05GSUdfQUREUl9XSURUSA=="
34 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfREFUQV9XSURUSA==::MzI=::UkVDT05GSUdfREFUQV9XSURUSA=="
35 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "cmVjb25mX3dpZHRo::NjQ=::cmVjb25mX3dpZHRo"
36 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_COMPONENT_PARAMETER "V0FJVF9GT1JfTE9DSw==::dHJ1ZQ==::V0FJVF9GT1JfTE9DSw=="
37 |
38 | set_global_assignment -library "pll_reconfig" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_reconfig.v"]
39 | set_global_assignment -library "pll_reconfig" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_reconfig/altera_pll_reconfig_top.v"]
40 | set_global_assignment -library "pll_reconfig" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_reconfig/altera_pll_reconfig_core.v"]
41 | set_global_assignment -library "pll_reconfig" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_reconfig/altera_std_synchronizer.v"]
42 |
43 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_TOOL_NAME "altera_pll_reconfig"
44 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_TOOL_VERSION "21.1"
45 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_reconfig" -name IP_TOOL_ENV "mwpim"
46 |
--------------------------------------------------------------------------------
/target/pocket/pll_reconfig.v:
--------------------------------------------------------------------------------
1 | // megafunction wizard: %PLL Reconfig Intel FPGA IP v21.1%
2 | // GENERATION: XML
3 | // pll_reconfig.v
4 |
5 | // Generated using ACDS version 21.1 850
6 |
7 | `timescale 1 ps / 1 ps
8 | module pll_reconfig #(
9 | parameter ENABLE_BYTEENABLE = 0,
10 | parameter BYTEENABLE_WIDTH = 4,
11 | parameter RECONFIG_ADDR_WIDTH = 6,
12 | parameter RECONFIG_DATA_WIDTH = 32,
13 | parameter reconf_width = 64,
14 | parameter WAIT_FOR_LOCK = 1
15 | ) (
16 | input wire mgmt_clk, // mgmt_clk.clk
17 | input wire mgmt_reset, // mgmt_reset.reset
18 | output wire mgmt_waitrequest, // mgmt_avalon_slave.waitrequest
19 | input wire mgmt_read, // .read
20 | input wire mgmt_write, // .write
21 | output wire [31:0] mgmt_readdata, // .readdata
22 | input wire [5:0] mgmt_address, // .address
23 | input wire [31:0] mgmt_writedata, // .writedata
24 | output wire [63:0] reconfig_to_pll, // reconfig_to_pll.reconfig_to_pll
25 | input wire [63:0] reconfig_from_pll // reconfig_from_pll.reconfig_from_pll
26 | );
27 |
28 | altera_pll_reconfig_top #(
29 | .device_family ("Cyclone V"),
30 | .ENABLE_MIF (0),
31 | .MIF_FILE_NAME (""),
32 | .ENABLE_BYTEENABLE (ENABLE_BYTEENABLE),
33 | .BYTEENABLE_WIDTH (BYTEENABLE_WIDTH),
34 | .RECONFIG_ADDR_WIDTH (RECONFIG_ADDR_WIDTH),
35 | .RECONFIG_DATA_WIDTH (RECONFIG_DATA_WIDTH),
36 | .reconf_width (reconf_width),
37 | .WAIT_FOR_LOCK (WAIT_FOR_LOCK)
38 | ) pll_reconfig_inst (
39 | .mgmt_clk (mgmt_clk), // mgmt_clk.clk
40 | .mgmt_reset (mgmt_reset), // mgmt_reset.reset
41 | .mgmt_waitrequest (mgmt_waitrequest), // mgmt_avalon_slave.waitrequest
42 | .mgmt_read (mgmt_read), // .read
43 | .mgmt_write (mgmt_write), // .write
44 | .mgmt_readdata (mgmt_readdata), // .readdata
45 | .mgmt_address (mgmt_address), // .address
46 | .mgmt_writedata (mgmt_writedata), // .writedata
47 | .reconfig_to_pll (reconfig_to_pll), // reconfig_to_pll.reconfig_to_pll
48 | .reconfig_from_pll (reconfig_from_pll), // reconfig_from_pll.reconfig_from_pll
49 | .mgmt_byteenable (4'b0000) // (terminated)
50 | );
51 |
52 | endmodule
53 | // Retrieval info:
54 | //
79 | // Retrieval info:
80 | // Retrieval info:
81 | // Retrieval info:
82 | // Retrieval info:
83 | // Retrieval info:
84 | // Retrieval info:
85 | // IPFS_FILES : pll_reconfig.vo
86 | // RELATED_FILES: pll_reconfig.v, altera_pll_reconfig_top.v, altera_pll_reconfig_core.v, altera_std_synchronizer.v
87 |
--------------------------------------------------------------------------------
/target/pocket/pll_reconfig/altera_std_synchronizer.v:
--------------------------------------------------------------------------------
1 | // (C) 2001-2022 Intel Corporation. All rights reserved.
2 | // Your use of Intel Corporation's design tools, logic functions and other
3 | // software and tools, and its AMPP partner logic functions, and any output
4 | // files from any of the foregoing (including device programming or simulation
5 | // files), and any associated documentation or information are expressly subject
6 | // to the terms and conditions of the Intel Program License Subscription
7 | // Agreement, Intel FPGA IP License Agreement, or other applicable
8 | // license agreement, including, without limitation, that your use is for the
9 | // sole purpose of programming logic devices manufactured by Intel and sold by
10 | // Intel or its authorized distributors. Please refer to the applicable
11 | // agreement for further details.
12 |
13 |
14 | // $Id: //acds/rel/21.1std/ip/sopc/components/primitives/altera_std_synchronizer/altera_std_synchronizer.v#1 $
15 | // $Revision: #1 $
16 | // $Date: 2020/06/22 $
17 | // $Author: psgswbuild $
18 | //-----------------------------------------------------------------------------
19 | //
20 | // File: altera_std_synchronizer.v
21 | //
22 | // Abstract: Single bit clock domain crossing synchronizer.
23 | // Composed of two or more flip flops connected in series.
24 | // Random metastable condition is simulated when the
25 | // __ALTERA_STD__METASTABLE_SIM macro is defined.
26 | // Use +define+__ALTERA_STD__METASTABLE_SIM argument
27 | // on the Verilog simulator compiler command line to
28 | // enable this mode. In addition, dfine the macro
29 | // __ALTERA_STD__METASTABLE_SIM_VERBOSE to get console output
30 | // with every metastable event generated in the synchronizer.
31 | //
32 | // Copyright (C) Altera Corporation 2009, All Rights Reserved
33 | //-----------------------------------------------------------------------------
34 |
35 | `timescale 1ns / 1ns
36 |
37 | module altera_std_synchronizer (
38 | clk,
39 | reset_n,
40 | din,
41 | dout
42 | );
43 |
44 | parameter depth = 3; // This value must be >= 2 !
45 |
46 | input clk;
47 | input reset_n;
48 | input din;
49 | output dout;
50 |
51 | // QuartusII synthesis directives:
52 | // 1. Preserve all registers ie. do not touch them.
53 | // 2. Do not merge other flip-flops with synchronizer flip-flops.
54 | // QuartusII TimeQuest directives:
55 | // 1. Identify all flip-flops in this module as members of the synchronizer
56 | // to enable automatic metastability MTBF analysis.
57 | // 2. Cut all timing paths terminating on data input pin of the first flop din_s1.
58 |
59 | (* altera_attribute = {"-name ADV_NETLIST_OPT_ALLOWED NEVER_ALLOW; -name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS; -name DONT_MERGE_REGISTER ON; -name PRESERVE_REGISTER ON; -name SDC_STATEMENT \"set_false_path -to [get_keepers {*altera_std_synchronizer:*|din_s1}]\" "} *) reg din_s1;
60 |
61 | (* altera_attribute = {"-name ADV_NETLIST_OPT_ALLOWED NEVER_ALLOW; -name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS; -name DONT_MERGE_REGISTER ON; -name PRESERVE_REGISTER ON"} *) reg [depth-2:0] dreg;
62 |
63 | //synthesis translate_off
64 | initial begin
65 | if (depth <2) begin
66 | $display("%m: Error: synchronizer length: %0d less than 2.", depth);
67 | end
68 | end
69 |
70 | // the first synchronizer register is either a simple D flop for synthesis
71 | // and non-metastable simulation or a D flop with a method to inject random
72 | // metastable events resulting in random delay of [0,1] cycles
73 |
74 | `ifdef __ALTERA_STD__METASTABLE_SIM
75 |
76 | reg[31:0] RANDOM_SEED = 123456;
77 | wire next_din_s1;
78 | wire dout;
79 | reg din_last;
80 | reg random;
81 | event metastable_event; // hook for debug monitoring
82 |
83 | initial begin
84 | $display("%m: Info: Metastable event injection simulation mode enabled");
85 | end
86 |
87 | always @(posedge clk) begin
88 | if (reset_n == 0)
89 | random <= $random(RANDOM_SEED);
90 | else
91 | random <= $random;
92 | end
93 |
94 | assign next_din_s1 = (din_last ^ din) ? random : din;
95 |
96 | always @(posedge clk or negedge reset_n) begin
97 | if (reset_n == 0)
98 | din_last <= 1'b0;
99 | else
100 | din_last <= din;
101 | end
102 |
103 | always @(posedge clk or negedge reset_n) begin
104 | if (reset_n == 0)
105 | din_s1 <= 1'b0;
106 | else
107 | din_s1 <= next_din_s1;
108 | end
109 |
110 | `else
111 |
112 | //synthesis translate_on
113 | always @(posedge clk or negedge reset_n) begin
114 | if (reset_n == 0)
115 | din_s1 <= 1'b0;
116 | else
117 | din_s1 <= din;
118 | end
119 | //synthesis translate_off
120 |
121 | `endif
122 |
123 | `ifdef __ALTERA_STD__METASTABLE_SIM_VERBOSE
124 | always @(*) begin
125 | if (reset_n && (din_last != din) && (random != din)) begin
126 | $display("%m: Verbose Info: metastable event @ time %t", $time);
127 | ->metastable_event;
128 | end
129 | end
130 | `endif
131 |
132 | //synthesis translate_on
133 |
134 | // the remaining synchronizer registers form a simple shift register
135 | // of length depth-1
136 | generate
137 | if (depth < 3) begin
138 | always @(posedge clk or negedge reset_n) begin
139 | if (reset_n == 0)
140 | dreg <= {depth-1{1'b0}};
141 | else
142 | dreg <= din_s1;
143 | end
144 | end else begin
145 | always @(posedge clk or negedge reset_n) begin
146 | if (reset_n == 0)
147 | dreg <= {depth-1{1'b0}};
148 | else
149 | dreg <= {dreg[depth-3:0], din_s1};
150 | end
151 | end
152 | endgenerate
153 |
154 | assign dout = dreg[depth-2];
155 |
156 | endmodule
157 |
158 |
159 |
160 |
--------------------------------------------------------------------------------
/target/pocket/sound_i2s.sv:
--------------------------------------------------------------------------------
1 | // MIT License
2 |
3 | // Copyright (c) 2022 Adam Gastineau
4 |
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 |
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 |
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 | //
23 | ////////////////////////////////////////////////////////////////////////////////
24 |
25 | // A very simple audio i2s bridge to APF, based on their example code
26 | module sound_i2s #(
27 | parameter CHANNEL_WIDTH = 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 |
--------------------------------------------------------------------------------
/target/pocket/sync_fifo.sv:
--------------------------------------------------------------------------------
1 | // MIT License
2 |
3 | // Copyright (c) 2022 Adam Gastineau
4 |
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 |
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 |
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 | //
23 | ////////////////////////////////////////////////////////////////////////////////
24 |
25 | // An easily reusable method for synchronizing multiple bits across clock domains
26 | // Uses a shallow depth (4 entries) FIFO, so make sure to empty it quickly
27 | module sync_fifo #(
28 | parameter WIDTH = 2
29 | ) (
30 | input wire clk_write,
31 | input wire clk_read,
32 |
33 | input wire write_en,
34 | input wire [WIDTH - 1:0] data,
35 | output reg [WIDTH - 1:0] data_s = 0,
36 | output reg write_en_s = 0
37 | );
38 |
39 | reg read_req = 0;
40 | wire empty;
41 |
42 | wire [WIDTH - 1:0] fifo_out;
43 |
44 | dcfifo dcfifo_component (
45 | .data(data),
46 | .rdclk(clk_read),
47 | .rdreq(read_req),
48 | .wrclk(clk_write),
49 | .wrreq(write_en),
50 | .q(fifo_out),
51 | .rdempty(empty),
52 | .aclr(),
53 | .eccstatus(),
54 | .rdfull(),
55 | .rdusedw(),
56 | .wrempty(),
57 | .wrfull(),
58 | .wrusedw()
59 | );
60 | defparam dcfifo_component.intended_device_family = "Cyclone V", dcfifo_component.lpm_numwords = 4,
61 | dcfifo_component.lpm_showahead = "OFF", dcfifo_component.lpm_type = "dcfifo",
62 | dcfifo_component.lpm_width = WIDTH, dcfifo_component.lpm_widthu = 2,
63 | dcfifo_component.overflow_checking = "ON", dcfifo_component.rdsync_delaypipe = 5,
64 | dcfifo_component.underflow_checking = "ON", dcfifo_component.use_eab = "ON",
65 | dcfifo_component.wrsync_delaypipe = 5;
66 |
67 | reg [1:0] read_state = 0;
68 |
69 | localparam READ_DELAY = 1;
70 | localparam READ_WRITE = 2;
71 |
72 | always @(posedge clk_read) begin
73 | read_req <= 0;
74 | write_en_s <= 0;
75 |
76 | if (~empty) begin
77 | read_state <= READ_DELAY;
78 | read_req <= 1;
79 | end
80 |
81 | case (read_state)
82 | READ_DELAY: begin
83 | read_state <= READ_WRITE;
84 | end
85 | READ_WRITE: begin
86 | read_state <= 0;
87 |
88 | data_s <= fifo_out;
89 | write_en_s <= 1;
90 | end
91 | endcase
92 | end
93 |
94 | endmodule
95 |
--------------------------------------------------------------------------------