From 39d4ce193c4d3ee2639b1ce122215ffdb30de17d Mon Sep 17 00:00:00 2001 From: gehstock Date: Sun, 3 Jun 2018 00:17:54 +0200 Subject: [PATCH] New Arcade Platform --- .../Custom Hardware/Sprint2_MiST/clean.bat | 37 + .../Sprint2_MiST/rtl/EngineSound.vhd | 159 +++ .../Custom Hardware/Sprint2_MiST/rtl/IO.vhd | 186 +++ .../Sprint2_MiST/rtl/Inputs.vhd | 183 +++ .../Sprint2_MiST/rtl/T65/Char_LSB.qip | 0 .../Sprint2_MiST/rtl/T65/Char_MSB.qip | 0 .../Sprint2_MiST/rtl/T65/T65.vhd | 564 +++++++++ .../Sprint2_MiST/rtl/T65/T65_ALU.vhd | 260 ++++ .../Sprint2_MiST/rtl/T65/T65_MCode.vhd | 1052 +++++++++++++++++ .../Sprint2_MiST/rtl/T65/T65_Pack.vhd | 117 ++ .../Sprint2_MiST/rtl/T65/addec_prom.qip | 0 .../rtl/T65/greybox_tmp/cbx_args.txt | 16 + .../Sprint2_MiST/rtl/T65/j6_prom.qip | 0 .../Sprint2_MiST/rtl/T65/k6_prom.qip | 0 .../Sprint2_MiST/rtl/T65/prog_rom1.qip | 0 .../Sprint2_MiST/rtl/T65/prog_rom2.qip | 0 .../Sprint2_MiST/rtl/T65/prog_rom3.qip | 0 .../Sprint2_MiST/rtl/T65/prog_rom4.qip | 0 .../Sprint2_MiST/rtl/T65/ram1k_dp.qip | 0 .../Sprint2_MiST/rtl/T65/sync_prom.qip | 0 .../Sprint2_MiST/rtl/build_id.sv | 2 + .../Sprint2_MiST/rtl/build_id.tcl | 35 + .../Sprint2_MiST/rtl/collision.vhd | 122 ++ .../Sprint2_MiST/rtl/cpu_mem.vhd | 436 +++++++ .../Custom Hardware/Sprint2_MiST/rtl/dac.sv | 33 + .../Custom Hardware/Sprint2_MiST/rtl/hq2x.sv | 454 +++++++ .../Sprint2_MiST/rtl/keyboard.sv | 79 ++ .../Sprint2_MiST/rtl/mist_io.sv | 491 ++++++++ .../Sprint2_MiST/rtl/motion.vhd | 361 ++++++ .../Custom Hardware/Sprint2_MiST/rtl/osd.sv | 179 +++ .../Sprint2_MiST/rtl/playfield.vhd | 148 +++ .../Custom Hardware/Sprint2_MiST/rtl/pll.v | 337 ++++++ .../Sprint2_MiST/rtl/ram1k_dp.qip | 3 + .../Sprint2_MiST/rtl/ram1k_dp.vhd | 224 ++++ .../Sprint2_MiST/rtl/roms/6290-01b1.hex | 129 ++ .../Sprint2_MiST/rtl/roms/6291-01c1.hex | 129 ++ .../Sprint2_MiST/rtl/roms/6396-01p4.hex | 33 + .../Sprint2_MiST/rtl/roms/6397-01r4.hex | 33 + .../Sprint2_MiST/rtl/roms/6398-01k6.hex | 33 + .../Sprint2_MiST/rtl/roms/6399-01j6.hex | 33 + .../Sprint2_MiST/rtl/roms/6400-01m2.hex | 17 + .../Sprint2_MiST/rtl/roms/6401-01e2.hex | 3 + .../Sprint2_MiST/rtl/roms/6404d1.hex | 129 ++ .../Sprint2_MiST/rtl/roms/6405-02e1.hex | 129 ++ .../Sprint2_MiST/rtl/roms/6442-01d1.hex | 129 ++ .../Sprint2_MiST/rtl/roms/6443-01e1.hex | 129 ++ .../Sprint2_MiST/rtl/roms/Char_LSB.qip | 3 + .../Sprint2_MiST/rtl/roms/Char_LSB.vhd | 141 +++ .../Sprint2_MiST/rtl/roms/Char_MSB.qip | 3 + .../Sprint2_MiST/rtl/roms/Char_MSB.vhd | 141 +++ .../Sprint2_MiST/rtl/roms/addec_prom.qip | 3 + .../Sprint2_MiST/rtl/roms/addec_prom.vhd | 141 +++ .../Sprint2_MiST/rtl/roms/j6_prom.qip | 3 + .../Sprint2_MiST/rtl/roms/j6_prom.vhd | 141 +++ .../Sprint2_MiST/rtl/roms/k6_prom.qip | 3 + .../Sprint2_MiST/rtl/roms/k6_prom.vhd | 141 +++ .../Sprint2_MiST/rtl/roms/prog_rom1.qip | 3 + .../Sprint2_MiST/rtl/roms/prog_rom1.vhd | 141 +++ .../Sprint2_MiST/rtl/roms/prog_rom2.qip | 3 + .../Sprint2_MiST/rtl/roms/prog_rom2.vhd | 141 +++ .../Sprint2_MiST/rtl/roms/prog_rom3.qip | 3 + .../Sprint2_MiST/rtl/roms/prog_rom3.vhd | 141 +++ .../Sprint2_MiST/rtl/roms/prog_rom4.qip | 3 + .../Sprint2_MiST/rtl/roms/prog_rom4.vhd | 141 +++ .../Sprint2_MiST/rtl/roms/sync_prom.qip | 3 + .../Sprint2_MiST/rtl/roms/sync_prom.vhd | 141 +++ .../Sprint2_MiST/rtl/scandoubler.sv | 195 +++ .../Sprint2_MiST/rtl/screech.vhd | 72 ++ .../Sprint2_MiST/rtl/sprint1.vhd | 313 +++++ .../Sprint2_MiST/rtl/sprint2.vhd | 338 ++++++ .../Sprint2_MiST/rtl/sprint2_mist.sv | 157 +++ .../Sprint2_MiST/rtl/sprint2_sound.vhd | 245 ++++ .../Custom Hardware/Sprint2_MiST/rtl/sync.vhd | 177 +++ .../Sprint2_MiST/rtl/video_mixer.sv | 242 ++++ .../Sprint2_MiST/snapshot/sprint2.rbf | Bin 0 -> 252260 bytes .../Custom Hardware/Sprint2_MiST/sprint2.qpf | 30 + .../Custom Hardware/Sprint2_MiST/sprint2.qsf | 186 +++ .../Custom Hardware/Sprint2_MiST/sprint2.srf | 8 + .../Custom Hardware/SprintOne_MiST/clean.bat | 37 + .../SprintOne_MiST/rtl/EngineSound.vhd | 159 +++ .../SprintOne_MiST/rtl/Inputs.vhd | 137 +++ .../SprintOne_MiST/rtl/T65/T65.vhd | 551 +++++++++ .../SprintOne_MiST/rtl/T65/T65_ALU.vhd | 260 ++++ .../SprintOne_MiST/rtl/T65/T65_MCode.vhd | 1050 ++++++++++++++++ .../SprintOne_MiST/rtl/T65/T65_Pack.vhd | 117 ++ .../SprintOne_MiST/rtl/build_id.sv | 2 + .../SprintOne_MiST/rtl/build_id.tcl | 35 + .../SprintOne_MiST/rtl/collision.vhd | 95 ++ .../SprintOne_MiST/rtl/cpu_mem.vhd | 506 ++++++++ .../Custom Hardware/SprintOne_MiST/rtl/dac.sv | 33 + .../SprintOne_MiST/rtl/dpram.vhd | 130 ++ .../SprintOne_MiST/rtl/hq2x.sv | 454 +++++++ .../SprintOne_MiST/rtl/keyboard.sv | 84 ++ .../SprintOne_MiST/rtl/mist_io.sv | 491 ++++++++ .../SprintOne_MiST/rtl/motion.vhd | 381 ++++++ .../Custom Hardware/SprintOne_MiST/rtl/osd.sv | 179 +++ .../SprintOne_MiST/rtl/playfield.vhd | 170 +++ .../Custom Hardware/SprintOne_MiST/rtl/pll.v | 337 ++++++ .../SprintOne_MiST/rtl/roms/6290-01b1.hex | 129 ++ .../SprintOne_MiST/rtl/roms/6291-01c1.hex | 129 ++ .../SprintOne_MiST/rtl/roms/6396-01p4.hex | 33 + .../SprintOne_MiST/rtl/roms/6397-01r4.hex | 33 + .../SprintOne_MiST/rtl/roms/6398-01k6.hex | 33 + .../SprintOne_MiST/rtl/roms/6399-01j6.hex | 33 + .../SprintOne_MiST/rtl/roms/6400-01m2.hex | 17 + .../SprintOne_MiST/rtl/roms/6401-01e2.hex | 3 + .../SprintOne_MiST/rtl/roms/6442-01d1.hex | 129 ++ .../SprintOne_MiST/rtl/roms/6443-01e1.hex | 129 ++ .../SprintOne_MiST/rtl/scandoubler.sv | 195 +++ .../SprintOne_MiST/rtl/screech.vhd | 73 ++ .../SprintOne_MiST/rtl/sprint1.vhd | 310 +++++ .../SprintOne_MiST/rtl/sprint1_mist.sv | 144 +++ .../SprintOne_MiST/rtl/sprint1_sound.vhd | 195 +++ .../SprintOne_MiST/rtl/sprom.vhd | 82 ++ .../SprintOne_MiST/rtl/sync.vhd | 188 +++ .../SprintOne_MiST/rtl/video_mixer.sv | 242 ++++ .../SprintOne_MiST/snapshot/sprint1.rbf | Bin 0 -> 248468 bytes .../SprintOne_MiST/sprint1.qpf | 31 + .../SprintOne_MiST/sprint1.qsf | 174 +++ .../SuperBreakout_MiST/SuperBreakout.qpf | 30 + .../SuperBreakout_MiST/SuperBreakout.qsf | 168 +++ .../SuperBreakout_MiST/clean.bat | 37 + .../SuperBreakout_MiST/rtl/IO.vhd | 173 +++ .../SuperBreakout_MiST/rtl/T65/Char_LSB.qip | 0 .../SuperBreakout_MiST/rtl/T65/Char_MSB.qip | 0 .../SuperBreakout_MiST/rtl/T65/T65.vhd | 551 +++++++++ .../SuperBreakout_MiST/rtl/T65/T65_ALU.vhd | 260 ++++ .../SuperBreakout_MiST/rtl/T65/T65_MCode.vhd | 1050 ++++++++++++++++ .../SuperBreakout_MiST/rtl/T65/T65_Pack.vhd | 117 ++ .../SuperBreakout_MiST/rtl/T65/addec_prom.qip | 0 .../rtl/T65/greybox_tmp/cbx_args.txt | 16 + .../SuperBreakout_MiST/rtl/T65/j6_prom.qip | 0 .../SuperBreakout_MiST/rtl/T65/k6_prom.qip | 0 .../SuperBreakout_MiST/rtl/T65/prog_rom1.qip | 0 .../SuperBreakout_MiST/rtl/T65/prog_rom2.qip | 0 .../SuperBreakout_MiST/rtl/T65/prog_rom3.qip | 0 .../SuperBreakout_MiST/rtl/T65/prog_rom4.qip | 0 .../SuperBreakout_MiST/rtl/T65/ram1k_dp.qip | 0 .../SuperBreakout_MiST/rtl/T65/sync_prom.qip | 0 .../SuperBreakout_MiST/rtl/audio.vhd | 69 ++ .../SuperBreakout_MiST/rtl/build_id.sv | 2 + .../SuperBreakout_MiST/rtl/build_id.tcl | 35 + .../SuperBreakout_MiST/rtl/cpu_mem.vhd | 435 +++++++ .../SuperBreakout_MiST/rtl/dac.sv | 33 + .../SuperBreakout_MiST/rtl/dpram.vhd | 130 ++ .../SuperBreakout_MiST/rtl/hq2x.sv | 454 +++++++ .../SuperBreakout_MiST/rtl/keyboard.sv | 79 ++ .../SuperBreakout_MiST/rtl/mist_io.sv | 491 ++++++++ .../SuperBreakout_MiST/rtl/motion.vhd | 290 +++++ .../SuperBreakout_MiST/rtl/osd.sv | 179 +++ .../SuperBreakout_MiST/rtl/paddle.vhd | 101 ++ .../SuperBreakout_MiST/rtl/paddle_analog.vhd | 53 + .../SuperBreakout_MiST/rtl/playfield.vhd | 148 +++ .../SuperBreakout_MiST/rtl/pll.v | 337 ++++++ .../rtl/quadrature_decoder.vhd | 103 ++ .../SuperBreakout_MiST/rtl/roms/006400_m2.hex | 17 + .../SuperBreakout_MiST/rtl/roms/006401_e2.hex | 3 + .../SuperBreakout_MiST/rtl/roms/033280_p4.hex | 33 + .../SuperBreakout_MiST/rtl/roms/033281_r4.hex | 33 + .../SuperBreakout_MiST/rtl/roms/033282_k6.hex | 3 + .../SuperBreakout_MiST/rtl/roms/033453_c1.hex | 129 ++ .../SuperBreakout_MiST/rtl/roms/033454_d1.hex | 129 ++ .../SuperBreakout_MiST/rtl/roms/033455_e1.hex | 129 ++ .../SuperBreakout_MiST/rtl/roms/roms.rar | Bin 0 -> 35063 bytes .../SuperBreakout_MiST/rtl/scandoubler.sv | 195 +++ .../SuperBreakout_MiST/rtl/sprom.vhd | 82 ++ .../SuperBreakout_MiST/rtl/super_breakout.vhd | 254 ++++ .../rtl/super_breakout_mist.sv | 147 +++ .../SuperBreakout_MiST/rtl/sync.vhd | 190 +++ .../SuperBreakout_MiST/rtl/video_mixer.sv | 242 ++++ .../snapshot/SuperBreakout.rbf | Bin 0 -> 239690 bytes 171 files changed, 24244 insertions(+) create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/clean.bat create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/EngineSound.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/IO.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/Inputs.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/Char_LSB.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/Char_MSB.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/T65.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/T65_ALU.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/T65_MCode.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/T65_Pack.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/addec_prom.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/greybox_tmp/cbx_args.txt create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/j6_prom.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/k6_prom.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/prog_rom1.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/prog_rom2.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/prog_rom3.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/prog_rom4.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/ram1k_dp.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/sync_prom.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/build_id.sv create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/build_id.tcl create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/collision.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/cpu_mem.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/dac.sv create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/hq2x.sv create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/keyboard.sv create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/mist_io.sv create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/motion.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/osd.sv create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/playfield.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/pll.v create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/ram1k_dp.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/ram1k_dp.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6290-01b1.hex create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6291-01c1.hex create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6396-01p4.hex create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6397-01r4.hex create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6398-01k6.hex create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6399-01j6.hex create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6400-01m2.hex create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6401-01e2.hex create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6404d1.hex create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6405-02e1.hex create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6442-01d1.hex create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6443-01e1.hex create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/Char_LSB.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/Char_LSB.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/Char_MSB.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/Char_MSB.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/addec_prom.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/addec_prom.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/j6_prom.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/j6_prom.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/k6_prom.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/k6_prom.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom1.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom1.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom2.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom2.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom3.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom3.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom4.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom4.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/sync_prom.qip create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/sync_prom.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/scandoubler.sv create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/screech.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sprint1.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sprint2.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sprint2_mist.sv create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sprint2_sound.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sync.vhd create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/video_mixer.sv create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/snapshot/sprint2.rbf create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/sprint2.qpf create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/sprint2.qsf create mode 100644 Arcade_MiST/Custom Hardware/Sprint2_MiST/sprint2.srf create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/clean.bat create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/EngineSound.vhd create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/Inputs.vhd create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/T65/T65.vhd create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/T65/T65_ALU.vhd create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/T65/T65_MCode.vhd create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/T65/T65_Pack.vhd create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/build_id.sv create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/build_id.tcl create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/collision.vhd create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/cpu_mem.vhd create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/dac.sv create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/dpram.vhd create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/hq2x.sv create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/keyboard.sv create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/mist_io.sv create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/motion.vhd create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/osd.sv create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/playfield.vhd create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/pll.v create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6290-01b1.hex create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6291-01c1.hex create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6396-01p4.hex create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6397-01r4.hex create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6398-01k6.hex create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6399-01j6.hex create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6400-01m2.hex create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6401-01e2.hex create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6442-01d1.hex create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6443-01e1.hex create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/scandoubler.sv create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/screech.vhd create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sprint1.vhd create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sprint1_mist.sv create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sprint1_sound.vhd create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sprom.vhd create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sync.vhd create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/video_mixer.sv create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/snapshot/sprint1.rbf create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/sprint1.qpf create mode 100644 Arcade_MiST/Custom Hardware/SprintOne_MiST/sprint1.qsf create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/SuperBreakout.qpf create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/SuperBreakout.qsf create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/clean.bat create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/IO.vhd create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/Char_LSB.qip create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/Char_MSB.qip create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/T65.vhd create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/T65_ALU.vhd create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/T65_MCode.vhd create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/T65_Pack.vhd create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/addec_prom.qip create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/greybox_tmp/cbx_args.txt create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/j6_prom.qip create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/k6_prom.qip create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/prog_rom1.qip create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/prog_rom2.qip create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/prog_rom3.qip create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/prog_rom4.qip create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/ram1k_dp.qip create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/sync_prom.qip create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/audio.vhd create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/build_id.sv create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/build_id.tcl create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/cpu_mem.vhd create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/dac.sv create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/dpram.vhd create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/hq2x.sv create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/keyboard.sv create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/mist_io.sv create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/motion.vhd create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/osd.sv create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/paddle.vhd create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/paddle_analog.vhd create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/playfield.vhd create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/pll.v create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/quadrature_decoder.vhd create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/006400_m2.hex create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/006401_e2.hex create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033280_p4.hex create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033281_r4.hex create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033282_k6.hex create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033453_c1.hex create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033454_d1.hex create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033455_e1.hex create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/roms.rar create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/scandoubler.sv create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/sprom.vhd create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/super_breakout.vhd create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/super_breakout_mist.sv create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/sync.vhd create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/video_mixer.sv create mode 100644 Arcade_MiST/Custom Hardware/SuperBreakout_MiST/snapshot/SuperBreakout.rbf diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/clean.bat b/Arcade_MiST/Custom Hardware/Sprint2_MiST/clean.bat new file mode 100644 index 00000000..b3b7c3b5 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/clean.bat @@ -0,0 +1,37 @@ +@echo off +del /s *.bak +del /s *.orig +del /s *.rej +del /s *~ +rmdir /s /q db +rmdir /s /q incremental_db +rmdir /s /q output_files +rmdir /s /q simulation +rmdir /s /q greybox_tmp +rmdir /s /q hc_output +rmdir /s /q .qsys_edit +rmdir /s /q hps_isw_handoff +rmdir /s /q sys\.qsys_edit +rmdir /s /q sys\vip +cd sys +for /d %%i in (*_sim) do rmdir /s /q "%%~nxi" +cd .. +for /d %%i in (*_sim) do rmdir /s /q "%%~nxi" +del build_id.v +del c5_pin_model_dump.txt +del PLLJ_PLLSPE_INFO.txt +del /s *.qws +del /s *.ppf +del /s *.ddb +del /s *.csv +del /s *.cmp +del /s *.sip +del /s *.spd +del /s *.bsf +del /s *.f +del /s *.sopcinfo +del /s *.xml +del /s new_rtl_netlist +del /s old_rtl_netlist + +pause diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/EngineSound.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/EngineSound.vhd new file mode 100644 index 00000000..d5dc9f3c --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/EngineSound.vhd @@ -0,0 +1,159 @@ +-- Motor sound generator for Kee Games Sprint 2 +-- Similar circuits are used in a number of other games +-- (c) 2017 James Sweet +-- +-- Original circuit used a 555 configured as an astable oscillator with the frequency controlled by +-- a four bit binary value. The output of this oscillator drives a counter configured to produce an +-- irregular thumping simulating the sound of an engine. +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity EngineSound is +generic( + constant Freq_tune : integer := 50 -- Value from 0-100 used to tune the overall engine sound frequency + ); +port( + Clk_6 : in std_logic; + Ena_3k : in std_logic; + EngineData : in std_logic_vector(3 downto 0); + Motor : out std_logic_vector(5 downto 0) + ); +end EngineSound; + +architecture rtl of EngineSound is + +signal RPM_val : integer range 1 to 350; +signal Ramp_term_unfilt : integer range 1 to 80000; +signal Ramp_Count : integer range 0 to 80000; +signal Ramp_term : integer range 1 to 80000; +signal Freq_mod : integer range 0 to 400; +signal Motor_Clk : std_logic; + +signal Counter_A : std_logic; +signal Counter_B : unsigned(2 downto 0); +signal Counter_A_clk : std_logic; + +signal Motor_prefilter : unsigned(1 downto 0); +signal Motor_filter_t1 : unsigned(3 downto 0); +signal Motor_filter_t2 : unsigned(3 downto 0); +signal Motor_filter_t3 : unsigned(3 downto 0); +signal Motor_filtered : unsigned(5 downto 0); + + +begin + +-- The frequency of the oscillator is set by a 4 bit binary value controlled by the game CPU +-- in the real hardware this is a 555 coupled to a 4 bit resistor DAC used to pull the frequency. +-- The output of this DAC has a capacitor to smooth out the frequency variation. +-- The constants assigned to RPM_val can be tweaked to adjust the frequency curve + +Speed_select: process(Clk_6) +begin + if rising_edge(Clk_6) then + case EngineData is + when "0000" => RPM_val <= 280; + when "0001" => RPM_val <= 245; + when "0010" => RPM_val <= 230; + when "0011" => RPM_val <= 205; + when "0100" => RPM_val <= 190; + when "0101" => RPM_val <= 175; + when "0110" => RPM_val <= 160; + when "0111" => RPM_val <= 145; + when "1000" => RPM_val <= 130; + when "1001" => RPM_val <= 115; + when "1010" => RPM_val <= 100; + when "1011" => RPM_val <= 85; + when "1100" => RPM_val <= 70; + when "1101" => RPM_val <= 55; + when "1110" => RPM_val <= 40; + when "1111" => RPM_val <= 25; + end case; + end if; +end process; + + +-- There is a RC filter between the frequency control DAC and the 555 to smooth out the transitions between the +-- 16 possible states. We can simulate a reasonable approximation of that behavior using a linear slope which is +-- not truly accurate but should be close enough. +RC_filt: process(clk_6, ena_3k, ramp_term_unfilt) +begin + if rising_edge(clk_6) then + if ena_3k = '1' then + if ramp_term_unfilt > ramp_term then + ramp_term <= ramp_term + 5; + elsif ramp_term_unfilt = ramp_term then + ramp_term <= ramp_term; + else + ramp_term <= ramp_term - 3; + end if; + end if; + end if; +end process; + + +-- Ramp_term terminates the ramp count, the higher this value, the longer the ramp will count up and the lower +-- the frequency. RPM_val is multiplied by a constant which can be adjusted by changing the value of freq_tune +-- to simulate the function of the frequency adjustment pot in the original hardware. +ramp_term_unfilt <= ((200 - freq_tune) * RPM_val); + +-- Variable frequency oscillator roughly approximating the function of a 555 astable oscillator +Ramp_osc: process(clk_6) +begin + if rising_edge(clk_6) then + motor_clk <= '1'; + ramp_count <= ramp_count + 1; + if ramp_count > ramp_term then + ramp_count <= 0; + motor_clk <= '0'; + end if; + end if; +end process; + + +-- 7492 counter with XOR on two of the outputs creates lumpy engine sound from smooth pulse train +-- 7492 has two sections, one div-by-2 and one div-by-6. +Engine_counter: process(motor_clk, counter_A_clk, counter_B) +begin + if rising_edge(motor_clk) then + Counter_B <= Counter_B + '1'; + end if; + Counter_A_clk <= Counter_B(0) xor Counter_B(2); + if rising_edge(counter_A_clk) then + Counter_A <= (not Counter_A); + end if; +end process; +motor_prefilter <= ('0' & Counter_B(2)) + ('0' & Counter_B(1)) + ('0' & Counter_A); + +-- Very simple low pass filter, borrowed from MikeJ's Asteroids code +Engine_filter: process(clk_6) +begin + if rising_edge(clk_6) then + if (ena_3k = '1') then + motor_filter_t1 <= ("00" & motor_prefilter) + ("00" & motor_prefilter); + motor_filter_t2 <= motor_filter_t1; + motor_filter_t3 <= motor_filter_t2; + end if; + motor_filtered <= ("00" & motor_filter_t1) + + ('0' & motor_filter_t2 & '0') + + ("00" & motor_filter_t3); + end if; +end process; + +motor <= std_logic_vector(motor_filtered); + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/IO.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/IO.vhd new file mode 100644 index 00000000..8f1523bc --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/IO.vhd @@ -0,0 +1,186 @@ +-- IO block for Kee Games Sprint 2 +-- 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; + +entity IO is +port( + CLK6 : in std_logic; + SW1 : in std_logic_vector(7 downto 0); -- DIP switches + Coin1_n : in std_logic; -- Coin switches + Coin2_n : in std_logic; + Start1 : in std_logic; -- 1 and 2 player start switches + Start2 : in std_logic; + Trak_Sel : in std_logic; + Gas1 : in std_logic; + Gas2 : in std_logic; + Gear1_1 : in std_logic; + Gear1_2 : in std_logic; + Gear2_1 : in std_logic; + Gear2_2 : in std_logic; + Gear3_1 : in std_logic; + Gear3_2 : in std_logic; + Test : in std_logic; -- Self test switch + Slam : in std_logic; -- Slam switch + + Steering1A : in std_logic; + Steering1B : in std_logic; + Steering2A : in std_logic; + Steering2B : in std_logic; + + + Lamp1 : out std_logic; -- Player 1 lamp + Lamp2 : out std_logic; -- Player 2 lamp + + Timer_Reset_n : out std_logic; + IntAck_n : out std_logic; + IO_wr : in std_logic; + + Counter : out std_logic; -- Coin counter + Adr : in std_logic_vector(9 downto 0); -- Adress bus, only the lower 9 bits used by IO circuitry + Inputs : out std_logic_vector(1 downto 0) -- Out to data bus, only upper two bits used + ); +end IO; + +architecture rtl of IO is + +signal A8_8 : std_logic; +signal H9_Q_n : std_logic; +signal H8_en : std_logic; +signal Coin1 : std_logic; +signal Coin2 : std_logic; +signal SW2_bank1 : std_logic; +signal SW2_bank2 : std_logic; +signal DipSW : std_logic_vector(7 downto 0); +signal E8_in : std_logic_vector(3 downto 0); +signal J9_out : std_logic_vector(7 downto 0); +signal E8_out : std_logic_vector(9 downto 0); + + +begin + +-- Inputs +--M8: process(Adr(7 downto 6), Coin1, Coin2, Start1_n, Start2_n, Test_n, Slam_n, A8_8, SW2_bank2) +--begin +-- case Adr(7 downto 6) is +-- when "00" => Inputs <= A8_8 & SW2_bank2; -- There is actually an inverter N9 fed by A8_8 so we will just account for that +-- when "01" => Inputs <= Coin2 & Coin1; +-- when "10" => Inputs <= Start2_n & Start1_n; +-- when "11" => Inputs <= Test_n & Slam_n; +-- when others => Inputs <= "11"; +-- end case; +--end process; +---- Coin switch inputs are active-high internally but inverted on board from active-low inputs +--Coin1 <= (not Coin1_n); +--Coin2 <= (not Coin2_n); + + +F9: process(Adr, Gear1_1, Gear1_2, Gear2_1, Gear2_2, Gear3_1, Gear3_2) +begin + if Adr(5) = '0' then -- Adr(5) is connected to enable + case Adr(2 downto 0) is + when "000" => F9_Q_n <= (not Gear1_1); + when "001" => F9_Q_n <= (not Gear1_2); + when "010" => F9_Q_n <= (not Gear2_1); + when "011" => F9_Q_n <= (not Gear2_2); + when "100" => F9_Q_n <= (not Gear3_1); + when "101" => F9_Q_n <= (not Gear3_2); + when "110" => F9_Q_n <= '0'; -- "Spare" switch on schematic + when "111" => F9_Q_n <= '0'; -- "Spare" switch on schematic + when others => F9_Q_n <= '1'; + end case; + else + F9_Q_n <= '1'; + end if; +end process; + +H9: process(Adr, Gas1, Gas2, Self_Test, Start1, Start2, Trak_Sel) +begin + if Adr(4) = '0' then -- Adr(4) is connected to enable + case Adr(2 downto 0) is + when "000" => H9_Q_n <= (not Gas1); + when "001" => H9_Q_n <= (not Gas2); + when "010" => H9_Q_n <= (not Self_Test); + when "011" => H9_Q_n <= '0'; + when "100" => H9_Q_n <= (not Start1); + when "101" => H9_Q_n <= (not Start2); + when "110" => H9_Q_n <= (not Trak_Sel); + when others => H9_Q_n <= '1'; + end case; + else + H9_Q_n <= '1'; + end if; +end process; + + +-- The way the dip switches are wired in the real hardware requires some changes +-- to achieve the same result while using standard active-low switch inputs. +-- Switches are split into two banks, each bank fed from half of selector J9. +J9: process(Adr) +begin + if Adr(3) = '1' then + J9_out <= "11111111"; + else + case Adr(1 downto 0) is + when "00" => J9_out <= "11101110"; + when "01" => J9_out <= "11011101"; + when "10" => J9_out <= "10111011"; + when "11" => J9_out <= "01110111"; + end case; + end if; +end process; + +-- Re-order the dip switch signals to match the physical order of the switches +-- Bank 1 +DipSW(7) <= J9_out(7) when SW2(1) = '0' else '1'; +DipSW(6) <= J9_out(6) when SW2(3) = '0' else '1'; +DipSW(5) <= J9_out(5) when SW2(5) = '0' else '1'; +DipSW(4) <= J9_out(4) when SW2(7) = '0' else '1'; + +--Bank 2 +DipSW(3) <= J9_out(3) when SW2(0) = '0' else '1'; +DipSW(2) <= J9_out(2) when SW2(2) = '0' else '1'; +DipSW(1) <= J9_out(1) when SW2(4) = '0' else '1'; +DipSW(0) <= J9_out(0) when SW2(6) = '0' else '1'; + +-- Outputs from each switch bank are tied together, logical AND since they are active low +SW2_bank1 <= DipSW(7) and DipSW(6) and DipSW(5) and DipSW(4); +SW2_bank2 <= DipSW(3) and DipSW(2) and DipSW(1) and DipSW(0); + +-- Bank 1 of dip switches is multiplexed with player inputs connected to selectors F9 and H9 +A8_8 <= SW2_bank1 and F9_Q_n and H9_Q_n; + + +-- Outputs +E8_in <= IO_wr & Adr(9 downto 7); +E8: process(E8_in) +begin + case E8_in is + when "0000" => E8_out <= "1111111110"; + when "0001" => E8_out <= "1111111101"; + when "0100" => E8_out <= "1111101111"; + when others => E8_out <= "1111111111"; + end case; +end process; + +H8_en <= E8_out(0); +TIMER_RESET_n <= E8_out(1); +INTACK_n <= E8_out(4); + + + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/Inputs.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/Inputs.vhd new file mode 100644 index 00000000..d99b16ee --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/Inputs.vhd @@ -0,0 +1,183 @@ +-- Input block for Kee Games Sprint 2 +-- 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; + +entity control_inputs is +port( + Clk6 : in std_logic; + SW1 : in std_logic_vector(7 downto 0); -- DIP switches + Coin1_n : in std_logic; -- Coin switches + Coin2_n : in std_logic; + Start1 : in std_logic; -- 1 and 2 player start switches + Start2 : in std_logic; + Trak_Sel : in std_logic; -- Track selection button + Gas1 : in std_logic; -- Gas pedals, these are simple on/off switches + Gas2 : in std_logic; + Gear1_1 : in std_logic; -- Player 1 and 2 gear select levers + Gear1_2 : in std_logic; + Gear2_1 : in std_logic; + Gear2_2 : in std_logic; + Gear3_1 : in std_logic; + Gear3_2 : in std_logic; + Self_Test : in std_logic; -- Self test switch + Steering1A_n : in std_logic; -- Steering wheel signals + Steering1B_n : in std_logic; + Steering2A_n : in std_logic; + Steering2B_n : in std_logic; + SteerRst1_n : in std_logic; + SteerRst2_n : in std_logic; + Adr : in std_logic_vector(9 downto 0); -- Adress bus, only the lower 9 bits used by IO circuitry + Inputs : out std_logic_vector(1 downto 0) -- Out to data bus, only upper two bits used + ); +end control_inputs; + +architecture rtl of control_inputs is + +signal A8_8 : std_logic; +signal F9_Q_n : std_logic; +signal H9_Q_n : std_logic; +signal H8_en : std_logic; +signal Coin1 : std_logic; +signal Coin2 : std_logic; +signal SW1_bank1 : std_logic; +signal SW1_bank2 : std_logic; +signal DipSW : std_logic_vector(7 downto 0); +signal E8_in : std_logic_vector(3 downto 0); +signal J9_out : std_logic_vector(7 downto 0); +signal E8_out : std_logic_vector(9 downto 0); + +signal Steering1B_Q_n : std_logic; +signal Steering1A_Q : std_logic; +signal Steering2B_Q_n : std_logic; +signal Steering2A_Q : std_logic; + + +begin + +-- Inputs +M8: process(Adr, A8_8, SW1_bank2, Coin2_n, Coin1_n, Steering1B_Q_n, Steering1A_Q, Steering2B_Q_n, Steering2A_Q) +begin + case Adr(7 downto 6) is + when "00" => Inputs <= A8_8 & SW1_bank2; -- There is actually an inverter N9 fed by A8_8 so we will just account for that + when "01" => Inputs <= Coin2_n & Coin1_n; + when "10" => Inputs <= Steering1B_Q_n & Steering1A_Q; + when "11" => Inputs <= Steering2B_Q_n & Steering2A_Q; + when others => Inputs <= "11"; + end case; +end process; + + +F9: process(Adr, Gear1_1, Gear1_2, Gear2_1, Gear2_2, Gear3_1, Gear3_2) +begin + if Adr(5) = '0' then -- Adr(5) is connected to enable + case Adr(2 downto 0) is + when "000" => F9_Q_n <= (not Gear1_1); + when "001" => F9_Q_n <= (not Gear1_2); + when "010" => F9_Q_n <= (not Gear2_1); + when "011" => F9_Q_n <= (not Gear2_2); + when "100" => F9_Q_n <= (not Gear3_1); + when "101" => F9_Q_n <= (not Gear3_2); + when "110" => F9_Q_n <= '1'; -- "Spare" switch on schematic + when "111" => F9_Q_n <= '1'; -- "Spare" switch on schematic + when others => F9_Q_n <= '1'; + end case; + else + F9_Q_n <= '1'; + end if; +end process; + +H9: process(Adr, Gas1, Gas2, Self_Test, Start1, Start2, Trak_Sel) +begin + if Adr(4) = '0' then -- Adr(4) is connected to enable + case Adr(2 downto 0) is + when "000" => H9_Q_n <= (not Gas1); + when "001" => H9_Q_n <= (not Gas2); + when "010" => H9_Q_n <= (not Self_Test); + when "011" => H9_Q_n <= '1'; + when "100" => H9_Q_n <= (not Start1); + when "101" => H9_Q_n <= (not Start2); + when "110" => H9_Q_n <= (not Trak_Sel); + when others => H9_Q_n <= '1'; + end case; + else + H9_Q_n <= '1'; + end if; +end process; + +-- Steering +M9: process(Steering1A_n, Steering1B_n, SteerRst1_n) +begin + if SteerRst1_n <= '0' then -- Asynchronous clear + Steering1B_Q_n <= '1'; + elsif rising_edge(Steering1B_n) then -- Steering encoders are active low but inverted on board + Steering1A_Q <= Steering1A_n; + Steering1B_Q_n <= '0'; + end if; +end process; + +L9: process(Steering2A_n, Steering2B_n, SteerRst2_n) +begin + if SteerRst2_n <= '0' then -- Asynchronous clear + Steering2B_Q_n <= '1'; + elsif rising_edge(Steering2B_n) then + Steering2A_Q <= Steering2A_n; + Steering2B_Q_n <= '0'; + end if; +end process; + + +-- The way the dip switches are wired in the real hardware requires OR logic +-- to achieve the same result while using standard active-low switch inputs. +-- Switches are split into two banks, each bank fed from half of selector J9. +J9: process(Adr) +begin + if Adr(3) = '1' then + J9_out <= "11111111"; + else + case Adr(1 downto 0) is + when "00" => J9_out <= "11101110"; + when "01" => J9_out <= "11011101"; + when "10" => J9_out <= "10111011"; + when "11" => J9_out <= "01110111"; + end case; + end if; +end process; + +-- Re-order the dip switch signals to match the physical order of the switches +-- Bank 1 +DipSW(7) <= J9_out(7) or SW1(1); +DipSW(6) <= J9_out(6) or SW1(3); +DipSW(5) <= J9_out(5) or SW1(5); +DipSW(4) <= J9_out(4) or SW1(7); + +--Bank 2 +DipSW(3) <= J9_out(3) or SW1(0); +DipSW(2) <= J9_out(2) or SW1(2); +DipSW(1) <= J9_out(1) or SW1(4); +DipSW(0) <= J9_out(0) or SW1(6); + +-- Outputs from each switch bank are tied together, logical AND since they are active low +SW1_bank1 <= DipSW(7) and DipSW(6) and DipSW(5) and DipSW(4); +SW1_bank2 <= DipSW(3) and DipSW(2) and DipSW(1) and DipSW(0); + +-- Bank 1 of dip switches is multiplexed with player inputs connected to selectors F9 and H9 +A8_8 <= SW1_bank1 and F9_Q_n and H9_Q_n; + + + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/Char_LSB.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/Char_LSB.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/Char_MSB.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/Char_MSB.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/T65.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/T65.vhd new file mode 100644 index 00000000..09253fe0 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/T65.vhd @@ -0,0 +1,564 @@ +-- **** +-- T65(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 301 more merging +-- Ver 300 Bugfixes by ehenciak added, started tidyup *bust* +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- 65xx compatible microprocessor core +-- +-- Version : 0246 +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t65/ +-- +-- Limitations : +-- +-- 65C02 and 65C816 modes are incomplete +-- Undocumented instructions are not supported +-- Some interface signals behaves incorrect +-- +-- File history : +-- +-- 0246 : First release +-- + +library IEEE; + use IEEE.std_logic_1164.all; + use IEEE.numeric_std.all; + use work.T65_Pack.all; + +-- ehenciak 2-23-2005 : Added the enable signal so that one doesn't have to use +-- the ready signal to limit the CPU. +entity T65 is + port( + Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816 + Res_n : in std_logic; + Enable : in std_logic; + Clk : in std_logic; + Rdy : in std_logic; + Abort_n : in std_logic; + IRQ_n : in std_logic; + NMI_n : in std_logic; + SO_n : in std_logic; + R_W_n : out std_logic; + Sync : out std_logic; + EF : out std_logic; + MF : out std_logic; + XF : out std_logic; + ML_n : out std_logic; + VP_n : out std_logic; + VDA : out std_logic; + VPA : out std_logic; + A : out std_logic_vector(23 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0) + ); +end T65; + +architecture rtl of T65 is + + -- Registers + signal ABC, X, Y, D : std_logic_vector(15 downto 0); + signal P, AD, DL : std_logic_vector(7 downto 0) := x"00"; + signal BAH : std_logic_vector(7 downto 0); + signal BAL : std_logic_vector(8 downto 0); + signal PBR : std_logic_vector(7 downto 0); + signal DBR : std_logic_vector(7 downto 0); + signal PC : unsigned(15 downto 0); + signal S : unsigned(15 downto 0); + signal EF_i : std_logic; + signal MF_i : std_logic; + signal XF_i : std_logic; + + signal IR : std_logic_vector(7 downto 0); + signal MCycle : std_logic_vector(2 downto 0); + + signal Mode_r : std_logic_vector(1 downto 0); + signal ALU_Op_r : std_logic_vector(3 downto 0); + signal Write_Data_r : std_logic_vector(2 downto 0); + signal Set_Addr_To_r : std_logic_vector(1 downto 0); + signal PCAdder : unsigned(8 downto 0); + + signal RstCycle : std_logic; + signal IRQCycle : std_logic; + signal NMICycle : std_logic; + + signal B_o : std_logic; + signal SO_n_o : std_logic; + signal IRQ_n_o : std_logic; + signal NMI_n_o : std_logic; + signal NMIAct : std_logic; + + signal Break : std_logic; + + -- ALU signals + signal BusA : std_logic_vector(7 downto 0); + signal BusA_r : std_logic_vector(7 downto 0); + signal BusB : std_logic_vector(7 downto 0); + signal ALU_Q : std_logic_vector(7 downto 0); + signal P_Out : std_logic_vector(7 downto 0); + + -- Micro code outputs + signal LCycle : std_logic_vector(2 downto 0); + signal ALU_Op : std_logic_vector(3 downto 0); + signal Set_BusA_To : std_logic_vector(2 downto 0); + signal Set_Addr_To : std_logic_vector(1 downto 0); + signal Write_Data : std_logic_vector(2 downto 0); + signal Jump : std_logic_vector(1 downto 0); + signal BAAdd : std_logic_vector(1 downto 0); + signal BreakAtNA : std_logic; + signal ADAdd : std_logic; + signal AddY : std_logic; + signal PCAdd : std_logic; + signal Inc_S : std_logic; + signal Dec_S : std_logic; + signal LDA : std_logic; + signal LDP : std_logic; + signal LDX : std_logic; + signal LDY : std_logic; + signal LDS : std_logic; + signal LDDI : std_logic; + signal LDALU : std_logic; + signal LDAD : std_logic; + signal LDBAL : std_logic; + signal LDBAH : std_logic; + signal SaveP : std_logic; + signal Write : std_logic; + + signal really_rdy : std_logic; + signal R_W_n_i : std_logic; + +begin + -- ehenciak : gate Rdy with read/write to make an "OK, it's + -- really OK to stop the processor now if Rdy is + -- deasserted" signal + really_rdy <= Rdy or not(R_W_n_i); + + -- ehenciak : Drive R_W_n_i off chip. + R_W_n <= R_W_n_i; + + Sync <= '1' when MCycle = "000" else '0'; + EF <= EF_i; + MF <= MF_i; + XF <= XF_i; + ML_n <= '0' when IR(7 downto 6) /= "10" and IR(2 downto 1) = "11" and MCycle(2 downto 1) /= "00" else '1'; + VP_n <= '0' when IRQCycle = '1' and (MCycle = "101" or MCycle = "110") else '1'; + VDA <= '1' when Set_Addr_To_r /= "00" else '0'; -- Incorrect !!!!!!!!!!!! + VPA <= '1' when Jump(1) = '0' else '0'; -- Incorrect !!!!!!!!!!!! + + mcode : T65_MCode + port map( + Mode => Mode_r, + IR => IR, + MCycle => MCycle, + P => P, + LCycle => LCycle, + ALU_Op => ALU_Op, + Set_BusA_To => Set_BusA_To, + Set_Addr_To => Set_Addr_To, + Write_Data => Write_Data, + Jump => Jump, + BAAdd => BAAdd, + BreakAtNA => BreakAtNA, + ADAdd => ADAdd, + AddY => AddY, + PCAdd => PCAdd, + Inc_S => Inc_S, + Dec_S => Dec_S, + LDA => LDA, + LDP => LDP, + LDX => LDX, + LDY => LDY, + LDS => LDS, + LDDI => LDDI, + LDALU => LDALU, + LDAD => LDAD, + LDBAL => LDBAL, + LDBAH => LDBAH, + SaveP => SaveP, + Write => Write + ); + + alu : T65_ALU + port map( + Mode => Mode_r, + Op => ALU_Op_r, + BusA => BusA_r, + BusB => BusB, + P_In => P, + P_Out => P_Out, + Q => ALU_Q + ); + + process (Res_n, Clk) + begin + if Res_n = '0' then + PC <= (others => '0'); -- Program Counter + IR <= "00000000"; + S <= (others => '0'); -- Dummy !!!!!!!!!!!!!!!!!!!!! + D <= (others => '0'); + PBR <= (others => '0'); + DBR <= (others => '0'); + + Mode_r <= (others => '0'); + ALU_Op_r <= "1100"; + Write_Data_r <= "000"; + Set_Addr_To_r <= "00"; + + R_W_n_i <= '1'; + EF_i <= '1'; + MF_i <= '1'; + XF_i <= '1'; + + elsif Clk'event and Clk = '1' then + if (Enable = '1') then + if (really_rdy = '1') then + R_W_n_i <= not Write or RstCycle; + + D <= (others => '1'); -- Dummy + PBR <= (others => '1'); -- Dummy + DBR <= (others => '1'); -- Dummy + EF_i <= '0'; -- Dummy + MF_i <= '0'; -- Dummy + XF_i <= '0'; -- Dummy + + if MCycle = "000" then + Mode_r <= Mode; + + if IRQCycle = '0' and NMICycle = '0' then + PC <= PC + 1; + end if; + + if IRQCycle = '1' or NMICycle = '1' then + IR <= "00000000"; + else + IR <= DI; + end if; + end if; + + ALU_Op_r <= ALU_Op; + Write_Data_r <= Write_Data; + if Break = '1' then + Set_Addr_To_r <= "00"; + else + Set_Addr_To_r <= Set_Addr_To; + end if; + + if Inc_S = '1' then + S <= S + 1; + end if; + if Dec_S = '1' and RstCycle = '0' then + S <= S - 1; + end if; + if LDS = '1' then + S(7 downto 0) <= unsigned(ALU_Q); + end if; + + if IR = "00000000" and MCycle = "001" and IRQCycle = '0' and NMICycle = '0' then + PC <= PC + 1; + end if; + -- + -- jump control logic + -- + case Jump is + when "01" => + PC <= PC + 1; + + when "10" => + PC <= unsigned(DI & DL); + + when "11" => + if PCAdder(8) = '1' then + if DL(7) = '0' then + PC(15 downto 8) <= PC(15 downto 8) + 1; + else + PC(15 downto 8) <= PC(15 downto 8) - 1; + end if; + end if; + PC(7 downto 0) <= PCAdder(7 downto 0); + + when others => null; + end case; + end if; + end if; + end if; + end process; + + PCAdder <= resize(PC(7 downto 0),9) + resize(unsigned(DL(7) & DL),9) when PCAdd = '1' + else "0" & PC(7 downto 0); + + process (Clk) + begin + if Clk'event and Clk = '1' then + if (Enable = '1') then + if (really_rdy = '1') then + if MCycle = "000" then + if LDA = '1' then + ABC(7 downto 0) <= ALU_Q; + end if; + if LDX = '1' then + X(7 downto 0) <= ALU_Q; + end if; + if LDY = '1' then + Y(7 downto 0) <= ALU_Q; + end if; + if (LDA or LDX or LDY) = '1' then + P <= P_Out; + end if; + end if; + if SaveP = '1' then + P <= P_Out; + end if; + if LDP = '1' then + P <= ALU_Q; + end if; + if IR(4 downto 0) = "11000" then + case IR(7 downto 5) is + when "000" => + P(Flag_C) <= '0'; + when "001" => + P(Flag_C) <= '1'; + when "010" => + P(Flag_I) <= '0'; + when "011" => + P(Flag_I) <= '1'; + when "101" => + P(Flag_V) <= '0'; + when "110" => + P(Flag_D) <= '0'; + when "111" => + P(Flag_D) <= '1'; + when others => + end case; + end if; + + --if IR = "00000000" and MCycle = "011" and RstCycle = '0' and NMICycle = '0' and IRQCycle = '0' then + -- P(Flag_B) <= '1'; + --end if; + --if IR = "00000000" and MCycle = "100" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then + -- P(Flag_I) <= '1'; + -- P(Flag_B) <= B_o; + --end if; + + -- B=1 always on the 6502 + P(Flag_B) <= '1'; + if IR = "00000000" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then + if MCycle = "011" then + -- B=0 in *copy* of P pushed onto the stack + P(Flag_B) <= '0'; + elsif MCycle = "100" then + P(Flag_I) <= '1'; + end if; + end if; + + if SO_n_o = '1' and SO_n = '0' then + P(Flag_V) <= '1'; + end if; + if RstCycle = '1' and Mode_r /= "00" then + P(Flag_1) <= '1'; + P(Flag_D) <= '0'; + P(Flag_I) <= '1'; + end if; + P(Flag_1) <= '1'; + + B_o <= P(Flag_B); + SO_n_o <= SO_n; + IRQ_n_o <= IRQ_n; + NMI_n_o <= NMI_n; + end if; + end if; + end if; + end process; + +--------------------------------------------------------------------------- +-- +-- Buses +-- +--------------------------------------------------------------------------- + + process (Res_n, Clk) + begin + if Res_n = '0' then + BusA_r <= (others => '0'); + BusB <= (others => '0'); + AD <= (others => '0'); + BAL <= (others => '0'); + BAH <= (others => '0'); + DL <= (others => '0'); + elsif Clk'event and Clk = '1' then + if (Enable = '1') then + if (Rdy = '1') then + BusA_r <= BusA; + BusB <= DI; + + case BAAdd is + when "01" => + -- BA Inc + AD <= std_logic_vector(unsigned(AD) + 1); + BAL <= std_logic_vector(unsigned(BAL) + 1); + when "10" => + -- BA Add + BAL <= std_logic_vector(resize(unsigned(BAL(7 downto 0)),9) + resize(unsigned(BusA),9)); + when "11" => + -- BA Adj + if BAL(8) = '1' then + BAH <= std_logic_vector(unsigned(BAH) + 1); + end if; + when others => + end case; + + -- ehenciak : modified to use Y register as well (bugfix) + if ADAdd = '1' then + if (AddY = '1') then + AD <= std_logic_vector(unsigned(AD) + unsigned(Y(7 downto 0))); + else + AD <= std_logic_vector(unsigned(AD) + unsigned(X(7 downto 0))); + end if; + end if; + + if IR = "00000000" then + BAL <= (others => '1'); + BAH <= (others => '1'); + if RstCycle = '1' then + BAL(2 downto 0) <= "100"; + elsif NMICycle = '1' then + BAL(2 downto 0) <= "010"; + else + BAL(2 downto 0) <= "110"; + end if; + if Set_addr_To_r = "11" then + BAL(0) <= '1'; + end if; + end if; + + + if LDDI = '1' then + DL <= DI; + end if; + if LDALU = '1' then + DL <= ALU_Q; + end if; + if LDAD = '1' then + AD <= DI; + end if; + if LDBAL = '1' then + BAL(7 downto 0) <= DI; + end if; + if LDBAH = '1' then + BAH <= DI; + end if; + end if; + end if; + end if; + end process; + + Break <= (BreakAtNA and not BAL(8)) or (PCAdd and not PCAdder(8)); + + + with Set_BusA_To select + BusA <= DI when "000", + ABC(7 downto 0) when "001", + X(7 downto 0) when "010", + Y(7 downto 0) when "011", + std_logic_vector(S(7 downto 0)) when "100", + P when "101", + (others => '-') when others; + + with Set_Addr_To_r select + A <= "0000000000000001" & std_logic_vector(S(7 downto 0)) when "01", + DBR & "00000000" & AD when "10", + "00000000" & BAH & BAL(7 downto 0) when "11", + PBR & std_logic_vector(PC(15 downto 8)) & std_logic_vector(PCAdder(7 downto 0)) when others; + + with Write_Data_r select + DO <= DL when "000", + ABC(7 downto 0) when "001", + X(7 downto 0) when "010", + Y(7 downto 0) when "011", + std_logic_vector(S(7 downto 0)) when "100", + P when "101", + std_logic_vector(PC(7 downto 0)) when "110", + std_logic_vector(PC(15 downto 8)) when others; + +------------------------------------------------------------------------- +-- +-- Main state machine +-- +------------------------------------------------------------------------- + + process (Res_n, Clk) + begin + if Res_n = '0' then + MCycle <= "001"; + RstCycle <= '1'; + IRQCycle <= '0'; + NMICycle <= '0'; + NMIAct <= '0'; + elsif Clk'event and Clk = '1' then + if (Enable = '1') then + if (really_rdy = '1') then + if MCycle = LCycle or Break = '1' then + MCycle <= "000"; + RstCycle <= '0'; + IRQCycle <= '0'; + NMICycle <= '0'; + if NMIAct = '1' then + NMICycle <= '1'; + elsif IRQ_n_o = '0' and P(Flag_I) = '0' then + IRQCycle <= '1'; + end if; + else + MCycle <= std_logic_vector(unsigned(MCycle) + 1); + end if; + + if NMICycle = '1' then + NMIAct <= '0'; + end if; + if NMI_n_o = '1' and NMI_n = '0' then + NMIAct <= '1'; + end if; + end if; + end if; + end if; + end process; + +end; diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/T65_ALU.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/T65_ALU.vhd new file mode 100644 index 00000000..b1f6d632 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/T65_ALU.vhd @@ -0,0 +1,260 @@ +-- **** +-- T65(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 300 Bugfixes by ehenciak added +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- 6502 compatible microprocessor core +-- +-- Version : 0245 +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t65/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0245 : First version +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T65_Pack.all; + +entity T65_ALU is + port( + Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 + Op : in std_logic_vector(3 downto 0); + BusA : in std_logic_vector(7 downto 0); + BusB : in std_logic_vector(7 downto 0); + P_In : in std_logic_vector(7 downto 0); + P_Out : out std_logic_vector(7 downto 0); + Q : out std_logic_vector(7 downto 0) + ); +end T65_ALU; + +architecture rtl of T65_ALU is + + -- AddSub variables (temporary signals) + signal ADC_Z : std_logic; + signal ADC_C : std_logic; + signal ADC_V : std_logic; + signal ADC_N : std_logic; + signal ADC_Q : std_logic_vector(7 downto 0); + signal SBC_Z : std_logic; + signal SBC_C : std_logic; + signal SBC_V : std_logic; + signal SBC_N : std_logic; + signal SBC_Q : std_logic_vector(7 downto 0); + +begin + + process (P_In, BusA, BusB) + variable AL : unsigned(6 downto 0); + variable AH : unsigned(6 downto 0); + variable C : std_logic; + begin + AL := resize(unsigned(BusA(3 downto 0) & P_In(Flag_C)), 7) + resize(unsigned(BusB(3 downto 0) & "1"), 7); + AH := resize(unsigned(BusA(7 downto 4) & AL(5)), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7); + +-- pragma translate_off + if is_x(std_logic_vector(AL)) then AL := "0000000"; end if; + if is_x(std_logic_vector(AH)) then AH := "0000000"; end if; +-- pragma translate_on + + if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then + ADC_Z <= '1'; + else + ADC_Z <= '0'; + end if; + + if AL(5 downto 1) > 9 and P_In(Flag_D) = '1' then + AL(6 downto 1) := AL(6 downto 1) + 6; + end if; + + C := AL(6) or AL(5); + AH := resize(unsigned(BusA(7 downto 4) & C), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7); + + ADC_N <= AH(4); + ADC_V <= (AH(4) xor BusA(7)) and not (BusA(7) xor BusB(7)); + +-- pragma translate_off + if is_x(std_logic_vector(AH)) then AH := "0000000"; end if; +-- pragma translate_on + + if AH(5 downto 1) > 9 and P_In(Flag_D) = '1' then + AH(6 downto 1) := AH(6 downto 1) + 6; + end if; + + ADC_C <= AH(6) or AH(5); + + ADC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1)); + end process; + + process (Op, P_In, BusA, BusB) + variable AL : unsigned(6 downto 0); + variable AH : unsigned(5 downto 0); + variable C : std_logic; + begin + C := P_In(Flag_C) or not Op(0); + AL := resize(unsigned(BusA(3 downto 0) & C), 7) - resize(unsigned(BusB(3 downto 0) & "1"), 6); + AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(5)), 6); + +-- pragma translate_off + if is_x(std_logic_vector(AL)) then AL := "0000000"; end if; + if is_x(std_logic_vector(AH)) then AH := "000000"; end if; +-- pragma translate_on + + if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then + SBC_Z <= '1'; + else + SBC_Z <= '0'; + end if; + + SBC_C <= not AH(5); + SBC_V <= (AH(4) xor BusA(7)) and (BusA(7) xor BusB(7)); + SBC_N <= AH(4); + + if P_In(Flag_D) = '1' then + if AL(5) = '1' then + AL(5 downto 1) := AL(5 downto 1) - 6; + end if; + AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(6)), 6); + if AH(5) = '1' then + AH(5 downto 1) := AH(5 downto 1) - 6; + end if; + end if; + + SBC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1)); + end process; + + process (Op, P_In, BusA, BusB, + ADC_Z, ADC_C, ADC_V, ADC_N, ADC_Q, + SBC_Z, SBC_C, SBC_V, SBC_N, SBC_Q) + variable Q_t : std_logic_vector(7 downto 0); + begin + -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC + -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC + P_Out <= P_In; + Q_t := BusA; + case Op(3 downto 0) is + when "0000" => + -- ORA + Q_t := BusA or BusB; + when "0001" => + -- AND + Q_t := BusA and BusB; + when "0010" => + -- EOR + Q_t := BusA xor BusB; + when "0011" => + -- ADC + P_Out(Flag_V) <= ADC_V; + P_Out(Flag_C) <= ADC_C; + Q_t := ADC_Q; + when "0101" | "1101" => + -- LDA + when "0110" => + -- CMP + P_Out(Flag_C) <= SBC_C; + when "0111" => + -- SBC + P_Out(Flag_V) <= SBC_V; + P_Out(Flag_C) <= SBC_C; + Q_t := SBC_Q; + when "1000" => + -- ASL + Q_t := BusA(6 downto 0) & "0"; + P_Out(Flag_C) <= BusA(7); + when "1001" => + -- ROL + Q_t := BusA(6 downto 0) & P_In(Flag_C); + P_Out(Flag_C) <= BusA(7); + when "1010" => + -- LSR + Q_t := "0" & BusA(7 downto 1); + P_Out(Flag_C) <= BusA(0); + when "1011" => + -- ROR + Q_t := P_In(Flag_C) & BusA(7 downto 1); + P_Out(Flag_C) <= BusA(0); + when "1100" => + -- BIT + P_Out(Flag_V) <= BusB(6); + when "1110" => + -- DEC + Q_t := std_logic_vector(unsigned(BusA) - 1); + when "1111" => + -- INC + Q_t := std_logic_vector(unsigned(BusA) + 1); + when others => + end case; + + case Op(3 downto 0) is + when "0011" => + P_Out(Flag_N) <= ADC_N; + P_Out(Flag_Z) <= ADC_Z; + when "0110" | "0111" => + P_Out(Flag_N) <= SBC_N; + P_Out(Flag_Z) <= SBC_Z; + when "0100" => + when "1100" => + P_Out(Flag_N) <= BusB(7); + if (BusA and BusB) = "00000000" then + P_Out(Flag_Z) <= '1'; + else + P_Out(Flag_Z) <= '0'; + end if; + when others => + P_Out(Flag_N) <= Q_t(7); + if Q_t = "00000000" then + P_Out(Flag_Z) <= '1'; + else + P_Out(Flag_Z) <= '0'; + end if; + end case; + + Q <= Q_t; + end process; + +end; diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/T65_MCode.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/T65_MCode.vhd new file mode 100644 index 00000000..6c6c864a --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/T65_MCode.vhd @@ -0,0 +1,1052 @@ +-- **** +-- T65(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 302 minor timing fixes +-- Ver 301 Jump timing fixed +-- Ver 300 Bugfixes by ehenciak added +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- 65xx compatible microprocessor core +-- +-- Version : 0246 + fix +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t65/ +-- +-- Limitations : +-- +-- 65C02 +-- supported : inc, dec, phx, plx, phy, ply +-- missing : bra, ora, lda, cmp, sbc, tsb*2, trb*2, stz*2, bit*2, wai, stp, jmp, bbr*8, bbs*8 +-- +-- File history : +-- +-- 0246 : First release +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T65_Pack.all; + +entity T65_MCode is + port( + Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 + IR : in std_logic_vector(7 downto 0); + MCycle : in std_logic_vector(2 downto 0); + P : in std_logic_vector(7 downto 0); + LCycle : out std_logic_vector(2 downto 0); + ALU_Op : out std_logic_vector(3 downto 0); + Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P + Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA + Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH + Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel + BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj + BreakAtNA : out std_logic; + ADAdd : out std_logic; + AddY : out std_logic; + PCAdd : out std_logic; + Inc_S : out std_logic; + Dec_S : out std_logic; + LDA : out std_logic; + LDP : out std_logic; + LDX : out std_logic; + LDY : out std_logic; + LDS : out std_logic; + LDDI : out std_logic; + LDALU : out std_logic; + LDAD : out std_logic; + LDBAL : out std_logic; + LDBAH : out std_logic; + SaveP : out std_logic; + Write : out std_logic + ); +end T65_MCode; + +architecture rtl of T65_MCode is + + signal Branch : std_logic; + +begin + + with IR(7 downto 5) select + Branch <= not P(Flag_N) when "000", + P(Flag_N) when "001", + not P(Flag_V) when "010", + P(Flag_V) when "011", + not P(Flag_C) when "100", + P(Flag_C) when "101", + not P(Flag_Z) when "110", + P(Flag_Z) when others; + + process (IR, MCycle, P, Branch, Mode) + begin + LCycle <= "001"; + Set_BusA_To <= "001"; -- A + Set_Addr_To <= (others => '0'); + Write_Data <= (others => '0'); + Jump <= (others => '0'); + BAAdd <= "00"; + BreakAtNA <= '0'; + ADAdd <= '0'; + PCAdd <= '0'; + Inc_S <= '0'; + Dec_S <= '0'; + LDA <= '0'; + LDP <= '0'; + LDX <= '0'; + LDY <= '0'; + LDS <= '0'; + LDDI <= '0'; + LDALU <= '0'; + LDAD <= '0'; + LDBAL <= '0'; + LDBAH <= '0'; + SaveP <= '0'; + Write <= '0'; + AddY <= '0'; + + case IR(7 downto 5) is + when "100" => + --{{{ + case IR(1 downto 0) is + when "00" => + Set_BusA_To <= "011"; -- Y + Write_Data <= "011"; -- Y + when "10" => + Set_BusA_To <= "010"; -- X + Write_Data <= "010"; -- X + when others => + Write_Data <= "001"; -- A + end case; + --}}} + when "101" => + --{{{ + case IR(1 downto 0) is + when "00" => + if IR(4) /= '1' or IR(2) /= '0' then + LDY <= '1'; + end if; + when "10" => + LDX <= '1'; + when others => + LDA <= '1'; + end case; + Set_BusA_To <= "000"; -- DI + --}}} + when "110" => + --{{{ + case IR(1 downto 0) is + when "00" => + if IR(4) = '0' then + LDY <= '1'; + end if; + Set_BusA_To <= "011"; -- Y + when others => + Set_BusA_To <= "001"; -- A + end case; + --}}} + when "111" => + --{{{ + case IR(1 downto 0) is + when "00" => + if IR(4) = '0' then + LDX <= '1'; + end if; + Set_BusA_To <= "010"; -- X + when others => + Set_BusA_To <= "001"; -- A + end case; + --}}} + when others => + end case; + + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + Set_BusA_To <= "000"; -- DI + end if; + + case IR(4 downto 0) is + when "00000" | "01000" | "01010" | "11000" | "11010" => + --{{{ + -- Implied + case IR is + when "00000000" => + -- BRK + LCycle <= "110"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= "01"; -- S + Write_Data <= "111"; -- PCH + Write <= '1'; + when 2 => + Dec_S <= '1'; + Set_Addr_To <= "01"; -- S + Write_Data <= "110"; -- PCL + Write <= '1'; + when 3 => + Dec_S <= '1'; + Set_Addr_To <= "01"; -- S + Write_Data <= "101"; -- P + Write <= '1'; + when 4 => + Dec_S <= '1'; + Set_Addr_To <= "11"; -- BA + when 5 => + LDDI <= '1'; + Set_Addr_To <= "11"; -- BA + when 6 => + Jump <= "10"; -- DIDL + when others => + end case; + when "00100000" => + -- JSR + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDDI <= '1'; + Set_Addr_To <= "01"; -- S + when 2 => + Set_Addr_To <= "01"; -- S + Write_Data <= "111"; -- PCH + Write <= '1'; + when 3 => + Dec_S <= '1'; + Set_Addr_To <= "01"; -- S + Write_Data <= "110"; -- PCL + Write <= '1'; + when 4 => + Dec_S <= '1'; + when 5 => + Jump <= "10"; -- DIDL + when others => + end case; + when "01000000" => + -- RTI + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= "01"; -- S + when 2 => + Inc_S <= '1'; + Set_Addr_To <= "01"; -- S + when 3 => + Inc_S <= '1'; + Set_Addr_To <= "01"; -- S + Set_BusA_To <= "000"; -- DI + when 4 => + LDP <= '1'; + Inc_S <= '1'; + LDDI <= '1'; + Set_Addr_To <= "01"; -- S + when 5 => + Jump <= "10"; -- DIDL + when others => + end case; + when "01100000" => + -- RTS + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= "01"; -- S + when 2 => + Inc_S <= '1'; + Set_Addr_To <= "01"; -- S + when 3 => + Inc_S <= '1'; + LDDI <= '1'; + Set_Addr_To <= "01"; -- S + when 4 => + Jump <= "10"; -- DIDL + when 5 => + Jump <= "01"; + when others => + end case; + when "00001000" | "01001000" | "01011010" | "11011010" => + -- PHP, PHA, PHY*, PHX* + LCycle <= "010"; + if Mode = "00" and IR(1) = '1' then + LCycle <= "001"; + end if; + case to_integer(unsigned(MCycle)) is + when 1 => + case IR(7 downto 4) is + when "0000" => + Write_Data <= "101"; -- P + when "0100" => + Write_Data <= "001"; -- A + when "0101" => + Write_Data <= "011"; -- Y + when "1101" => + Write_Data <= "010"; -- X + when others => + end case; + Write <= '1'; + Set_Addr_To <= "01"; -- S + when 2 => + Dec_S <= '1'; + when others => + end case; + when "00101000" | "01101000" | "01111010" | "11111010" => + -- PLP, PLA, PLY*, PLX* + LCycle <= "011"; + if Mode = "00" and IR(1) = '1' then + LCycle <= "001"; + end if; + case IR(7 downto 4) is + when "0010" => + LDP <= '1'; + when "0110" => + LDA <= '1'; + when "0111" => + if Mode /= "00" then + LDY <= '1'; + end if; + when "1111" => + if Mode /= "00" then + LDX <= '1'; + end if; + when others => + end case; + case to_integer(unsigned(MCycle)) is + when 0 => + SaveP <= '1'; + when 1 => + Set_Addr_To <= "01"; -- S + when 2 => + Inc_S <= '1'; + Set_Addr_To <= "01"; -- S + when 3 => + Set_BusA_To <= "000"; -- DI + when others => + end case; + when "10100000" | "11000000" | "11100000" => + -- LDY, CPY, CPX + -- Immediate + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + when others => + end case; + when "10001000" => + -- DEY + LDY <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "011"; -- Y + when others => + end case; + when "11001010" => + -- DEX + LDX <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "010"; -- X + when others => + end case; + when "00011010" | "00111010" => + -- INC*, DEC* + if Mode /= "00" then + LDA <= '1'; -- A + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "100"; -- S + when others => + end case; + when "00001010" | "00101010" | "01001010" | "01101010" => + -- ASL, ROL, LSR, ROR + LDA <= '1'; -- A + Set_BusA_To <= "001"; -- A + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + when others => + end case; + when "10001010" | "10011000" => + -- TYA, TXA + LDA <= '1'; -- A + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + when others => + end case; + when "10101010" | "10101000" => + -- TAX, TAY + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "001"; -- A + when others => + end case; + when "10011010" => + -- TXS + case to_integer(unsigned(MCycle)) is + when 0 => + LDS <= '1'; + when 1 => + when others => + end case; + when "10111010" => + -- TSX + LDX <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "100"; -- S + when others => + end case; + + -- when "00011000" | "00111000" | "01011000" | "01111000" | "10111000" | "11011000" | "11111000" | "11001000" | "11101000" => + -- -- CLC, SEC, CLI, SEI, CLV, CLD, SED, INY, INX + -- case to_integer(unsigned(MCycle)) is + -- when 1 => + -- when others => + -- end case; + when others => + case to_integer(unsigned(MCycle)) is + when 0 => + when others => + end case; + end case; + --}}} + + when "00001" | "00011" => + --{{{ + -- Zero Page Indexed Indirect (d,x) + LCycle <= "101"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + ADAdd <= '1'; + Set_Addr_To <= "10"; -- AD + when 3 => + BAAdd <= "01"; -- DB Inc + LDBAL <= '1'; + Set_Addr_To <= "10"; -- AD + when 4 => + LDBAH <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 5 => + when others => + end case; + --}}} + + when "01001" | "01011" => + --{{{ + -- Immediate + LDA <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + when others => + end case; + + --}}} + + when "00010" | "10010" => + --{{{ + -- Immediate, KIL + LDX <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + if IR = "10100010" then + -- LDX + Jump <= "01"; + else + -- KIL !!!!!!!!!!!!!!!!!!!!!!!!!!!!! + end if; + when others => + end case; + --}}} + + when "00100" => + --{{{ + -- Zero Page + LCycle <= "010"; + case to_integer(unsigned(MCycle)) is + when 0 => + if IR(7 downto 5) = "001" then + SaveP <= '1'; + end if; + when 1 => + Jump <= "01"; + LDAD <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "10"; -- AD + when 2 => + when others => + end case; + --}}} + + when "00101" | "00110" | "00111" => + --{{{ + -- Zero Page + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + -- Read-Modify-Write + LCycle <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + LDDI <= '1'; + Write <= '1'; + Set_Addr_To <= "10"; -- AD + when 3 => + LDALU <= '1'; + SaveP <= '1'; + Write <= '1'; + Set_Addr_To <= "10"; -- AD + when 4 => + when others => + end case; + else + LCycle <= "010"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDAD <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "10"; -- AD + when 2 => + when others => + end case; + end if; + --}}} + + when "01100" => + --{{{ + -- Absolute + if IR(7 downto 6) = "01" and IR(4 downto 0) = "01100" then + -- JMP + if IR(5) = '0' then + --LCycle <= "011"; + LCycle <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDDI <= '1'; + when 2 => + Jump <= "10"; -- DIDL + when others => + end case; + else + --LCycle <= "101"; + LCycle <= "100"; -- mikej + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDDI <= '1'; + LDBAL <= '1'; + when 2 => + LDBAH <= '1'; + if Mode /= "00" then + Jump <= "10"; -- DIDL + end if; + if Mode = "00" then + Set_Addr_To <= "11"; -- BA + end if; + when 3 => + LDDI <= '1'; + if Mode = "00" then + Set_Addr_To <= "11"; -- BA + BAAdd <= "01"; -- DB Inc + else + Jump <= "01"; + end if; + when 4 => + Jump <= "10"; -- DIDL + when others => + end case; + end if; + else + LCycle <= "011"; + case to_integer(unsigned(MCycle)) is + when 0 => + if IR(7 downto 5) = "001" then + SaveP <= '1'; + end if; + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + LDBAH <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 3 => + when others => + end case; + end if; + --}}} + + when "01101" | "01110" | "01111" => + --{{{ + -- Absolute + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + -- Read-Modify-Write + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 3 => + LDDI <= '1'; + Write <= '1'; + Set_Addr_To <= "11"; -- BA + when 4 => + Write <= '1'; + LDALU <= '1'; + SaveP <= '1'; + Set_Addr_To <= "11"; -- BA + when 5 => + SaveP <= '0'; -- MIKEJ was 1 + when others => + end case; + else + LCycle <= "011"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + LDBAH <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 3 => + when others => + end case; + end if; + --}}} + + when "10000" => + --{{{ + -- Relative + + -- This circuit dictates when the last + -- microcycle occurs for the branch depending on + -- whether or not the branch is taken and if a page + -- is crossed... + if (Branch = '1') then + + LCycle <= "011"; -- We're done @ T3 if branching...upper + -- level logic will stop at T2 if no page cross + -- (See the Break signal) + else + + LCycle <= "001"; + + end if; + + -- This decodes the current microcycle and takes the + -- proper course of action... + case to_integer(unsigned(MCycle)) is + + -- On the T1 microcycle, increment the program counter + -- and instruct the upper level logic to fetch the offset + -- from the Din bus and store it in the data latches. This + -- will be the last microcycle if the branch isn't taken. + when 1 => + + Jump <= "01"; -- Increments the PC by one (PC will now be PC+2) + -- from microcycle T0. + + LDDI <= '1'; -- Tells logic in top level (T65.vhd) to route + -- the Din bus to the memory data latch (DL) + -- so that the branch offset is fetched. + + -- In microcycle T2, tell the logic in the top level to + -- add the offset. If the most significant byte of the + -- program counter (i.e. the current "page") does not need + -- updating, we are done here...the Break signal at the + -- T65.vhd level takes care of that... + when 2 => + + Jump <= "11"; -- Tell the PC Jump logic to use relative mode. + + PCAdd <= '1'; -- This tells the PC adder to update itself with + -- the current offset recently fetched from + -- memory. + + -- The following is microcycle T3 : + -- The program counter should be completely updated + -- on this cycle after the page cross is detected. + -- We don't need to do anything here... + when 3 => + + + when others => null; -- Do nothing. + + end case; + --}}} + + when "10001" | "10011" => + --{{{ + -- Zero Page Indirect Indexed (d),y + LCycle <= "101"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + LDBAL <= '1'; + BAAdd <= "01"; -- DB Inc + Set_Addr_To <= "10"; -- AD + when 3 => + Set_BusA_To <= "011"; -- Y + BAAdd <= "10"; -- BA Add + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 4 => + BAAdd <= "11"; -- BA Adj + if IR(7 downto 5) = "100" then + Write <= '1'; + else + BreakAtNA <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 5 => + when others => + end case; + --}}} + + when "10100" | "10101" | "10110" | "10111" => + --{{{ + -- Zero Page, X + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + -- Read-Modify-Write + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + ADAdd <= '1'; + Set_Addr_To <= "10"; -- AD + when 3 => + LDDI <= '1'; + Write <= '1'; + Set_Addr_To <= "10"; -- AD + when 4 => + LDALU <= '1'; + SaveP <= '1'; + Write <= '1'; + Set_Addr_To <= "10"; -- AD + when 5 => + when others => + end case; + else + LCycle <= "011"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + ADAdd <= '1'; + -- Added this check for Y reg. use... + if (IR(3 downto 0) = "0110") then + AddY <= '1'; + end if; + + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "10"; -- AD + when 3 => null; + when others => + end case; + end if; + --}}} + + when "11001" | "11011" => + --{{{ + -- Absolute Y + LCycle <= "100"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + Set_BusA_To <= "011"; -- Y + BAAdd <= "10"; -- BA Add + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 3 => + BAAdd <= "11"; -- BA adj + if IR(7 downto 5) = "100" then + Write <= '1'; + else + BreakAtNA <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 4 => + when others => + end case; + --}}} + + when "11100" | "11101" | "11110" | "11111" => + --{{{ + -- Absolute X + + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + -- Read-Modify-Write + LCycle <= "110"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + Set_BusA_To <= "010"; -- X + BAAdd <= "10"; -- BA Add + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 3 => + BAAdd <= "11"; -- BA adj + Set_Addr_To <= "11"; -- BA + when 4 => + LDDI <= '1'; + Write <= '1'; + Set_Addr_To <= "11"; -- BA + when 5 => + LDALU <= '1'; + SaveP <= '1'; + Write <= '1'; + Set_Addr_To <= "11"; -- BA + when 6 => + when others => + end case; + else + LCycle <= "100"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + -- mikej + -- special case 0xBE which uses Y reg as index!! + if (IR = "10111110") then + Set_BusA_To <= "011"; -- Y + else + Set_BusA_To <= "010"; -- X + end if; + BAAdd <= "10"; -- BA Add + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 3 => + BAAdd <= "11"; -- BA adj + if IR(7 downto 5) = "100" then + Write <= '1'; + else + BreakAtNA <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 4 => + when others => + end case; + end if; + --}}} + when others => + end case; + end process; + + process (IR, MCycle) + begin + -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC + -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC + case IR(1 downto 0) is + when "00" => + --{{{ + case IR(4 downto 2) is + when "000" | "001" | "011" => + case IR(7 downto 5) is + when "110" | "111" => + -- CP + ALU_Op <= "0110"; + when "101" => + -- LD + ALU_Op <= "0101"; + when "001" => + -- BIT + ALU_Op <= "1100"; + when others => + -- NOP/ST + ALU_Op <= "0100"; + end case; + when "010" => + case IR(7 downto 5) is + when "111" | "110" => + -- IN + ALU_Op <= "1111"; + when "100" => + -- DEY + ALU_Op <= "1110"; + when others => + -- LD + ALU_Op <= "1101"; + end case; + when "110" => + case IR(7 downto 5) is + when "100" => + -- TYA + ALU_Op <= "1101"; + when others => + ALU_Op <= "----"; + end case; + when others => + case IR(7 downto 5) is + when "101" => + -- LD + ALU_Op <= "1101"; + when others => + ALU_Op <= "0100"; + end case; + end case; + --}}} + when "01" => -- OR + --{{{ + ALU_Op(3) <= '0'; + ALU_Op(2 downto 0) <= IR(7 downto 5); + --}}} + when "10" => + --{{{ + ALU_Op(3) <= '1'; + ALU_Op(2 downto 0) <= IR(7 downto 5); + case IR(7 downto 5) is + when "000" => + if IR(4 downto 2) = "110" then + -- INC + ALU_Op <= "1111"; + end if; + when "001" => + if IR(4 downto 2) = "110" then + -- DEC + ALU_Op <= "1110"; + end if; + when "100" => + if IR(4 downto 2) = "010" then + -- TXA + ALU_Op <= "0101"; + else + ALU_Op <= "0100"; + end if; + when others => + end case; + --}}} + when others => + --{{{ + case IR(7 downto 5) is + when "100" => + ALU_Op <= "0100"; + when others => + if MCycle = "000" then + ALU_Op(3) <= '0'; + ALU_Op(2 downto 0) <= IR(7 downto 5); + else + ALU_Op(3) <= '1'; + ALU_Op(2 downto 0) <= IR(7 downto 5); + end if; + end case; + --}}} + end case; + end process; + +end; diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/T65_Pack.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/T65_Pack.vhd new file mode 100644 index 00000000..e025e1bf --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/T65_Pack.vhd @@ -0,0 +1,117 @@ +-- **** +-- T65(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 300 Bugfixes by ehenciak added +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- 65xx compatible microprocessor core +-- +-- Version : 0246 +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t65/ +-- +-- Limitations : +-- +-- File history : +-- + +library IEEE; +use IEEE.std_logic_1164.all; + +package T65_Pack is + + constant Flag_C : integer := 0; + constant Flag_Z : integer := 1; + constant Flag_I : integer := 2; + constant Flag_D : integer := 3; + constant Flag_B : integer := 4; + constant Flag_1 : integer := 5; + constant Flag_V : integer := 6; + constant Flag_N : integer := 7; + + component T65_MCode + port( + Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 + IR : in std_logic_vector(7 downto 0); + MCycle : in std_logic_vector(2 downto 0); + P : in std_logic_vector(7 downto 0); + LCycle : out std_logic_vector(2 downto 0); + ALU_Op : out std_logic_vector(3 downto 0); + Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P + Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA + Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH + Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel + BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj + BreakAtNA : out std_logic; + ADAdd : out std_logic; + AddY : out std_logic; + PCAdd : out std_logic; + Inc_S : out std_logic; + Dec_S : out std_logic; + LDA : out std_logic; + LDP : out std_logic; + LDX : out std_logic; + LDY : out std_logic; + LDS : out std_logic; + LDDI : out std_logic; + LDALU : out std_logic; + LDAD : out std_logic; + LDBAL : out std_logic; + LDBAH : out std_logic; + SaveP : out std_logic; + Write : out std_logic + ); + end component; + + component T65_ALU + port( + Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816 + Op : in std_logic_vector(3 downto 0); + BusA : in std_logic_vector(7 downto 0); + BusB : in std_logic_vector(7 downto 0); + P_In : in std_logic_vector(7 downto 0); + P_Out : out std_logic_vector(7 downto 0); + Q : out std_logic_vector(7 downto 0) + ); + end component; + +end; diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/addec_prom.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/addec_prom.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/greybox_tmp/cbx_args.txt b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/greybox_tmp/cbx_args.txt new file mode 100644 index 00000000..deea9283 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/greybox_tmp/cbx_args.txt @@ -0,0 +1,16 @@ +ADDRESS_ACLR_A=NONE +CLOCK_ENABLE_INPUT_A=BYPASS +CLOCK_ENABLE_OUTPUT_A=BYPASS +INIT_FILE=../roms/6400-01m2.hex +INTENDED_DEVICE_FAMILY="Cyclone III" +NUMWORDS_A=256 +OPERATION_MODE=ROM +OUTDATA_ACLR_A=NONE +OUTDATA_REG_A=UNREGISTERED +WIDTHAD_A=8 +WIDTH_A=4 +WIDTH_BYTEENA_A=1 +DEVICE_FAMILY="Cyclone III" +address_a +clock0 +q_a diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/j6_prom.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/j6_prom.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/k6_prom.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/k6_prom.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/prog_rom1.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/prog_rom1.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/prog_rom2.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/prog_rom2.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/prog_rom3.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/prog_rom3.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/prog_rom4.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/prog_rom4.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/ram1k_dp.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/ram1k_dp.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/sync_prom.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/T65/sync_prom.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/build_id.sv b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/build_id.sv new file mode 100644 index 00000000..1d53a3f2 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/build_id.sv @@ -0,0 +1,2 @@ +`define BUILD_DATE "171221" +`define BUILD_TIME "172231" diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/build_id.tcl b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/build_id.tcl new file mode 100644 index 00000000..be673dac --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/build_id.tcl @@ -0,0 +1,35 @@ +# ================================================================================ +# +# Build ID Verilog Module Script +# Jeff Wiencrot - 8/1/2011 +# +# Generates a Verilog module that contains a timestamp, +# from the current build. These values are available from the build_date, build_time, +# physical_address, and host_name output ports of the build_id module in the build_id.v +# Verilog source file. +# +# ================================================================================ + +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate [ clock format [ clock seconds ] -format %y%m%d ] + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + + # Create a Verilog file for output + set outputFileName "rtl/build_id.sv" + set outputFile [open $outputFileName "w"] + + # Output the Verilog source + puts $outputFile "`define BUILD_DATE \"$buildDate\"" + puts $outputFile "`define BUILD_TIME \"$buildTime\"" + close $outputFile + + # Send confirmation message to the Messages window + post_message "Generated build identification Verilog module: [pwd]/$outputFileName" + post_message "Date: $buildDate" + post_message "Time: $buildTime" +} + +# Comment out this line to prevent the process from automatically executing when the file is sourced: +generateBuildID_Verilog \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/collision.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/collision.vhd new file mode 100644 index 00000000..ec1d8dbb --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/collision.vhd @@ -0,0 +1,122 @@ +-- Collision detection logic for for Kee Games Sprint 2 +-- This is called the "Car/Playfield Comparator" in the manual and works by comparing the +-- video signals representing player and computer cars, track boundaries and oil slicks generating +-- collision signals when multiple objects appear at the same time (location) in the video. +-- Car 1 and Car 2 are human players, Car 3 and Car 4 are computer controlled. +-- +-- NOTE: There is an error in the original schematic, F8 pin 5 should go to CAR1 (not inverted) and +-- F8 pin 9 to CAR2 (not inverted) while the schematic shows them connecting to the inverted signals +-- +-- Tests for the following conditions: +-- Car 1 equals Car 2 +-- Car 1 equals Car 3 or 4 +-- Car 2 equals Car 3 or 4 +-- Car 1 equals Black Playfield (Oil slick) +-- Car 2 equals Black Playfield (Oil slick) +-- Car 1 equals White Playfield (Track boundary) +-- Car 2 equals White Playfield (Track boundary) +-- +-- (c) 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity collision_detect is +port( + Clk6 : in std_logic; + Car1 : in std_logic; + Car1_n : in std_logic; + Car2 : in std_logic; + Car2_n : in std_logic; + Car3_4_n : in std_logic; + WhitePF_n : in std_logic; + BlackPF_n : in std_logic; + CollRst1_n : in std_logic; + CollRst2_n : in std_logic; + Collisions1 : out std_logic_vector(1 downto 0); + Collisions2 : out std_logic_vector(1 downto 0) + ); +end collision_detect; + +architecture rtl of collision_detect is + +signal Col_latch_Q : std_logic_vector(4 downto 1) := (others => '0'); +signal S1_n : std_logic_vector(4 downto 1); +signal S2_n : std_logic_vector(4 downto 1); +signal R_n : std_logic_vector(4 downto 1); + + +begin + +-- Tristate buffers at E5 and E6 route collision signals to data bus 7-6 +Collisions1 <= Col_latch_Q(2 downto 1); +Collisions2 <= Col_latch_Q(4 downto 3); + +-- 74LS279 quad SR latch at H6, all inputs are active low +-- These should probably be written as synchronous latches +H6: process(Clk6, S1_n, S2_n, R_n, Col_latch_Q) +begin + if rising_edge(Clk6) then +-- Units 1 and 3 each have an extra Set element +-- Ordered from top to bottom as drawn in the schematic + if R_n(1) = '0' then + Col_latch_Q(1) <= '0'; + elsif (S1_n(1) and S2_n(1)) = '0' then + Col_latch_Q(1) <= '1'; + else + Col_latch_Q(1) <= Col_latch_Q(1); + end if; + if R_n(2) = '0' then + Col_latch_Q(2) <= '0'; + elsif S1_n(2) = '0' then + Col_latch_Q(2) <= '1'; + else + Col_latch_Q(2) <= Col_latch_Q(2); + end if; + if R_n(4) = '0' then + Col_latch_Q(4) <= '0'; + elsif S1_n(4) = '0' then + Col_latch_Q(4) <= '1'; + else + Col_latch_Q(4) <= Col_latch_Q(4); + end if; + if R_n(3) = '0' then + Col_latch_Q(3) <= '0'; + elsif (S1_n(3) and S2_n(3)) = '0' then + Col_latch_Q(3) <= '1'; + else + Col_latch_Q(3) <= Col_latch_Q(3); + end if; + end if; +end process; + +-- Glue logic +S2_n(1) <= BlackPF_n or Car1_n; +S1_n(1) <= Car1 nand (Car2_n nand Car3_4_n); +R_n(1) <= CollRst1_n; + +R_n(2) <= CollRst1_n; +S1_n(2) <= Car1_n or WhitePF_n; + +R_n(4) <= CollRst2_n; +S1_n(4) <= Car2_n or WhitePF_n; + +S2_n(3) <= BlackPF_n or Car2_n; +S1_n(3) <= Car2 nand (Car1_n nand Car3_4_n); +R_n(3) <= CollRst2_n; + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/cpu_mem.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/cpu_mem.vhd new file mode 100644 index 00000000..8f4813d3 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/cpu_mem.vhd @@ -0,0 +1,436 @@ +-- CPU, RAM, ROM and address decoder for Kee Games Sprint 2 +-- (c) 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity CPU_mem is +port( + CLK12 : in std_logic; + CLK6 : in std_logic; -- 6MHz on schematic + Reset_n : in std_logic; + VCount : in std_logic_vector(7 downto 0); + HCount : in std_logic_vector(8 downto 0); + Vblank_s : in std_logic; -- Vblank* on schematic + Vreset : in std_logic; + Hsync_n : in std_logic; + Test_n : in std_logic; + Attract : out std_logic; + Skid1 : out std_logic; + Skid2 : out std_logic; + NoiseReset_n : out std_logic; + CollRst1_n : out std_logic; + CollRst2_n : out std_logic; + Lamp1 : out std_logic; + Lamp2 : out std_logic; + SteerRst1_n : out std_logic; + SteerRst2_n : out std_logic; + PHI1_O : out std_logic; + PHI2_O : out std_logic; + DISPLAY : out std_logic_vector(7 downto 0); + IO_Adr : out std_logic_vector(9 downto 0); + Collisions1 : in std_logic_vector(1 downto 0); + Collisions2 : in std_logic_vector(1 downto 0); + Inputs : in std_logic_vector(1 downto 0) + ); +end CPU_mem; + +architecture rtl of CPU_mem is + +signal cpu_clk : std_logic; +signal PHI1 : std_logic; +signal PHI2 : std_logic; +signal Q5 : std_logic; +signal Q6 : std_logic; +signal A7_2 : std_logic; +signal A7_5 : std_logic; +signal A7_7 : std_logic; + +signal A8_6 : std_logic; + +signal H256 : std_logic; +signal H256_n : std_logic; +signal H128 : std_logic; +signal H64 : std_logic; +signal H32 : std_logic; +signal H16 : std_logic; +signal H8 : std_logic; +signal H4 : std_logic; + +signal V128 : std_logic; +signal V64 : std_logic; +signal V32 : std_logic; +signal V16 : std_logic; +signal V8 : std_logic; + +signal IRQ_n : std_logic; +signal NMI_n : std_logic; +signal RW_n : std_logic; +signal RnW : std_logic; +signal A : std_logic_vector(15 downto 0); +signal ADR : std_logic_vector(9 downto 0); +signal cpuDin : std_logic_vector(7 downto 0); +signal cpuDout : std_logic_vector(7 downto 0); +signal DBUS_n : std_logic_vector(7 downto 0); +signal DBUS : std_logic_vector(7 downto 0); + + +signal ROM1_dout : std_logic_vector(7 downto 0); +signal ROM2_dout : std_logic_vector(7 downto 0); +signal ROM3_dout : std_logic_vector(7 downto 0); +signal ROM4_dout : std_logic_vector(7 downto 0); +signal ROM_dout : std_logic_vector(7 downto 0); + +signal ROM1 : std_logic; +signal ROM2 : std_logic; +signal ROM3 : std_logic; +signal ROM4 : std_logic; +signal ROM_ce : std_logic; +signal ROM_mux_in : std_logic_vector(3 downto 0); + +signal cpuRAM_dout : std_logic_vector(7 downto 0); +signal Vram_dout : std_logic_vector(7 downto 0); +signal RAM_addr : std_logic_vector(9 downto 0) := (others => '0'); +signal Vram_addr : std_logic_vector(9 downto 0) := (others => '0'); +signal Scanbus : std_logic_vector(9 downto 0) := (others => '0'); +signal RAM_dout : std_logic_vector(7 downto 0); +signal RAM_we : std_logic := '0'; +signal RAM_RW_n : std_logic := '1'; +signal RAM_ce_n : std_logic := '1'; +signal RAM_n : std_logic := '1'; +signal WRAM : std_logic := '0'; +signal WRITE_n : std_logic := '1'; + +signal F2_in : std_logic_vector(3 downto 0) := "0000"; +signal F2_out : std_logic_vector(9 downto 0) := "1111111111"; +signal D2_in : std_logic_vector(3 downto 0) := "0000"; +signal D2_out : std_logic_vector(9 downto 0) := "1111111111"; +signal E8_in : std_logic_vector(3 downto 0) := "0000"; +signal E8_out : std_logic_vector(9 downto 0) := "1111111111"; +signal P3_8 : std_logic := '0'; + +signal Sync : std_logic := '0'; +signal Sync_n : std_logic := '1'; +signal Switch_n : std_logic := '1'; +signal Display_n : std_logic := '1'; +signal Addec_bus : std_logic_vector(7 downto 0); + +signal Timer_Reset_n : std_logic := '1'; +signal Collision1_n : std_logic := '1'; +signal Collision2_n : std_logic := '1'; + +signal J6_5 : std_logic := '0'; +signal J6_9 : std_logic := '0'; + +signal Coin1 : std_logic := '0'; +signal Coin2 : std_logic := '0'; +signal Input_mux : std_logic := '0'; +signal A8_8 : std_logic := '0'; +signal H9_Q_n : std_logic := '1'; +signal J9_out : std_logic_vector(7 downto 0); +signal H8_en : std_logic := '0'; +signal Attract_int : std_logic := '1'; + +begin + +H8 <= HCount(3); +H16 <= HCount(4); +H32 <= HCount(5); +H64 <= HCount(6); +H128 <= HCount(7); +H256 <= HCount(8); +H256_n <= (not HCount(8)); + +V8 <= VCount(3); +V16 <= VCount(4); +V32 <= VCount(5); +V64 <= VCount(6); +V128 <= VCount(7); + + +CPU: entity work.T65 +port map( + Enable => '1', + Mode => "00", + Res_n => reset_n, + Clk => phi1, + Rdy => '1', + Abort_n => '1', + IRQ_n => '1', + NMI_n => NMI_n, + SO_n => '1', + R_W_n => RW_n, + A(15 downto 0) => A, + DI => cpuDin, + DO => cpuDout + ); + +DBUS_n <= (not cpuDout); -- Data bus to video RAM is inverted +ADR(9 downto 7) <= (A(9) or WRAM) & (A(8) or WRAM) & (A(7) or WRAM); +ADR(6 downto 0) <= A(6 downto 0); +RnW <= (not RW_n); +IO_Adr <= Adr; + +NMI_n <= not (Vblank_s and Test_n); + + +-- CPU clock +H4 <= Hcount(2); +CPU_clock: process(clk12, H4, Q5, Q6) +begin + if rising_edge(clk12) then + Q5 <= H4; + Q6 <= Q5; + end if; + phi1 <= not (Q5 or Q6); --? +end process; + +PHI2 <= (not PHI1); +PHI1_O <= PHI1; +PHI2_O <= PHI2; + + +A8_6 <= not(RnW and PHI2 and H4 and WRITE_n); +A7: process(clk12, A8_6) -- Shift register chain of 4 DFF's clocked by clk12, creates a delayed WRITE_n +begin + if rising_edge(clk12) then + A7_2 <= A8_6; + A7_5 <= A7_2; + A7_7 <= A7_5; + WRITE_n <= A7_7; + end if; +end process; + + +-- Program ROMs +A1: entity work.prog_rom1 +port map( + clock => clk6, + address => A(10) & ADR(9 downto 0), + q => rom1_dout + ); + +C1: entity work.prog_rom2 +port map( + clock => clk6, + address => A(10) & ADR(9 downto 0), + q => rom2_dout + ); + +D1: entity work.prog_rom3 +port map( + clock => clk6, + address => A(10) & ADR(9 downto 0), + q => rom3_dout + ); + +E1: entity work.prog_rom4 +port map( + clock => clk6, + address => A(10) & ADR(9 downto 0), + q => rom4_dout + ); + +-- ROM data mux +ROM_mux_in <= (ROM1 & ROM2 & ROM3 & ROM4); +ROM_mux: process(ROM_mux_in, rom1_dout, rom2_dout, rom3_dout, rom4_dout) +begin + ROM_dout <= (others => '0'); + case ROM_mux_in is + when "1000" => rom_dout <= rom1_dout; + when "0100" => rom_dout <= rom2_dout; + when "0010" => rom_dout <= rom3_dout; + when "0001" => rom_dout <= rom4_dout; + when others => null; + end case; +end process; + +-- RAM +-- The original hardware multiplexes access to the RAM between the CPU and video hardware. In the FPGA it's +-- easier to use dual-ported RAM +RAM: entity work.ram1k_dp +port map( + clock => clk6, +-- CPU side + address_a => adr(9 downto 0), + wren_a => ram_we, + data_a => DBUS_n, + q_a=> CPUram_dout, + +-- Video side + address_b => Vram_addr, + wren_b => '0', + data_b => x"FF", + q_b => Vram_dout + ); + +Vram_addr <= (V128 or H256_n) & (V64 or H256_n) & (V32 or H256_n) & (V16 and H256) & (V8 and H256) & H128 & H64 & H32 & H16 & H8; + +-- Real hardware has both WE and CE which are selected by K2 according to the state of the phase 2 clock +-- Altera block RAM has active high WE, original RAM had active low WE +ram_we <= (not Write_n) and (not Display_n) and Phi2; + +-- Rising edge of phi2 clock latches inverted output of VRAM data bus +F5: process(phi2) +begin + if rising_edge(phi2) then + display <= not Vram_dout; + end if; +end process; + + +-- Address decoder +-- A15 and A14 are not used +-- Original circuit uses a bipolar PROM in the address decoder, this could be replaced with combinational logic + +-- E2 PROM +E2: entity work.addec_prom +port map( + clock => clk12, + address => A(13 downto 9), + q => addec_bus + ); + +F2_in <= addec_bus(0) & addec_bus(1) & addec_bus(2) & addec_bus(3); +WRAM <= addec_bus(4); +D2_in <= RnW & addec_bus(5) & addec_bus(6) & addec_bus(7); + +-- Decoder code could be cleaned up a bit, unused decoder states are not explicitly implemented +F2: process(F2_in) +begin + case F2_in is + when "0000" => + F2_out <= "1111111110"; + when "0001" => + F2_out <= "1111111101"; + when "0010" => + F2_out <= "1111111011"; + when "0011" => + F2_out <= "1111110111"; + when "0100" => + F2_out <= "1111101111"; + when "0101" => + F2_out <= "1111011111"; + when "0110" => + F2_out <= "1110111111"; + when "0111" => + F2_out <= "1101111111"; + when others => + F2_out <= "1111111111"; + end case; +end process; + +ROM1 <= (F2_out(0) nand F2_out(1)); +ROM2 <= (F2_out(2) nand F2_out(3)); +ROM3 <= (F2_out(4) nand F2_out(5)); +ROM4 <= (F2_out(6) nand F2_out(7)); +ROM_ce <= (ROM1 or ROM2 or ROM3 or ROM4); + +D2: process(D2_in) +begin + case D2_in is + when "0000" => + D2_out <= "1111111110"; + when "0001" => + D2_out <= "1111111101"; + when "0010" => + D2_out <= "1111111011"; + when "0011" => + D2_out <= "1111110111"; + when "0100" => + D2_out <= "1111101111"; + when "1000" => + D2_out <= "1011111111"; + when "1001" => + D2_out <= "0111111111"; + when others => + D2_out <= "1111111111"; + end case; +end process; + +RAM_n <= D2_out(0); +SYNC_n <= D2_out(1); +SYNC <= (not SYNC_n); +SWITCH_n <= D2_out(2); +COLLISION1_n <= D2_out(3); +COLLISION2_n <= D2_out(4); +DISPLAY_n <= (D2_out(0) and D2_out(8)); +P3_8 <= (D2_out(9) or WRITE_n); + +E8_in <= P3_8 & ADR(9 downto 7); + +E8: process(E8_in) +begin + case E8_in is + when "0000" => + E8_out <= "1111111110"; + when "0001" => + E8_out <= "1111111101"; + when "0010" => + E8_out <= "1111111011"; + when "0011" => + E8_out <= "1111110111"; + when "0100" => + E8_out <= "1111101111"; + when "0101" => + E8_out <= "1111011111"; + when "0110" => + E8_out <= "1110111111"; + when others => + E8_out <= "1111111111"; + end case; +end process; + +H8_en <= E8_out(0); +Timer_Reset_n <= E8_out(1); +CollRst1_n <= E8_out(2); +CollRst2_n <= E8_out(3); +SteerRst1_n <= E8_out(4); +SteerRst2_n <= E8_out(5); +NoiseReset_n <= E8_out(6); + +-- H8 9334 +H8_dec: process(clk6, Adr) +begin +if rising_edge(clk6) then + if (H8_en = '0') then + case Adr(6 downto 4) is + when "000" => Attract_int <= Adr(0); + when "001" => Skid1 <= Adr(0); + when "010" => Skid2 <= Adr(0); + when "011" => LAMP1 <= Adr(0); + when "100" => LAMP2 <= Adr(0); + when "101" => null; -- "Spare" on schematic + when "110" => null; + when "111" => null; + when others => null; + end case; + end if; + end if; +end process; +Attract <= Attract_Int; + +-- CPU Din mux +cpuDin <= ROM_dout when rom_ce = '1' else + (not CPUram_dout) when Display_n = '0' else -- Remember RAM data is inverted + VCount(7) & VBlank_s & Vreset & Attract_int & "1111" when Sync_n = '0' else -- Using V128 (VCount(7)) in place of 60Hz mains reference + Collisions1 & "111111" when Collision1_n = '0' else + Collisions2 & "111111" when Collision2_n = '0' else + Inputs & "111111" when SWITCH_n = '0' else + x"FF"; + +end rtl; diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/dac.sv b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/dac.sv new file mode 100644 index 00000000..d5f08d27 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/dac.sv @@ -0,0 +1,33 @@ +// +// PWM DAC +// +// MSBI is the highest bit number. NOT amount of bits! +// +module dac #(parameter MSBI=13, parameter INV=1'b1) +( + output reg DACout, //Average Output feeding analog lowpass + input [MSBI:0] DACin, //DAC input (excess 2**MSBI) + input CLK, + input RESET +); + +reg [MSBI+2:0] DeltaAdder; //Output of Delta Adder +reg [MSBI+2:0] SigmaAdder; //Output of Sigma Adder +reg [MSBI+2:0] SigmaLatch; //Latches output of Sigma Adder +reg [MSBI+2:0] DeltaB; //B input of Delta Adder + +always @(*) DeltaB = {SigmaLatch[MSBI+2], SigmaLatch[MSBI+2]} << (MSBI+1); +always @(*) DeltaAdder = DACin + DeltaB; +always @(*) SigmaAdder = DeltaAdder + SigmaLatch; + +always @(posedge CLK or posedge RESET) begin + if(RESET) begin + SigmaLatch <= 1'b1 << (MSBI+1); + DACout <= INV; + end else begin + SigmaLatch <= SigmaAdder; + DACout <= SigmaLatch[MSBI+2] ^ INV; + end +end + +endmodule diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/hq2x.sv b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/hq2x.sv new file mode 100644 index 00000000..f17732b6 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/hq2x.sv @@ -0,0 +1,454 @@ +// +// +// Copyright (c) 2012-2013 Ludvig Strigeus +// Copyright (c) 2017 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on + +`define BITS_TO_FIT(N) ( \ + N <= 2 ? 0 : \ + N <= 4 ? 1 : \ + N <= 8 ? 2 : \ + N <= 16 ? 3 : \ + N <= 32 ? 4 : \ + N <= 64 ? 5 : \ + N <= 128 ? 6 : \ + N <= 256 ? 7 : \ + N <= 512 ? 8 : \ + N <=1024 ? 9 : 10 ) + +module hq2x_in #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input rdbuf, + output[DWIDTH:0] q, + + input [AWIDTH:0] wraddr, + input wrbuf, + input [DWIDTH:0] data, + input wren +); + + localparam AWIDTH = `BITS_TO_FIT(LENGTH); + wire [DWIDTH:0] out[2]; + assign q = out[rdbuf]; + + hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); + hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); +endmodule + + +module hq2x_out #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input [1:0] rdbuf, + output[DWIDTH:0] q, + + input [AWIDTH:0] wraddr, + input [1:0] wrbuf, + input [DWIDTH:0] data, + input wren +); + + localparam AWIDTH = `BITS_TO_FIT(LENGTH*2); + wire [DWIDTH:0] out[4]; + assign q = out[rdbuf]; + + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf2(clk,data,rdaddr,wraddr,wren && (wrbuf == 2),out[2]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf3(clk,data,rdaddr,wraddr,wren && (wrbuf == 3),out[3]); +endmodule + + +module hq2x_buf #(parameter NUMWORDS, parameter AWIDTH, parameter DWIDTH) +( + input clock, + input [DWIDTH:0] data, + input [AWIDTH:0] rdaddress, + input [AWIDTH:0] wraddress, + input wren, + output [DWIDTH:0] q +); + + altsyncram altsyncram_component ( + .address_a (wraddress), + .clock0 (clock), + .data_a (data), + .wren_a (wren), + .address_b (rdaddress), + .q_b(q), + .aclr0 (1'b0), + .aclr1 (1'b0), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_b ({(DWIDTH+1){1'b1}}), + .eccstatus (), + .q_a (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_b (1'b0)); + defparam + altsyncram_component.address_aclr_b = "NONE", + altsyncram_component.address_reg_b = "CLOCK0", + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_input_b = "BYPASS", + altsyncram_component.clock_enable_output_b = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = NUMWORDS, + altsyncram_component.numwords_b = NUMWORDS, + altsyncram_component.operation_mode = "DUAL_PORT", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.outdata_reg_b = "UNREGISTERED", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE", + altsyncram_component.widthad_a = AWIDTH+1, + altsyncram_component.widthad_b = AWIDTH+1, + altsyncram_component.width_a = DWIDTH+1, + altsyncram_component.width_b = DWIDTH+1, + altsyncram_component.width_byteena_a = 1; + +endmodule + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +module DiffCheck +( + input [17:0] rgb1, + input [17:0] rgb2, + output result +); + + wire [5:0] r = rgb1[5:1] - rgb2[5:1]; + wire [5:0] g = rgb1[11:7] - rgb2[11:7]; + wire [5:0] b = rgb1[17:13] - rgb2[17:13]; + wire [6:0] t = $signed(r) + $signed(b); + wire [6:0] gx = {g[5], g}; + wire [7:0] y = $signed(t) + $signed(gx); + wire [6:0] u = $signed(r) - $signed(b); + wire [7:0] v = $signed({g, 1'b0}) - $signed(t); + + // if y is inside (-24..24) + wire y_inside = (y < 8'h18 || y >= 8'he8); + + // if u is inside (-4, 4) + wire u_inside = (u < 7'h4 || u >= 7'h7c); + + // if v is inside (-6, 6) + wire v_inside = (v < 8'h6 || v >= 8'hfA); + assign result = !(y_inside && u_inside && v_inside); +endmodule + +module InnerBlend +( + input [8:0] Op, + input [5:0] A, + input [5:0] B, + input [5:0] C, + output [5:0] O +); + + function [8:0] mul6x3; + input [5:0] op1; + input [2:0] op2; + begin + mul6x3 = 9'd0; + if(op2[0]) mul6x3 = mul6x3 + op1; + if(op2[1]) mul6x3 = mul6x3 + {op1, 1'b0}; + if(op2[2]) mul6x3 = mul6x3 + {op1, 2'b00}; + end + endfunction + + wire OpOnes = Op[4]; + wire [8:0] Amul = mul6x3(A, Op[7:5]); + wire [8:0] Bmul = mul6x3(B, {Op[3:2], 1'b0}); + wire [8:0] Cmul = mul6x3(C, {Op[1:0], 1'b0}); + wire [8:0] At = Amul; + wire [8:0] Bt = (OpOnes == 0) ? Bmul : {3'b0, B}; + wire [8:0] Ct = (OpOnes == 0) ? Cmul : {3'b0, C}; + wire [9:0] Res = {At, 1'b0} + Bt + Ct; + assign O = Op[8] ? A : Res[9:4]; +endmodule + +module Blend +( + input [5:0] rule, + input disable_hq2x, + input [17:0] E, + input [17:0] A, + input [17:0] B, + input [17:0] D, + input [17:0] F, + input [17:0] H, + output [17:0] Result +); + + reg [1:0] input_ctrl; + reg [8:0] op; + localparam BLEND0 = 9'b1_xxx_x_xx_xx; // 0: A + localparam BLEND1 = 9'b0_110_0_10_00; // 1: (A * 12 + B * 4) >> 4 + localparam BLEND2 = 9'b0_100_0_10_10; // 2: (A * 8 + B * 4 + C * 4) >> 4 + localparam BLEND3 = 9'b0_101_0_10_01; // 3: (A * 10 + B * 4 + C * 2) >> 4 + localparam BLEND4 = 9'b0_110_0_01_01; // 4: (A * 12 + B * 2 + C * 2) >> 4 + localparam BLEND5 = 9'b0_010_0_11_11; // 5: (A * 4 + (B + C) * 6) >> 4 + localparam BLEND6 = 9'b0_111_1_xx_xx; // 6: (A * 14 + B + C) >> 4 + localparam AB = 2'b00; + localparam AD = 2'b01; + localparam DB = 2'b10; + localparam BD = 2'b11; + wire is_diff; + DiffCheck diff_checker(rule[1] ? B : H, rule[0] ? D : F, is_diff); + + always @* begin + case({!is_diff, rule[5:2]}) + 1,17: {op, input_ctrl} = {BLEND1, AB}; + 2,18: {op, input_ctrl} = {BLEND1, DB}; + 3,19: {op, input_ctrl} = {BLEND1, BD}; + 4,20: {op, input_ctrl} = {BLEND2, DB}; + 5,21: {op, input_ctrl} = {BLEND2, AB}; + 6,22: {op, input_ctrl} = {BLEND2, AD}; + + 8: {op, input_ctrl} = {BLEND0, 2'bxx}; + 9: {op, input_ctrl} = {BLEND0, 2'bxx}; + 10: {op, input_ctrl} = {BLEND0, 2'bxx}; + 11: {op, input_ctrl} = {BLEND1, AB}; + 12: {op, input_ctrl} = {BLEND1, AB}; + 13: {op, input_ctrl} = {BLEND1, AB}; + 14: {op, input_ctrl} = {BLEND1, DB}; + 15: {op, input_ctrl} = {BLEND1, BD}; + + 24: {op, input_ctrl} = {BLEND2, DB}; + 25: {op, input_ctrl} = {BLEND5, DB}; + 26: {op, input_ctrl} = {BLEND6, DB}; + 27: {op, input_ctrl} = {BLEND2, DB}; + 28: {op, input_ctrl} = {BLEND4, DB}; + 29: {op, input_ctrl} = {BLEND5, DB}; + 30: {op, input_ctrl} = {BLEND3, BD}; + 31: {op, input_ctrl} = {BLEND3, DB}; + default: {op, input_ctrl} = 11'bx; + endcase + + // Setting op[8] effectively disables HQ2X because blend will always return E. + if (disable_hq2x) op[8] = 1; + end + + // Generate inputs to the inner blender. Valid combinations. + // 00: E A B + // 01: E A D + // 10: E D B + // 11: E B D + wire [17:0] Input1 = E; + wire [17:0] Input2 = !input_ctrl[1] ? A : + !input_ctrl[0] ? D : B; + + wire [17:0] Input3 = !input_ctrl[0] ? B : D; + InnerBlend inner_blend1(op, Input1[5:0], Input2[5:0], Input3[5:0], Result[5:0]); + InnerBlend inner_blend2(op, Input1[11:6], Input2[11:6], Input3[11:6], Result[11:6]); + InnerBlend inner_blend3(op, Input1[17:12], Input2[17:12], Input3[17:12], Result[17:12]); +endmodule + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +module Hq2x #(parameter LENGTH, parameter HALF_DEPTH) +( + input clk, + input ce_x4, + input [DWIDTH:0] inputpixel, + input mono, + input disable_hq2x, + input reset_frame, + input reset_line, + input [1:0] read_y, + input [AWIDTH+1:0] read_x, + output [DWIDTH:0] outpixel +); + + +localparam AWIDTH = `BITS_TO_FIT(LENGTH); +localparam DWIDTH = HALF_DEPTH ? 8 : 17; + +wire [5:0] hqTable[256] = '{ + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 35, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 35, 35, 23, 61, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 7, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 58, 23, 15, 51, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 39, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 7, 35, 23, 15, 7, 43 +}; + +reg [17:0] Prev0, Prev1, Prev2, Curr0, Curr1, Next0, Next1, Next2; +reg [17:0] A, B, D, F, G, H; +reg [7:0] pattern, nextpatt; +reg [1:0] i; +reg [7:0] y; + +wire curbuf = y[0]; +reg prevbuf = 0; +wire iobuf = !curbuf; + +wire diff0, diff1; +DiffCheck diffcheck0(Curr1, (i == 0) ? Prev0 : (i == 1) ? Curr0 : (i == 2) ? Prev2 : Next1, diff0); +DiffCheck diffcheck1(Curr1, (i == 0) ? Prev1 : (i == 1) ? Next0 : (i == 2) ? Curr2 : Next2, diff1); + +wire [7:0] new_pattern = {diff1, diff0, pattern[7:2]}; + +wire [17:0] X = (i == 0) ? A : (i == 1) ? Prev1 : (i == 2) ? Next1 : G; +wire [17:0] blend_result; +Blend blender(hqTable[nextpatt], disable_hq2x, Curr0, X, B, D, F, H, blend_result); + +reg Curr2_addr1; +reg [AWIDTH:0] Curr2_addr2; +wire [17:0] Curr2 = HALF_DEPTH ? h2rgb(Curr2tmp) : Curr2tmp; +wire [DWIDTH:0] Curr2tmp; + +reg [AWIDTH:0] wrin_addr2; +reg [DWIDTH:0] wrpix; +reg wrin_en; + +function [17:0] h2rgb; + input [8:0] v; +begin + h2rgb = mono ? {v[5:3],v[2:0], v[5:3],v[2:0], v[5:3],v[2:0]} : {v[8:6],v[8:6],v[5:3],v[5:3],v[2:0],v[2:0]}; +end +endfunction + +function [8:0] rgb2h; + input [17:0] v; +begin + rgb2h = mono ? {3'b000, v[17:15], v[14:12]} : {v[17:15], v[11:9], v[5:3]}; +end +endfunction + +hq2x_in #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_in +( + .clk(clk), + + .rdaddr(Curr2_addr2), + .rdbuf(Curr2_addr1), + .q(Curr2tmp), + + .wraddr(wrin_addr2), + .wrbuf(iobuf), + .data(wrpix), + .wren(wrin_en) +); + +reg [1:0] wrout_addr1; +reg [AWIDTH+1:0] wrout_addr2; +reg wrout_en; +reg [DWIDTH:0] wrdata; + +hq2x_out #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_out +( + .clk(clk), + + .rdaddr(read_x), + .rdbuf(read_y), + .q(outpixel), + + .wraddr(wrout_addr2), + .wrbuf(wrout_addr1), + .data(wrdata), + .wren(wrout_en) +); + +always @(posedge clk) begin + reg [AWIDTH:0] offs; + reg old_reset_line; + reg old_reset_frame; + + wrout_en <= 0; + wrin_en <= 0; + + if(ce_x4) begin + + pattern <= new_pattern; + + if(~&offs) begin + if (i == 0) begin + Curr2_addr1 <= prevbuf; + Curr2_addr2 <= offs; + end + if (i == 1) begin + Prev2 <= Curr2; + Curr2_addr1 <= curbuf; + Curr2_addr2 <= offs; + end + if (i == 2) begin + Next2 <= HALF_DEPTH ? h2rgb(inputpixel) : inputpixel; + wrpix <= inputpixel; + wrin_addr2 <= offs; + wrin_en <= 1; + end + if (i == 3) begin + offs <= offs + 1'd1; + end + + if(HALF_DEPTH) wrdata <= rgb2h(blend_result); + else wrdata <= blend_result; + + wrout_addr1 <= {curbuf, i[1]}; + wrout_addr2 <= {offs, i[1]^i[0]}; + wrout_en <= 1; + end + + if(i==3) begin + nextpatt <= {new_pattern[7:6], new_pattern[3], new_pattern[5], new_pattern[2], new_pattern[4], new_pattern[1:0]}; + {A, G} <= {Prev0, Next0}; + {B, F, H, D} <= {Prev1, Curr2, Next1, Curr0}; + {Prev0, Prev1} <= {Prev1, Prev2}; + {Curr0, Curr1} <= {Curr1, Curr2}; + {Next0, Next1} <= {Next1, Next2}; + end else begin + nextpatt <= {nextpatt[5], nextpatt[3], nextpatt[0], nextpatt[6], nextpatt[1], nextpatt[7], nextpatt[4], nextpatt[2]}; + {B, F, H, D} <= {F, H, D, B}; + end + + i <= i + 1'b1; + if(old_reset_line && ~reset_line) begin + old_reset_frame <= reset_frame; + offs <= 0; + i <= 0; + y <= y + 1'd1; + prevbuf <= curbuf; + if(old_reset_frame & ~reset_frame) begin + y <= 0; + prevbuf <= 0; + end + end + + old_reset_line <= reset_line; + end +end + +endmodule // Hq2x diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/keyboard.sv b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/keyboard.sv new file mode 100644 index 00000000..01625319 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/keyboard.sv @@ -0,0 +1,79 @@ + + +module keyboard +( + input clk, + input reset, + input ps2_kbd_clk, + input ps2_kbd_data, + + output reg[7:0] joystick +); + +reg [11:0] shift_reg = 12'hFFF; +wire[11:0] kdata = {ps2_kbd_data,shift_reg[11:1]}; +wire [7:0] kcode = kdata[9:2]; +reg release_btn = 0; + +reg [7:0] code; +reg input_strobe = 0; + +always @(negedge clk) begin + reg old_reset = 0; + + old_reset <= reset; + + if(~old_reset & reset)begin + joystick <= 0; + end + + if(input_strobe) begin + case(code) + 'h75: joystick[3] <= ~release_btn; // arrow up + 'h72: joystick[2] <= ~release_btn; // arrow down + 'h6B: joystick[1] <= ~release_btn; // arrow left + 'h74: joystick[0] <= ~release_btn; // arrow right + + 'h29: joystick[4] <= ~release_btn; // Space + 'h05: joystick[5] <= ~release_btn; // F1 + 'h06: joystick[6] <= ~release_btn; // F2 + 'h76: joystick[7] <= ~release_btn; // Escape + endcase + end +end + +always @(posedge clk) begin + reg [3:0] prev_clk = 0; + reg old_reset = 0; + reg action = 0; + + old_reset <= reset; + input_strobe <= 0; + + if(~old_reset & reset)begin + prev_clk <= 0; + shift_reg <= 12'hFFF; + end else begin + prev_clk <= {ps2_kbd_clk,prev_clk[3:1]}; + if(prev_clk == 1) begin + if (kdata[11] & ^kdata[10:2] & ~kdata[1] & kdata[0]) begin + shift_reg <= 12'hFFF; + if (kcode == 8'he0) ; + // Extended key code follows + else if (kcode == 8'hf0) + // Release code follows + action <= 1; + else begin + // Cancel extended/release flags for next time + action <= 0; + release_btn <= action; + code <= kcode; + input_strobe <= 1; + end + end else begin + shift_reg <= kdata; + end + end + end +end +endmodule diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/mist_io.sv b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/mist_io.sv new file mode 100644 index 00000000..dcc7ecde --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/mist_io.sv @@ -0,0 +1,491 @@ +// +// mist_io.v +// +// mist_io for the MiST board +// http://code.google.com/p/mist-board/ +// +// Copyright (c) 2014 Till Harbaum +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////// + +// +// Use buffer to access SD card. It's time-critical part. +// Made module synchroneous with 2 clock domains: clk_sys and SPI_SCK +// (Sorgelig) +// +// for synchronous projects default value for PS2DIV is fine for any frequency of system clock. +// clk_ps2 = clk_sys/(PS2DIV*2) +// + +module mist_io #(parameter STRLEN=0, parameter PS2DIV=100) +( + + // parameter STRLEN and the actual length of conf_str have to match + input [(8*STRLEN)-1:0] conf_str, + + // Global clock. It should be around 100MHz (higher is better). + input clk_sys, + + // Global SPI clock from ARM. 24MHz + input SPI_SCK, + + input CONF_DATA0, + input SPI_SS2, + output SPI_DO, + input SPI_DI, + + output reg [7:0] joystick_0, + output reg [7:0] joystick_1, + output reg [15:0] joystick_analog_0, + output reg [15:0] joystick_analog_1, + output [1:0] buttons, + output [1:0] switches, + output scandoubler_disable, + output ypbpr, + + output reg [31:0] status, + + // SD config + input sd_conf, + input sd_sdhc, + output img_mounted, // signaling that new image has been mounted + output reg [31:0] img_size, // size of image in bytes + + // SD block level access + input [31:0] sd_lba, + input sd_rd, + input sd_wr, + output reg sd_ack, + output reg sd_ack_conf, + + // SD byte level access. Signals for 2-PORT altsyncram. + output reg [8:0] sd_buff_addr, + output reg [7:0] sd_buff_dout, + input [7:0] sd_buff_din, + output reg sd_buff_wr, + + // ps2 keyboard emulation + output ps2_kbd_clk, + output reg ps2_kbd_data, + output ps2_mouse_clk, + output reg ps2_mouse_data, + input ps2_caps_led, + + // ARM -> FPGA download + output reg ioctl_download = 0, // signal indicating an active download + output reg [7:0] ioctl_index, // menu index used to upload the file + output ioctl_wr, + output reg [23:0] ioctl_addr, + output reg [7:0] ioctl_dout +); + +reg [7:0] b_data; +reg [6:0] sbuf; +reg [7:0] cmd; +reg [2:0] bit_cnt; // counts bits 0-7 0-7 ... +reg [9:0] byte_cnt; // counts bytes +reg [7:0] but_sw; +reg [2:0] stick_idx; + +reg mount_strobe = 0; +assign img_mounted = mount_strobe; + +assign buttons = but_sw[1:0]; +assign switches = but_sw[3:2]; +assign scandoubler_disable = but_sw[4]; +assign ypbpr = but_sw[5]; + +wire [7:0] spi_dout = { sbuf, SPI_DI}; + +// this variant of user_io is for 8 bit cores (type == a4) only +wire [7:0] core_type = 8'ha4; + +// command byte read by the io controller +wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd }; + +reg spi_do; +assign SPI_DO = CONF_DATA0 ? 1'bZ : spi_do; + +wire [7:0] kbd_led = { 2'b01, 4'b0000, ps2_caps_led, 1'b1}; + +// drive MISO only when transmitting core id +always@(negedge SPI_SCK) begin + if(!CONF_DATA0) begin + // first byte returned is always core type, further bytes are + // command dependent + if(byte_cnt == 0) begin + spi_do <= core_type[~bit_cnt]; + + end else begin + case(cmd) + // reading config string + 8'h14: begin + // returning a byte from string + if(byte_cnt < STRLEN + 1) spi_do <= conf_str[{STRLEN - byte_cnt,~bit_cnt}]; + else spi_do <= 0; + end + + // reading sd card status + 8'h16: begin + if(byte_cnt == 1) spi_do <= sd_cmd[~bit_cnt]; + else if((byte_cnt >= 2) && (byte_cnt < 6)) spi_do <= sd_lba[{5-byte_cnt, ~bit_cnt}]; + else spi_do <= 0; + end + + // reading sd card write data + 8'h18: + spi_do <= b_data[~bit_cnt]; + + // reading keyboard LED status + 8'h1f: + spi_do <= kbd_led[~bit_cnt]; + + default: + spi_do <= 0; + endcase + end + end +end + +reg b_wr2,b_wr3; +always @(negedge clk_sys) begin + b_wr3 <= b_wr2; + sd_buff_wr <= b_wr3; +end + +// SPI receiver +always@(posedge SPI_SCK or posedge CONF_DATA0) begin + + if(CONF_DATA0) begin + b_wr2 <= 0; + bit_cnt <= 0; + byte_cnt <= 0; + sd_ack <= 0; + sd_ack_conf <= 0; + end else begin + b_wr2 <= 0; + + sbuf <= spi_dout[6:0]; + bit_cnt <= bit_cnt + 1'd1; + if(bit_cnt == 5) begin + if (byte_cnt == 0) sd_buff_addr <= 0; + if((byte_cnt != 0) & (sd_buff_addr != 511)) sd_buff_addr <= sd_buff_addr + 1'b1; + if((byte_cnt == 1) & ((cmd == 8'h17) | (cmd == 8'h19))) sd_buff_addr <= 0; + end + + // finished reading command byte + if(bit_cnt == 7) begin + if(~&byte_cnt) byte_cnt <= byte_cnt + 8'd1; + if(byte_cnt == 0) begin + cmd <= spi_dout; + + if(spi_dout == 8'h19) begin + sd_ack_conf <= 1; + sd_buff_addr <= 0; + end + if((spi_dout == 8'h17) || (spi_dout == 8'h18)) begin + sd_ack <= 1; + sd_buff_addr <= 0; + end + if(spi_dout == 8'h18) b_data <= sd_buff_din; + + mount_strobe <= 0; + + end else begin + + case(cmd) + // buttons and switches + 8'h01: but_sw <= spi_dout; + 8'h02: joystick_0 <= spi_dout; + 8'h03: joystick_1 <= spi_dout; + + // store incoming ps2 mouse bytes + 8'h04: begin + ps2_mouse_fifo[ps2_mouse_wptr] <= spi_dout; + ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1; + end + + // store incoming ps2 keyboard bytes + 8'h05: begin + ps2_kbd_fifo[ps2_kbd_wptr] <= spi_dout; + ps2_kbd_wptr <= ps2_kbd_wptr + 1'd1; + end + + 8'h15: status[7:0] <= spi_dout; + + // send SD config IO -> FPGA + // flag that download begins + // sd card knows data is config if sd_dout_strobe is asserted + // with sd_ack still being inactive (low) + 8'h19, + // send sector IO -> FPGA + // flag that download begins + 8'h17: begin + sd_buff_dout <= spi_dout; + b_wr2 <= 1; + end + + 8'h18: b_data <= sd_buff_din; + + // joystick analog + 8'h1a: begin + // first byte is joystick index + if(byte_cnt == 1) stick_idx <= spi_dout[2:0]; + else if(byte_cnt == 2) begin + // second byte is x axis + if(stick_idx == 0) joystick_analog_0[15:8] <= spi_dout; + else if(stick_idx == 1) joystick_analog_1[15:8] <= spi_dout; + end else if(byte_cnt == 3) begin + // third byte is y axis + if(stick_idx == 0) joystick_analog_0[7:0] <= spi_dout; + else if(stick_idx == 1) joystick_analog_1[7:0] <= spi_dout; + end + end + + // notify image selection + 8'h1c: mount_strobe <= 1; + + // send image info + 8'h1d: if(byte_cnt<5) img_size[(byte_cnt-1)<<3 +:8] <= spi_dout; + + // status, 32bit version + 8'h1e: if(byte_cnt<5) status[(byte_cnt-1)<<3 +:8] <= spi_dout; + default: ; + endcase + end + end + end +end + + +/////////////////////////////// PS2 /////////////////////////////// +// 8 byte fifos to store ps2 bytes +localparam PS2_FIFO_BITS = 3; + +reg clk_ps2; +always @(negedge clk_sys) begin + integer cnt; + cnt <= cnt + 1'd1; + if(cnt == PS2DIV) begin + clk_ps2 <= ~clk_ps2; + cnt <= 0; + end +end + +// keyboard +reg [7:0] ps2_kbd_fifo[1<= 1)&&(ps2_kbd_tx_state < 9)) begin + ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits + ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down + if(ps2_kbd_tx_byte[0]) + ps2_kbd_parity <= !ps2_kbd_parity; + end + + // transmission of parity + if(ps2_kbd_tx_state == 9) ps2_kbd_data <= ps2_kbd_parity; + + // transmission of stop bit + if(ps2_kbd_tx_state == 10) ps2_kbd_data <= 1; // stop bit is 1 + + // advance state machine + if(ps2_kbd_tx_state < 11) ps2_kbd_tx_state <= ps2_kbd_tx_state + 1'd1; + else ps2_kbd_tx_state <= 0; + end + end +end + +// mouse +reg [7:0] ps2_mouse_fifo[1<= 1)&&(ps2_mouse_tx_state < 9)) begin + ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits + ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down + if(ps2_mouse_tx_byte[0]) + ps2_mouse_parity <= !ps2_mouse_parity; + end + + // transmission of parity + if(ps2_mouse_tx_state == 9) ps2_mouse_data <= ps2_mouse_parity; + + // transmission of stop bit + if(ps2_mouse_tx_state == 10) ps2_mouse_data <= 1; // stop bit is 1 + + // advance state machine + if(ps2_mouse_tx_state < 11) ps2_mouse_tx_state <= ps2_mouse_tx_state + 1'd1; + else ps2_mouse_tx_state <= 0; + end + end +end + + +/////////////////////////////// DOWNLOADING /////////////////////////////// + +reg [7:0] data_w; +reg [23:0] addr_w; +reg rclk = 0; + +localparam UIO_FILE_TX = 8'h53; +localparam UIO_FILE_TX_DAT = 8'h54; +localparam UIO_FILE_INDEX = 8'h55; + +// data_io has its own SPI interface to the io controller +always@(posedge SPI_SCK, posedge SPI_SS2) begin + reg [6:0] sbuf; + reg [7:0] cmd; + reg [4:0] cnt; + reg [23:0] addr; + + if(SPI_SS2) cnt <= 0; + else begin + rclk <= 0; + + // don't shift in last bit. It is evaluated directly + // when writing to ram + if(cnt != 15) sbuf <= { sbuf[5:0], SPI_DI}; + + // increase target address after write + if(rclk) addr <= addr + 1'd1; + + // count 0-7 8-15 8-15 ... + if(cnt < 15) cnt <= cnt + 1'd1; + else cnt <= 8; + + // finished command byte + if(cnt == 7) cmd <= {sbuf, SPI_DI}; + + // prepare/end transmission + if((cmd == UIO_FILE_TX) && (cnt == 15)) begin + // prepare + if(SPI_DI) begin + addr <= 0; + ioctl_download <= 1; + end else begin + addr_w <= addr; + ioctl_download <= 0; + end + end + + // command 0x54: UIO_FILE_TX + if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin + addr_w <= addr; + data_w <= {sbuf, SPI_DI}; + rclk <= 1; + end + + // expose file (menu) index + if((cmd == UIO_FILE_INDEX) && (cnt == 15)) ioctl_index <= {sbuf, SPI_DI}; + end +end + +assign ioctl_wr = |ioctl_wrd; +reg [1:0] ioctl_wrd; + +always@(negedge clk_sys) begin + reg rclkD, rclkD2; + + rclkD <= rclk; + rclkD2 <= rclkD; + ioctl_wrd<= {ioctl_wrd[0],1'b0}; + + if(rclkD & ~rclkD2) begin + ioctl_dout <= data_w; + ioctl_addr <= addr_w; + ioctl_wrd <= 2'b11; + end +end + +endmodule diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/motion.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/motion.vhd new file mode 100644 index 00000000..f9010db1 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/motion.vhd @@ -0,0 +1,361 @@ +-- Motion object generation circuitry for Kee Games Sprint 2 +-- This generates the four cars which are the only moving objects in the game +-- (c) 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity motion is +port( + CLK6 : in std_logic; -- 6MHz* on schematic + CLK12 : in std_logic; + PHI2 : in std_logic; + DISPLAY : in std_logic_vector(7 downto 0); + H256_s : in std_logic; -- 256H* on schematic + VCount : in std_logic_vector(7 downto 0); + HCount : in std_logic_vector(8 downto 0); + Crash_n : out std_logic; + Motor1_n : out std_logic; + Motor2_n : out std_logic; + Car1 : out std_logic; + Car1_n : out std_logic; + Car2 : out std_logic; + Car2_n : out std_logic; + Car3_4_n : out std_logic + ); +end motion; + +architecture rtl of motion is + +signal phi0 : std_logic; + +signal LDH1_n : std_logic; +signal LDH2_n : std_logic; +signal LDH3_n : std_logic; +signal LDH4_n : std_logic; + +signal LDV1A_n : std_logic; +signal LDV2A_n : std_logic; +signal LDV3A_n : std_logic; +signal LDV4A_n : std_logic; + +signal LDV1B_n : std_logic; +signal LDV2B_n : std_logic; +signal LDV3B_n : std_logic; +signal LDV4B_n : std_logic; + +signal Car1_Inh : std_logic; +signal Car2_Inh : std_logic; +signal Car3_Inh : std_logic; +signal Car4_Inh : std_logic; + +signal LM4_sum : std_logic_vector(7 downto 0) := x"00"; +signal N4_8 : std_logic; + +signal H256_n : std_logic; +signal H256 : std_logic; +signal H64 : std_logic; +signal H32 : std_logic; +signal H16 : std_logic; +signal H8 : std_logic; +signal H4 : std_logic; + +signal L5_reg : std_logic_vector(3 downto 0); + +signal J8_3 : std_logic; +signal J8_6 : std_logic; + +signal K8_in : std_logic_vector(3 downto 0); +signal K8_out : std_logic_vector(9 downto 0); +signal P7_in : std_logic_vector(3 downto 0); +signal P7_out : std_logic_vector(9 downto 0); + +signal Car1_Hpos : std_logic_vector(7 downto 0) := x"00"; +signal Car2_Hpos : std_logic_vector(7 downto 0) := x"00"; +signal Car3_Hpos : std_logic_vector(7 downto 0) := x"00"; +signal Car4_Hpos : std_logic_vector(7 downto 0) := x"00"; + +signal Car1_reg : std_logic_vector(15 downto 0) := x"0000"; +signal Car2_reg : std_logic_vector(15 downto 0) := x"0000"; +signal Car3_reg : std_logic_vector(15 downto 0) := x"0000"; +signal Car4_reg : std_logic_vector(15 downto 0) := x"0000"; + +signal Vid : std_logic_vector(7 downto 0); + + +begin +phi0 <= phi2; + +H4 <= Hcount(2); +H8 <= Hcount(3); +H16 <= Hcount(4); +H32 <= Hcount(5); +H64 <= Hcount(6); +H256 <= Hcount(8); +H256_n <= not(Hcount(8)); + +-- Vertical line comparator +LM4_sum <= Display + VCount; +N4_8 <= not(LM4_sum(7) and LM4_sum(6) and LM4_sum(5) and LM4_sum(4) and LM4_sum(3) and H256_n and H64 and H8); + + +-- D type flip-flops in L5 +L5: process(phi2, N4_8, LM4_sum(2 downto 0)) +begin + if rising_edge(phi2) then + L5_reg <= N4_8 & LM4_sum(2 downto 0); + end if; +end process; + + +-- Motion object PROMs - These contain the car images for all 32 possible orientations +J6: entity work.j6_prom +port map( + clock => clk6, + address => Display(7 downto 3) & L5_reg(2 downto 0) & phi2, + q => Vid(7 downto 4) + ); + +K6: entity work.k6_prom +port map( + clock => clk6, + address => Display(7 downto 3) & L5_reg(2 downto 0) & phi2, + q => Vid(3 downto 0) + ); + + +-- Some glue logic +J8_3 <= (H4 or L5_reg(3)); +J8_6 <= (H256 or H64 or H4); + + +-- Decoders +-- Making K8 synchronous fixes weird problem with ghost artifacts of motion objects +K8_in <= J8_3 & H32 & H16 & phi0; +K8: process(clk6, K8_in) +begin + if rising_edge(clk6) then + case K8_in is + when "0000" => + K8_out <= "1111111110"; + when "0001" => + K8_out <= "1111111101"; + when "0010" => + K8_out <= "1111111011"; + when "0011" => + K8_out <= "1111110111"; + when "0100" => + K8_out <= "1111101111"; + when "0101" => + K8_out <= "1111011111"; + when "0110" => + K8_out <= "1110111111"; + when "0111" => + K8_out <= "1101111111"; + when "1000" => + K8_out <= "1011111111"; + when "1001" => + K8_out <= "0111111111"; + when others => + K8_out <= "1111111111"; + end case; + end if; +end process; +LDV3B_n <= K8_out(7); +LDV3A_n <= K8_out(6); +LDV2B_n <= K8_out(5); +LDV2A_n <= K8_out(4); +LDV1B_n <= K8_out(3); +LDV1A_n <= K8_out(2); +LDV4B_n <= K8_out(1); +LDV4A_n <= K8_out(0); + +P7_in <= J8_6 & H32 & H16 & H8; +P7: process(P7_in) +begin + case P7_in is + when "0000" => + P7_out <= "1111111110"; + when "0001" => + P7_out <= "1111111101"; + when "0010" => + P7_out <= "1111111011"; + when "0011" => + P7_out <= "1111110111"; + when "0100" => + P7_out <= "1111101111"; + when "0101" => + P7_out <= "1111011111"; + when "0110" => + P7_out <= "1110111111"; + when "0111" => + P7_out <= "1101111111"; + when "1000" => + P7_out <= "1011111111"; + when "1001" => + P7_out <= "0111111111"; + when others => + P7_out <= "1111111111"; + end case; +end process; +Crash_n <= P7_out(7); +Motor2_n <= P7_out(6); +Motor1_n <= P7_out(5); +LDH4_n <= P7_out(4); +LDH3_n <= P7_out(3); +LDH2_n <= P7_out(2); +LDH1_n <= P7_out(1); + + +-- Car 1 Horizontal position counter +-- This combines two 74163s at locations R5 and R6 on the PCB +R5_6: process(clk6, H256_s, LDH1_n, Display) +begin + if rising_edge(clk6) then + if LDH1_n = '0' then -- preload the counter + Car1_Hpos <= Display; + elsif H256_s = '1' then -- increment the counter + Car1_Hpos <= Car1_Hpos + '1'; + end if; + if Car1_Hpos(7 downto 3) = "11111" then + Car1_Inh <= '0'; + else + Car1_Inh <= '1'; + end if; + end if; +end process; + +-- Car 1 video shift register +-- This combines two 74165s at locations M7 and N7 on the PCB +M_N7: process(clk12, Car1_Inh, LDV1A_n, LDV1B_n, Vid) +begin + if LDV1A_n = '0' then + Car1_reg(7 downto 0) <= Vid(7 downto 1) & '0'; -- Preload the LSB register + elsif LDV1B_n = '0' then + Car1_reg(15 downto 8) <= Vid(7 downto 0); -- Preload the MSB register + elsif rising_edge(clk12) then + if Car1_Inh = '0' then + Car1_reg <= '0' & Car1_reg(15 downto 1); + end if; + end if; +end process; +Car1 <= Car1_reg(0); +Car1_n <= not Car1_reg(0); + + +-- Car 2 Horizontal position counter +-- This combines two 74LS163s at locations P5 and P6 on the PCB +P5_6: process(clk6, H256_s, LDH2_n, Display) +begin + if rising_edge(clk6) then + if LDH2_n = '0' then -- preload the counter + Car2_Hpos <= Display; + elsif H256_s = '1' then -- increment the counter + Car2_Hpos <= Car2_Hpos + '1'; + end if; + if Car2_Hpos(7 downto 3) = "11111" then + Car2_Inh <= '0'; + else + Car2_Inh <= '1'; + end if; + end if; +end process; + +-- Car 2 video shift register +K_L7: process(clk12, Car2_Inh, LDV2A_n, LDV2B_n, Vid) +begin + if LDV2A_n = '0' then + Car2_reg(7 downto 0) <= Vid(7 downto 1) & '0'; -- Preload the LSB register + elsif LDV2B_n = '0' then + Car2_reg(15 downto 8) <= Vid(7 downto 0); -- Preload the MSB register + elsif rising_edge(clk12) then + if Car2_Inh = '0' then + Car2_reg <= '0' & Car2_reg(15 downto 1); + end if; + end if; +end process; +Car2 <= Car2_reg(0); +Car2_n <= not Car2_reg(0); + + +-- Car 3 Horizontal position counter +-- This combines two 74LS163s at locations N5 and N6 on the PCB +N5_6: process(clk6, H256_s, LDH3_n, Display) +begin + if rising_edge(clk6) then + if LDH3_n = '0' then -- preload the counter + Car3_Hpos <= Display; + elsif H256_s = '1' then -- increment the counter + Car3_Hpos <= Car3_Hpos + '1'; + end if; + if Car3_Hpos(7 downto 3) = "11111" then + Car3_Inh <= '0'; + else + Car3_Inh <= '1'; + end if; + end if; +end process; + +-- Car 3 video shift register +H_J7: process(clk12, Car3_Inh, LDV3A_n, LDV3B_n, Vid) +begin + if LDV3A_n = '0' then + Car3_reg(7 downto 0) <= Vid(7 downto 1) & '0'; -- Preload the LSB register + elsif LDV3B_n = '0' then + Car3_reg(15 downto 8) <= Vid(7 downto 0); -- Preload the MSB register + elsif rising_edge(clk12) then + if Car3_Inh = '0' then + Car3_reg <= '0' & Car3_reg(15 downto 1); + end if; + end if; +end process; + + +-- Car 4 Horizontal position counter +-- This combines two 74LS163s at locations M5 and M6 on the PCB +M5_6: process(clk6, H256_s, LDH4_n, Display) +begin + if rising_edge(clk6) then + if LDH4_n = '0' then -- preload the counter + Car4_Hpos <= Display; + elsif H256_s = '1' then -- increment the counter + Car4_Hpos <= Car4_Hpos + '1'; + end if; + if Car4_Hpos(7 downto 3) = "11111" then + Car4_Inh <= '0'; + else + Car4_Inh <= '1'; + end if; + end if; +end process; + +-- Car 4 video shift register +E_F7: process(clk12, Car4_Inh, LDV4A_n, LDV4B_n, Vid) +begin + if LDV4A_n = '0' then + Car4_reg(7 downto 0) <= Vid(7 downto 1) & '0'; -- Preload the LSB register + elsif LDV4B_n = '0' then + Car4_reg(15 downto 8) <= Vid(7 downto 0); -- Preload the MSB register + elsif rising_edge(clk12) then + if Car4_Inh = '0' then + Car4_reg <= '0' & Car4_reg(15 downto 1); + end if; + end if; +end process; +Car3_4_n <= not (Car3_reg(0) or Car4_reg(0)); + +end rtl; diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/osd.sv b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/osd.sv new file mode 100644 index 00000000..c62c10af --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/osd.sv @@ -0,0 +1,179 @@ +// A simple OSD implementation. Can be hooked up between a cores +// VGA output and the physical VGA pins + +module osd ( + // OSDs pixel clock, should be synchronous to cores pixel clock to + // avoid jitter. + input clk_sys, + + // SPI interface + input SPI_SCK, + input SPI_SS3, + input SPI_DI, + + // VGA signals coming from core + input [5:0] R_in, + input [5:0] G_in, + input [5:0] B_in, + input HSync, + input VSync, + + // VGA signals going to video connector + output [5:0] R_out, + output [5:0] G_out, + output [5:0] B_out +); + +parameter OSD_X_OFFSET = 10'd0; +parameter OSD_Y_OFFSET = 10'd0; +parameter OSD_COLOR = 3'd0; + +localparam OSD_WIDTH = 10'd256; +localparam OSD_HEIGHT = 10'd128; + +// ********************************************************************************* +// spi client +// ********************************************************************************* + +// this core supports only the display related OSD commands +// of the minimig +reg osd_enable; +(* ramstyle = "no_rw_check" *) reg [7:0] osd_buffer[2047:0]; // the OSD buffer itself + +// the OSD has its own SPI interface to the io controller +always@(posedge SPI_SCK, posedge SPI_SS3) begin + reg [4:0] cnt; + reg [10:0] bcnt; + reg [7:0] sbuf; + reg [7:0] cmd; + + if(SPI_SS3) begin + cnt <= 0; + bcnt <= 0; + end else begin + sbuf <= {sbuf[6:0], SPI_DI}; + + // 0:7 is command, rest payload + if(cnt < 15) cnt <= cnt + 1'd1; + else cnt <= 8; + + if(cnt == 7) begin + cmd <= {sbuf[6:0], SPI_DI}; + + // lower three command bits are line address + bcnt <= {sbuf[1:0], SPI_DI, 8'h00}; + + // command 0x40: OSDCMDENABLE, OSDCMDDISABLE + if(sbuf[6:3] == 4'b0100) osd_enable <= SPI_DI; + end + + // command 0x20: OSDCMDWRITE + if((cmd[7:3] == 5'b00100) && (cnt == 15)) begin + osd_buffer[bcnt] <= {sbuf[6:0], SPI_DI}; + bcnt <= bcnt + 1'd1; + end + end +end + +// ********************************************************************************* +// video timing and sync polarity anaylsis +// ********************************************************************************* + +// horizontal counter +reg [9:0] h_cnt; +reg [9:0] hs_low, hs_high; +wire hs_pol = hs_high < hs_low; +wire [9:0] dsp_width = hs_pol ? hs_low : hs_high; + +// vertical counter +reg [9:0] v_cnt; +reg [9:0] vs_low, vs_high; +wire vs_pol = vs_high < vs_low; +wire [9:0] dsp_height = vs_pol ? vs_low : vs_high; + +wire doublescan = (dsp_height>350); + +reg ce_pix; +always @(negedge clk_sys) begin + integer cnt = 0; + integer pixsz, pixcnt; + reg hs; + + cnt <= cnt + 1; + hs <= HSync; + + pixcnt <= pixcnt + 1; + if(pixcnt == pixsz) pixcnt <= 0; + ce_pix <= !pixcnt; + + if(hs && ~HSync) begin + cnt <= 0; + pixsz <= (cnt >> 9) - 1; + pixcnt <= 0; + ce_pix <= 1; + end +end + +always @(posedge clk_sys) begin + reg hsD, hsD2; + reg vsD, vsD2; + + if(ce_pix) begin + // bring hsync into local clock domain + hsD <= HSync; + hsD2 <= hsD; + + // falling edge of HSync + if(!hsD && hsD2) begin + h_cnt <= 0; + hs_high <= h_cnt; + end + + // rising edge of HSync + else if(hsD && !hsD2) begin + h_cnt <= 0; + hs_low <= h_cnt; + v_cnt <= v_cnt + 1'd1; + end else begin + h_cnt <= h_cnt + 1'd1; + end + + vsD <= VSync; + vsD2 <= vsD; + + // falling edge of VSync + if(!vsD && vsD2) begin + v_cnt <= 0; + vs_high <= v_cnt; + end + + // rising edge of VSync + else if(vsD && !vsD2) begin + v_cnt <= 0; + vs_low <= v_cnt; + end + end +end + +// area in which OSD is being displayed +wire [9:0] h_osd_start = ((dsp_width - OSD_WIDTH)>> 1) + OSD_X_OFFSET; +wire [9:0] h_osd_end = h_osd_start + OSD_WIDTH; +wire [9:0] v_osd_start = ((dsp_height- (OSD_HEIGHT<> 1) + OSD_Y_OFFSET; +wire [9:0] v_osd_end = v_osd_start + (OSD_HEIGHT<= h_osd_start) && (h_cnt < h_osd_end) && + (VSync != vs_pol) && (v_cnt >= v_osd_start) && (v_cnt < v_osd_end); + +reg [7:0] osd_byte; +always @(posedge clk_sys) if(ce_pix) osd_byte <= osd_buffer[{doublescan ? osd_vcnt[7:5] : osd_vcnt[6:4], osd_hcnt[7:0]}]; + +wire osd_pixel = osd_byte[doublescan ? osd_vcnt[4:2] : osd_vcnt[3:1]]; + +assign R_out = !osd_de ? R_in : {osd_pixel, osd_pixel, OSD_COLOR[2], R_in[5:3]}; +assign G_out = !osd_de ? G_in : {osd_pixel, osd_pixel, OSD_COLOR[1], G_in[5:3]}; +assign B_out = !osd_de ? B_in : {osd_pixel, osd_pixel, OSD_COLOR[0], B_in[5:3]}; + +endmodule diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/playfield.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/playfield.vhd new file mode 100644 index 00000000..86425cbc --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/playfield.vhd @@ -0,0 +1,148 @@ +-- Playfield generation circuitry for Sprint 2 by Kee Games +-- (c) 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity playfield is +port( + clk6 : in std_logic; + display : in std_logic_vector(7 downto 0); + HCount : in std_logic_vector(8 downto 0); + VCount : in std_logic_vector(7 downto 0); + H256_s : out std_logic; + HBlank : in std_logic; + VBlank : in std_logic; + VBlank_n_s : in std_logic; -- VBLANK* on the schematic + HSync : in std_logic; + VSync : in std_logic; + CompSync_n_s : out std_logic; -- COMP SYNC* on schematic + CompBlank_s : out std_logic; -- COMP BLANK* on schematic + WhitePF_n : out std_logic; + BlackPF_n : out std_logic + ); +end playfield; + +architecture rtl of playfield is + +signal H1 : std_logic; +signal H2 : std_logic; +signal H4 : std_logic; +signal H256 : std_logic; +signal H256_n : std_logic; + +signal V1 : std_logic; +signal V2 : std_logic; +signal V4 : std_logic; + +signal char_addr : std_logic_vector(8 downto 0) := (others => '0'); +signal char_data : std_logic_vector(7 downto 0) := (others => '0'); + +signal shift_data : std_logic_vector(7 downto 0) := (others => '0'); +signal QH : std_logic; + +signal R2_reg : std_logic_vector(3 downto 0) := (others => '0'); + + +-- These signals are based off the schematic and are formatted as Designator_PinNumber +signal R7_12 : std_logic; +signal P3_3 : std_logic; +signal P2_13 : std_logic; +signal P3_6 : std_logic; +signal A6_6 : std_logic; +signal A6_3 : std_logic; + +begin + +-- Video synchronization signals +H1 <= Hcount(0); +H2 <= Hcount(1); +H4 <= Hcount(2); +H256 <= Hcount(8); +H256_n <= not(Hcount(8)); + +V1 <= Vcount(0); +V2 <= Vcount(1); +V4 <= Vcount(2); + +-- Some glue logic, may be re-written later to be cleaner and easier to follow without referring to schematic +R7_12 <= not(H1 and H2 and H4); + +P3_3 <= (H256_n or R7_12); + +P2_13 <= (HSync nor VSync); + +P3_6 <= (HBlank or VBlank); + + + +char_addr <= display(5 downto 0) & V4 & V2 & V1; + +-- Background character ROMs +R4: entity work.Char_MSB +port map( + clock => clk6, + Address => char_addr, + q => char_data(3 downto 0) + ); + +P4: entity work.Char_LSB +port map( + clock => clk6, + Address => char_addr, + q => char_data(7 downto 4) + ); + + +-- 74LS166 video shift register +R3: process(clk6, P3_3, VBlank_n_s, char_data, shift_data) +begin + if VBlank_n_s = '0' then -- Connected Clear input + shift_data <= (others => '0'); + elsif rising_edge(clk6) then + if P3_3 = '0' then -- Parallel load + shift_data <= char_data(7 downto 0); + else + shift_data <= shift_data(6 downto 0) & '0'; + end if; + end if; + QH <= shift_data(7); +end process; + + +-- 9316 counter at R2 +-- CEP and CET tied to ground, counter is used only as a synchronous latch +R2: process(clk6, R7_12, display, H256, P2_13, P3_6) +begin + if rising_edge(clk6) then + if R7_12 = '0' then + R2_reg <= (H256 & display(7) & P3_6 & P2_13); + end if; + end if; +end process; + + +H256_s <= R2_reg(3); +CompBlank_s <= R2_reg(1); +CompSync_n_s <= R2_reg(0); +A6_6 <= (R2_reg(2) and QH); +A6_3 <= ((not R2_reg(2)) and QH); + +WhitePF_n <= (not A6_6); +BlackPF_n <= (not A6_3); + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/pll.v b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/pll.v new file mode 100644 index 00000000..6a352243 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/pll.v @@ -0,0 +1,337 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.4 Build 182 03/12/2014 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2014 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll ( + inclk0, + c0, + c1, + locked); + + input inclk0; + output c0; + output c1; + output locked; + + wire [4:0] sub_wire0; + wire sub_wire2; + wire [0:0] sub_wire6 = 1'h0; + wire [0:0] sub_wire3 = sub_wire0[0:0]; + wire [1:1] sub_wire1 = sub_wire0[1:1]; + wire c1 = sub_wire1; + wire locked = sub_wire2; + wire c0 = sub_wire3; + wire sub_wire4 = inclk0; + wire [1:0] sub_wire5 = {sub_wire6, sub_wire4}; + + altpll altpll_component ( + .inclk (sub_wire5), + .clk (sub_wire0), + .locked (sub_wire2), + .activeclock (), + .areset (1'b0), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "AUTO", + altpll_component.clk0_divide_by = 125, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 224, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 125, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 56, + altpll_component.clk1_phase_shift = "0", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 37037, + altpll_component.intended_device_family = "Cyclone III", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "NORMAL", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_UNUSED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_USED", + altpll_component.port_clk2 = "PORT_UNUSED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "125" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "125" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "48.383999" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "12.096000" +// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps" +// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "224" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "56" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "48.38400000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "12.09600000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: USE_CLK1 STRING "1" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "125" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "224" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "125" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "56" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/ram1k_dp.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/ram1k_dp.qip new file mode 100644 index 00000000..a2e1e6a2 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/ram1k_dp.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "ram1k_dp.vhd"] diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/ram1k_dp.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/ram1k_dp.vhd new file mode 100644 index 00000000..0907d677 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/ram1k_dp.vhd @@ -0,0 +1,224 @@ +-- megafunction wizard: %RAM: 2-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: ram1k_dp.vhd +-- Megafunction Name(s): +-- altsyncram +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.1.4 Build 182 03/12/2014 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2014 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files from any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.altera_mf_components.all; + +ENTITY ram1k_dp IS + PORT + ( + address_a : IN STD_LOGIC_VECTOR (9 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (9 DOWNTO 0); + clock : IN STD_LOGIC := '1'; + data_a : IN STD_LOGIC_VECTOR (7 DOWNTO 0); + data_b : IN STD_LOGIC_VECTOR (7 DOWNTO 0); + wren_a : IN STD_LOGIC := '0'; + wren_b : IN STD_LOGIC := '0'; + q_a : OUT STD_LOGIC_VECTOR (7 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) + ); +END ram1k_dp; + + +ARCHITECTURE SYN OF ram1k_dp IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0); + SIGNAL sub_wire1 : STD_LOGIC_VECTOR (7 DOWNTO 0); + +BEGIN + q_a <= sub_wire0(7 DOWNTO 0); + q_b <= sub_wire1(7 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_reg_b => "CLOCK0", + clock_enable_input_a => "BYPASS", + clock_enable_input_b => "BYPASS", + clock_enable_output_a => "BYPASS", + clock_enable_output_b => "BYPASS", + indata_reg_b => "CLOCK0", + intended_device_family => "Cyclone III", + lpm_type => "altsyncram", + numwords_a => 1024, + numwords_b => 1024, + operation_mode => "BIDIR_DUAL_PORT", + outdata_aclr_a => "NONE", + outdata_aclr_b => "NONE", + outdata_reg_a => "CLOCK0", + outdata_reg_b => "CLOCK0", + power_up_uninitialized => "FALSE", + read_during_write_mode_mixed_ports => "DONT_CARE", + read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", + read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ", + widthad_a => 10, + widthad_b => 10, + width_a => 8, + width_b => 8, + width_byteena_a => 1, + width_byteena_b => 1, + wrcontrol_wraddress_reg_b => "CLOCK0" + ) + PORT MAP ( + clock0 => clock, + wren_a => wren_a, + address_b => address_b, + data_b => data_b, + wren_b => wren_b, + address_a => address_a, + data_a => data_a, + q_a => sub_wire0, + q_b => sub_wire1 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0" +-- Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0" +-- Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "1" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0" +-- Retrieval info: PRIVATE: CLRdata NUMERIC "0" +-- Retrieval info: PRIVATE: CLRq NUMERIC "0" +-- Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0" +-- Retrieval info: PRIVATE: CLRrren NUMERIC "0" +-- Retrieval info: PRIVATE: CLRwraddress NUMERIC "0" +-- Retrieval info: PRIVATE: CLRwren NUMERIC "0" +-- Retrieval info: PRIVATE: Clock NUMERIC "0" +-- Retrieval info: PRIVATE: Clock_A NUMERIC "0" +-- Retrieval info: PRIVATE: Clock_B NUMERIC "0" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0" +-- Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "1" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MEMSIZE NUMERIC "8192" +-- Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0" +-- Retrieval info: PRIVATE: MIFfilename STRING "../roms/033455e1.hex" +-- Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "3" +-- Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0" +-- Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "1" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +-- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2" +-- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" +-- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3" +-- Retrieval info: PRIVATE: REGdata NUMERIC "1" +-- Retrieval info: PRIVATE: REGq NUMERIC "1" +-- Retrieval info: PRIVATE: REGrdaddress NUMERIC "0" +-- Retrieval info: PRIVATE: REGrren NUMERIC "0" +-- Retrieval info: PRIVATE: REGwraddress NUMERIC "1" +-- Retrieval info: PRIVATE: REGwren NUMERIC "1" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0" +-- Retrieval info: PRIVATE: UseDPRAM NUMERIC "1" +-- Retrieval info: PRIVATE: VarWidth NUMERIC "0" +-- Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "8" +-- Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "8" +-- Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "8" +-- Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "8" +-- Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0" +-- Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "1" +-- Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0" +-- Retrieval info: PRIVATE: enable NUMERIC "0" +-- Retrieval info: PRIVATE: rden NUMERIC "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK0" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "BYPASS" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS" +-- Retrieval info: CONSTANT: INDATA_REG_B STRING "CLOCK0" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "1024" +-- Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "1024" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "BIDIR_DUAL_PORT" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +-- Retrieval info: CONSTANT: OUTDATA_REG_B STRING "CLOCK0" +-- Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" +-- Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_MIXED_PORTS STRING "DONT_CARE" +-- Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ" +-- Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_B STRING "NEW_DATA_NO_NBE_READ" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "10" +-- Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "10" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +-- Retrieval info: CONSTANT: WIDTH_B NUMERIC "8" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_B NUMERIC "1" +-- Retrieval info: CONSTANT: WRCONTROL_WRADDRESS_REG_B STRING "CLOCK0" +-- Retrieval info: USED_PORT: address_a 0 0 10 0 INPUT NODEFVAL "address_a[9..0]" +-- Retrieval info: USED_PORT: address_b 0 0 10 0 INPUT NODEFVAL "address_b[9..0]" +-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +-- Retrieval info: USED_PORT: data_a 0 0 8 0 INPUT NODEFVAL "data_a[7..0]" +-- Retrieval info: USED_PORT: data_b 0 0 8 0 INPUT NODEFVAL "data_b[7..0]" +-- Retrieval info: USED_PORT: q_a 0 0 8 0 OUTPUT NODEFVAL "q_a[7..0]" +-- Retrieval info: USED_PORT: q_b 0 0 8 0 OUTPUT NODEFVAL "q_b[7..0]" +-- Retrieval info: USED_PORT: wren_a 0 0 0 0 INPUT GND "wren_a" +-- Retrieval info: USED_PORT: wren_b 0 0 0 0 INPUT GND "wren_b" +-- Retrieval info: CONNECT: @address_a 0 0 10 0 address_a 0 0 10 0 +-- Retrieval info: CONNECT: @address_b 0 0 10 0 address_b 0 0 10 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +-- Retrieval info: CONNECT: @data_a 0 0 8 0 data_a 0 0 8 0 +-- Retrieval info: CONNECT: @data_b 0 0 8 0 data_b 0 0 8 0 +-- Retrieval info: CONNECT: @wren_a 0 0 0 0 wren_a 0 0 0 0 +-- Retrieval info: CONNECT: @wren_b 0 0 0 0 wren_b 0 0 0 0 +-- Retrieval info: CONNECT: q_a 0 0 8 0 @q_a 0 0 8 0 +-- Retrieval info: CONNECT: q_b 0 0 8 0 @q_b 0 0 8 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL ram1k_dp.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL ram1k_dp.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL ram1k_dp.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL ram1k_dp.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL ram1k_dp_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6290-01b1.hex b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6290-01b1.hex new file mode 100644 index 00000000..e99c247b --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6290-01b1.hex @@ -0,0 +1,129 @@ +:100000000620262120053FCCCCCCCCCC9344555F98 +:10001000CCCCCCCCCC95FB2223334444D94555FBE6 +:100020002222233444D9A222223444444E655FB2B2 +:1000300012222234444EA221122244444E65FB1166 +:1000400012222224544EA223222243344E6FB11195 +:1000500022222123434EA230018344334EFB11114F +:100060001111F833444EA1000E0A34444DB1111160 +:10007000111FB2A4444EA0000E6A33333311122173 +:1000800011FB12A4444EA0000E6A33233111222129 +:100090001FB112A4444EA0000E6A22221122211187 +:1000A000FB1112A4544EA0000D9D91111221111F9D +:1000B000B1111FB5544EA07007DCCCCCCCCCCCCC4D +:1000C000CCCCCB55544EA0007666666666666666F6 +:1000D00065566666644EA001666666667766666605 +:1000E00066666666655EA0007666666666667766C4 +:1000F00066666666655EA0007766666665566666D5 +:1001000066666666666ED9000776666666666666C9 +:100110006666776666FB1D888888888888888888F0 +:100120008888888888B72C214C2260043FCCCCCCAE +:10013000C9223333333223FCCCCCCC95FB3333444C +:100140004D92233333333FB3333444D9A223333472 +:1001500044E3FCCCCCC92A233334444EA2223333AB +:1001600044EFB333444D9A223334444EA222233316 +:1001700044EB23334444DA222334444EA222223374 +:1001800034E2223344445A121234444EA1111E2345 +:100190003331222334445A1217A4444EA1110E22A3 +:1001A0002311111134455A1107A4444EA1100E22F7 +:1001B00022111110A4455A1007A4444EA2000E9219 +:1001C0002111110FB3455A0007A4444EA0000ED9C7 +:1001D000111110FB3335FB0007A4444EA0000E7D27 +:1001E000888888A33333B10007A4444EA0000E775B +:1001F000666666A22222110007A4444EA0000E7774 +:10020000666666A2222211000FA4444EA0000E775B +:10021000666666A222211100FBA4444EA0000E7760 +:10022000666666D92211110FB5A4444EA0000D9741 +:100230006666666D8888888B5FB5444EA00007DCD3 +:10024000CCCCCCCCCCCCCCCCCB55444E5222722393 +:1002500060043FCCCCCCCCCC9543FCCCCCCCCCCC2F +:10026000CC95FB2223333444D93FB222233333339A +:1002700044D9A222223334444D8B222222333333F9 +:10028000444EA2222223344444E222222223333445 +:10029000444EA2222222344444E222222122334428 +:1002A000444EA11111FC944444E1111110FC9344FB +:1002B000444EA11110D9A44444E1111100A1D94424 +:1002C000444EA111077DA44445E1111070D92A4480 +:1002D000444EA11F9777A44455E11100777D9A44BD +:1002E000444EA10AE007A34455E910000077DA4420 +:1002F000444EA00DB107A33445ED900000777A4439 +:10030000444EA077100FB33444A2A00007077A44EC +:10031000444EA00711FB333333CC110800007A445C +:10032000444EA07710E22222222110E0A0007A445D +:10033000445EA00010E222222211001C10007A4428 +:10034000455EA07710D92222222222211000FB54E0 +:10035000454EA000107D911111111111100FB554CF +:10036000544EA0777077DCCCCCCCCCCCCCCB5554D5 +:10037000544E7823982460044FCCCCCCCCCCCCCC3D +:10038000CCCCCCCCCCCCCC95FB222222222222225B +:1003900022222222333344D9A222221221221233D2 +:1003A000333228222333444EA22222222222222325 +:1003B0003333D8B22233444EA222222222222222D6 +:1003C000233322222223445EA11111FCCCCCCCCCBD +:1003D000C92222111FC9455EA1111FB444455555BC +:1003E0006D911111FBFB555EA1110E34444555561C +:1003F00066DCCCCCCCB5555EA1100E3344455566B9 +:10040000666666666666666EA1000E33344556669D +:10041000666666666666666EA0000E33334589774B +:10042000766666666666666EA0000E33333E3D975E +:1004300077666667777777FBA0000E22233DCCCCEA +:10044000CCCCCCCCCCCCCCA5A0000E22222222221B +:1004500022222223334444D9A0000E222222222227 +:10046000222222223344455EA0000D922222222223 +:10047000222222222344555EA00007D91111111116 +:10048000111111222245555EA000077DCCCCCCCCA9 +:10049000CCCCCCCCCC55555E9E24BE2560043FCC44 +:1004A000CCCCCCCCCCCCCCCCCCCCCCCCCC95FB223E +:1004B00022222222233222222223333444D9A2228E +:1004C000222122222223222222223334444EA2221B +:1004D000211222222222232222222334445EA2221B +:1004E000222222222222222211222234455EA1111E +:1004F0001F8888888888888888888844555EA111E4 +:1005000007665555555D9111FB555555555EA11022 +:10051000077666666666D91FB5555566666EA10094 +:100520000777666666666EFB44555666666ED9004A +:100530000777766777666EB344456666666E1D908C +:10054000077777777776FB3334466666666E3FCCFF +:10055000CCCCC007777FB33333488888888BFB22A5 +:100560002222211077FB22222223333444D9A222D3 +:10057000222211100FA2222222223334444EA22220 +:1005800022111100FBA2222222222334445EA22245 +:100590002111100FB5D9222222222234455EA11149 +:1005A000111100FB555D911111111124555EA1111E +:1005B00011DCCCCCCCCCCCCCCCCCCCB5555EC425D1 +:1005C000E42660043FCCCCCC953FCCCCCCCCCCCC7E +:1005D000CCCCCC95FB333444D9FB222222222223DB +:1005E000333444D9A22334444DA22222222222228F +:1005F0003334444EA222334445A222222222222214 +:100600002334444EA222234445A111111F88888817 +:100610009334444EA111E34445A11111FB555555A6 +:10062000D934444EA110E34445A1111FB555556678 +:100630006D94444EA100E34445A1100E55555566F6 +:1006400066A4444EA000E33445A100075555566604 +:1006500066A4444EA000E33345A0000766665A77BF +:1006600077A4444EA000E33334A000077666FB076E +:1006700077A4444EA000E33333D90077776FB100FD +:1006800077A4444EA000E333333DCCCCCCCB110057 +:1006900007A4444EA000E22222222222222111009D +:1006A00000A4444EA000E2222222222222111100A4 +:1006B00000A4444EA000D92222222222211111009E +:1006C0000FB5444EA0007D911111111111111100AF +:1006D000FB55444EA00077DCCCCCCCCCCCCCCCCCE5 +:1006E000B555444EEA260A2860043FCCCCCCCCCC8D +:1006F000CCCCCCCCCCCCCCCCCC95FB4445555666A4 +:10070000666666666666666666D9A444455566662C +:100710006666666666666666666EA4444555666687 +:100720006666666666666666666EA344445F88882B +:100730008888888888888897777EA333444D9FB3BC +:1007400033333333333D9FB0777ED9333444DB22A8 +:10075000222223333333DB10077E1D93334442229E +:100760002222223332222110007E11D93334122268 +:100770002222222222221110000E111D9333111168 +:100780001F88888922211110000E0001E113133304 +:100790003A11111D9211111000FB000FB1133333E8 +:1007A0003D933333D888888888B700FB11103333E2 +:1007B00033DCCCCCCCCCCCCCCC950FB111072222E5 +:1007C000222222222222333444D9FB111007F9229B +:1007D0002222222222222334444EA111100FBD9244 +:1007E0002222222222222234444EA11000FB55D97B +:1007F0001111111111112224444EA100007CCCCC06 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6291-01c1.hex b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6291-01c1.hex new file mode 100644 index 00000000..e362de36 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6291-01c1.hex @@ -0,0 +1,129 @@ +:10000000CCCCCCCCCCCCCCB4444E10283029600421 +:100010003FCCCCCCCCC953FCCCCCCCCCCCCCCC9530 +:10002000FB233334444D9FB222222223334444D94C +:10003000A22233344444EB22222222223344445E5F +:10004000A22223344444E222222222222344455E77 +:10005000A22222344444E222222221111244555E7B +:10006000A11110A44444E111111F88888845555EF0 +:10007000A11107A44444E111100A11FB4455556E27 +:10008000A11007A44444E111000D9FB44455566EDD +:10009000A10007A34444E1100077EB344455666E99 +:1000A000A00007A33444E9100777E333445666FB06 +:1000B000A00007A33344ED900777E33334666FB7AE +:1000C000A00007A33333D8B00077E333333CCC959B +:1000D000A00007A2222222100007E233334444D9B1 +:1000E000A00007A2222221100000E2233344444E44 +:1000F000A00007A2222211100000E9222344444E4E +:10010000A00007A222211110000FBD922244444EEC +:10011000A00007D91111111000FB55D92245444EFA +:10012000A000077DCCCCCCCCCCCCCCCCCC55444E98 +:100130003629562A60043FCCCCCCCCCCCCCCCCCC11 +:1001400093FCCCCCCC95FB222222222223333444B4 +:10015000D8B2333444D9A222222222222223344587 +:100160005A222334444EA222222222222222345511 +:100170005A222234444EA11111F888888888855566 +:100180005A1111F4444EA1111FB4444555566666E8 +:100190006A1110E4444EA111FB444455566666664C +:1001A0006A1100E4444EA110E34444556666666655 +:1001B000FA1000E4444EA110E34444566666777F8B +:1001C000BA0000E4444EA000E344445FCCCCCCCC65 +:1001D0009A0000E4444EA000E33444FB233333444C +:1001E000DA0000E4444EA000E33344E22233333427 +:1001F0004A0000E4444EA000E33334E222233333C8 +:100200004A0000E4444EA000E2222221111F3222C3 +:10021000210000E4444EA000E2222211110E22220D +:10022000110000E4444EA000D9222111100E9221A9 +:10023000110000E4444EA0007D91111100FBD91182 +:1002400011000FB5444EA00077DCCCCCCCCCCCCC8C +:10025000CCCCCB55444E5C2A7C2B60043FCCCCCC20 +:10026000CCCCCC9543FCCCCCCCCCCC95FB444555EC +:10027000666666D94FB22223333444D9A444455626 +:100280006666666E4A2222223334444EA344456693 +:100290006666666E4A2222222334444EA3344F8877 +:1002A0008897777E4A11111FC933444EA3334A33CE +:1002B00077E0777E4A11110D9D93444EA3333DCCD8 +:1002C000CCC0077DCC911007D9A4444EA33333335F +:1002D0003333002334D910077DA4444EA2222223B5 +:1002E00023220122344D900777A4444ED9222222A2 +:1002F000222202223444D90077A4444E3E888888C2 +:100300008881077F93445A0077A4444EFB33333DE2 +:1003100093E0077EE3345A0007A4444EA22233330D +:10032000D8B0077EB3334A0007A4444EA22222224B +:100330002210077E3333310007A4444EA22222222A +:100340002110077E2222211007A4444EA1111892E9 +:100350001110077E222211100FB5444EA111E1D9D0 +:10036000111007FC91111110FB55444EA1107CCCCB +:10037000CCCCCCCCCCCCCCCCB555444E822BA22C06 +:1003800060043FCCCCCCCCCCCCCCCCCC953FCCCC32 +:10039000CC95FB222222222233333444D9FB33343E +:1003A00044D9A22222222222233334444EB22334BF +:1003B000444EA22222222222223334444E222234CC +:1003C000444EA11108888888889334444E22222400 +:1003D000444EA1100665555555D934444E2211E4BA +:1003E000444EA11007665555555D94444E2110E4C6 +:1003F000444EA100077666666666E3444E1100E44B +:10040000444ED900077766666666E3444E1000E402 +:10041000444E1D88888889777777E3444E0000E44E +:10042000444E3FB333344D977777E3344E0000E4C6 +:10043000444EFB22223344E00777E3334E0000E4CE +:10044000444EA222222334E00077E3333D0000E44F +:10045000444EA222223333210007E222210000E48D +:10046000444EA1110A2222110000E222110000E4F0 +:10047000444EA1100A222111000FC92111000FB50D +:10048000444EA1000D91111100FB4D911100FB553F +:10049000444EA00007DCCCCCCCCCCCCCCCCCB555DD +:1004A000444EA82CC82D6004333FCCCCCCCCC953CF +:1004B000FCCCCCCCCCCCCC9533FB333334445D9FDB +:1004C000B2222222233344D93FB22233344455DAB4 +:1004D000222222222233445EFB2222233445555A13 +:1004E000222222222223455EA111111F4445555A82 +:1004F000111118888884555EA11111FB444555FBE4 +:100500001110EFB55556666EA1111FB444455FB189 +:100510001100EB555566666EA1110E344445FB1172 +:10052000110FB455556666FBA1100E34444FB1113E +:1005300010FB44555F8888A5A1000E33444E11116D +:100540000FB44445FB3344D9A0000E33344E111090 +:100550007A34445FB333444EA0000E33334E11005F +:100560007A3344FB2333444EA0000E333332100061 +:100570007A3334B22233444EA0000E2222211000DE +:100580007A2222222223444EA0000E2222111000A1 +:10059000FA22221111F3444EA0000D922111000FF6 +:1005A000BD9221111FBA444EA00007D9111100FBC2 +:1005B00055D91111FBFB544EA000077DCCCCCCCCFF +:1005C000CCCCCCCCCCB5544E0093E22DEC2DF62DFA +:1005D000002E0A2E142E1E2E282E322E3C2E462E93 +:1005E000502E5A2E5E2E622E662E6A2E5A2E6E2E99 +:1005F000722EA22E6A2E5A2E762E7A2ED22E6A2E87 +:100600005A2E7A2E7E2E822E6A2E862E8A2E8E2E9E +:10061000922E6A2E962E9A2E9E2EA22E6A2E5A2E3A +:10062000A62EAA2EAE2E6A2E5A2EB22EB62EBA2E76 +:100630006A2E962EBE2EC22EA22E6A2E962E9A2E8E +:10064000C62EA22E6A2E962E9A2EC62EA22E6A2E66 +:10065000962ECA2ECE2ED22E6A2E6F6E6D6C7C7B9D +:100660007A79838393A360606162273747578A9AB8 +:10067000AABA5565758598999A9BA4B4C4D48999EA +:10068000A9B9545464745B6B7B8BBCBCCCDCB3B336 +:10069000C3D3536373836F6E6D6DBDBDCDDD959513 +:1006A000A5B5A0A0A1A28393A3B3BFBEBDBC535365 +:1006B0006373BFBEBDBC85868788B0B1B2B3B5B524 +:1006C000B6B77576777855556575A9AAABACB2B251 +:1006D000C2D260616263D205EA06FB05EA067205D2 +:1006E000EA064E06EA06C904EA060706EA064F05C8 +:1006F000EA06EA06EA06EA06EA06EA06EA06EA067A +:10070000EA06EA06EA0600FEFCFAF8F7F6F5F5F561 +:10071000F6F7F8FAFCFE0002040608090A0B0B0BB8 +:100720000A09080604020B0B0A090806040200FE67 +:10073000FCFAF8F7F6F5F5F5F6F7F8FAFCFE000224 +:10074000040608090A0B0000FFFFEFFFDFFFCFFFE1 +:10075000BEFFAEFF9EFF9EFF9DEF9DEF9DEF9DEFC5 +:100760009CEF9CEF9CEF9CEF9BDE9BDE9BDE9BDE79 +:100770009ADE9ADE9ADE9ADE99CE99CE99CE99CEFD +:1007800099CE99CE99CE71117111611162115311E7 +:100790003411252105210521F421F331F231E13114 +:1007A000E041E041D041DF32DF32CF22CF12CF0231 +:1007B000BE03BE03BEF3AEF3AEF3ADF39DF29DE216 +:1007C0009DE29CE19CE000000000000000000000B1 +:1007D0000000000000000000000000000000000019 +:1007E0000000000000000000000000000000000009 +:1007F00000000000000000000000000000000000F9 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6396-01p4.hex b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6396-01p4.hex new file mode 100644 index 00000000..28243917 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6396-01p4.hex @@ -0,0 +1,33 @@ +:1000000000000000000000000003060C0C0F0C0CA8 +:10001000000F0C0C0F0C0C0F0003060C0C0C06034D +:10002000000F0C0C0C0C0C0F000F0C0C0F0C0C0F19 +:10003000000F0C0C0F0C0C0C0003060C0C0C060330 +:10004000000C0C0C0F0C0C0C000F03030303030F2C +:100050000000000000000C07000C0C0D0F0F0D0C31 +:10006000000C0C0C0C0C0C0F000C0E0F0F0D0C0CDC +:10007000000C0E0F0F0D0C0C00070C0C0C0C0C07D9 +:10008000000F0C0C0C0F0C0C00070C0C0C0D0C07CB +:10009000000F0C0C0C0F0D0C00070C0C07000C07CC +:1000A000000F030303030303000C0C0C0C0C0C07E0 +:1000B000000C0C0C0E070301000C0C0D0F0F0E0CA6 +:1000C000000C0E0703070E0C000C0C0C07030303B7 +:1000D000000F000103070E0F0000000000000000E9 +:1000E0000000000000000000000000000000000010 +:1000F0000000000000000000000000000000000000 +:1001000000000000000000000000000000000000EF +:1001100000000000000000000000000000000000DF +:1001200000000000000000000000000000000000CF +:1001300000000000000000000000000000000000BF +:100140000000000000060600000000000006060097 +:10015000000606000006060000060600000000007B +:100160000006060000000000000000000000000083 +:10017000000000000000000000000000000000007F +:100180000003040C0C0C0603000307030303030F16 +:1001900000070C0003070E0F0007000103000C0707 +:1001A000000103060C0F0000000F0C0F00000C07ED +:1001B0000003060C0F0C0C07000F0C0001030303D7 +:1001C00000070C0E0709080700070C0C07000007C2 +:1001D000000000000000000000000000000000001F +:1001E000000000000000030700080C0C0E0F0F05B4 +:1001F0000F0F0703010000000505040F0F0B01009E +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6397-01r4.hex b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6397-01r4.hex new file mode 100644 index 00000000..72e395fe --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6397-01r4.hex @@ -0,0 +1,33 @@ +:10000000000000000000000000080C06060E0606B6 +:10001000000C06060C06060C000C06000000060C80 +:1000200000080C0606060C08000C00000800000E74 +:10003000000E00000C000000000E00000E06060E70 +:10004000000606060E060606000C00000000000C66 +:10005000000606060606060C00060C0800080C0E34 +:10006000000000000000000C00060E0E0E06060642 +:10007000000606060E0E0E06000C06060606060C08 +:10008000000C0606060C0000000C0606060E0C0A04 +:10009000000C06060E080C0E00080C000C06060CE0 +:1000A000000C000000000000000606060606060C14 +:1000B000000606060E0C0800000606060E0E0E06CA +:1000C00000060E0C080C0E06000C0C0C08000000BC +:1000D000000E0E0C0800000E0000000000000000E2 +:1000E0000000000000000000000000000000000010 +:1000F0000000000000000000000000000000000000 +:1001000000000000000000000000000000000000EF +:1001100000000000000000000000000000000000DF +:1001200000000000000000000000000000000000CF +:1001300000000000000000000000000000000000BF +:1001400000000000000606000000000000000000A3 +:10015000000000000000000000000000000000009F +:100160000006060000000000000606000000000077 +:10017000000606000006060000000000000606005B +:1001800000080C0606060408000000000000000C31 +:10019000000C060E0C08000E000E0C080C06060CD7 +:1001A000000C0C0C0C0E0C0C000C000C0606060CC3 +:1001B000000C00000C06060C000E060C08000000E7 +:1001C00000080404080E060C000C06060E060C08B7 +:1001D000000000000000000000000000000000001F +:1001E0000001070F0F0F0F01000000000C0E0F0F92 +:1001F0000505010F0F0F0F060E06040E0E0C08006A +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6398-01k6.hex b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6398-01k6.hex new file mode 100644 index 00000000..391da240 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6398-01k6.hex @@ -0,0 +1,33 @@ +:10000000000100030E0B0E0B00030E0B0E0B000085 +:10001000000700070E070E03000307090709000089 +:10002000000E000F0C070E0700030F030709000C5A +:10003000000C080F000F0E07070300010008000C5A +:100040000000000C0E0F070F00070801000C000E47 +:10005000000100000F0E030F08070C00080E000738 +:1000600000070E030F0C000F0E070C000009000024 +:100070000E070E070C030C0F080F000C080E080EDD +:100080000C0E0C0E080C0C0F0C0F080C0C0E0C0EAA +:10009000080E080E000C080F0C0F0C030E070E07BD +:1000A000000000090C000E07000F0F0C0E030007E4 +:1000B0000007080E0C000807030F0F0E00000001D8 +:1000C000000E000C08010007070F0E0F000C0000C7 +:1000D000000C0008000107030E07000F080F000CBA +:1000E000000C07090F0300030E070C07000F000E9A +:1000F00000000709070900030E030E0700070007A9 +:1001000000000E0B0E0B00030E0B0E0B0003000184 +:1001100000000C070C0700030E030E010001000095 +:1001200008000C0700070E03070300090000000089 +:1001300008000C07000F0E0707030001080C080E4B +:100140000000080E000F070F030308000E0E0F0734 +:100150000001000C0E0F030F08030E000F0E00032A +:10016000000F0E070F0E000F0C070F00000B000111 +:10017000080E080E000C0C0F0F0F000000090009FC +:10018000080C080C00080F0F0F0F0008080C080CD3 +:100190000009000900000F0F0C0F000C080E080EDC +:1001A000000100090F000C07000F0F0E0E07000FD3 +:1001B00000030F0E0E000803030F0E0F000C0001CA +:1001C0000F070E0E08000303070F000F080E0000B4 +:1001D000080E080C000103030E07000F0C070800AF +:1001E00000000000000907030E0300070C070800C9 +:1001F000000000010E010E0300030C070C070000B5 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6399-01j6.hex b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6399-01j6.hex new file mode 100644 index 00000000..74a9d0b9 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6399-01j6.hex @@ -0,0 +1,33 @@ +:1000000008000C000D070D070C000D070D07000080 +:100010000000080008070C070C000E030E03000088 +:100020000000000009000C0E0C070E000E0300017A +:100030000701030108000C0E0E070F000E0300015C +:100040000E0F070700010C0C0F0E0F000701000038 +:100050000C00070F00070C010F0C0F07030008002E +:1000600008000D00000F0E030F00070F0E070F0012 +:100070000900090000000F0F0F030300070107012B +:100080000301030101000F0F0F0F01000301030122 +:100090000701070103000F030F0F0000090009000B +:1000A0000F000E07070F0F000E03000F0D000800D2 +:1000B000080003000F070F0C0C010007070F0C00CE +:1000C000000007010F000F0E0C0C000107070E0FB8 +:1000D00000010E030F000E070C0E080003010701BC +:1000E00000010E030E000C070C0E090000000000BA +:1000F00000000E030E030C000C07080708000000A8 +:1001000000000D070D070C000D070D070C0008007F +:100110000000090E090E0C000C070E070E000E0061 +:100120000300090E0C0F0C000E070E030F000F004A +:100130000300010008000C0E0E070F000F01030062 +:100140000700030008010E000F0E0F070300000058 +:100150000E00070100030E010F0C070F000008003E +:100160000000090000030E070F00030F0C070E002C +:100170000701070103000F010F030C030E070E0711 +:100180000703070303010F030F030301070307031B +:100190000E070E070C030F030F01030007010701F1 +:1001A0000E000C07030F0F000E07000309000000EC +:1001B00008000000070F0F0C0E01000307010E00DE +:1001C000000003000F070F0E0E00080103000700D8 +:1001D00003000F010F000F070C0E080001000300C1 +:1001E00007000F000E030E070C000C0F090E030092 +:1001F0000E000E000E070C070C00090E090E000081 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6400-01m2.hex b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6400-01m2.hex new file mode 100644 index 00000000..9dbfacea --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6400-01m2.hex @@ -0,0 +1,17 @@ +:1000000000000000000000000000000000000000F0 +:1000100000000000000000000000000000000000E0 +:1000200000000000000000000000000000000000D0 +:1000300000000000000000000000000000000000C0 +:1000400000000000000000000000000000000000B0 +:1000500000000000000000000000000000000000A0 +:100060000000000000000000000000000000000090 +:100070000000000000000000000000000000000878 +:100080000A0A0A0A0A0E0000000000000000000030 +:100090000000000000000000000000000000000060 +:1000A0000000000000000000000000000000000050 +:1000B0000000000000000000000000000000000040 +:1000C0000000000000000000000000000000000030 +:1000D0000000000000000000000000000000000020 +:1000E0000808080808080808080808080808080A8E +:1000F0000A0A0B0B0B0A0A0A0A0A0A0A0A0A0A0A5D +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6401-01e2.hex b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6401-01e2.hex new file mode 100644 index 00000000..975d72ea --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6401-01e2.hex @@ -0,0 +1,3 @@ +:100000001111010141418181C1C12121E1E1E1E100 +:10001000E0E0E8E8E4E4ECECE2E2EAEAE6E6EEEE70 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6404d1.hex b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6404d1.hex new file mode 100644 index 00000000..aa71f3fd --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6404d1.hex @@ -0,0 +1,129 @@ +:10000000488A48D8A530D0038D000F2C2A0810202C +:10001000A561C992D01EA560C93FD018BABD05011F +:10002000C920B00CC9409008C9109010C918B00C74 +:1000300068AA6840A9928561A93F856078D8A27FA7 +:100040009AAD0018C9AAF0034C4E30200018A20047 +:10005000205238A210205238A22820523820FA36D6 +:100060002069302007314C6030A90085358D010CA6 +:1000700020683820323620B137A900A65120253813 +:10008000A920A2009D2E04E8E004D0F8A226A90130 +:10009000202538A20AA900202538A535D007A900B7 +:1000A000A218202538E630A530D017E635A535C989 +:1000B0000CD007A90085354C70302C300850032037 +:1000C00068382C2A0830034C623B204D3BA20020AC +:1000D000E734E8E004D0F8A9008D16008D14008DF7 +:1000E00015008D100C8D200C2C000C50FB8D800CFD +:1000F00020B137A536D004A520F0AA20AB39A5360B +:10010000D004A520F09F60EAA9008535206838A2B8 +:1001100010205238A900A651202538A900852A2090 +:100120003236204D3BA551C904D00A20B1378D800D +:100130000CA520F0F68D310CA9008520A20E2025FB +:1001400038A900A20C202538A551C906D0038D413D +:100150000C20E2398D800CA551C906D0112C2D0838 +:10016000101E2C2C0830EA8D400CA901101720B16C +:1001700037A520F0ED8D300C8D410C2C2D0830D1A1 +:100180008D300CA902855CA20E205238A53AC940D8 +:10019000F015A900A214202538A53AC930F0038D26 +:1001A0007407A53B8D7507A2042052388D000C20E2 +:1001B0006838204D3BE630A200206E37E8E45CD082 +:1001C000F8A65C20E734E8E004D0F8A55CC901D0CB +:1001D00005A20120A83A8D100C8D200CA200A900C8 +:1001E0008522A9101002A9148523A000B12230098C +:1001F000B53DF005D63D4C1C32B1223009A9009521 +:100200003D95544C1C32A9009533B554D00AA55CD9 +:1002100095009554A90F8516A910953DA516F00ACD +:10022000A5304A90054A9002C616B533F02BE0007F +:10023000F0058D210CD0038D110CD6338A0AA8A9A4 +:1002400002E000F0062CC0084C4E322C80087002F0 +:10025000A9FE18791900991900A000B1222A1004EA +:10026000A9209533E000F0058D800DD0038D000DA1 +:10027000A5304A90234A9020200D378524C9F910D3 +:100280000CE000F0058D210CD0038D110CA5241875 +:100290007500D002A9019500B5004A4A4A8522B4EA +:1002A0005AB55A0A8524B9E43DA8A90018652288E0 +:1002B000D0FA4A4A4A38E5241002A900C91030028F +:1002C000A90F95148A0AA8206E37B50049FF4A4A3B +:1002D0004A4A4A4A29061869038522B9190029F8A9 +:1002E0008524B50429F838E524F033301AC91030D4 +:1002F0000CE000F0058D210CD0038D110CA9003805 +:10030000E52285224C1733C9F8100CE000F0058D6A +:10031000210CD0038D110CA52218750495042072B0 +:100320003520A83A862AA531F01CA5302920F00FE7 +:10033000A9209D2904E8E00DD0F8A62A4C4633A256 +:1003400012A900202538A62AE000D007AD5B0429B9 +:100350003F1003AD4204C53A3022E000D007AD5C47 +:1003600004293F1009A55CC901F011AD4304C53B48 +:10037000300AA531D006A532D002E632E000D039ED +:10038000C63CD035A550D014E650A9208D4E04A906 +:10039000398D4F04A93A8D50044CB233AD5004C985 +:1003A00030D00FAD4F04C930F012CE4F04A93A8DB2 +:1003B0005004CE5004A53F853C4CD134A532F01DED +:1003C000A9008532E631A9338D4F04A900862AA2FF +:1003D00012202538A62AA53F853C4CD1348D010C2E +:1003E0008D100C8D200CA900851685148515A9018A +:1003F000A2102025388D300C8D400CA90085208559 +:1004000036A208205238A901A208202538AD5B0485 +:10041000290F0A0A0A0A8522AD5C04290F05228DDC +:100420002200A522C5583004A21C100AC559300468 +:10043000A21A1002A216A901202538A55CC901F054 +:100440002DAD4204290F0A0A0A0A8522AD43042968 +:100450000F05228522A522C5583004A224100AC502 +:10046000593004A2221002A21EA900202538A90892 +:10047000A27FA07F85268628842A20B137A536D082 +:1004800049A520D045F000A526A628A42A88D0E4B6 +:10049000852A862BE630A5302920F008A2102052AC +:1004A000384CAB34A901A210202538A52AA62B8DE3 +:1004B000800CA07FCAD0BDA07FA27FC9099002A9ED +:1004C0000538E90110AEA901852A604C08314CE6D7 +:1004D00031206E37E8E45CD0F520183A2C000C503F +:1004E000FB8D800C4CB231202B35B5004A4A4A4A6C +:1004F0004A1869018522A003B50438F52C29F8F0C3 +:10050000173002A0FD98187504950486260626A4C7 +:1005100026991900A9FF8522B500186522DDF53D51 +:100520009003BDF53D950020723560A9008522A994 +:10053000048523B5401869044A4A4A491F186522B0 +:100540008522A900852465238523B54418690409FB +:100550000749FF0A26240A26241865228522A52495 +:1005600065238523A000B12210070A0A0A0A0A950A +:100570002C608622A9008552B500F0724A4A4A854D +:1005800024B5044A4A4AAA8626BD062FF02D0AAA97 +:1005900020FF35A622A5281875089508A5297540BD +:1005A0001017C9FC3008A9018552A900F00BC9F742 +:1005B0003007A9018D5200A9F79540A626BD262F28 +:1005C000F02C0AAA20FF35A622A52818750C950C38 +:1005D000A5297544100CC9E83012A9018552A9E873 +:1005E000300AC9201006A9018552A9209544A622E7 +:1005F000E45C300AA552F006B504492095046086F3 +:10060000258A100649FF186901AAA90085288529AD +:10061000A5281865248528A90065298529CAD0F050 +:10062000A525100DA90038E5288528A900E529850C +:100630002960A200A920A00095409408940CE8E04D +:1006400004D0F5A200A9019500E8E004D0F9A200C9 +:10065000A000A9C09504991900C8C8E8E004D0F426 +:10066000A92C8547A9388546A9448545A9508544C4 +:10067000AD330849FF182A2A2A2903A8B9F13D8574 +:100680003C853FA900A2009533953D9554E8E002D2 +:10069000D0F5A900853785308557853285318D1095 +:1006A0000C8D200C85148515853885508D16008D90 +:1006B000000D8D800D8D000E8D800EA901855CA929 +:1006C00020A2009D4B04E8E00AD0F8A900A2002077 +:1006D0002538A52AD016A9B08D5D048D5C048D5BEC +:1006E00004A9308D44048D43048D4204A9308D4FFC +:1006F000048D5004A9318D4E0460A90085208536F3 +:100700008D300C8D400C852AA9028551608626A962 +:1007100000955ABD18081010F65ABD1A081009F6AF +:100720005ABD1C081002F65AB50029F84A4A852815 +:10073000B55A2902F002E628BD28081008A628BDEF +:10074000462F4C4A37A628BD862FA62618565AB0E3 +:100750000629F04A4A4A4A290F8524365AA908240C +:1007600024F006A52409F08524A524A626608A0A7B +:10077000A8B533D03BE000F0062CC0084C82372CE3 +:100780008008302CA9038522E000F0062CC0084C1C +:1007900095372C80087004A9FD8522B919001865C9 +:1007A00022991900E000F0058D800ED0038D000E17 +:1007B0006020E237A90685512C31081011701EA95E +:1007C000048551A536C902F00160C636100F7004C9 +:1007D000A9028551A536D001605002E620E620C668 +:1007E0003660A90F852285242C4008100350016033 +:1007F0008D800CA0FA88D0FD2C40085006A90F85EA +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6405-02e1.hex b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6405-02e1.hex new file mode 100644 index 00000000..d06308f0 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6405-02e1.hex @@ -0,0 +1,129 @@ +:1000000022100AA522F006C622D002E6362C4008AD +:100010001006A90F8524100AA524F006C624D002D4 +:10002000E6364C603FA000C900F002A0808428BDE5 +:10003000863D8522BD873D8523BDAE3D8524BDAF70 +:100040003D8525A000B122F00805289124C84C4523 +:100050003860BDAE3D8522BDAF3D8523A920A000FF +:100060009122C8C020D0F960A535D00DA22A205217 +:1000700038E8E8E036D0F7A5350AAABD6E3D8524FC +:10008000BD6F3D8525A000B124994800C8C006D0A9 +:10009000F620B137A000B14829F04A4A4A4A09A0DF +:1000A000914CA54C186901854CA900654D854DB151 +:1000B00048290F09A0914CA5481869018548A90055 +:1000C00065498549A54C186901854CA900654D8590 +:1000D0004DA549C54BF002D0B8A548C54AD0B22CB1 +:1000E0003008303CA5350A0AA8A200B9D62E9522C0 +:1000F000C8E8E004D0F5A200A000A93C9122A0012C +:10010000A93D9122A020A93E9122A021A93F9122A0 +:10011000E8E001D00BA5248522A52585234CF838DD +:10012000A200A535F00EE8C9043009C906F005C9DA +:1001300007F001E8BDE83D8558BDEB3D8559BDEEB2 +:100140003D8556AD330849FF182A2A2A2903186924 +:10015000028522A200862486268628A524F8186512 +:10016000588524A5261865598526A528186556851D +:1001700028D8E8E422D0E4A5248558A5268559A5E9 +:100180002885568D800CAD3208100BA940853A8524 +:100190003BA556855860A55629F04A4A4A4A093077 +:1001A000853AA556290F0930853B60AD4B04C9CB74 +:1001B000D029AD553FC94BD0222C2F083001602CDF +:1001C000000C10FB2C000C30FBA90AA000C8D0FDCD +:1001D00038E901D0F62C000C300160A9008520859B +:1001E00036602C2E081005A900855760A557F00130 +:1001F00060A9F08538A0FA88D0FD2C2E0810016087 +:10020000E638D0F1E635A535C90CD002A900853510 +:10021000206838A901855760AD5D04293F20973AD1 +:10022000A522F005A9B08D5D04AD5C04293F20979F +:100230003AA522F005A9B08D5C04AD5B04293F20EE +:10024000973AA522F005A9B08D5B04AD4404209730 +:100250003AA522F005A9308D4404AD430420973A15 +:10026000A522F005A9308D4304AD420420973AA59C +:1002700022F005A9308D4204AD4F0420973AA52203 +:10028000F005A9398D4F04AD500420973AA522F00E +:1002900005A9398D500460C9309008C93AB004A945 +:1002A00000F002A901852260A5350AA8B9CA2D85EA +:1002B00024B9CB2D8525E000F005AD44041003AD35 +:1002C0005D044A29070AA8B1248528C8B1248529D4 +:1002D000B54429F018690429F0852AB5404A4A4AEC +:1002E0004A290F052A852AA000B128C52AF008C886 +:1002F000C004D0F54C4C3BE000D02AAD5D04186939 +:1003000002C9BAD01AAD5C04186901C9BAD00BADE4 +:100310005B041869018D5B04A9B08D5C04A9B08DE4 +:100320005D044C4C3BAD4404186902C93AD01AAD87 +:100330004304186901C93AD00BAD42041869018D14 +:100340004204A9308D4304A9308D440460A200A06A +:1003500000B5409510B544991800E8C8C8E004D02D +:10036000F060A200A9019D00048D800CDD0004D086 +:10037000F59D00058D800CDD0005D0F59D00068DF6 +:10038000800CDD0006D0F59D00078D800CDD000798 +:10039000D0F5E8D0D1186901C901D0CAA9008516E5 +:1003A000A200A9108524A9058525A900857EA9207C +:1003B000857FA000A90085268522A52218717E854B +:1003C00022C8D0F68D800CE67FE626A526C904D08B +:1003D000E9A522DD643DF009A0008A09309124E6F8 +:1003E00024E8E008D0CCA9D48D6A04A9C98D6B0497 +:1003F000A9CD8D6C04A9C58D6D04A9B08D71042C97 +:100400003008501AA9C38DCA048DCC04A9D98DCB4C +:1004100004A9CC8DCD04A9C58DCE044C2A3CA200E4 +:10042000A9209DCA04E8E005D0F8A9202C330830A3 +:1004300002A9B18D6F04A9B62C33083008A9B27097 +:1004400002A9B530047002A9B98D7004A98A852269 +:10045000A90485232C31083018700BA9208524A904 +:100460003E85254CA13CA9598524A93E85254CA152 +:100470003C700BA93B8524A93E85254CA13CA9C411 +:100480008D8A04A9C58D8B04A9CD8D8C04A9CF8D2F +:100490008D04A200A9209D8E04E8E013D0F84CAE94 +:1004A0003CA000B12409809122C8C013D0F52C32A1 +:1004B00008100FA200A9209DAA04E8E00DD0F84C76 +:1004C000DF3CA9AA8522A9048523A9F98524A93E90 +:1004D0008525A000B12409809122C8C00DD0F5A9BE +:1004E000202C30083002A93C8DEA042C3008300260 +:1004F000A93D8DEB042C30083002A93E8D0A052C55 +:1005000030083002A93F8D0B052C2A0810034C3C03 +:10051000308D310C8D410C8D100CA200BD18088D52 +:10052000800C30038D110CE8E006D0F0AD280830C7 +:10053000038D110CAD290830038D110C2C400830AF +:10054000038D110C70038D110C2C2E0830038D11AE +:100550000C2C2C0830038D110C2C2D0830038D1120 +:100560000C4CFF3BCC510991360F3AD4F6310020A8 +:1005700026214C2272239824BE25E4260A283029FD +:10058000562A7C2BA22CF93D193E343E503E6D3E3E +:10059000813EA23EC13EE13EF93E073F273F2E3F4E +:1005A000483F4F3F273F2E3F483F4F3F553F200496 +:1005B00000040004000460076007C0046007000432 +:1005C000290460077807C004780778076307630782 +:1005D000630763074B04400460048004A004C00464 +:1005E000E00400050C0806050704030302010503E7 +:1005F0000226384B5EA090807020424C41434B2035 +:100600002020202020202054494D4520202020203B +:10061000202020D7C8C9D4C5002020202020202099 +:100620003120434F494E2050455220504C415945AE +:1006300052202000202020202020203220434F491B +:100640004E532050455220504C41594552202000D5 +:100650002020202031204F52203220504C4159453B +:1006600052532050455220434F494E200020202015 +:1006700020202020202020202020524154494E4775 +:100680000020475245592043415253204452495675 +:1006900045204155544F4D41544943414C4C5920FC +:1006A000200020205055534820425554544F4E208E +:1006B000544F204348414E474520545241434B53E9 +:1006C0000020202020202020505553482053544102 +:1006D000525420425554544F4E2020202020202098 +:1006E00000202020202020202020202047414D4590 +:1006F00020204F564552202000455854454E444531 +:100700004420504C4159002020455854454E444502 +:100710004420504C415920464F5220202030205038 +:100720004F494E545320004752414E4E590020200D +:1007300020202020313220444946464552454E541F +:1007400020545241434B5300524F4F4B49450020D8 +:100750002050524F004B4545202047414D45530006 +:10076000A52238E9068522A52438E90685242C40EF +:100770000810035001608D800CA0FA88D0FD2C4039 +:10078000085006A9098522100AA522F006C622D023 +:1007900002E6362C40081006A909852410D0A524AD +:1007A000F0CCC624D0C8E6364C6E3F0000000000F6 +:1007B0000000000000000000000000000000000039 +:1007C0000000000000000000000000000000000029 +:1007D0000000000000000000000000000000000019 +:1007E0000000000000000000000000000000000009 +:1007F0000000000000000000000000303C303C30F1 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6442-01d1.hex b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6442-01d1.hex new file mode 100644 index 00000000..160cbf39 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6442-01d1.hex @@ -0,0 +1,129 @@ +:10000000488A48D8A530D0038D000F2C2C0810202A +:10001000A561C992D01EA560C93FD018BABD05011F +:10002000C920B00CC9409008C9109010C918B00C74 +:1000300068AA6840A9928561A93F856078D8A27FA7 +:100040009AAD0018C9AAF0034C4E30200018A21631 +:1000500020B738A20420B738A20C20B738200337C5 +:1000600020693020F7304C6030A900853585388D07 +:10007000010C20CD3820DA3520EE3920FF37A901D8 +:10008000A21E208A38A900A651208A38A900A20EF3 +:10009000208A38A900A210208A38E630AD3000D07E +:1000A00011E635A535C90CD009A900853585384C30 +:1000B00072302C2C0830034C523A203D3AA20020DA +:1000C0008534E8E004D0F8A90085168D14008D1061 +:1000D0000C2C40081002700320FF372C000C50F14C +:1000E0008D800CA536D004A520F0AF20BA39A536F6 +:1000F000D004A520F0A460EAA2008635863820CD81 +:1001000038A20620B738A900A200208A38A90085A5 +:100110002A20DA35203D3A20FF378D800CA520F0CB +:10012000F68D310CA900A214208A382C2D0830E756 +:10013000C620A20020B738A21420B738A21220B7D8 +:1001400038A53AC940F015A900A212208A38A53A6C +:10015000C930F0038D7407A53B8D75078D000C2009 +:100160003D3AA538F00320CD38E63020D837A2013B +:10017000208534E8E004D0F88D100CA2002C00108B +:100180003009A53DF005C63D4CAF312C00103009BB +:10019000A900853D853E4CAF31A9008533A53ED0F1 +:1001A0000AA9019500853EA90F8516A910853DA5D0 +:1001B00016F00AA5304A90054A9002C616A533F0FB +:1001C000188D110CC6338A0AA8A9022C8008700267 +:1001D000A9FE187919009919002C00105004A920C3 +:1001E00085338D000DA5304A901A4A90172082372A +:1001F0008524C9F910038D110CA524187500D002AF +:10020000A9019500B5004A4A4A8522A432A5320ABE +:100210008524B9A13CA8A90018652288D0FA4A4AC9 +:100220004A38E5241002A900C9103002A90F85142C +:100230008A0AA820D837B50049FF4A4A4A4A4A4A9A +:1002400085261869038522B9190029F88524B50483 +:1002500029F838E524F0213011C91030038D110C34 +:10026000A90038E52285224C7132C9F810038D119E +:100270000CA5221875049504201035A5350AAABDD1 +:10028000CA2D8524BDCB2D8525AD2A044A29070A10 +:10029000A8B1248528C8B1248529A622B54429F00F +:1002A000852AB5404A4A4A4A290F052A852AA000CC +:1002B000B128C52AF008C8C004D0F54C0A33AD2ACD +:1002C00004186902C9BAD01AAD2904186901C9BA5B +:1002D000D00BAD28041869018D2804A9B08D29041C +:1002E000A9B08D2A04C9B0D0212C30087009A537D7 +:1002F000D005E6374C0A33A9008537E635A535C960 +:100300000CD004A906853520CD38A531F015A530CF +:100310002920F008A20220B7384C2333A202A900FA +:10032000208A38AD2804293FC53A3013AD29042965 +:100330003FC53B300AA531D006A534D002E634C60D +:100340003CD035A550D014E650A9208D3A04A9B967 +:100350008D3B04A9BA8D3C044C7133AD3C04C9B04B +:10036000D00FAD3B04C9B0F012CE3B04A9BA8D3C0E +:1003700004CE3C04A53F853C4C6A34A534F019A951 +:10038000008534E631A9B38D3B04A900A202208A7E +:1003900038A53F853C4C6A348D010C8D100CA900AA +:1003A00085168514A20220B738A20C20B738A90000 +:1003B000A20C208A38A900A216208A38AD28042968 +:1003C0000F0A0A0A0A8522AD2904290F052285226F +:1003D000A522C5543004A218100AC5553004A21A2B +:1003E0001002A21CA901208A38A520D0038D300C50 +:1003F00020EE39A908A27FA07F85268628842A209E +:10040000FF37A536D04FA520F0088D310C2C2D08D4 +:100410001043A526A628A42A88D0DE852A862BE6A6 +:1004200030A5302920F008A21620B7384C3634A960 +:1004300001A216208A38A52AA62B8D800CA07FCA7F +:10044000D0B7A07FA27FC9099002A90538E90110A1 +:10045000A8A901852AA21620B738A20C20B738A572 +:1004600020D0048D300C604CF83020D8372C400858 +:100470001002700320FF372C000C50F1201B378D29 +:10048000800C4C5F3120C934B5004A4A4A4A4A18A8 +:1004900069018522A003B50438F52C29F8F017303E +:1004A00002A0FD98187504950486260626A42699B0 +:1004B0001900A9FF8522B500186522DDA93C90032B +:1004C000BDA93C950020103560A9008522A90485AE +:1004D00023B5401869044A4A4A491F1865228522F3 +:1004E000A900852465238523B544186904090749B3 +:1004F000FF0A26240A26241865228522A5246523BE +:100500008523A000B12210070A0A0A0A0A952C6066 +:100510008622A9008552B500F0724A4A4A8524B560 +:10052000044A4A4AAA8626BD062FF02D0AAA20A709 +:1005300035A622A5281875089508A5297540101715 +:10054000C9FC3008A9018552A900F00BC9F7300792 +:10055000A9018D5200A9F79540A626BD262FF02CA3 +:100560000AAA20A735A622A52818750C950CA5293E +:100570007544100CC9E83012A9018552A9E8300A67 +:10058000C9201006A9018552A9209544A622E000A1 +:10059000F014A552F010A9209540A9509544A9C087 +:1005A0009504A90195006086258A100649FF1869FF +:1005B00001AAA90085288529A5281865248528A9C8 +:1005C0000065298529CAD0F0A525100DA90038E5B8 +:1005D000288528A900E529852960A200A920A00076 +:1005E00095409408940CE8E004D0F5A200A9019588 +:1005F00000E8E004D0F9A200A000A9C09504991970 +:1006000000C8C8E8E004D0F4A9508544A944854551 +:10061000A9388546A92C8547AD330849FF182A2AF1 +:100620002A2903A8B9A53C853C853FA9048554A97E +:10063000028555A9038556AD330849FF182A2A2A91 +:1006400029031869028522A200862486268628A509 +:1006500024F81865548524A5261865558526A528EF +:100660001865568528D8E8E422D0E4A5248554A549 +:10067000268555A5288556AD3208100DA940853A26 +:10068000853BA55685544C9D36A55629F04A4A4AC5 +:100690004A0930853AA556290F0930853BA90085BE +:1006A0003785308D100C851485158533853D853E45 +:1006B00085388534853185508D16008D000D8D006F +:1006C0000EAD2A048526AD29048527AD2804852B87 +:1006D000A901A204208A38A5268D2A04A5278D29E0 +:1006E00004A52B8D2804A52AD00BA9B08D2A048D32 +:1006F00029048D2804A9B08D3B048D3C04A9B18D3B +:100700003A0460A900852085368D300C852AA930F1 +:10071000855785588559A906855160AD2A04293F1A +:10072000207137A522F005A9B08D2A04AD2904292E +:100730003F207137A522F005A9B08D2904AD28040A +:10074000293F207137A522F005A9B08D2804AD3BC3 +:1007500004293F207137A522F005A9B98D3B04ADCE +:100760003C04293F207137A522F005A9B98D3C042E +:1007700060C9309008C93AB004A900F002A9018507 +:1007800022608626A90085322C28081010E6322C1B +:1007900029081009E6322C2A081002E632B5002991 +:1007A000F84A4AAAA9022432F001E8BD462F2C2BB0 +:1007B000083003BD862F184632B00629F04A4A4A4F +:1007C0004A290F85242632A9082424F006A52409E5 +:1007D000F08524A524A62660A200A000A533D01E83 +:1007E0002C80083019A90385222C80087004A9FDEB +:1007F0008522B919001865229919008D000E602014 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6443-01e1.hex b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6443-01e1.hex new file mode 100644 index 00000000..ae79880b --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/6443-01e1.hex @@ -0,0 +1,129 @@ +:100000003038A90A85512C31081011701EA90885B5 +:1000100051A536C902F00160C636100F7004A9065A +:100020008551A536D001605002E620E620C6366034 +:10003000A90985228523852485252C4008100B508D +:1000400009A5222523C909D001608D800CA201A039 +:10005000FA88D0FD8AD0072C4008501F70052C402C +:10006000081018B522F006A9099522D018D624D078 +:1000700014E636A90995229524D00AA9099524B534 +:1000800022F002D622CA10CC30B0A000C900F00283 +:10009000A0808428BD4F3C8522BD503C8523BD7186 +:1000A0003C8524BD723C8525A000B122F0080528BE +:1000B0009124C84CAA3860BD713C8522BD723C8534 +:1000C00023A920A0009122C8C020D0F9608D800C07 +:1000D000A538D029A535D00DA22220B738E8E8E010 +:1000E00030D0F7A5350AAABD373C8524BD383C85FC +:1000F00025A000B124994800C8C006D0F618A5482C +:100100006918854EA9006549854FA901853820FFEA +:1001100037A000B14829F04A4A4A4A09A0914CA5A3 +:100120004C186901854CA900654D854DB148290FD2 +:1001300009A0914CA5481869018548A90065498521 +:1001400049A54C186901854CA900654D854DA54907 +:10015000C54BF00CA535F0BBA549C54FF00ED0B38B +:10016000A548C54AD0EEA9008538F006A548C54E79 +:10017000D0A120FF372C3008303CA5350A0AA8A2B0 +:1001800000B9D62E9522C8E8E004D0F5A200A00060 +:10019000A93C9122A001A93D9122A020A93E912233 +:1001A000A021A93F9122E8E001D00BA5248522A53A +:1001B0002585234C8E398D800C60AD6B04C9CBD066 +:1001C00026AD043EC94BD01F2C2F083001602C00F7 +:1001D0000C10FB2C000C30FBA90AA000C8D0FD3885 +:1001E000E901D0F6300160A9008520853660A900BC +:1001F000A220208A38AD2804293FC559302FF002AB +:100200001016AD2904293FC5583022F0021009AD5F +:100210002A04293FC5573015AD2804293F8559AD1B +:100220002904293F8558AD2A04293F8557A5578DB4 +:100230003B04A5588D3A04A5598D390460A200A04D +:1002400000B5409510B544991800E8C8C8E004D03E +:10025000F060A200A9019D00048D800CDD0004D097 +:10026000F59D00058D800CDD0005D0F59D00068D07 +:10027000800CDD0006D0F59D00078D800CDD0007A9 +:10028000D0F5E8D0D1186901C901D0CAA9008516F6 +:10029000A200A9108524A9058525A900857EA9208D +:1002A000857FA000A90085268522A52218717E855C +:1002B00022C8D0F68D800CE67FE626A526C904D09C +:1002C000E9A522DD2E3CF009A0008A09309124E640 +:1002D00024E8E008D0CCA9D48D6A04A9C98D6B04A8 +:1002E000A9CD8D6C04A9C58D6D04A9CC8DCC04A9B4 +:1002F000C18DCD04A9D08DCE04A9D38DCF04A9B0D2 +:100300008D7104A9B12C30087002A9B28DCA04A95C +:10031000202C33083002A9B18D6F04A9B62C330804 +:100320003008A9B27002A9B530047002A9B98D7065 +:1003300004A98A8522A90485232C31083018700B62 +:10034000A9058524A93D85254C863BA93C8524A982 +:100350003D85254C863B700BA9208524A93D85252C +:100360004C863BA9C48D8A04A9C58D8B04A9CD8D6B +:100370008C04A9CF8D8D04A200A9209D8E04E8E0F5 +:100380000CD0F84C933BA000B12409809122C8C046 +:1003900010D0F52C3208100FA200A9209DAA04E865 +:1003A000E00DD0F84CC43BA9AA8522A9048523A955 +:1003B000D58524A93C8525A000B12409809122C8B7 +:1003C000C00DD0F5A9202C30083002A93C8DEA04DC +:1003D0002C30083002A93D8DEB042C30083002A9E6 +:1003E0003E8D0A052C30083002A93F8D0B052C2CC0 +:1003F0000810034C3C308D300C8D100CA200BD2831 +:10040000088D800C30038D110CE8E003D0F0AD2B8B +:100410000830038D110C2C400830038D110C700333 +:100420008D110C2C2D0830038D110C4C033BCC513D +:100430000991382FAC4630002026214C2272239897 +:1004400024BE25E4260A283029562A7C2BA22CAD6E +:100450003CCB3CE33CFE3C193D343D4F3D5D3D7D96 +:100460003D9B3DBC3DDB3DF23DF63DFD3D043E0F79 +:100470003EA004400420046007600760076007E0B6 +:1004800004A0046007E00400047507750775076B96 +:10049000042E04400460048004A004C004E00400AE +:1004A000050C08060526384B5EA0908070202020A1 +:1004B00020202020594F555220434152204953209B +:1004C000D7C8C9D4C52020202020002020202020EB +:1004D0002020202020455854454E44454420504C6F +:1004E000415900202053434F5245202020202020F6 +:1004F000202020202020202054494D45200020206D +:100500002020202020203120434F494E20504552AA +:100510002047414D45202020002020202020202061 +:100520003220434F494E53205045522047414D45BC +:100530002020200020202020202020203220474181 +:100540004D45532050455220434F494E2020002016 +:10055000202020202020524154494E470020424C68 +:1005600041434B2043415253204452495645204178 +:1005700055544F4D41544943414C4C59002020544F +:100580005241434B53204348414E47452041555427 +:100590004F4D41544943414C4C590020204558543B +:1005A000454E44454420504C415920464F5220204E +:1005B000203020504F494E5453202000202020202E +:1005C0002020205055534820535441525420425526 +:1005D00054544F4E20202020202000202020202076 +:1005E0002020202020202047414D4520204F5645E7 +:1005F000520050524F00524F4F4B49450047524115 +:100600004E4E59004B4545202047414D455300482B +:100610004947482053434F524520202020200000C6 +:1006200000000000000000000000000000000000CA +:1006300000000000000000000000000000000000BA +:1006400000000000000000000000000000000000AA +:10065000000000000000000000000000000000009A +:10066000000000000000000000000000000000008A +:10067000000000000000000000000000000000007A +:10068000000000000000000000000000000000006A +:10069000000000000000000000000000000000005A +:1006A000000000000000000000000000000000004A +:1006B000000000000000000000000000000000003A +:1006C000000000000000000000000000000000002A +:1006D000000000000000000000000000000000001A +:1006E000000000000000000000000000000000000A +:1006F00000000000000000000000000000000000FA +:1007000000000000000000000000000000000000E9 +:1007100000000000000000000000000000000000D9 +:1007200000000000000000000000000000000000C9 +:1007300000000000000000000000000000000000B9 +:1007400000000000000000000000000000000000A9 +:100750000000000000000000000000000000000099 +:100760000000000000000000000000000000000089 +:100770000000000000000000000000000000000079 +:100780000000000000000000000000000000000069 +:100790000000000000000000000000000000000059 +:1007A0000000000000000000000000000000000049 +:1007B0000000000000000000000000000000000039 +:1007C0000000000000000000000000000000000029 +:1007D0000000000000000000000000000000000019 +:1007E0000000000000000000000000000000000009 +:1007F0000000000000000000000000303C303C30F1 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/Char_LSB.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/Char_LSB.qip new file mode 100644 index 00000000..2ce4cc47 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/Char_LSB.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "ROM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "Char_LSB.vhd"] diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/Char_LSB.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/Char_LSB.vhd new file mode 100644 index 00000000..9c7bdfc3 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/Char_LSB.vhd @@ -0,0 +1,141 @@ +-- megafunction wizard: %ROM: 1-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: Char_LSB.vhd +-- Megafunction Name(s): +-- altsyncram +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.1.4 Build 182 03/12/2014 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2014 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files from any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.altera_mf_components.all; + +ENTITY Char_LSB IS + PORT + ( + address : IN STD_LOGIC_VECTOR (8 DOWNTO 0); + clock : IN STD_LOGIC := '1'; + q : OUT STD_LOGIC_VECTOR (3 DOWNTO 0) + ); +END Char_LSB; + + +ARCHITECTURE SYN OF char_lsb IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (3 DOWNTO 0); + +BEGIN + q <= sub_wire0(3 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + init_file => "./rtl/roms/6396-01p4.hex", + intended_device_family => "Cyclone II", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 512, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => "CLOCK0", + widthad_a => 9, + width_a => 4, + width_byteena_a => 1 + ) + PORT MAP ( + address_a => address, + clock0 => clock, + q_a => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +-- Retrieval info: PRIVATE: AclrByte NUMERIC "0" +-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: Clken NUMERIC "0" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MIFfilename STRING "./rtl/roms/6396-01p4.hex" +-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "512" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +-- Retrieval info: PRIVATE: RegAddr NUMERIC "1" +-- Retrieval info: PRIVATE: RegOutput NUMERIC "1" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: SingleClock NUMERIC "1" +-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" +-- Retrieval info: PRIVATE: WidthAddr NUMERIC "9" +-- Retrieval info: PRIVATE: WidthData NUMERIC "4" +-- Retrieval info: PRIVATE: rden NUMERIC "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: INIT_FILE STRING "./rtl/roms/6396-01p4.hex" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "512" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "9" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "4" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: USED_PORT: address 0 0 9 0 INPUT NODEFVAL "address[8..0]" +-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +-- Retrieval info: USED_PORT: q 0 0 4 0 OUTPUT NODEFVAL "q[3..0]" +-- Retrieval info: CONNECT: @address_a 0 0 9 0 address 0 0 9 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +-- Retrieval info: CONNECT: q 0 0 4 0 @q_a 0 0 4 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL Char_LSB.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL Char_LSB.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL Char_LSB.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL Char_LSB.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL Char_LSB_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/Char_MSB.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/Char_MSB.qip new file mode 100644 index 00000000..9c809207 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/Char_MSB.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "ROM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "Char_MSB.vhd"] diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/Char_MSB.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/Char_MSB.vhd new file mode 100644 index 00000000..bfa538dd --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/Char_MSB.vhd @@ -0,0 +1,141 @@ +-- megafunction wizard: %ROM: 1-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: Char_MSB.vhd +-- Megafunction Name(s): +-- altsyncram +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.1.4 Build 182 03/12/2014 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2014 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files from any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.altera_mf_components.all; + +ENTITY Char_MSB IS + PORT + ( + address : IN STD_LOGIC_VECTOR (8 DOWNTO 0); + clock : IN STD_LOGIC := '1'; + q : OUT STD_LOGIC_VECTOR (3 DOWNTO 0) + ); +END Char_MSB; + + +ARCHITECTURE SYN OF char_msb IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (3 DOWNTO 0); + +BEGIN + q <= sub_wire0(3 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + init_file => "./rtl/roms/6397-01r4.hex", + intended_device_family => "Cyclone II", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 512, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => "CLOCK0", + widthad_a => 9, + width_a => 4, + width_byteena_a => 1 + ) + PORT MAP ( + address_a => address, + clock0 => clock, + q_a => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +-- Retrieval info: PRIVATE: AclrByte NUMERIC "0" +-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: Clken NUMERIC "0" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MIFfilename STRING "./rtl/roms/6397-01r4.hex" +-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "512" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +-- Retrieval info: PRIVATE: RegAddr NUMERIC "1" +-- Retrieval info: PRIVATE: RegOutput NUMERIC "1" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: SingleClock NUMERIC "1" +-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" +-- Retrieval info: PRIVATE: WidthAddr NUMERIC "9" +-- Retrieval info: PRIVATE: WidthData NUMERIC "4" +-- Retrieval info: PRIVATE: rden NUMERIC "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: INIT_FILE STRING "./rtl/roms/6397-01r4.hex" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "512" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "9" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "4" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: USED_PORT: address 0 0 9 0 INPUT NODEFVAL "address[8..0]" +-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +-- Retrieval info: USED_PORT: q 0 0 4 0 OUTPUT NODEFVAL "q[3..0]" +-- Retrieval info: CONNECT: @address_a 0 0 9 0 address 0 0 9 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +-- Retrieval info: CONNECT: q 0 0 4 0 @q_a 0 0 4 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL Char_MSB.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL Char_MSB.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL Char_MSB.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL Char_MSB.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL Char_MSB_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/addec_prom.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/addec_prom.qip new file mode 100644 index 00000000..81a66586 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/addec_prom.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "ROM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "addec_prom.vhd"] diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/addec_prom.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/addec_prom.vhd new file mode 100644 index 00000000..6cd74f62 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/addec_prom.vhd @@ -0,0 +1,141 @@ +-- megafunction wizard: %ROM: 1-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: addec_prom.vhd +-- Megafunction Name(s): +-- altsyncram +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.1.4 Build 182 03/12/2014 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2014 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files from any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.altera_mf_components.all; + +ENTITY addec_prom IS + PORT + ( + address : IN STD_LOGIC_VECTOR (4 DOWNTO 0); + clock : IN STD_LOGIC := '1'; + q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) + ); +END addec_prom; + + +ARCHITECTURE SYN OF addec_prom IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0); + +BEGIN + q <= sub_wire0(7 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + init_file => "./rtl/roms/6401-01e2.hex", + intended_device_family => "Cyclone II", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 32, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => "UNREGISTERED", + widthad_a => 5, + width_a => 8, + width_byteena_a => 1 + ) + PORT MAP ( + address_a => address, + clock0 => clock, + q_a => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +-- Retrieval info: PRIVATE: AclrByte NUMERIC "0" +-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: Clken NUMERIC "0" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MIFfilename STRING "./rtl/roms/6401-01e2.hex" +-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "32" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +-- Retrieval info: PRIVATE: RegAddr NUMERIC "1" +-- Retrieval info: PRIVATE: RegOutput NUMERIC "0" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: SingleClock NUMERIC "1" +-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" +-- Retrieval info: PRIVATE: WidthAddr NUMERIC "5" +-- Retrieval info: PRIVATE: WidthData NUMERIC "8" +-- Retrieval info: PRIVATE: rden NUMERIC "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: INIT_FILE STRING "./rtl/roms/6401-01e2.hex" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "32" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "5" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: USED_PORT: address 0 0 5 0 INPUT NODEFVAL "address[4..0]" +-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" +-- Retrieval info: CONNECT: @address_a 0 0 5 0 address 0 0 5 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +-- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL addec_prom.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL addec_prom.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL addec_prom.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL addec_prom.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL addec_prom_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/j6_prom.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/j6_prom.qip new file mode 100644 index 00000000..a6b355f4 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/j6_prom.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "ROM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "j6_prom.vhd"] diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/j6_prom.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/j6_prom.vhd new file mode 100644 index 00000000..cc6c3558 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/j6_prom.vhd @@ -0,0 +1,141 @@ +-- megafunction wizard: %ROM: 1-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: j6_prom.vhd +-- Megafunction Name(s): +-- altsyncram +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.1.4 Build 182 03/12/2014 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2014 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files from any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.altera_mf_components.all; + +ENTITY j6_prom IS + PORT + ( + address : IN STD_LOGIC_VECTOR (8 DOWNTO 0); + clock : IN STD_LOGIC := '1'; + q : OUT STD_LOGIC_VECTOR (3 DOWNTO 0) + ); +END j6_prom; + + +ARCHITECTURE SYN OF j6_prom IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (3 DOWNTO 0); + +BEGIN + q <= sub_wire0(3 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + init_file => "./rtl/roms/6399-01j6.hex", + intended_device_family => "Cyclone II", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 512, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => "CLOCK0", + widthad_a => 9, + width_a => 4, + width_byteena_a => 1 + ) + PORT MAP ( + address_a => address, + clock0 => clock, + q_a => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +-- Retrieval info: PRIVATE: AclrByte NUMERIC "0" +-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: Clken NUMERIC "0" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MIFfilename STRING "./rtl/roms/6399-01j6.hex" +-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "512" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +-- Retrieval info: PRIVATE: RegAddr NUMERIC "1" +-- Retrieval info: PRIVATE: RegOutput NUMERIC "1" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: SingleClock NUMERIC "1" +-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" +-- Retrieval info: PRIVATE: WidthAddr NUMERIC "9" +-- Retrieval info: PRIVATE: WidthData NUMERIC "4" +-- Retrieval info: PRIVATE: rden NUMERIC "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: INIT_FILE STRING "./rtl/roms/6399-01j6.hex" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "512" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "9" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "4" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: USED_PORT: address 0 0 9 0 INPUT NODEFVAL "address[8..0]" +-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +-- Retrieval info: USED_PORT: q 0 0 4 0 OUTPUT NODEFVAL "q[3..0]" +-- Retrieval info: CONNECT: @address_a 0 0 9 0 address 0 0 9 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +-- Retrieval info: CONNECT: q 0 0 4 0 @q_a 0 0 4 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL j6_prom.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL j6_prom.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL j6_prom.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL j6_prom.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL j6_prom_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/k6_prom.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/k6_prom.qip new file mode 100644 index 00000000..9735dccb --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/k6_prom.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "ROM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "k6_prom.vhd"] diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/k6_prom.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/k6_prom.vhd new file mode 100644 index 00000000..5c772b25 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/k6_prom.vhd @@ -0,0 +1,141 @@ +-- megafunction wizard: %ROM: 1-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: k6_prom.vhd +-- Megafunction Name(s): +-- altsyncram +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.1.4 Build 182 03/12/2014 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2014 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files from any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.altera_mf_components.all; + +ENTITY k6_prom IS + PORT + ( + address : IN STD_LOGIC_VECTOR (8 DOWNTO 0); + clock : IN STD_LOGIC := '1'; + q : OUT STD_LOGIC_VECTOR (3 DOWNTO 0) + ); +END k6_prom; + + +ARCHITECTURE SYN OF k6_prom IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (3 DOWNTO 0); + +BEGIN + q <= sub_wire0(3 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + init_file => "./rtl/roms/6398-01k6.hex", + intended_device_family => "Cyclone II", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 512, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => "CLOCK0", + widthad_a => 9, + width_a => 4, + width_byteena_a => 1 + ) + PORT MAP ( + address_a => address, + clock0 => clock, + q_a => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +-- Retrieval info: PRIVATE: AclrByte NUMERIC "0" +-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: Clken NUMERIC "0" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MIFfilename STRING "./rtl/roms/6398-01k6.hex" +-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "512" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +-- Retrieval info: PRIVATE: RegAddr NUMERIC "1" +-- Retrieval info: PRIVATE: RegOutput NUMERIC "1" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: SingleClock NUMERIC "1" +-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" +-- Retrieval info: PRIVATE: WidthAddr NUMERIC "9" +-- Retrieval info: PRIVATE: WidthData NUMERIC "4" +-- Retrieval info: PRIVATE: rden NUMERIC "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: INIT_FILE STRING "./rtl/roms/6398-01k6.hex" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "512" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "9" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "4" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: USED_PORT: address 0 0 9 0 INPUT NODEFVAL "address[8..0]" +-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +-- Retrieval info: USED_PORT: q 0 0 4 0 OUTPUT NODEFVAL "q[3..0]" +-- Retrieval info: CONNECT: @address_a 0 0 9 0 address 0 0 9 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +-- Retrieval info: CONNECT: q 0 0 4 0 @q_a 0 0 4 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL k6_prom.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL k6_prom.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL k6_prom.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL k6_prom.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL k6_prom_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom1.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom1.qip new file mode 100644 index 00000000..ca8648de --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom1.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "ROM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "prog_rom1.vhd"] diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom1.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom1.vhd new file mode 100644 index 00000000..0539e859 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom1.vhd @@ -0,0 +1,141 @@ +-- megafunction wizard: %ROM: 1-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: prog_rom1.vhd +-- Megafunction Name(s): +-- altsyncram +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.1.4 Build 182 03/12/2014 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2014 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files from any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.altera_mf_components.all; + +ENTITY prog_rom1 IS + PORT + ( + address : IN STD_LOGIC_VECTOR (10 DOWNTO 0); + clock : IN STD_LOGIC := '1'; + q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) + ); +END prog_rom1; + + +ARCHITECTURE SYN OF prog_rom1 IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0); + +BEGIN + q <= sub_wire0(7 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + init_file => "./rtl/roms/6290-01b1.hex", + intended_device_family => "Cyclone II", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 2048, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => "CLOCK0", + widthad_a => 11, + width_a => 8, + width_byteena_a => 1 + ) + PORT MAP ( + address_a => address, + clock0 => clock, + q_a => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +-- Retrieval info: PRIVATE: AclrByte NUMERIC "0" +-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: Clken NUMERIC "0" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MIFfilename STRING "./rtl/roms/6290-01b1.hex" +-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "2048" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +-- Retrieval info: PRIVATE: RegAddr NUMERIC "1" +-- Retrieval info: PRIVATE: RegOutput NUMERIC "1" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: SingleClock NUMERIC "1" +-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" +-- Retrieval info: PRIVATE: WidthAddr NUMERIC "11" +-- Retrieval info: PRIVATE: WidthData NUMERIC "8" +-- Retrieval info: PRIVATE: rden NUMERIC "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: INIT_FILE STRING "./rtl/roms/6290-01b1.hex" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "2048" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "11" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: USED_PORT: address 0 0 11 0 INPUT NODEFVAL "address[10..0]" +-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" +-- Retrieval info: CONNECT: @address_a 0 0 11 0 address 0 0 11 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +-- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom1.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom1.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom1.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom1.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom1_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom2.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom2.qip new file mode 100644 index 00000000..aefde75d --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom2.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "ROM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "prog_rom2.vhd"] diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom2.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom2.vhd new file mode 100644 index 00000000..d2ee7a7e --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom2.vhd @@ -0,0 +1,141 @@ +-- megafunction wizard: %ROM: 1-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: prog_rom2.vhd +-- Megafunction Name(s): +-- altsyncram +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.1.4 Build 182 03/12/2014 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2014 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files from any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.altera_mf_components.all; + +ENTITY prog_rom2 IS + PORT + ( + address : IN STD_LOGIC_VECTOR (10 DOWNTO 0); + clock : IN STD_LOGIC := '1'; + q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) + ); +END prog_rom2; + + +ARCHITECTURE SYN OF prog_rom2 IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0); + +BEGIN + q <= sub_wire0(7 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + init_file => "./rtl/roms/6291-01c1.hex", + intended_device_family => "Cyclone II", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 2048, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => "CLOCK0", + widthad_a => 11, + width_a => 8, + width_byteena_a => 1 + ) + PORT MAP ( + address_a => address, + clock0 => clock, + q_a => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +-- Retrieval info: PRIVATE: AclrByte NUMERIC "0" +-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: Clken NUMERIC "0" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MIFfilename STRING "./rtl/roms/6291-01c1.hex" +-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "2048" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +-- Retrieval info: PRIVATE: RegAddr NUMERIC "1" +-- Retrieval info: PRIVATE: RegOutput NUMERIC "1" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: SingleClock NUMERIC "1" +-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" +-- Retrieval info: PRIVATE: WidthAddr NUMERIC "11" +-- Retrieval info: PRIVATE: WidthData NUMERIC "8" +-- Retrieval info: PRIVATE: rden NUMERIC "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: INIT_FILE STRING "./rtl/roms/6291-01c1.hex" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "2048" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "11" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: USED_PORT: address 0 0 11 0 INPUT NODEFVAL "address[10..0]" +-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" +-- Retrieval info: CONNECT: @address_a 0 0 11 0 address 0 0 11 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +-- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom2.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom2.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom2.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom2.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom2_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom3.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom3.qip new file mode 100644 index 00000000..562f4ad7 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom3.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "ROM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "prog_rom3.vhd"] diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom3.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom3.vhd new file mode 100644 index 00000000..41a5470c --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom3.vhd @@ -0,0 +1,141 @@ +-- megafunction wizard: %ROM: 1-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: prog_rom3.vhd +-- Megafunction Name(s): +-- altsyncram +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.1.4 Build 182 03/12/2014 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2014 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files from any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.altera_mf_components.all; + +ENTITY prog_rom3 IS + PORT + ( + address : IN STD_LOGIC_VECTOR (10 DOWNTO 0); + clock : IN STD_LOGIC := '1'; + q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) + ); +END prog_rom3; + + +ARCHITECTURE SYN OF prog_rom3 IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0); + +BEGIN + q <= sub_wire0(7 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + init_file => "./rtl/roms/6404d1.hex", + intended_device_family => "Cyclone II", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 2048, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => "CLOCK0", + widthad_a => 11, + width_a => 8, + width_byteena_a => 1 + ) + PORT MAP ( + address_a => address, + clock0 => clock, + q_a => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +-- Retrieval info: PRIVATE: AclrByte NUMERIC "0" +-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: Clken NUMERIC "0" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MIFfilename STRING "./rtl/roms/6404d1.hex" +-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "2048" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +-- Retrieval info: PRIVATE: RegAddr NUMERIC "1" +-- Retrieval info: PRIVATE: RegOutput NUMERIC "1" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: SingleClock NUMERIC "1" +-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" +-- Retrieval info: PRIVATE: WidthAddr NUMERIC "11" +-- Retrieval info: PRIVATE: WidthData NUMERIC "8" +-- Retrieval info: PRIVATE: rden NUMERIC "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: INIT_FILE STRING "./rtl/roms/6404d1.hex" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "2048" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "11" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: USED_PORT: address 0 0 11 0 INPUT NODEFVAL "address[10..0]" +-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" +-- Retrieval info: CONNECT: @address_a 0 0 11 0 address 0 0 11 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +-- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom3.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom3.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom3.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom3.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom3_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom4.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom4.qip new file mode 100644 index 00000000..30906c90 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom4.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "ROM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "prog_rom4.vhd"] diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom4.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom4.vhd new file mode 100644 index 00000000..b71ccb64 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/prog_rom4.vhd @@ -0,0 +1,141 @@ +-- megafunction wizard: %ROM: 1-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: prog_rom4.vhd +-- Megafunction Name(s): +-- altsyncram +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.1.4 Build 182 03/12/2014 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2014 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files from any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.altera_mf_components.all; + +ENTITY prog_rom4 IS + PORT + ( + address : IN STD_LOGIC_VECTOR (10 DOWNTO 0); + clock : IN STD_LOGIC := '1'; + q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) + ); +END prog_rom4; + + +ARCHITECTURE SYN OF prog_rom4 IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0); + +BEGIN + q <= sub_wire0(7 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + init_file => "./rtl/roms/6405-02e1.hex", + intended_device_family => "Cyclone II", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 2048, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => "CLOCK0", + widthad_a => 11, + width_a => 8, + width_byteena_a => 1 + ) + PORT MAP ( + address_a => address, + clock0 => clock, + q_a => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +-- Retrieval info: PRIVATE: AclrByte NUMERIC "0" +-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: Clken NUMERIC "0" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MIFfilename STRING "./rtl/roms/6405-02e1.hex" +-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "2048" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +-- Retrieval info: PRIVATE: RegAddr NUMERIC "1" +-- Retrieval info: PRIVATE: RegOutput NUMERIC "1" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: SingleClock NUMERIC "1" +-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" +-- Retrieval info: PRIVATE: WidthAddr NUMERIC "11" +-- Retrieval info: PRIVATE: WidthData NUMERIC "8" +-- Retrieval info: PRIVATE: rden NUMERIC "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: INIT_FILE STRING "./rtl/roms/6405-02e1.hex" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "2048" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "11" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: USED_PORT: address 0 0 11 0 INPUT NODEFVAL "address[10..0]" +-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" +-- Retrieval info: CONNECT: @address_a 0 0 11 0 address 0 0 11 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +-- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom4.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom4.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom4.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom4.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL prog_rom4_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/sync_prom.qip b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/sync_prom.qip new file mode 100644 index 00000000..9a31148f --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/sync_prom.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "ROM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "sync_prom.vhd"] diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/sync_prom.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/sync_prom.vhd new file mode 100644 index 00000000..b078c62d --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/roms/sync_prom.vhd @@ -0,0 +1,141 @@ +-- megafunction wizard: %ROM: 1-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: sync_prom.vhd +-- Megafunction Name(s): +-- altsyncram +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.1.4 Build 182 03/12/2014 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2014 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files from any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.altera_mf_components.all; + +ENTITY sync_prom IS + PORT + ( + address : IN STD_LOGIC_VECTOR (7 DOWNTO 0); + clock : IN STD_LOGIC := '1'; + q : OUT STD_LOGIC_VECTOR (3 DOWNTO 0) + ); +END sync_prom; + + +ARCHITECTURE SYN OF sync_prom IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (3 DOWNTO 0); + +BEGIN + q <= sub_wire0(3 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + init_file => "./rtl/roms/6400-01m2.hex", + intended_device_family => "Cyclone II", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 256, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => "UNREGISTERED", + widthad_a => 8, + width_a => 4, + width_byteena_a => 1 + ) + PORT MAP ( + address_a => address, + clock0 => clock, + q_a => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +-- Retrieval info: PRIVATE: AclrByte NUMERIC "0" +-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: Clken NUMERIC "0" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MIFfilename STRING "./rtl/roms/6400-01m2.hex" +-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "256" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +-- Retrieval info: PRIVATE: RegAddr NUMERIC "1" +-- Retrieval info: PRIVATE: RegOutput NUMERIC "0" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: SingleClock NUMERIC "1" +-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" +-- Retrieval info: PRIVATE: WidthAddr NUMERIC "8" +-- Retrieval info: PRIVATE: WidthData NUMERIC "4" +-- Retrieval info: PRIVATE: rden NUMERIC "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: INIT_FILE STRING "./rtl/roms/6400-01m2.hex" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "256" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "8" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "4" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: USED_PORT: address 0 0 8 0 INPUT NODEFVAL "address[7..0]" +-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +-- Retrieval info: USED_PORT: q 0 0 4 0 OUTPUT NODEFVAL "q[3..0]" +-- Retrieval info: CONNECT: @address_a 0 0 8 0 address 0 0 8 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +-- Retrieval info: CONNECT: q 0 0 4 0 @q_a 0 0 4 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL sync_prom.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL sync_prom.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL sync_prom.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL sync_prom.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL sync_prom_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/scandoubler.sv b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/scandoubler.sv new file mode 100644 index 00000000..0213d20c --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/scandoubler.sv @@ -0,0 +1,195 @@ +// +// scandoubler.v +// +// Copyright (c) 2015 Till Harbaum +// Copyright (c) 2017 Sorgelig +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// TODO: Delay vsync one line + +module scandoubler #(parameter LENGTH, parameter HALF_DEPTH) +( + // system interface + input clk_sys, + input ce_pix, + input ce_pix_actual, + + input hq2x, + + // shifter video interface + input hs_in, + input vs_in, + input line_start, + + input [DWIDTH:0] r_in, + input [DWIDTH:0] g_in, + input [DWIDTH:0] b_in, + input mono, + + // output interface + output reg hs_out, + output vs_out, + output [DWIDTH:0] r_out, + output [DWIDTH:0] g_out, + output [DWIDTH:0] b_out +); + + +localparam DWIDTH = HALF_DEPTH ? 2 : 5; + +assign vs_out = vs_in; + +reg [2:0] phase; +reg [2:0] ce_div; +reg [7:0] pix_len = 0; +wire [7:0] pl = pix_len + 1'b1; + +reg ce_x1, ce_x4; +reg req_line_reset; +wire ls_in = hs_in | line_start; +always @(negedge clk_sys) begin + reg old_ce; + reg [2:0] ce_cnt; + + reg [7:0] pixsz2, pixsz4 = 0; + + old_ce <= ce_pix; + if(~&pix_len) pix_len <= pix_len + 1'd1; + + ce_x4 <= 0; + ce_x1 <= 0; + + // use such odd comparison to place c_x4 evenly if master clock isn't multiple 4. + if((pl == pixsz4) || (pl == pixsz2) || (pl == (pixsz2+pixsz4))) begin + phase <= phase + 1'd1; + ce_x4 <= 1; + end + + if(~old_ce & ce_pix) begin + pixsz2 <= {1'b0, pl[7:1]}; + pixsz4 <= {2'b00, pl[7:2]}; + ce_x1 <= 1; + ce_x4 <= 1; + pix_len <= 0; + phase <= phase + 1'd1; + + ce_cnt <= ce_cnt + 1'd1; + if(ce_pix_actual) begin + phase <= 0; + ce_div <= ce_cnt + 1'd1; + ce_cnt <= 0; + req_line_reset <= 0; + end + + if(ls_in) req_line_reset <= 1; + end +end + +reg ce_sd; +always @(*) begin + case(ce_div) + 2: ce_sd = !phase[0]; + 4: ce_sd = !phase[1:0]; + default: ce_sd <= 1; + endcase +end + +`define BITS_TO_FIT(N) ( \ + N <= 2 ? 0 : \ + N <= 4 ? 1 : \ + N <= 8 ? 2 : \ + N <= 16 ? 3 : \ + N <= 32 ? 4 : \ + N <= 64 ? 5 : \ + N <= 128 ? 6 : \ + N <= 256 ? 7 : \ + N <= 512 ? 8 : \ + N <=1024 ? 9 : 10 ) + +localparam AWIDTH = `BITS_TO_FIT(LENGTH); +Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x +( + .clk(clk_sys), + .ce_x4(ce_x4 & ce_sd), + .inputpixel({b_in,g_in,r_in}), + .mono(mono), + .disable_hq2x(~hq2x), + .reset_frame(vs_in), + .reset_line(req_line_reset), + .read_y(sd_line), + .read_x(sd_h_actual), + .outpixel({b_out,g_out,r_out}) +); + +reg [10:0] sd_h_actual; +always @(*) begin + case(ce_div) + 2: sd_h_actual = sd_h[10:1]; + 4: sd_h_actual = sd_h[10:2]; + default: sd_h_actual = sd_h; + endcase +end + +reg [10:0] sd_h; +reg [1:0] sd_line; +always @(posedge clk_sys) begin + + reg [11:0] hs_max,hs_rise,hs_ls; + reg [10:0] hcnt; + reg [11:0] sd_hcnt; + + reg hs, hs2, vs, ls; + + if(ce_x1) begin + hs <= hs_in; + ls <= ls_in; + + if(ls && !ls_in) hs_ls <= {hcnt,1'b1}; + + // falling edge of hsync indicates start of line + if(hs && !hs_in) begin + hs_max <= {hcnt,1'b1}; + hcnt <= 0; + if(ls && !ls_in) hs_ls <= {10'd0,1'b1}; + end else begin + hcnt <= hcnt + 1'd1; + end + + // save position of rising edge + if(!hs && hs_in) hs_rise <= {hcnt,1'b1}; + + vs <= vs_in; + if(vs && ~vs_in) sd_line <= 0; + end + + if(ce_x4) begin + hs2 <= hs_in; + + // output counter synchronous to input and at twice the rate + sd_hcnt <= sd_hcnt + 1'd1; + sd_h <= sd_h + 1'd1; + if(hs2 && !hs_in) sd_hcnt <= hs_max; + if(sd_hcnt == hs_max) sd_hcnt <= 0; + + // replicate horizontal sync at twice the speed + if(sd_hcnt == hs_max) hs_out <= 0; + if(sd_hcnt == hs_rise) hs_out <= 1; + + if(sd_hcnt == hs_ls) sd_h <= 0; + if(sd_hcnt == hs_ls) sd_line <= sd_line + 1'd1; + end +end + +endmodule diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/screech.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/screech.vhd new file mode 100644 index 00000000..10dcab3e --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/screech.vhd @@ -0,0 +1,72 @@ +-- Tire screech sound generator for Kee Games Sprint 2 +-- (c) 2017 James Sweet +-- +-- Original circuit used a 7414 Schmitt trigger oscillator operating at approximately +-- 1.2kHz producing a sawtooth with the frequency modulated slightly by the pseudo-random +-- noise generator. This is an extension of work initially done in Verilog by Jonas Elofsson. +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity tire_screech is +generic( + constant Inc1 : integer := 24; -- These constants can be adjusted to tune the frequency and modulation + constant Inc2 : integer := 34; + constant Dec1 : integer := 23; + constant Dec2 : integer := 12 + ); +port( + Clk : in std_logic; -- 750kHz from the horizontal line counter chain works well here + Noise : in std_logic; -- Output from LFSR pseudo-random noise generator + Screech_out : out std_logic -- Screech output - single bit + ); +end tire_screech; + +architecture rtl of tire_screech is + +signal Screech_count : integer range 1000 to 11000; +signal Screech_state : std_logic; + +begin + +Screech: process(Clk, Screech_state) +begin + if rising_edge(Clk) then + if screech_state = '1' then -- screech_state is 1, counter is rising + if noise = '1' then -- Noise signal from LFSR, when high increases the slope of the rising ramp + screech_count <= screech_count + inc2; + else -- When Noise is low, decreas the slope of the ramp + screech_count <= screech_count + inc1; + end if; + if screech_count > 10000 then -- Reverse the ramp direction when boundary value of 10,000 is reached + screech_state <= '0'; + end if; + elsif screech_state = '0' then -- screech_state is now low, decrement the counter (ramp down) + if noise = '1' then + screech_count <= screech_count - dec2; -- Slope is influenced by the Noise signal + else + screech_count <= screech_count - dec1; + end if; + if screech_count < 1000 then -- Reverse the ramp direction again when the lower boundary of 1,000 is crossed + screech_state <= '1'; + end if; + end if; + end if; +screech_out <= screech_state; +end process; + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sprint1.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sprint1.vhd new file mode 100644 index 00000000..83424a60 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sprint1.vhd @@ -0,0 +1,313 @@ +-- Top level file for Kee Games Sprint 1 +-- (c) 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +-- Targeted to EP2C5T144C8 mini board but porting to nearly any FPGA should be fairly simple +-- See Sprint 1 manual for video output details. Resistor values listed here have been scaled +-- for 3.3V logic. +-- R48 1k Ohm +-- R49 1k Ohm +-- R50 680R +-- R51 330R + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + + +entity sprint1 is +port( + Clk_50_I : in std_logic; -- 50MHz input clock + clk_12 : in std_logic; -- 12MHz input clock + Reset_n : in std_logic; -- Reset button (Active low) + + + VideoW_O : out std_logic; -- White video output (680 Ohm) + VideoB_O : out std_logic; -- Black video output (1.2k) + Sync_O : out std_logic; -- Composite sync output (1.2k) + + + Hs : out std_logic; + Vs : out std_logic; + Vb : out std_logic; + Hb : out std_logic; + Video : out std_logic; + + Audio : out std_logic_vector(6 downto 0); + Coin1_I : in std_logic; -- Coin switches (Active low) + Coin2_I : in std_logic; + Start_I : in std_logic; -- Start button + Gas_I : in std_logic; -- Gas pedal + Gear1_I : in std_logic; -- Gear shifter, 4th gear = no other gear selected + Gear2_I : in std_logic; + Gear3_I : in std_logic; + Test_I : in std_logic; -- Self-test switch + SteerA_I : in std_logic; -- Steering wheel inputs, these are quadrature encoders + SteerB_I : in std_logic; + StartLamp_O : out std_logic -- Start button lamp + ); +end sprint1; + +architecture rtl of sprint1 is + +signal clk_6 : std_logic; +signal phi1 : std_logic; +signal phi2 : std_logic; + +signal Hcount : std_logic_vector(8 downto 0) := (others => '0'); +signal H256 : std_logic; +signal H256_s : std_logic; +signal H256_n : std_logic; +signal H128 : std_logic; +signal H64 : std_logic; +signal H32 : std_logic; +signal H16 : std_logic; +signal H8 : std_logic; +signal H8_n : std_logic; +signal H4 : std_logic; +signal H4_n : std_logic; +signal H2 : std_logic; +signal H1 : std_logic; + + + +signal Vcount : std_logic_vector(7 downto 0) := (others => '0'); +signal V128 : std_logic; +signal V64 : std_logic; +signal V32 : std_logic; +signal V16 : std_logic; +signal V8 : std_logic; +signal V4 : std_logic; +signal V2 : std_logic; +signal V1 : std_logic; + + +signal Vreset : std_logic; +signal Vblank_s : std_logic; +signal Vblank_n_s : std_logic; +signal Vblank : std_logic; +signal Hblank : std_logic; +signal Hsync : std_logic; +signal Vsync : std_logic; + +signal CompBlank_s : std_logic; +signal CompSync_n_s : std_logic; + +signal WhitePF_n : std_logic; +signal BlackPF_n : std_logic; + +signal Display : std_logic_vector(7 downto 0); + +-- Address decoder +signal addec_bus : std_logic_vector(7 downto 0); +signal RnW : std_logic; +signal Write_n : std_logic; +signal ROM1 : std_logic; +signal ROM2 : std_logic; +signal ROM3 : std_logic; +signal WRAM : std_logic; +signal RAM_n : std_logic; +signal Sync_n : std_logic; +signal Switch_n : std_logic; +signal Collision1_n : std_logic; +signal Collision2_n : std_logic; +signal Display_n : std_logic; +signal TimerReset_n : std_logic; +signal CollRst1_n : std_logic; +signal CollRst2_n : std_logic; +signal SteerRst1_n : std_logic; +signal SteerRst2_n : std_logic; +signal NoiseRst_n : std_logic; +signal Attract : std_logic; +signal Skid1 : std_logic; +signal Skid2 : std_logic; + +signal Crash_n : std_logic; +signal Motor1_n : std_logic; +signal Motor2_n : std_logic; +signal Car1 : std_logic; +signal Car1_n : std_logic; +signal Car2 : std_logic; +signal Car2_n : std_logic; +signal Car3_4_n : std_logic; + +signal NMI_n : std_logic; + +signal Adr : std_logic_vector(9 downto 0); + +signal SW1 : std_logic_vector(7 downto 0); + +signal Inputs : std_logic_vector(1 downto 0); +signal Collisions1 : std_logic_vector(1 downto 0); +signal Collisions2 : std_logic_vector(1 downto 0); + +begin +-- Configuration DIP switches, these can be brought out to external switches if desired +-- See Sprint 2 manual page 11 for complete information. Active low (0 = On, 1 = Off) +-- 1 Oil slicks (0 - Oil slicks enabled) +-- 2 Cycle tracks (0/1 - Cycle every lap/every two laps) +-- 3 4 Coins per play (00 - 1 Coin per player) +-- 5 Extended Play (0 - Extended Play enabled) +-- 6 Not used (X - Don't care) +-- 7 8 Game time (01 - 120 Seconds) +SW1 <= "11000101"; -- Config dip switches + + +Vid_sync: entity work.synchronizer +port map( + clk_12 => clk_12, + clk_6 => clk_6, + hcount => hcount, + vcount => vcount, + hsync => hsync, + hblank => hblank, + vblank_s => vblank_s, + vblank_n_s => vblank_n_s, + vblank => vblank, + vsync => vsync, + vreset => vreset + ); + + +Background: entity work.playfield +port map( + clk6 => clk_6, + display => display, + HCount => HCount, + VCount => VCount, + HBlank => HBlank, + H256_s => H256_s, + VBlank => VBlank, + VBlank_n_s => Vblank_n_s, + HSync => Hsync, + VSync => VSync, + CompSync_n_s => CompSync_n_s, + CompBlank_s => CompBlank_s, + WhitePF_n => WhitePF_n, + BlackPF_n => BlackPF_n + ); + + +Cars: entity work.motion +port map( + CLK6 => clk_6, + CLK12 => clk_12, + PHI2 => phi2, + DISPLAY => Display, + H256_s => H256_s, + VCount => VCount, + HCount => HCount, + Crash_n => Crash_n, + Motor1_n => Motor1_n, + Car1 => Car1, + Car1_n => Car1_n, + Car2 => Car2, + Car2_n => Car2_n, + Car3_4_n => Car3_4_n + ); + + +PF_Comparator: entity work.collision_detect +port map( + Clk6 => Clk_6, + Car1 => Car1, + Car1_n => Car1_n, + Car2 => Car2, + Car2_n => Car2_n, + Car3_4_n => Car3_4_n, + WhitePF_n => WhitePF_n, + BlackPF_n => BlackPF_n, + CollRst1_n => CollRst1_n, + Collisions1 => Collisions1 + ); + + +CPU: entity work.cpu_mem +port map( + Clk12 => clk_12, + Clk6 => clk_6, + Reset_n => reset_n, + VCount => VCount, + HCount => HCount, + Hsync_n => not Hsync, + Vblank_s => Vblank_s, + Vreset => Vreset, + Test_n => not Test_I, + Attract => Attract, + Skid1 => Skid1, + Skid2 => Skid2, + NoiseReset_n => NoiseRst_n, + CollRst1_n => CollRst1_n, + CollRst2_n => CollRst2_n, + SteerRst1_n => SteerRst1_n, + Lamp1 => StartLamp_O, + Phi1_o => Phi1, + Phi2_o => Phi2, + Display => Display, + IO_Adr => Adr, + Collisions1 => Collisions1, + Collisions2 => Collisions2, + Inputs => Inputs + ); + + +Input: entity work.Control_Inputs +port map( + clk6 => clk_6, + SW1 => SW1, -- DIP switches + Coin1_n => Coin1_I, + Coin2_n => Coin2_I, + Start => not Start_I, -- Active high in real hardware, inverting these makes more sense with the FPGA + Gas => not Gas_I, + Gear1 => not Gear1_I, + Gear2 => not Gear2_I, + Gear3 => not Gear3_I, + Self_Test => not Test_I, + Steering1A_n => SteerA_I, + Steering1B_n => SteerB_I, + SteerRst1_n => SteerRst1_n, + Adr => Adr, + Inputs => Inputs + ); + + +Sound: entity work.audio +port map( + Clk_50 => Clk_50_I, + Clk_6 => Clk_6, + Reset_n => Reset_n, + Motor1_n => Motor1_n, + Skid1 => Skid1, + Crash_n => Crash_n, + NoiseReset_n => NoiseRst_n, + Attract => Attract, + Display => Display, + HCount => HCount, + VCount => VCount, + Audio1 => Audio + ); + +-- Video mixing +VideoB_O <= (not(BlackPF_n and Car2_n and Car3_4_n)) nor CompBlank_s; +VideoW_O <= not(WhitePF_n and Car1_n); +Sync_O <= CompSync_n_s; + +Vb <= VBLANK; +Hb <= HBLANK; +Hs <= Hsync; +Vs <= Vsync; +Video <= (WhitePF_n and blackpf_n and car1_n and Car2_n and Car3_4_n) nor CompBlank_s; + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sprint2.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sprint2.vhd new file mode 100644 index 00000000..d147f567 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sprint2.vhd @@ -0,0 +1,338 @@ +-- Top level file for Kee Games Sprint 2 +-- (c) 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +-- Targeted to EP2C5T144C8 mini board but porting to nearly any FPGA should be fairly simple +-- See Sprint 2 manual for video output details. Resistor values listed here have been scaled +-- for 3.3V logic. +-- R48 1k Ohm +-- R49 1k Ohm +-- R50 680R +-- R51 330R + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + + +entity sprint2 is +port( + clk_12 : in std_logic; -- 12MHz input clock + Reset_n : in std_logic; -- Reset button (Active low) + VideoW_O : out std_logic; -- White video output (680 Ohm) + VideoB_O : out std_logic; -- Black video output (1.2k) + Sync_O : out std_logic; -- Composite sync output (1.2k) + Audio1_O : out std_logic_vector(6 downto 0); -- Ideally this should have a simple low pass filter + Audio2_O : out std_logic_vector(6 downto 0); + + Hs : out std_logic; + Vs : out std_logic; + Vb : out std_logic; + Hb : out std_logic; + Video : out std_logic; + + Coin1_I : in std_logic; -- Coin switches (Active low) + Coin2_I : in std_logic; + Start1_I : in std_logic; -- Start buttons + Start2_I : in std_logic; + Trak_Sel_I : in std_logic; -- Track select button + Gas1_I : in std_logic; -- Gas pedals + Gas2_I : in std_logic; + Gear1_1_I : in std_logic; -- Gear shifters, 4th gear = no other gear selected + Gear1_2_I : in std_logic; + Gear2_1_I : in std_logic; + Gear2_2_I : in std_logic; + Gear3_1_I : in std_logic; + Gear3_2_I : in std_logic; + Test_I : in std_logic; -- Self-test switch + Steer_1A_I : in std_logic; -- Steering wheel inputs, these are quadrature encoders + Steer_1B_I : in std_logic; + Steer_2A_I : in std_logic; + Steer_2B_I : in std_logic; + Lamp1_O : out std_logic; -- Player 1 and 2 start button LEDs + Lamp2_O : out std_logic + ); +end sprint2; + +architecture rtl of sprint2 is + +signal clk_6 : std_logic; +signal phi1 : std_logic; +signal phi2 : std_logic; + +signal Hcount : std_logic_vector(8 downto 0) := (others => '0'); +signal H256 : std_logic; +signal H256_s : std_logic; +signal H256_n : std_logic; +signal H128 : std_logic; +signal H64 : std_logic; +signal H32 : std_logic; +signal H16 : std_logic; +signal H8 : std_logic; +signal H8_n : std_logic; +signal H4 : std_logic; +signal H4_n : std_logic; +signal H2 : std_logic; +signal H1 : std_logic; + +signal Hsync : std_logic; +signal Vsync : std_logic; + +signal Vcount : std_logic_vector(7 downto 0) := (others => '0'); +signal V128 : std_logic; +signal V64 : std_logic; +signal V32 : std_logic; +signal V16 : std_logic; +signal V8 : std_logic; +signal V4 : std_logic; +signal V2 : std_logic; +signal V1 : std_logic; + +signal Vblank : std_logic; +signal Vreset : std_logic; +signal Vblank_s : std_logic; +signal Vblank_n_s : std_logic; +signal HBlank : std_logic; + +signal CompBlank_s : std_logic; +signal CompSync_n_s : std_logic; + +signal WhitePF_n : std_logic; +signal BlackPF_n : std_logic; + +signal Display : std_logic_vector(7 downto 0); + + +-- Address decoder +signal addec_bus : std_logic_vector(7 downto 0); +signal RnW : std_logic; +signal Write_n : std_logic; +signal ROM1 : std_logic; +signal ROM2 : std_logic; +signal ROM3 : std_logic; +signal WRAM : std_logic; +signal RAM_n : std_logic; +signal Sync_n : std_logic; +signal Switch_n : std_logic; +signal Collision1_n : std_logic; +signal Collision2_n : std_logic; +signal Display_n : std_logic; +signal TimerReset_n : std_logic; +signal CollRst1_n : std_logic; +signal CollRst2_n : std_logic; +signal SteerRst1_n : std_logic; +signal SteerRst2_n : std_logic; +signal NoiseRst_n : std_logic; +signal Attract : std_logic := '1'; +signal Skid1 : std_logic; +signal Skid2 : std_logic; +signal Lamp1 : std_logic; +signal Lamp2 : std_logic; + +signal Crash_n : std_logic; +signal Motor1_n : std_logic; +signal Motor2_n : std_logic; +signal Car1 : std_logic; +signal Car1_n : std_logic; +signal Car2 : std_logic; +signal Car2_n : std_logic; +signal Car3_4_n : std_logic; + +signal NMI_n : std_logic; + +signal Adr : std_logic_vector(9 downto 0); + +signal SW1 : std_logic_vector(7 downto 0); + +signal Inputs : std_logic_vector(1 downto 0); +signal Collisions1 : std_logic_vector(1 downto 0); +signal Collisions2 : std_logic_vector(1 downto 0); + + +begin +-- Configuration DIP switches, these can be brought out to external switches if desired +-- See Sprint 2 manual page 11 for complete information. Active low (0 = On, 1 = Off) +-- 1 Oil slicks (0 - Oil slicks enabled) +-- 2 Cycle tracks (1 - Cycle through all tracks in attract mode) +-- 3 4 Coins per play (00 - 1 Coin per player) +-- 5 Extended Play (0 - Extended Play enabled) +-- 6 Not used (X - Don't care) +-- 7 8 Game time (01 - 120 Seconds) +SW1 <= "01000101"; -- Config dip switches + + +Vid_sync: entity work.synchronizer +port map( + clk_12 => clk_12, + clk_6 => clk_6, + hcount => hcount, + vcount => vcount, + hsync => hsync, + hblank => hblank, + vblank_s => vblank_s, + vblank_n_s => vblank_n_s, + vblank => vblank, + vsync => vsync, + vreset => vreset + ); + + +Background: entity work.playfield +port map( + clk6 => clk_6, + display => display, + HCount => HCount, + VCount => VCount, + HBlank => HBlank, + H256_s => H256_s, + VBlank => VBlank, + VBlank_n_s => Vblank_n_s, + HSync => Hsync, + VSync => VSync, + CompSync_n_s => CompSync_n_s, + CompBlank_s => CompBlank_s, + WhitePF_n => WhitePF_n, + BlackPF_n => BlackPF_n + ); + + +Cars: entity work.motion +port map( + CLK6 => clk_6, + CLK12 => clk_12, + PHI2 => phi2, + DISPLAY => Display, + H256_s => H256_s, + VCount => VCount, + HCount => HCount, + Crash_n => Crash_n, + Motor1_n => Motor1_n, + Motor2_n => Motor2_n, + Car1 => Car1, + Car1_n => Car1_n, + Car2 => Car2, + Car2_n => Car2_n, + Car3_4_n => Car3_4_n + ); + + +PF_Comparator: entity work.collision_detect +port map( + Clk6 => clk_6, + Car1 => Car1, + Car1_n => Car1_n, + Car2 => Car2, + Car2_n => Car2_n, + Car3_4_n => Car3_4_n, + WhitePF_n => WhitePF_n, + BlackPF_n => BlackPF_n, + CollRst1_n => CollRst1_n, + CollRst2_n => CollRst2_n, + Collisions1 => Collisions1, + Collisions2 => Collisions2 + ); + + +CPU: entity work.cpu_mem +port map( + Clk12 => clk_12, + Clk6 => clk_6, + Reset_n => reset_n, + VCount => VCount, + HCount => HCount, + Hsync_n => not Hsync, + Vblank_s => Vblank_s, + Vreset => Vreset, + Test_n => not Test_I, + Attract => Attract, + Skid1 => Skid1, + Skid2 => Skid2, + NoiseReset_n => NoiseRst_n, + CollRst1_n => CollRst1_n, + CollRst2_n => CollRst2_n, + SteerRst1_n => SteerRst1_n, + SteerRst2_n => SteerRst2_n, + Lamp1 => Lamp1_O, + Lamp2 => Lamp2_O, + Phi1_o => Phi1, + Phi2_o => Phi2, + Display => Display, + IO_Adr => Adr, + Collisions1 => Collisions1, + Collisions2 => Collisions2, + Inputs => Inputs + ); + + +Input: entity work.Control_Inputs +port map( + clk6 => clk_6, + SW1 => SW1, -- DIP switches + Coin1_n => Coin1_I, + Coin2_n => Coin2_I, + Start1 => not Start1_I, -- Active high in real hardware, inverting these makes more sense with the FPGA + Start2 => not Start2_I, + Trak_Sel => not Trak_Sel_I, + Gas1 => not Gas1_I, + Gas2 => not Gas2_I, + Gear1_1 => not Gear1_1_I, + Gear1_2 => not Gear1_2_I, + Gear2_1 => not Gear2_1_I, + Gear2_2 => not Gear2_2_I, + Gear3_1 => not Gear3_1_I, + Gear3_2 => not Gear3_2_I, + Self_Test => not Test_I, + Steering1A_n => Steer_1A_I, + Steering1B_n => Steer_1B_I, + Steering2A_n => Steer_2A_I, + Steering2B_n => Steer_2B_I, + SteerRst1_n => SteerRst1_n, + SteerRst2_n => SteerRst2_n, + Adr => Adr, + Inputs => Inputs + ); + + +Sound: entity work.audio +port map( + Clk_6 => Clk_6, + Reset_n => Reset_n, + Motor1_n => Motor1_n, + Motor2_n => Motor2_n, + Skid1 => Skid1, + Skid2 => Skid2, + Crash_n => Crash_n, + NoiseReset_n => NoiseRst_n, + Attract => Attract, + Display => Display, + HCount => HCount, + VCount => VCount, + Audio1 => Audio1_O, + Audio2 => Audio2_O + ); + +-- Video mixing +VideoB_O <= (not(BlackPF_n and Car2_n and Car3_4_n)) nor CompBlank_s; +VideoW_O <= not(WhitePF_n and Car1_n and Car3_4_n); +Sync_O <= CompSync_n_s; + + +Vb <= VBLANK; +Hb <= HBLANK; +Hs <= Hsync; +Vs <= Vsync; +Video <= (WhitePF_n and blackpf_n and car1_n and Car2_n and Car3_4_n) nor CompBlank_s; + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sprint2_mist.sv b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sprint2_mist.sv new file mode 100644 index 00000000..eef9fcb4 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sprint2_mist.sv @@ -0,0 +1,157 @@ +module sprint2_mist( + output LED, + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_HS, + output VGA_VS, + output AUDIO_L, + output AUDIO_R, + input SPI_SCK, + output SPI_DO, + input SPI_DI, + input SPI_SS2, + input SPI_SS3, + input CONF_DATA0, + input CLOCK_27 +); + +`include "rtl\build_id.sv" + +localparam CONF_STR = { + "Sprint2;;", + "O1,Test Mode,Off,On;", + "T2,Next Track;", + "O34,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;", + "T6,Reset;", + "V,v1.00.",`BUILD_DATE +}; + +wire [31:0] status; +wire [1:0] buttons; +wire [1:0] switches; +wire [9:0] kbjoy; +wire [7:0] joystick_0; +wire [7:0] joystick_1; +wire scandoubler_disable; +wire ypbpr; +wire ps2_kbd_clk, ps2_kbd_data; +wire [6:0] audio1, audio2; +wire video; + +wire clk_48, clk_12; +wire locked; +pll pll +( + .inclk0(CLOCK_27), + .c0(clk_48), + .c1(clk_12), + .locked(locked) +); + +wire led1, led2; +assign LED = (led1 | led2); + +sprint2 sprint2 ( + .clk_12(clk_12), + .Reset_n(~(status[0] | status[6] | buttons[1])), + .VideoW_O(), + .VideoB_O(), + .Sync_O(), + .Hs(hs), + .Vs(vs), + .Vb(vb), + .Hb(hb), + .Video(video), + .Audio1_O(audio1), + .Audio2_O(audio2), + .Coin1_I(~kbjoy[7]), + .Coin2_I(~kbjoy[7]), + .Start1_I(~kbjoy[5]), + .Start2_I(~kbjoy[6]), + .Trak_Sel_I(~status[2]), + .Gas1_I(~kbjoy[4]), + .Gas2_I(), +// .Gear1_1_I(),// Gear shifters, 4th gear = no other gear selected +// .Gear1_2_I(), +// .Gear1_3_I(), +// .Gear2_1_I(), +// .Gear2_2_I(), +// .Gear2_3_I(), + .Test_I(~status[1]), + .Steer_1A_I(~kbjoy[1]),// Steering wheel inputs, these are quadrature encoders + .Steer_1B_I(~kbjoy[0]), +// .Steer_2A_I(), +// .Steer_2B_I(), + .Lamp1_O(led1), + .Lamp2_O(led2) +); + +dac dac ( + .CLK(clk_48), + .RESET(1'b0), + .DACin({audio1, audio2}), + .DACout(AUDIO_L) + ); + +assign AUDIO_R = AUDIO_L; + +wire hs, vs; +wire hb, vb; +wire blankn = ~(hb | vb); +video_mixer #(.LINE_LENGTH(480), .HALF_DEPTH(1)) video_mixer +( + .clk_sys(clk_48), + .ce_pix(clk_12), + .ce_pix_actual(clk_12), + .SPI_SCK(SPI_SCK), + .SPI_SS3(SPI_SS3), + .SPI_DI(SPI_DI), + .R(blankn ? {video,video,video} : "000"), + .G(blankn ? {video,video,video} : "000"), + .B(blankn ? {video,video,video} : "000"), + .HSync(hs), + .VSync(vs), + .VGA_R(VGA_R), + .VGA_G(VGA_G), + .VGA_B(VGA_B), + .VGA_VS(VGA_VS), + .VGA_HS(VGA_HS), + .scandoubler_disable(scandoubler_disable), + .scanlines(scandoubler_disable ? 2'b00 : {status[4:3] == 3, status[4:3] == 2}), + .hq2x(status[4:3]==1), + .ypbpr_full(1), + .line_start(0), + .mono(0) +); + +mist_io #(.STRLEN(($size(CONF_STR)>>3))) mist_io +( + .clk_sys (clk_48 ), + .conf_str (CONF_STR ), + .SPI_SCK (SPI_SCK ), + .CONF_DATA0 (CONF_DATA0 ), + .SPI_SS2 (SPI_SS2 ), + .SPI_DO (SPI_DO ), + .SPI_DI (SPI_DI ), + .buttons (buttons ), + .switches (switches ), + .scandoubler_disable(scandoubler_disable), + .ypbpr (ypbpr ), + .ps2_kbd_clk (ps2_kbd_clk ), + .ps2_kbd_data (ps2_kbd_data ), + .joystick_0 (joystick_0 ), + .joystick_1 (joystick_1 ), + .status (status ) +); + +keyboard keyboard( + .clk(clk_48), + .reset(), + .ps2_kbd_clk(ps2_kbd_clk), + .ps2_kbd_data(ps2_kbd_data), + .joystick(kbjoy) + ); + + +endmodule diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sprint2_sound.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sprint2_sound.vhd new file mode 100644 index 00000000..f0bd0765 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sprint2_sound.vhd @@ -0,0 +1,245 @@ +-- Audio for Sprint 2 +-- First attempt at modeling the analog sound circuits used in Sprint 2, may be room for improvement as +-- I do not have a real board to compare. +-- (c) 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity audio is +port( + Clk_6 : in std_logic; + Reset_n : in std_logic; + Motor1_n : in std_logic; + Motor2_n : in std_logic; + Skid1 : in std_logic; + Skid2 : in std_logic; + Crash_n : in std_logic; + NoiseReset_n : in std_logic; + Attract : in std_logic; + Display : in std_logic_vector(7 downto 0); + HCount : in std_logic_vector(8 downto 0); + VCount : in std_logic_vector(7 downto 0); + Audio1 : out std_logic_vector(6 downto 0); + Audio2 : out std_logic_vector(6 downto 0) + ); +end audio; + +architecture rtl of audio is + +signal reset : std_logic; + +signal H4 : std_logic; +signal V2 : std_logic; + +signal Noise : std_logic; +signal Noise_Shift : std_logic_vector(15 downto 0); +signal Shift_in : std_logic; + +signal Screech_count : integer range 1000 to 11000; +signal Screech_state : std_logic; +signal Screech_snd1 : std_logic; +signal Screech_snd2 : std_logic; +signal Screech1 : std_logic_vector(3 downto 0); +signal Screech2 : std_logic_vector(3 downto 0); + +signal Crash : std_logic_vector(3 downto 0); +signal Bang : std_logic_vector(3 downto 0); + +signal Mtr1_Freq : std_logic_vector(3 downto 0); +signal Mtr2_Freq : std_logic_vector(3 downto 0); +signal Motor1_speed : std_logic_vector(3 downto 0); +signal Motor1_snd : std_logic_vector(5 downto 0); +signal Motor2_speed : std_logic_vector(3 downto 0); +signal Motor2_snd : std_logic_vector(5 downto 0); + +signal ena_count : std_logic_vector(10 downto 0); +signal ena_3k : std_logic; + +signal bang_prefilter : std_logic_vector(3 downto 0); +signal bang_filter_t1 : std_logic_vector(3 downto 0); +signal bang_filter_t2 : std_logic_vector(3 downto 0); +signal bang_filter_t3 : std_logic_vector(3 downto 0); +signal bang_filtered : std_logic_vector(5 downto 0); + + +begin + +-- HCount +-- (0) 1H 3 MHz +-- (1) 2H 1.5MHz +-- (2) 4H 750 kHz +-- (3) 8H 375 kHz +-- (4) 16H 187 kHz +-- (5) 32H 93 kHz +-- (6) 64H 46 kHz +-- (7) 128H 23 kHz +-- (8) 256H 12 kHz + +reset <= (not reset_n); + +H4 <= HCount(2); +V2 <= VCount(1); + +-- Generate the 3kHz clock enable used by the filter +Enable: process(clk_6) +begin + if rising_edge(CLK_6) then + ena_count <= ena_count + "1"; + ena_3k <= '0'; + if (ena_count(10 downto 0) = "00000000000") then + ena_3k <= '1'; + end if; + end if; +end process; + + +-- LFSR that generates pseudo-random noise +Noise_gen: process(NoiseReset_n, V2) +begin + if (noisereset_n = '0') then + noise_shift <= (others => '0'); + noise <= '0'; + elsif rising_edge(V2) then + shift_in <= not(noise_shift(6) xor noise_shift(8)); + noise_shift <= shift_in & noise_shift(15 downto 1); + noise <= noise_shift(0); + end if; +end process; + + +-- Tire screech sound for player 1 and 2 cars. These can be tuned slightly differently to model variations in analog sound hardware. +Screech_gen1: entity work.tire_screech +generic map( -- These values can be tweaked to tune the screech sound + Inc1 => 24, -- Ramp increase rate when noise = 0 + Inc2 => 33, -- Ramp increase rate when noise = 1 + Dec1 => 29, -- Ramp decrease rate when noise = 0 + Dec2 => 16 -- Ramp decrease rate when noise = 1 + ) +port map( + Clk => H4, + Noise => noise, + Screech_out => screech_snd1 + ); + + +Screech_gen2: entity work.tire_screech +generic map( -- These values can be tweaked to tune the screech sound + Inc1 => 24, -- Ramp increase rate when noise = 0 + Inc2 => 34, -- Ramp increase rate when noise = 1 + Dec1 => 23, -- Ramp decrease rate when noise = 0 + Dec2 => 12 -- Ramp decrease rate when noise = 1 + ) +port map( + Clk => H4, + Noise => noise, + Screech_out => screech_snd2 + ); + +-- Convert screech from 1 bit to 4 bits wide and enable via skid1 and skid2 signals +Screech_ctrl: process(screech_snd1, screech_snd2, skid1, skid2) +begin + if (skid1 and screech_snd1) = '1' then + screech1 <= "1111"; + else + screech1 <= "0000"; + end if; + + if (skid2 and screech_snd2) = '1' then + screech2 <= "1111"; + else + screech2 <= "0000"; + end if; +end process; + + +Crash_sound: process(crash_n, crash, display, noise) +begin + if crash_n = '0' then + crash <= display(3 downto 0); + end if; + if noise = '1' then + bang_prefilter <= crash; + else + bang_prefilter <= "0000"; + end if; +end process; + +---- Very simple low pass filter, borrowed from MikeJ's Asteroids code +Crash_filter: process(clk_6) +begin + if rising_edge(clk_6) then + if (ena_3k = '1') then + bang_filter_t1 <= bang_prefilter; + bang_filter_t2 <= bang_filter_t1; + bang_filter_t3 <= bang_filter_t2; + end if; + bang_filtered <= ("00" & bang_filter_t1) + + ('0' & bang_filter_t2 & '0') + + ("00" & bang_filter_t3); + end if; +end process; + + +Motor1_latch: process(Motor1_n, Display) +begin + if Motor1_n = '0' then + Motor1_speed <= Display(3 downto 0); + end if; +end process; + +Motor1: entity work.EngineSound +generic map( + Freq_tune => 50 -- Tuning pot for engine sound frequency + ) +port map( + Clk_6 => clk_6, + Ena_3k => ena_3k, + EngineData => motor1_speed, + Motor => motor1_snd + ); + + +Motor2_latch: process(Motor2_n, Display) +begin + if Motor2_n = '0' then + Motor2_speed <= Display(3 downto 0); + end if; +end process; + +Motor2: entity work.EngineSound +generic map( + Freq_tune => 48 -- Tuning pot for engine sound frequency + ) +port map( + Clk_6 => clk_6, + Ena_3k => ena_3k, + EngineData => motor2_speed, + Motor => motor2_snd + ); + + +-- Audio mixer, also mutes sound in attract mode +Audio1 <= ('0' & motor1_snd) + ("00" & screech1) + ('0' & bang_filtered);-- when attract = '0' + --else "0000000"; + +Audio2 <= ('0' & motor2_snd) + ("00" & screech2) + ('0' & bang_filtered);-- when attract = '0' + --else "0000000"; + + + + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sync.vhd b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sync.vhd new file mode 100644 index 00000000..544cee27 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/sync.vhd @@ -0,0 +1,177 @@ +-- Video synchronizer circuit for Sprint 2 +-- Similar circuit used in many other Atari and Kee Games arcade games +-- (c) 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity synchronizer is +port( + clk_12 : in std_logic; + clk_6 : out std_logic; + hcount : out std_logic_vector(8 downto 0); + vcount : out std_logic_vector(7 downto 0); + hsync : out std_logic; + hblank : out std_logic; + vblank_s : out std_logic; + vblank_n_s : out std_logic; + vblank : out std_logic; + vsync : out std_logic; + vreset : out std_logic); +end synchronizer; + +architecture rtl of synchronizer is + +signal h_counter : std_logic_vector(9 downto 0) := (others => '0'); +signal H256 : std_logic; +signal H256_n : std_logic; +signal H128 : std_logic; +signal H64 : std_logic; +signal H32 : std_logic; +signal H16 : std_logic; +signal H8 : std_logic; +signal H8_n : std_logic; +signal H4 : std_logic; +signal H4_n : std_logic; +signal H2 : std_logic; +signal H1 : std_logic; + +signal v_counter : std_logic_vector(7 downto 0) := (others => '0'); +signal V128 : std_logic; +signal V64 : std_logic; +signal V32 : std_logic; +signal V16 : std_logic; +signal V8 : std_logic; +signal V4 : std_logic; +signal V2 : std_logic; +signal V1 : std_logic; + +signal sync_bus : std_logic_vector(3 downto 0) := (others => '0'); +signal sync_reg : std_logic_vector(3 downto 0) := (others => '0'); +signal vblank_int : std_logic := '0'; +signal vreset_n : std_logic := '0'; + +signal hblank_int : std_logic := '0'; +signal hsync_int : std_logic := '0'; +signal hsync_reset : std_logic := '0'; + + +begin + +-- Horizontal counter is 9 bits long plus additional flip flop. The last 4 bit IC in the chain resets to 0010 so total count resets to 128 +-- using only the last three count states +H_count: process(clk_12) +begin + if rising_edge(clk_12) then + if h_counter = "1111111111" then + h_counter <= "0100000000"; + else + h_counter <= h_counter + 1; + end if; + end if; +end process; + +-- Vertical counter is 8 bits, clocked by the rising edge of H256 at the end of each horizontal line +V_count: process(hsync_int) +begin + if rising_edge(Hsync_int) then + if vreset_n = '0' then + v_counter <= (others => '0'); + else + v_counter <= v_counter + '1'; + end if; + end if; +end process; + +-- Many Atari raster games use a 256 x 4 bit prom to decode vertical sync signals +-- This could be replaced by combinatorial logic +M2: entity work.sync_prom +port map( + clock => clk_12, + address => sync_reg(3) & V128 & V64 & V16 & V8 & V4 & V2 & V1, + q => sync_bus + ); + +-- Register fed by the sync PROM, in the original hardware this also creates the complements of these signals +sync_register: process(hsync_int) +begin + if rising_edge(hsync_int) then + sync_reg <= sync_bus; + end if; +end process; + +-- Outputs of sync PROM +vblank_s <= sync_reg(3); +vblank_n_s <= not sync_reg(3); +vreset <= sync_reg(2); +vreset_n <= not sync_reg(2); +vblank <= sync_reg(1); +vsync <= sync_reg(0); + +-- A pair of D type flip-flops that generate the Hsync signal +Hsync_1: process(H256_n, H32) +begin + if H256_n = '0' then + hblank_int <= '0'; + else + if rising_edge(H32) then + hblank_int <= not H64; + end if; + end if; +end process; + +Hsync_2: process(hblank_int, H8) +begin + if hblank_int = '0' then + hsync_int <= '0'; + else + if rising_edge(H8) then + hsync_int <= H32; + end if; + end if; +end process; + +-- Assign various signals +clk_6 <= h_counter(0); +H1 <= h_counter(1); +H2 <= h_counter(2); +H4 <= h_counter(3); +H8 <= h_counter(4); +H16 <= h_counter(5); +H32 <= h_counter(6); +H64 <= h_counter(7); +H128 <= h_counter(8); +H256 <= h_counter(9); +H4_n <= not H4; +H8_n <= not H8; +H256_n <= not H256; + +V1 <= v_counter(0); +V2 <= v_counter(1); +V4 <= v_counter(2); +V8 <= v_counter(3); +V16 <= v_counter(4); +V32 <= v_counter(5); +V64 <= v_counter(6); +V128 <= v_counter(7); + +hcount <= h_counter(9 downto 1); +vcount <= v_counter; +hsync <= hsync_int; +hblank <= hblank_int; + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/video_mixer.sv b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/video_mixer.sv new file mode 100644 index 00000000..04cfd4ba --- /dev/null +++ b/Arcade_MiST/Custom Hardware/Sprint2_MiST/rtl/video_mixer.sv @@ -0,0 +1,242 @@ +// +// +// Copyright (c) 2017 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + +// +// LINE_LENGTH: Length of display line in pixels +// Usually it's length from HSync to HSync. +// May be less if line_start is used. +// +// HALF_DEPTH: If =1 then color dept is 3 bits per component +// For half depth 6 bits monochrome is available with +// mono signal enabled and color = {G, R} + +module video_mixer +#( + parameter LINE_LENGTH = 768, + parameter HALF_DEPTH = 0, + + parameter OSD_COLOR = 3'd4, + parameter OSD_X_OFFSET = 10'd0, + parameter OSD_Y_OFFSET = 10'd0 +) +( + // master clock + // it should be multiple by (ce_pix*4). + input clk_sys, + + // Pixel clock or clock_enable (both are accepted). + input ce_pix, + + // Some systems have multiple resolutions. + // ce_pix_actual should match ce_pix where every second or fourth pulse is enabled, + // thus half or qurter resolutions can be used without brake video sync while switching resolutions. + // For fixed single resolution (or when video sync stability isn't required) ce_pix_actual = ce_pix. + input ce_pix_actual, + + // OSD SPI interface + input SPI_SCK, + input SPI_SS3, + input SPI_DI, + + // scanlines (00-none 01-25% 10-50% 11-75%) + input [1:0] scanlines, + + // 0 = HVSync 31KHz, 1 = CSync 15KHz + input scandoubler_disable, + + // High quality 2x scaling + input hq2x, + + // YPbPr always uses composite sync + input ypbpr, + + // 0 = 16-240 range. 1 = 0-255 range. (only for YPbPr color space) + input ypbpr_full, + + // color + input [DWIDTH:0] R, + input [DWIDTH:0] G, + input [DWIDTH:0] B, + + // Monochrome mode (for HALF_DEPTH only) + input mono, + + // interlace sync. Positive pulses. + input HSync, + input VSync, + + // Falling of this signal means start of informative part of line. + // It can be horizontal blank signal. + // This signal can be used to reduce amount of required FPGA RAM for HQ2x scan doubler + // If FPGA RAM is not an issue, then simply set it to 0 for whole line processing. + // Keep in mind: due to algo first and last pixels of line should be black to avoid side artefacts. + // Thus, if blank signal is used to reduce the line, make sure to feed at least one black (or paper) pixel + // before first informative pixel. + input line_start, + + // MiST video output signals + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_VS, + output VGA_HS +); + +localparam DWIDTH = HALF_DEPTH ? 2 : 5; + +wire [DWIDTH:0] R_sd; +wire [DWIDTH:0] G_sd; +wire [DWIDTH:0] B_sd; +wire hs_sd, vs_sd; + +scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH)) scandoubler +( + .*, + .hs_in(HSync), + .vs_in(VSync), + .r_in(R), + .g_in(G), + .b_in(B), + + .hs_out(hs_sd), + .vs_out(vs_sd), + .r_out(R_sd), + .g_out(G_sd), + .b_out(B_sd) +); + +wire [DWIDTH:0] rt = (scandoubler_disable ? R : R_sd); +wire [DWIDTH:0] gt = (scandoubler_disable ? G : G_sd); +wire [DWIDTH:0] bt = (scandoubler_disable ? B : B_sd); + +generate + if(HALF_DEPTH) begin + wire [5:0] r = mono ? {gt,rt} : {rt,rt}; + wire [5:0] g = mono ? {gt,rt} : {gt,gt}; + wire [5:0] b = mono ? {gt,rt} : {bt,bt}; + end else begin + wire [5:0] r = rt; + wire [5:0] g = gt; + wire [5:0] b = bt; + end +endgenerate + +wire hs = (scandoubler_disable ? HSync : hs_sd); +wire vs = (scandoubler_disable ? VSync : vs_sd); + +reg scanline = 0; +always @(posedge clk_sys) begin + reg old_hs, old_vs; + + old_hs <= hs; + old_vs <= vs; + + if(old_hs && ~hs) scanline <= ~scanline; + if(old_vs && ~vs) scanline <= 0; +end + +wire [5:0] r_out, g_out, b_out; +always @(*) begin + case(scanlines & {scanline, scanline}) + 1: begin // reduce 25% = 1/2 + 1/4 + r_out = {1'b0, r[5:1]} + {2'b00, r[5:2]}; + g_out = {1'b0, g[5:1]} + {2'b00, g[5:2]}; + b_out = {1'b0, b[5:1]} + {2'b00, b[5:2]}; + end + + 2: begin // reduce 50% = 1/2 + r_out = {1'b0, r[5:1]}; + g_out = {1'b0, g[5:1]}; + b_out = {1'b0, b[5:1]}; + end + + 3: begin // reduce 75% = 1/4 + r_out = {2'b00, r[5:2]}; + g_out = {2'b00, g[5:2]}; + b_out = {2'b00, b[5:2]}; + end + + default: begin + r_out = r; + g_out = g; + b_out = b; + end + endcase +end + +wire [5:0] red, green, blue; +osd #(OSD_X_OFFSET, OSD_Y_OFFSET, OSD_COLOR) osd +( + .*, + + .R_in(r_out), + .G_in(g_out), + .B_in(b_out), + .HSync(hs), + .VSync(vs), + + .R_out(red), + .G_out(green), + .B_out(blue) +); + +wire [5:0] yuv_full[225] = '{ + 6'd0, 6'd0, 6'd0, 6'd0, 6'd1, 6'd1, 6'd1, 6'd1, + 6'd2, 6'd2, 6'd2, 6'd3, 6'd3, 6'd3, 6'd3, 6'd4, + 6'd4, 6'd4, 6'd5, 6'd5, 6'd5, 6'd5, 6'd6, 6'd6, + 6'd6, 6'd7, 6'd7, 6'd7, 6'd7, 6'd8, 6'd8, 6'd8, + 6'd9, 6'd9, 6'd9, 6'd9, 6'd10, 6'd10, 6'd10, 6'd11, + 6'd11, 6'd11, 6'd11, 6'd12, 6'd12, 6'd12, 6'd13, 6'd13, + 6'd13, 6'd13, 6'd14, 6'd14, 6'd14, 6'd15, 6'd15, 6'd15, + 6'd15, 6'd16, 6'd16, 6'd16, 6'd17, 6'd17, 6'd17, 6'd17, + 6'd18, 6'd18, 6'd18, 6'd19, 6'd19, 6'd19, 6'd19, 6'd20, + 6'd20, 6'd20, 6'd21, 6'd21, 6'd21, 6'd21, 6'd22, 6'd22, + 6'd22, 6'd23, 6'd23, 6'd23, 6'd23, 6'd24, 6'd24, 6'd24, + 6'd25, 6'd25, 6'd25, 6'd25, 6'd26, 6'd26, 6'd26, 6'd27, + 6'd27, 6'd27, 6'd27, 6'd28, 6'd28, 6'd28, 6'd29, 6'd29, + 6'd29, 6'd29, 6'd30, 6'd30, 6'd30, 6'd31, 6'd31, 6'd31, + 6'd31, 6'd32, 6'd32, 6'd32, 6'd33, 6'd33, 6'd33, 6'd33, + 6'd34, 6'd34, 6'd34, 6'd35, 6'd35, 6'd35, 6'd35, 6'd36, + 6'd36, 6'd36, 6'd36, 6'd37, 6'd37, 6'd37, 6'd38, 6'd38, + 6'd38, 6'd38, 6'd39, 6'd39, 6'd39, 6'd40, 6'd40, 6'd40, + 6'd40, 6'd41, 6'd41, 6'd41, 6'd42, 6'd42, 6'd42, 6'd42, + 6'd43, 6'd43, 6'd43, 6'd44, 6'd44, 6'd44, 6'd44, 6'd45, + 6'd45, 6'd45, 6'd46, 6'd46, 6'd46, 6'd46, 6'd47, 6'd47, + 6'd47, 6'd48, 6'd48, 6'd48, 6'd48, 6'd49, 6'd49, 6'd49, + 6'd50, 6'd50, 6'd50, 6'd50, 6'd51, 6'd51, 6'd51, 6'd52, + 6'd52, 6'd52, 6'd52, 6'd53, 6'd53, 6'd53, 6'd54, 6'd54, + 6'd54, 6'd54, 6'd55, 6'd55, 6'd55, 6'd56, 6'd56, 6'd56, + 6'd56, 6'd57, 6'd57, 6'd57, 6'd58, 6'd58, 6'd58, 6'd58, + 6'd59, 6'd59, 6'd59, 6'd60, 6'd60, 6'd60, 6'd60, 6'd61, + 6'd61, 6'd61, 6'd62, 6'd62, 6'd62, 6'd62, 6'd63, 6'd63, + 6'd63 +}; + +// http://marsee101.blog19.fc2.com/blog-entry-2311.html +// Y = 16 + 0.257*R + 0.504*G + 0.098*B (Y = 0.299*R + 0.587*G + 0.114*B) +// Pb = 128 - 0.148*R - 0.291*G + 0.439*B (Pb = -0.169*R - 0.331*G + 0.500*B) +// Pr = 128 + 0.439*R - 0.368*G - 0.071*B (Pr = 0.500*R - 0.419*G - 0.081*B) + +wire [18:0] y_8 = 19'd04096 + ({red, 8'd0} + {red, 3'd0}) + ({green, 9'd0} + {green, 2'd0}) + ({blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0}); +wire [18:0] pb_8 = 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0}) - ({green, 8'd0} + {green, 5'd0} + {green, 3'd0}) + ({blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0}); +wire [18:0] pr_8 = 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0}) - ({green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0}) - ({blue, 6'd0} + {blue , 3'd0}); + +wire [7:0] y = ( y_8[17:8] < 16) ? 8'd16 : ( y_8[17:8] > 235) ? 8'd235 : y_8[15:8]; +wire [7:0] pb = (pb_8[17:8] < 16) ? 8'd16 : (pb_8[17:8] > 240) ? 8'd240 : pb_8[15:8]; +wire [7:0] pr = (pr_8[17:8] < 16) ? 8'd16 : (pr_8[17:8] > 240) ? 8'd240 : pr_8[15:8]; + +assign VGA_R = ypbpr ? (ypbpr_full ? yuv_full[pr-8'd16] : pr[7:2]) : red; +assign VGA_G = ypbpr ? (ypbpr_full ? yuv_full[y -8'd16] : y[7:2]) : green; +assign VGA_B = ypbpr ? (ypbpr_full ? yuv_full[pb-8'd16] : pb[7:2]) : blue; +assign VGA_VS = (scandoubler_disable | ypbpr) ? 1'b1 : ~vs_sd; +assign VGA_HS = scandoubler_disable ? ~(HSync ^ VSync) : ypbpr ? ~(hs_sd ^ vs_sd) : ~hs_sd; + +endmodule diff --git a/Arcade_MiST/Custom Hardware/Sprint2_MiST/snapshot/sprint2.rbf b/Arcade_MiST/Custom Hardware/Sprint2_MiST/snapshot/sprint2.rbf new file mode 100644 index 0000000000000000000000000000000000000000..1a2d62dc7346bf60cf839fa348c514f06345bb09 GIT binary patch literal 252260 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 RPM_val <= 280; + when "0001" => RPM_val <= 245; + when "0010" => RPM_val <= 230; + when "0011" => RPM_val <= 205; + when "0100" => RPM_val <= 190; + when "0101" => RPM_val <= 175; + when "0110" => RPM_val <= 160; + when "0111" => RPM_val <= 145; + when "1000" => RPM_val <= 130; + when "1001" => RPM_val <= 115; + when "1010" => RPM_val <= 100; + when "1011" => RPM_val <= 85; + when "1100" => RPM_val <= 70; + when "1101" => RPM_val <= 55; + when "1110" => RPM_val <= 40; + when "1111" => RPM_val <= 25; + end case; + end if; +end process; + + +-- There is a RC filter between the frequency control DAC and the 555 to smooth out the transitions between the +-- 16 possible states. We can simulate a reasonable approximation of that behavior using a linear slope which is +-- not truly accurate but should be close enough. +RC_filt: process(clk_6, ena_3k, ramp_term_unfilt) +begin + if rising_edge(clk_6) then + if ena_3k = '1' then + if ramp_term_unfilt > ramp_term then + ramp_term <= ramp_term + 5; + elsif ramp_term_unfilt = ramp_term then + ramp_term <= ramp_term; + else + ramp_term <= ramp_term - 3; + end if; + end if; + end if; +end process; + + +-- Ramp_term terminates the ramp count, the higher this value, the longer the ramp will count up and the lower +-- the frequency. RPM_val is multiplied by a constant which can be adjusted by changing the value of freq_tune +-- to simulate the function of the frequency adjustment pot in the original hardware. +ramp_term_unfilt <= ((200 - freq_tune) * RPM_val); + +-- Variable frequency oscillator roughly approximating the function of a 555 astable oscillator +Ramp_osc: process(clk_6) +begin + if rising_edge(clk_6) then + motor_clk <= '1'; + ramp_count <= ramp_count + 1; + if ramp_count > ramp_term then + ramp_count <= 0; + motor_clk <= '0'; + end if; + end if; +end process; + + +-- 7492 counter with XOR on two of the outputs creates lumpy engine sound from smooth pulse train +-- 7492 has two sections, one div-by-2 and one div-by-6. +Engine_counter: process(motor_clk, Counter_A_clk, Counter_B) +begin + if rising_edge(motor_clk) then + Counter_B <= Counter_B + '1'; + end if; + Counter_A_clk <= Counter_B(0) xor Counter_B(2); + if rising_edge(counter_A_clk) then + Counter_A <= (not Counter_A); + end if; +end process; +motor_prefilter <= ('0' & Counter_B(2)) + ('0' & Counter_B(1)) + ('0' & Counter_A); + +-- Very simple low pass filter, borrowed from MikeJ's Asteroids code +Engine_filter: process(clk_6) +begin + if rising_edge(clk_6) then + if (ena_3k = '1') then + motor_filter_t1 <= ("00" & motor_prefilter) + ("00" & motor_prefilter); + motor_filter_t2 <= motor_filter_t1; + motor_filter_t3 <= motor_filter_t2; + end if; + motor_filtered <= ("00" & motor_filter_t1) + + ('0' & motor_filter_t2 & '0') + + ("00" & motor_filter_t3); + end if; +end process; + +motor <= std_logic_vector(motor_filtered); + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/Inputs.vhd b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/Inputs.vhd new file mode 100644 index 00000000..56944d09 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/Inputs.vhd @@ -0,0 +1,137 @@ +-- Input block for Kee Games Sprint 1 +-- 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; + +entity control_inputs is +port( + Clk6 : in std_logic; + SW1 : in std_logic_vector(7 downto 0); -- DIP switches + Coin1_n : in std_logic; -- Coin switches + Coin2_n : in std_logic; + Start : in std_logic; -- player start switch + Gas : in std_logic; -- Gas pedal, simple on/off switche + Gear1 : in std_logic; -- Gear select lever + Gear2 : in std_logic; + Gear3 : in std_logic; + Self_Test : in std_logic; -- Self test switch + Steering1A_n : in std_logic; -- Steering wheel signals + Steering1B_n : in std_logic; + SteerRst1_n : in std_logic; + Adr : in std_logic_vector(9 downto 0); -- Adress bus, only the lower 9 bits used by IO circuitry + Inputs : out std_logic_vector(1 downto 0) -- Out to data bus, only upper two bits used + ); +end control_inputs; + +architecture rtl of control_inputs is + +signal A8_8 : std_logic; +signal H9_Q_n : std_logic; +signal H8_en : std_logic; +signal Coin1 : std_logic; +signal Coin2 : std_logic; +signal SW1_bank1 : std_logic; +signal SW1_bank2 : std_logic; +signal DipSW : std_logic_vector(7 downto 0); +signal E8_in : std_logic_vector(3 downto 0); +signal J9_out : std_logic_vector(7 downto 0); +signal E8_out : std_logic_vector(9 downto 0); + +signal Steering1B_Q_n : std_logic; +signal Steering1A_Q : std_logic; + + +begin + +-- Inputs +M8: process(Adr, A8_8, SW1_bank2, Coin2_n, Coin1_n, Steering1B_Q_n, Steering1A_Q) +begin + case Adr(7 downto 6) is + when "00" => Inputs <= A8_8 & SW1_bank2; -- There is actually an inverter N9 fed by A8_8 so we will just account for that + when "01" => Inputs <= Coin2_n & Coin1_n; + when "10" => Inputs <= Steering1B_Q_n & Steering1A_Q; + when others => Inputs <= "11"; + end case; +end process; + +H9: process(Adr, Gear1, Gear2, Gear3, Gas, Self_Test, Start) +begin + if Adr(4) = '0' then -- Adr(4) is connected to enable + case Adr(2 downto 0) is + when "000" => H9_Q_n <= (not Gear1); + when "001" => H9_Q_n <= (not Gear2); + when "010" => H9_Q_n <= (not Gear3); + when "011" => H9_Q_n <= (not Gas); + when "100" => H9_Q_n <= (not Self_Test); + when "101" => H9_Q_n <= (not Start); + when "110" => H9_Q_n <= '1'; + when others => H9_Q_n <= '1'; + end case; + else + H9_Q_n <= '1'; + end if; +end process; + +-- Steering +M9: process(Steering1A_n, Steering1B_n, SteerRst1_n) +begin + if SteerRst1_n <= '0' then -- Asynchronous clear + Steering1B_Q_n <= '1'; + elsif rising_edge(Steering1B_n) then -- Steering encoders are active low but inverted on board + Steering1A_Q <= Steering1A_n; + Steering1B_Q_n <= '0'; + end if; +end process; + +-- The way the dip switches are wired in the real hardware requires OR logic +-- to achieve the same result while using standard active-low switch inputs. +-- Switches are split into two banks, each bank fed from half of selector J9. +J9: process(Adr) +begin + if Adr(3) = '1' then + J9_out <= "11111111"; + else + case Adr(1 downto 0) is + when "00" => J9_out <= "11101110"; + when "01" => J9_out <= "11011101"; + when "10" => J9_out <= "10111011"; + when "11" => J9_out <= "01110111"; + end case; + end if; +end process; + +-- Re-order the dip switch signals to match the physical order of the switches +-- Bank 1 +DipSW(7) <= J9_out(7) or SW1(1); +DipSW(6) <= J9_out(6) or SW1(3); +DipSW(5) <= J9_out(5) or SW1(5); +DipSW(4) <= J9_out(4) or SW1(7); + +--Bank 2 +DipSW(3) <= J9_out(3) or SW1(0); +DipSW(2) <= J9_out(2) or SW1(2); +DipSW(1) <= J9_out(1) or SW1(4); +DipSW(0) <= J9_out(0) or SW1(6); + +-- Outputs from each switch bank are tied together, logical AND since they are active low +SW1_bank1 <= DipSW(7) and DipSW(6) and DipSW(5) and DipSW(4); +SW1_bank2 <= DipSW(3) and DipSW(2) and DipSW(1) and DipSW(0); + +-- Bank 1 of dip switches is multiplexed with player inputs connected to selectors F9 and H9 +A8_8 <= SW1_bank1 and H9_Q_n; + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/T65/T65.vhd b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/T65/T65.vhd new file mode 100644 index 00000000..161debea --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/T65/T65.vhd @@ -0,0 +1,551 @@ +-- **** +-- T65(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 301 more merging +-- Ver 300 Bugfixes by ehenciak added, started tidyup *bust* +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- 65xx compatible microprocessor core +-- +-- Version : 0246 +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t65/ +-- +-- Limitations : +-- +-- 65C02 and 65C816 modes are incomplete +-- Undocumented instructions are not supported +-- Some interface signals behaves incorrect +-- +-- File history : +-- +-- 0246 : First release +-- + +library IEEE; + use IEEE.std_logic_1164.all; + use IEEE.numeric_std.all; + use work.T65_Pack.all; + +-- ehenciak 2-23-2005 : Added the enable signal so that one doesn't have to use +-- the ready signal to limit the CPU. +entity T65 is + port( + Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816 + Res_n : in std_logic; + Enable : in std_logic; + Clk : in std_logic; + Rdy : in std_logic; + Abort_n : in std_logic; + IRQ_n : in std_logic; + NMI_n : in std_logic; + SO_n : in std_logic; + R_W_n : out std_logic; + Sync : out std_logic; + EF : out std_logic; + MF : out std_logic; + XF : out std_logic; + ML_n : out std_logic; + VP_n : out std_logic; + VDA : out std_logic; + VPA : out std_logic; + A : out std_logic_vector(23 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0) + ); +end T65; + +architecture rtl of T65 is + + -- Registers + signal ABC, X, Y, D : std_logic_vector(15 downto 0); + signal P, AD, DL : std_logic_vector(7 downto 0) := x"00"; + signal BAH : std_logic_vector(7 downto 0); + signal BAL : std_logic_vector(8 downto 0); + signal PBR : std_logic_vector(7 downto 0); + signal DBR : std_logic_vector(7 downto 0); + signal PC : unsigned(15 downto 0); + signal S : unsigned(15 downto 0); + signal EF_i : std_logic; + signal MF_i : std_logic; + signal XF_i : std_logic; + + signal IR : std_logic_vector(7 downto 0); + signal MCycle : std_logic_vector(2 downto 0); + + signal Mode_r : std_logic_vector(1 downto 0); + signal ALU_Op_r : std_logic_vector(3 downto 0); + signal Write_Data_r : std_logic_vector(2 downto 0); + signal Set_Addr_To_r : std_logic_vector(1 downto 0); + signal PCAdder : unsigned(8 downto 0); + + signal RstCycle : std_logic; + signal IRQCycle : std_logic; + signal NMICycle : std_logic; + + signal B_o : std_logic; + signal SO_n_o : std_logic; + signal IRQ_n_o : std_logic; + signal NMI_n_o : std_logic; + signal NMIAct : std_logic; + + signal Break : std_logic; + + -- ALU signals + signal BusA : std_logic_vector(7 downto 0); + signal BusA_r : std_logic_vector(7 downto 0); + signal BusB : std_logic_vector(7 downto 0); + signal ALU_Q : std_logic_vector(7 downto 0); + signal P_Out : std_logic_vector(7 downto 0); + + -- Micro code outputs + signal LCycle : std_logic_vector(2 downto 0); + signal ALU_Op : std_logic_vector(3 downto 0); + signal Set_BusA_To : std_logic_vector(2 downto 0); + signal Set_Addr_To : std_logic_vector(1 downto 0); + signal Write_Data : std_logic_vector(2 downto 0); + signal Jump : std_logic_vector(1 downto 0); + signal BAAdd : std_logic_vector(1 downto 0); + signal BreakAtNA : std_logic; + signal ADAdd : std_logic; + signal AddY : std_logic; + signal PCAdd : std_logic; + signal Inc_S : std_logic; + signal Dec_S : std_logic; + signal LDA : std_logic; + signal LDP : std_logic; + signal LDX : std_logic; + signal LDY : std_logic; + signal LDS : std_logic; + signal LDDI : std_logic; + signal LDALU : std_logic; + signal LDAD : std_logic; + signal LDBAL : std_logic; + signal LDBAH : std_logic; + signal SaveP : std_logic; + signal Write : std_logic; + + signal really_rdy : std_logic; + signal R_W_n_i : std_logic; + +begin + -- ehenciak : gate Rdy with read/write to make an "OK, it's + -- really OK to stop the processor now if Rdy is + -- deasserted" signal + really_rdy <= Rdy or not(R_W_n_i); + + -- ehenciak : Drive R_W_n_i off chip. + R_W_n <= R_W_n_i; + + Sync <= '1' when MCycle = "000" else '0'; + EF <= EF_i; + MF <= MF_i; + XF <= XF_i; + ML_n <= '0' when IR(7 downto 6) /= "10" and IR(2 downto 1) = "11" and MCycle(2 downto 1) /= "00" else '1'; + VP_n <= '0' when IRQCycle = '1' and (MCycle = "101" or MCycle = "110") else '1'; + VDA <= '1' when Set_Addr_To_r /= "000" else '0'; -- Incorrect !!!!!!!!!!!! + VPA <= '1' when Jump(1) = '0' else '0'; -- Incorrect !!!!!!!!!!!! + + mcode : T65_MCode + port map( + Mode => Mode_r, + IR => IR, + MCycle => MCycle, + P => P, + LCycle => LCycle, + ALU_Op => ALU_Op, + Set_BusA_To => Set_BusA_To, + Set_Addr_To => Set_Addr_To, + Write_Data => Write_Data, + Jump => Jump, + BAAdd => BAAdd, + BreakAtNA => BreakAtNA, + ADAdd => ADAdd, + AddY => AddY, + PCAdd => PCAdd, + Inc_S => Inc_S, + Dec_S => Dec_S, + LDA => LDA, + LDP => LDP, + LDX => LDX, + LDY => LDY, + LDS => LDS, + LDDI => LDDI, + LDALU => LDALU, + LDAD => LDAD, + LDBAL => LDBAL, + LDBAH => LDBAH, + SaveP => SaveP, + Write => Write + ); + + alu : T65_ALU + port map( + Mode => Mode_r, + Op => ALU_Op_r, + BusA => BusA_r, + BusB => BusB, + P_In => P, + P_Out => P_Out, + Q => ALU_Q + ); + + process (Res_n, Clk) + begin + if Res_n = '0' then + PC <= (others => '0'); -- Program Counter + IR <= "00000000"; + S <= (others => '0'); -- Dummy !!!!!!!!!!!!!!!!!!!!! + D <= (others => '0'); + PBR <= (others => '0'); + DBR <= (others => '0'); + + Mode_r <= (others => '0'); + ALU_Op_r <= "1100"; + Write_Data_r <= "000"; + Set_Addr_To_r <= "00"; + + R_W_n_i <= '1'; + EF_i <= '1'; + MF_i <= '1'; + XF_i <= '1'; + + elsif Clk'event and Clk = '1' then + if (Enable = '1') then + if (really_rdy = '1') then + R_W_n_i <= not Write or RstCycle; + + D <= (others => '1'); -- Dummy + PBR <= (others => '1'); -- Dummy + DBR <= (others => '1'); -- Dummy + EF_i <= '0'; -- Dummy + MF_i <= '0'; -- Dummy + XF_i <= '0'; -- Dummy + + if MCycle = "000" then + Mode_r <= Mode; + + if IRQCycle = '0' and NMICycle = '0' then + PC <= PC + 1; + end if; + + if IRQCycle = '1' or NMICycle = '1' then + IR <= "00000000"; + else + IR <= DI; + end if; + end if; + + ALU_Op_r <= ALU_Op; + Write_Data_r <= Write_Data; + if Break = '1' then + Set_Addr_To_r <= "00"; + else + Set_Addr_To_r <= Set_Addr_To; + end if; + + if Inc_S = '1' then + S <= S + 1; + end if; + if Dec_S = '1' and RstCycle = '0' then + S <= S - 1; + end if; + if LDS = '1' then + S(7 downto 0) <= unsigned(ALU_Q); + end if; + + if IR = "00000000" and MCycle = "001" and IRQCycle = '0' and NMICycle = '0' then + PC <= PC + 1; + end if; + -- + -- jump control logic + -- + case Jump is + when "01" => + PC <= PC + 1; + + when "10" => + PC <= unsigned(DI & DL); + + when "11" => + if PCAdder(8) = '1' then + if DL(7) = '0' then + PC(15 downto 8) <= PC(15 downto 8) + 1; + else + PC(15 downto 8) <= PC(15 downto 8) - 1; + end if; + end if; + PC(7 downto 0) <= PCAdder(7 downto 0); + + when others => null; + end case; + end if; + end if; + end if; + end process; + + PCAdder <= resize(PC(7 downto 0),9) + resize(unsigned(DL(7) & DL),9) when PCAdd = '1' + else "0" & PC(7 downto 0); + + process (Clk) + begin + if Clk'event and Clk = '1' then + if (Enable = '1') then + if (really_rdy = '1') then + if MCycle = "000" then + if LDA = '1' then + ABC(7 downto 0) <= ALU_Q; + end if; + if LDX = '1' then + X(7 downto 0) <= ALU_Q; + end if; + if LDY = '1' then + Y(7 downto 0) <= ALU_Q; + end if; + if (LDA or LDX or LDY) = '1' then + P <= P_Out; + end if; + end if; + if SaveP = '1' then + P <= P_Out; + end if; + if LDP = '1' then + P <= ALU_Q; + end if; + if IR(4 downto 0) = "11000" then + case IR(7 downto 5) is + when "000" => + P(Flag_C) <= '0'; + when "001" => + P(Flag_C) <= '1'; + when "010" => + P(Flag_I) <= '0'; + when "011" => + P(Flag_I) <= '1'; + when "101" => + P(Flag_V) <= '0'; + when "110" => + P(Flag_D) <= '0'; + when "111" => + P(Flag_D) <= '1'; + when others => + end case; + end if; + if IR = "00000000" and MCycle = "011" and RstCycle = '0' and NMICycle = '0' and IRQCycle = '0' then + P(Flag_B) <= '1'; + end if; + if IR = "00000000" and MCycle = "100" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then + P(Flag_I) <= '1'; + P(Flag_B) <= B_o; + end if; + if SO_n_o = '1' and SO_n = '0' then + P(Flag_V) <= '1'; + end if; + if RstCycle = '1' and Mode_r /= "00" then + P(Flag_1) <= '1'; + P(Flag_D) <= '0'; + P(Flag_I) <= '1'; + end if; + P(Flag_1) <= '1'; + + B_o <= P(Flag_B); + SO_n_o <= SO_n; + IRQ_n_o <= IRQ_n; + NMI_n_o <= NMI_n; + end if; + end if; + end if; + end process; + +--------------------------------------------------------------------------- +-- +-- Buses +-- +--------------------------------------------------------------------------- + + process (Res_n, Clk) + begin + if Res_n = '0' then + BusA_r <= (others => '0'); + BusB <= (others => '0'); + AD <= (others => '0'); + BAL <= (others => '0'); + BAH <= (others => '0'); + DL <= (others => '0'); + elsif Clk'event and Clk = '1' then + if (Enable = '1') then + if (Rdy = '1') then + BusA_r <= BusA; + BusB <= DI; + + case BAAdd is + when "01" => + -- BA Inc + AD <= std_logic_vector(unsigned(AD) + 1); + BAL <= std_logic_vector(unsigned(BAL) + 1); + when "10" => + -- BA Add + BAL <= std_logic_vector(resize(unsigned(BAL(7 downto 0)),9) + resize(unsigned(BusA),9)); + when "11" => + -- BA Adj + if BAL(8) = '1' then + BAH <= std_logic_vector(unsigned(BAH) + 1); + end if; + when others => + end case; + + -- ehenciak : modified to use Y register as well (bugfix) + if ADAdd = '1' then + if (AddY = '1') then + AD <= std_logic_vector(unsigned(AD) + unsigned(Y(7 downto 0))); + else + AD <= std_logic_vector(unsigned(AD) + unsigned(X(7 downto 0))); + end if; + end if; + + if IR = "00000000" then + BAL <= (others => '1'); + BAH <= (others => '1'); + if RstCycle = '1' then + BAL(2 downto 0) <= "100"; + elsif NMICycle = '1' then + BAL(2 downto 0) <= "010"; + else + BAL(2 downto 0) <= "110"; + end if; + if Set_addr_To_r = "11" then + BAL(0) <= '1'; + end if; + end if; + + + if LDDI = '1' then + DL <= DI; + end if; + if LDALU = '1' then + DL <= ALU_Q; + end if; + if LDAD = '1' then + AD <= DI; + end if; + if LDBAL = '1' then + BAL(7 downto 0) <= DI; + end if; + if LDBAH = '1' then + BAH <= DI; + end if; + end if; + end if; + end if; + end process; + + Break <= (BreakAtNA and not BAL(8)) or (PCAdd and not PCAdder(8)); + + + with Set_BusA_To select + BusA <= DI when "000", + ABC(7 downto 0) when "001", + X(7 downto 0) when "010", + Y(7 downto 0) when "011", + std_logic_vector(S(7 downto 0)) when "100", + P when "101", + (others => '-') when others; + + with Set_Addr_To_r select + A <= "0000000000000001" & std_logic_vector(S(7 downto 0)) when "01", + DBR & "00000000" & AD when "10", + "00000000" & BAH & BAL(7 downto 0) when "11", + PBR & std_logic_vector(PC(15 downto 8)) & std_logic_vector(PCAdder(7 downto 0)) when others; + + with Write_Data_r select + DO <= DL when "000", + ABC(7 downto 0) when "001", + X(7 downto 0) when "010", + Y(7 downto 0) when "011", + std_logic_vector(S(7 downto 0)) when "100", + P when "101", + std_logic_vector(PC(7 downto 0)) when "110", + std_logic_vector(PC(15 downto 8)) when others; + +------------------------------------------------------------------------- +-- +-- Main state machine +-- +------------------------------------------------------------------------- + + process (Res_n, Clk) + begin + if Res_n = '0' then + MCycle <= "001"; + RstCycle <= '1'; + IRQCycle <= '0'; + NMICycle <= '0'; + NMIAct <= '0'; + elsif Clk'event and Clk = '1' then + if (Enable = '1') then + if (really_rdy = '1') then + if MCycle = LCycle or Break = '1' then + MCycle <= "000"; + RstCycle <= '0'; + IRQCycle <= '0'; + NMICycle <= '0'; + if NMIAct = '1' then + NMICycle <= '1'; + elsif IRQ_n_o = '0' and P(Flag_I) = '0' then + IRQCycle <= '1'; + end if; + else + MCycle <= std_logic_vector(unsigned(MCycle) + 1); + end if; + + if NMICycle = '1' then + NMIAct <= '0'; + end if; + if NMI_n_o = '1' and NMI_n = '0' then + NMIAct <= '1'; + end if; + end if; + end if; + end if; + end process; + +end; diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/T65/T65_ALU.vhd b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/T65/T65_ALU.vhd new file mode 100644 index 00000000..b1f6d632 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/T65/T65_ALU.vhd @@ -0,0 +1,260 @@ +-- **** +-- T65(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 300 Bugfixes by ehenciak added +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- 6502 compatible microprocessor core +-- +-- Version : 0245 +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t65/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0245 : First version +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T65_Pack.all; + +entity T65_ALU is + port( + Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 + Op : in std_logic_vector(3 downto 0); + BusA : in std_logic_vector(7 downto 0); + BusB : in std_logic_vector(7 downto 0); + P_In : in std_logic_vector(7 downto 0); + P_Out : out std_logic_vector(7 downto 0); + Q : out std_logic_vector(7 downto 0) + ); +end T65_ALU; + +architecture rtl of T65_ALU is + + -- AddSub variables (temporary signals) + signal ADC_Z : std_logic; + signal ADC_C : std_logic; + signal ADC_V : std_logic; + signal ADC_N : std_logic; + signal ADC_Q : std_logic_vector(7 downto 0); + signal SBC_Z : std_logic; + signal SBC_C : std_logic; + signal SBC_V : std_logic; + signal SBC_N : std_logic; + signal SBC_Q : std_logic_vector(7 downto 0); + +begin + + process (P_In, BusA, BusB) + variable AL : unsigned(6 downto 0); + variable AH : unsigned(6 downto 0); + variable C : std_logic; + begin + AL := resize(unsigned(BusA(3 downto 0) & P_In(Flag_C)), 7) + resize(unsigned(BusB(3 downto 0) & "1"), 7); + AH := resize(unsigned(BusA(7 downto 4) & AL(5)), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7); + +-- pragma translate_off + if is_x(std_logic_vector(AL)) then AL := "0000000"; end if; + if is_x(std_logic_vector(AH)) then AH := "0000000"; end if; +-- pragma translate_on + + if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then + ADC_Z <= '1'; + else + ADC_Z <= '0'; + end if; + + if AL(5 downto 1) > 9 and P_In(Flag_D) = '1' then + AL(6 downto 1) := AL(6 downto 1) + 6; + end if; + + C := AL(6) or AL(5); + AH := resize(unsigned(BusA(7 downto 4) & C), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7); + + ADC_N <= AH(4); + ADC_V <= (AH(4) xor BusA(7)) and not (BusA(7) xor BusB(7)); + +-- pragma translate_off + if is_x(std_logic_vector(AH)) then AH := "0000000"; end if; +-- pragma translate_on + + if AH(5 downto 1) > 9 and P_In(Flag_D) = '1' then + AH(6 downto 1) := AH(6 downto 1) + 6; + end if; + + ADC_C <= AH(6) or AH(5); + + ADC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1)); + end process; + + process (Op, P_In, BusA, BusB) + variable AL : unsigned(6 downto 0); + variable AH : unsigned(5 downto 0); + variable C : std_logic; + begin + C := P_In(Flag_C) or not Op(0); + AL := resize(unsigned(BusA(3 downto 0) & C), 7) - resize(unsigned(BusB(3 downto 0) & "1"), 6); + AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(5)), 6); + +-- pragma translate_off + if is_x(std_logic_vector(AL)) then AL := "0000000"; end if; + if is_x(std_logic_vector(AH)) then AH := "000000"; end if; +-- pragma translate_on + + if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then + SBC_Z <= '1'; + else + SBC_Z <= '0'; + end if; + + SBC_C <= not AH(5); + SBC_V <= (AH(4) xor BusA(7)) and (BusA(7) xor BusB(7)); + SBC_N <= AH(4); + + if P_In(Flag_D) = '1' then + if AL(5) = '1' then + AL(5 downto 1) := AL(5 downto 1) - 6; + end if; + AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(6)), 6); + if AH(5) = '1' then + AH(5 downto 1) := AH(5 downto 1) - 6; + end if; + end if; + + SBC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1)); + end process; + + process (Op, P_In, BusA, BusB, + ADC_Z, ADC_C, ADC_V, ADC_N, ADC_Q, + SBC_Z, SBC_C, SBC_V, SBC_N, SBC_Q) + variable Q_t : std_logic_vector(7 downto 0); + begin + -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC + -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC + P_Out <= P_In; + Q_t := BusA; + case Op(3 downto 0) is + when "0000" => + -- ORA + Q_t := BusA or BusB; + when "0001" => + -- AND + Q_t := BusA and BusB; + when "0010" => + -- EOR + Q_t := BusA xor BusB; + when "0011" => + -- ADC + P_Out(Flag_V) <= ADC_V; + P_Out(Flag_C) <= ADC_C; + Q_t := ADC_Q; + when "0101" | "1101" => + -- LDA + when "0110" => + -- CMP + P_Out(Flag_C) <= SBC_C; + when "0111" => + -- SBC + P_Out(Flag_V) <= SBC_V; + P_Out(Flag_C) <= SBC_C; + Q_t := SBC_Q; + when "1000" => + -- ASL + Q_t := BusA(6 downto 0) & "0"; + P_Out(Flag_C) <= BusA(7); + when "1001" => + -- ROL + Q_t := BusA(6 downto 0) & P_In(Flag_C); + P_Out(Flag_C) <= BusA(7); + when "1010" => + -- LSR + Q_t := "0" & BusA(7 downto 1); + P_Out(Flag_C) <= BusA(0); + when "1011" => + -- ROR + Q_t := P_In(Flag_C) & BusA(7 downto 1); + P_Out(Flag_C) <= BusA(0); + when "1100" => + -- BIT + P_Out(Flag_V) <= BusB(6); + when "1110" => + -- DEC + Q_t := std_logic_vector(unsigned(BusA) - 1); + when "1111" => + -- INC + Q_t := std_logic_vector(unsigned(BusA) + 1); + when others => + end case; + + case Op(3 downto 0) is + when "0011" => + P_Out(Flag_N) <= ADC_N; + P_Out(Flag_Z) <= ADC_Z; + when "0110" | "0111" => + P_Out(Flag_N) <= SBC_N; + P_Out(Flag_Z) <= SBC_Z; + when "0100" => + when "1100" => + P_Out(Flag_N) <= BusB(7); + if (BusA and BusB) = "00000000" then + P_Out(Flag_Z) <= '1'; + else + P_Out(Flag_Z) <= '0'; + end if; + when others => + P_Out(Flag_N) <= Q_t(7); + if Q_t = "00000000" then + P_Out(Flag_Z) <= '1'; + else + P_Out(Flag_Z) <= '0'; + end if; + end case; + + Q <= Q_t; + end process; + +end; diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/T65/T65_MCode.vhd b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/T65/T65_MCode.vhd new file mode 100644 index 00000000..06229751 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/T65/T65_MCode.vhd @@ -0,0 +1,1050 @@ +-- **** +-- T65(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 301 Jump timing fixed +-- Ver 300 Bugfixes by ehenciak added +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- 65xx compatible microprocessor core +-- +-- Version : 0246 + fix +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t65/ +-- +-- Limitations : +-- +-- 65C02 +-- supported : inc, dec, phx, plx, phy, ply +-- missing : bra, ora, lda, cmp, sbc, tsb*2, trb*2, stz*2, bit*2, wai, stp, jmp, bbr*8, bbs*8 +-- +-- File history : +-- +-- 0246 : First release +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T65_Pack.all; + +entity T65_MCode is + port( + Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 + IR : in std_logic_vector(7 downto 0); + MCycle : in std_logic_vector(2 downto 0); + P : in std_logic_vector(7 downto 0); + LCycle : out std_logic_vector(2 downto 0); + ALU_Op : out std_logic_vector(3 downto 0); + Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P + Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA + Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH + Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel + BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj + BreakAtNA : out std_logic; + ADAdd : out std_logic; + AddY : out std_logic; + PCAdd : out std_logic; + Inc_S : out std_logic; + Dec_S : out std_logic; + LDA : out std_logic; + LDP : out std_logic; + LDX : out std_logic; + LDY : out std_logic; + LDS : out std_logic; + LDDI : out std_logic; + LDALU : out std_logic; + LDAD : out std_logic; + LDBAL : out std_logic; + LDBAH : out std_logic; + SaveP : out std_logic; + Write : out std_logic + ); +end T65_MCode; + +architecture rtl of T65_MCode is + + signal Branch : std_logic; + +begin + + with IR(7 downto 5) select + Branch <= not P(Flag_N) when "000", + P(Flag_N) when "001", + not P(Flag_V) when "010", + P(Flag_V) when "011", + not P(Flag_C) when "100", + P(Flag_C) when "101", + not P(Flag_Z) when "110", + P(Flag_Z) when others; + + process (IR, MCycle, P, Branch, Mode) + begin + LCycle <= "001"; + Set_BusA_To <= "001"; -- A + Set_Addr_To <= (others => '0'); + Write_Data <= (others => '0'); + Jump <= (others => '0'); + BAAdd <= "00"; + BreakAtNA <= '0'; + ADAdd <= '0'; + PCAdd <= '0'; + Inc_S <= '0'; + Dec_S <= '0'; + LDA <= '0'; + LDP <= '0'; + LDX <= '0'; + LDY <= '0'; + LDS <= '0'; + LDDI <= '0'; + LDALU <= '0'; + LDAD <= '0'; + LDBAL <= '0'; + LDBAH <= '0'; + SaveP <= '0'; + Write <= '0'; + AddY <= '0'; + + case IR(7 downto 5) is + when "100" => + --{{{ + case IR(1 downto 0) is + when "00" => + Set_BusA_To <= "011"; -- Y + Write_Data <= "011"; -- Y + when "10" => + Set_BusA_To <= "010"; -- X + Write_Data <= "010"; -- X + when others => + Write_Data <= "001"; -- A + end case; + --}}} + when "101" => + --{{{ + case IR(1 downto 0) is + when "00" => + if IR(4) /= '1' or IR(2) /= '0' then + LDY <= '1'; + end if; + when "10" => + LDX <= '1'; + when others => + LDA <= '1'; + end case; + Set_BusA_To <= "000"; -- DI + --}}} + when "110" => + --{{{ + case IR(1 downto 0) is + when "00" => + if IR(4) = '0' then + LDY <= '1'; + end if; + Set_BusA_To <= "011"; -- Y + when others => + Set_BusA_To <= "001"; -- A + end case; + --}}} + when "111" => + --{{{ + case IR(1 downto 0) is + when "00" => + if IR(4) = '0' then + LDX <= '1'; + end if; + Set_BusA_To <= "010"; -- X + when others => + Set_BusA_To <= "001"; -- A + end case; + --}}} + when others => + end case; + + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + Set_BusA_To <= "000"; -- DI + end if; + + case IR(4 downto 0) is + when "00000" | "01000" | "01010" | "11000" | "11010" => + --{{{ + -- Implied + case IR is + when "00000000" => + -- BRK + LCycle <= "110"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= "01"; -- S + Write_Data <= "111"; -- PCH + Write <= '1'; + when 2 => + Dec_S <= '1'; + Set_Addr_To <= "01"; -- S + Write_Data <= "110"; -- PCL + Write <= '1'; + when 3 => + Dec_S <= '1'; + Set_Addr_To <= "01"; -- S + Write_Data <= "101"; -- P + Write <= '1'; + when 4 => + Dec_S <= '1'; + Set_Addr_To <= "11"; -- BA + when 5 => + LDDI <= '1'; + Set_Addr_To <= "11"; -- BA + when 6 => + Jump <= "10"; -- DIDL + when others => + end case; + when "00100000" => + -- JSR + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDDI <= '1'; + Set_Addr_To <= "01"; -- S + when 2 => + Set_Addr_To <= "01"; -- S + Write_Data <= "111"; -- PCH + Write <= '1'; + when 3 => + Dec_S <= '1'; + Set_Addr_To <= "01"; -- S + Write_Data <= "110"; -- PCL + Write <= '1'; + when 4 => + Dec_S <= '1'; + when 5 => + Jump <= "10"; -- DIDL + when others => + end case; + when "01000000" => + -- RTI + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= "01"; -- S + when 2 => + Inc_S <= '1'; + Set_Addr_To <= "01"; -- S + when 3 => + Inc_S <= '1'; + Set_Addr_To <= "01"; -- S + Set_BusA_To <= "000"; -- DI + when 4 => + LDP <= '1'; + Inc_S <= '1'; + LDDI <= '1'; + Set_Addr_To <= "01"; -- S + when 5 => + Jump <= "10"; -- DIDL + when others => + end case; + when "01100000" => + -- RTS + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= "01"; -- S + when 2 => + Inc_S <= '1'; + Set_Addr_To <= "01"; -- S + when 3 => + Inc_S <= '1'; + LDDI <= '1'; + Set_Addr_To <= "01"; -- S + when 4 => + Jump <= "10"; -- DIDL + when 5 => + Jump <= "01"; + when others => + end case; + when "00001000" | "01001000" | "01011010" | "11011010" => + -- PHP, PHA, PHY*, PHX* + LCycle <= "010"; + if Mode = "00" and IR(1) = '1' then + LCycle <= "001"; + end if; + case to_integer(unsigned(MCycle)) is + when 1 => + case IR(7 downto 4) is + when "0000" => + Write_Data <= "101"; -- P + when "0100" => + Write_Data <= "001"; -- A + when "0101" => + Write_Data <= "011"; -- Y + when "1101" => + Write_Data <= "010"; -- X + when others => + end case; + Write <= '1'; + Set_Addr_To <= "01"; -- S + when 2 => + Dec_S <= '1'; + when others => + end case; + when "00101000" | "01101000" | "01111010" | "11111010" => + -- PLP, PLA, PLY*, PLX* + LCycle <= "011"; + if Mode = "00" and IR(1) = '1' then + LCycle <= "001"; + end if; + case IR(7 downto 4) is + when "0010" => + LDP <= '1'; + when "0110" => + LDA <= '1'; + when "0111" => + if Mode /= "00" then + LDY <= '1'; + end if; + when "1111" => + if Mode /= "00" then + LDX <= '1'; + end if; + when others => + end case; + case to_integer(unsigned(MCycle)) is + when 0 => + SaveP <= '1'; + when 1 => + Set_Addr_To <= "01"; -- S + when 2 => + Inc_S <= '1'; + Set_Addr_To <= "01"; -- S + when 3 => + Set_BusA_To <= "000"; -- DI + when others => + end case; + when "10100000" | "11000000" | "11100000" => + -- LDY, CPY, CPX + -- Immediate + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + when others => + end case; + when "10001000" => + -- DEY + LDY <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "011"; -- Y + when others => + end case; + when "11001010" => + -- DEX + LDX <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "010"; -- X + when others => + end case; + when "00011010" | "00111010" => + -- INC*, DEC* + if Mode /= "00" then + LDA <= '1'; -- A + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "100"; -- S + when others => + end case; + when "00001010" | "00101010" | "01001010" | "01101010" => + -- ASL, ROL, LSR, ROR + LDA <= '1'; -- A + Set_BusA_To <= "001"; -- A + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + when others => + end case; + when "10001010" | "10011000" => + -- TYA, TXA + LDA <= '1'; -- A + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + when others => + end case; + when "10101010" | "10101000" => + -- TAX, TAY + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "001"; -- A + when others => + end case; + when "10011010" => + -- TXS + case to_integer(unsigned(MCycle)) is + when 0 => + LDS <= '1'; + when 1 => + when others => + end case; + when "10111010" => + -- TSX + LDX <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "100"; -- S + when others => + end case; + + -- when "00011000" | "00111000" | "01011000" | "01111000" | "10111000" | "11011000" | "11111000" | "11001000" | "11101000" => + -- -- CLC, SEC, CLI, SEI, CLV, CLD, SED, INY, INX + -- case to_integer(unsigned(MCycle)) is + -- when 1 => + -- when others => + -- end case; + when others => + case to_integer(unsigned(MCycle)) is + when 0 => + when others => + end case; + end case; + --}}} + + when "00001" | "00011" => + --{{{ + -- Zero Page Indexed Indirect (d,x) + LCycle <= "101"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + ADAdd <= '1'; + Set_Addr_To <= "10"; -- AD + when 3 => + BAAdd <= "01"; -- DB Inc + LDBAL <= '1'; + Set_Addr_To <= "10"; -- AD + when 4 => + LDBAH <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 5 => + when others => + end case; + --}}} + + when "01001" | "01011" => + --{{{ + -- Immediate + LDA <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + when others => + end case; + + --}}} + + when "00010" | "10010" => + --{{{ + -- Immediate, KIL + LDX <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + if IR = "10100010" then + -- LDX + Jump <= "01"; + else + -- KIL !!!!!!!!!!!!!!!!!!!!!!!!!!!!! + end if; + when others => + end case; + --}}} + + when "00100" => + --{{{ + -- Zero Page + LCycle <= "010"; + case to_integer(unsigned(MCycle)) is + when 0 => + if IR(7 downto 5) = "001" then + SaveP <= '1'; + end if; + when 1 => + Jump <= "01"; + LDAD <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "10"; -- AD + when 2 => + when others => + end case; + --}}} + + when "00101" | "00110" | "00111" => + --{{{ + -- Zero Page + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + -- Read-Modify-Write + LCycle <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + LDDI <= '1'; + Write <= '1'; + Set_Addr_To <= "10"; -- AD + when 3 => + LDALU <= '1'; + SaveP <= '1'; + Write <= '1'; + Set_Addr_To <= "10"; -- AD + when 4 => + when others => + end case; + else + LCycle <= "010"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDAD <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "10"; -- AD + when 2 => + when others => + end case; + end if; + --}}} + + when "01100" => + --{{{ + -- Absolute + if IR(7 downto 6) = "01" and IR(4 downto 0) = "01100" then + -- JMP + if IR(5) = '0' then + --LCycle <= "011"; + LCycle <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDDI <= '1'; + when 2 => + Jump <= "10"; -- DIDL + when others => + end case; + else + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Jump <= "01"; + LDDI <= '1'; + LDBAL <= '1'; + when 3 => + LDBAH <= '1'; + if Mode /= "00" then + Jump <= "10"; -- DIDL + end if; + if Mode = "00" then + Set_Addr_To <= "11"; -- BA + end if; + when 4 => + LDDI <= '1'; + if Mode = "00" then + Set_Addr_To <= "11"; -- BA + BAAdd <= "01"; -- DB Inc + else + Jump <= "01"; + end if; + when 5 => + Jump <= "10"; -- DIDL + when others => + end case; + end if; + else + LCycle <= "011"; + case to_integer(unsigned(MCycle)) is + when 0 => + if IR(7 downto 5) = "001" then + SaveP <= '1'; + end if; + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + LDBAH <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 3 => + when others => + end case; + end if; + --}}} + + when "01101" | "01110" | "01111" => + --{{{ + -- Absolute + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + -- Read-Modify-Write + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 3 => + LDDI <= '1'; + Write <= '1'; + Set_Addr_To <= "11"; -- BA + when 4 => + Write <= '1'; + LDALU <= '1'; + SaveP <= '1'; + Set_Addr_To <= "11"; -- BA + when 5 => + SaveP <= '0'; -- MIKEJ was 1 + when others => + end case; + else + LCycle <= "011"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + LDBAH <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 3 => + when others => + end case; + end if; + --}}} + + when "10000" => + --{{{ + -- Relative + + -- This circuit dictates when the last + -- microcycle occurs for the branch depending on + -- whether or not the branch is taken and if a page + -- is crossed... + if (Branch = '1') then + + LCycle <= "011"; -- We're done @ T3 if branching...upper + -- level logic will stop at T2 if no page cross + -- (See the Break signal) + else + + LCycle <= "001"; + + end if; + + -- This decodes the current microcycle and takes the + -- proper course of action... + case to_integer(unsigned(MCycle)) is + + -- On the T1 microcycle, increment the program counter + -- and instruct the upper level logic to fetch the offset + -- from the Din bus and store it in the data latches. This + -- will be the last microcycle if the branch isn't taken. + when 1 => + + Jump <= "01"; -- Increments the PC by one (PC will now be PC+2) + -- from microcycle T0. + + LDDI <= '1'; -- Tells logic in top level (T65.vhd) to route + -- the Din bus to the memory data latch (DL) + -- so that the branch offset is fetched. + + -- In microcycle T2, tell the logic in the top level to + -- add the offset. If the most significant byte of the + -- program counter (i.e. the current "page") does not need + -- updating, we are done here...the Break signal at the + -- T65.vhd level takes care of that... + when 2 => + + Jump <= "11"; -- Tell the PC Jump logic to use relative mode. + + PCAdd <= '1'; -- This tells the PC adder to update itself with + -- the current offset recently fetched from + -- memory. + + -- The following is microcycle T3 : + -- The program counter should be completely updated + -- on this cycle after the page cross is detected. + -- We don't need to do anything here... + when 3 => + + + when others => null; -- Do nothing. + + end case; + --}}} + + when "10001" | "10011" => + --{{{ + -- Zero Page Indirect Indexed (d),y + LCycle <= "101"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + LDBAL <= '1'; + BAAdd <= "01"; -- DB Inc + Set_Addr_To <= "10"; -- AD + when 3 => + Set_BusA_To <= "011"; -- Y + BAAdd <= "10"; -- BA Add + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 4 => + BAAdd <= "11"; -- BA Adj + if IR(7 downto 5) = "100" then + Write <= '1'; + else + BreakAtNA <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 5 => + when others => + end case; + --}}} + + when "10100" | "10101" | "10110" | "10111" => + --{{{ + -- Zero Page, X + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + -- Read-Modify-Write + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + ADAdd <= '1'; + Set_Addr_To <= "10"; -- AD + when 3 => + LDDI <= '1'; + Write <= '1'; + Set_Addr_To <= "10"; -- AD + when 4 => + LDALU <= '1'; + SaveP <= '1'; + Write <= '1'; + Set_Addr_To <= "10"; -- AD + when 5 => + when others => + end case; + else + LCycle <= "011"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + ADAdd <= '1'; + -- Added this check for Y reg. use... + if (IR(3 downto 0) = "0110") then + AddY <= '1'; + end if; + + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "10"; -- AD + when 3 => null; + when others => + end case; + end if; + --}}} + + when "11001" | "11011" => + --{{{ + -- Absolute Y + LCycle <= "100"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + Set_BusA_To <= "011"; -- Y + BAAdd <= "10"; -- BA Add + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 3 => + BAAdd <= "11"; -- BA adj + if IR(7 downto 5) = "100" then + Write <= '1'; + else + BreakAtNA <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 4 => + when others => + end case; + --}}} + + when "11100" | "11101" | "11110" | "11111" => + --{{{ + -- Absolute X + + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + -- Read-Modify-Write + LCycle <= "110"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + Set_BusA_To <= "010"; -- X + BAAdd <= "10"; -- BA Add + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 3 => + BAAdd <= "11"; -- BA adj + Set_Addr_To <= "11"; -- BA + when 4 => + LDDI <= '1'; + Write <= '1'; + Set_Addr_To <= "11"; -- BA + when 5 => + LDALU <= '1'; + SaveP <= '1'; + Write <= '1'; + Set_Addr_To <= "11"; -- BA + when 6 => + when others => + end case; + else + LCycle <= "100"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + -- mikej + -- special case 0xBE which uses Y reg as index!! + if (IR = "10111110") then + Set_BusA_To <= "011"; -- Y + else + Set_BusA_To <= "010"; -- X + end if; + BAAdd <= "10"; -- BA Add + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 3 => + BAAdd <= "11"; -- BA adj + if IR(7 downto 5) = "100" then + Write <= '1'; + else + BreakAtNA <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 4 => + when others => + end case; + end if; + --}}} + when others => + end case; + end process; + + process (IR, MCycle) + begin + -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC + -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC + case IR(1 downto 0) is + when "00" => + --{{{ + case IR(4 downto 2) is + when "000" | "001" | "011" => + case IR(7 downto 5) is + when "110" | "111" => + -- CP + ALU_Op <= "0110"; + when "101" => + -- LD + ALU_Op <= "0101"; + when "001" => + -- BIT + ALU_Op <= "1100"; + when others => + -- NOP/ST + ALU_Op <= "0100"; + end case; + when "010" => + case IR(7 downto 5) is + when "111" | "110" => + -- IN + ALU_Op <= "1111"; + when "100" => + -- DEY + ALU_Op <= "1110"; + when others => + -- LD + ALU_Op <= "1101"; + end case; + when "110" => + case IR(7 downto 5) is + when "100" => + -- TYA + ALU_Op <= "1101"; + when others => + ALU_Op <= "----"; + end case; + when others => + case IR(7 downto 5) is + when "101" => + -- LD + ALU_Op <= "1101"; + when others => + ALU_Op <= "0100"; + end case; + end case; + --}}} + when "01" => -- OR + --{{{ + ALU_Op(3) <= '0'; + ALU_Op(2 downto 0) <= IR(7 downto 5); + --}}} + when "10" => + --{{{ + ALU_Op(3) <= '1'; + ALU_Op(2 downto 0) <= IR(7 downto 5); + case IR(7 downto 5) is + when "000" => + if IR(4 downto 2) = "110" then + -- INC + ALU_Op <= "1111"; + end if; + when "001" => + if IR(4 downto 2) = "110" then + -- DEC + ALU_Op <= "1110"; + end if; + when "100" => + if IR(4 downto 2) = "010" then + -- TXA + ALU_Op <= "0101"; + else + ALU_Op <= "0100"; + end if; + when others => + end case; + --}}} + when others => + --{{{ + case IR(7 downto 5) is + when "100" => + ALU_Op <= "0100"; + when others => + if MCycle = "000" then + ALU_Op(3) <= '0'; + ALU_Op(2 downto 0) <= IR(7 downto 5); + else + ALU_Op(3) <= '1'; + ALU_Op(2 downto 0) <= IR(7 downto 5); + end if; + end case; + --}}} + end case; + end process; + +end; diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/T65/T65_Pack.vhd b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/T65/T65_Pack.vhd new file mode 100644 index 00000000..e025e1bf --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/T65/T65_Pack.vhd @@ -0,0 +1,117 @@ +-- **** +-- T65(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 300 Bugfixes by ehenciak added +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- 65xx compatible microprocessor core +-- +-- Version : 0246 +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t65/ +-- +-- Limitations : +-- +-- File history : +-- + +library IEEE; +use IEEE.std_logic_1164.all; + +package T65_Pack is + + constant Flag_C : integer := 0; + constant Flag_Z : integer := 1; + constant Flag_I : integer := 2; + constant Flag_D : integer := 3; + constant Flag_B : integer := 4; + constant Flag_1 : integer := 5; + constant Flag_V : integer := 6; + constant Flag_N : integer := 7; + + component T65_MCode + port( + Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 + IR : in std_logic_vector(7 downto 0); + MCycle : in std_logic_vector(2 downto 0); + P : in std_logic_vector(7 downto 0); + LCycle : out std_logic_vector(2 downto 0); + ALU_Op : out std_logic_vector(3 downto 0); + Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P + Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA + Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH + Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel + BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj + BreakAtNA : out std_logic; + ADAdd : out std_logic; + AddY : out std_logic; + PCAdd : out std_logic; + Inc_S : out std_logic; + Dec_S : out std_logic; + LDA : out std_logic; + LDP : out std_logic; + LDX : out std_logic; + LDY : out std_logic; + LDS : out std_logic; + LDDI : out std_logic; + LDALU : out std_logic; + LDAD : out std_logic; + LDBAL : out std_logic; + LDBAH : out std_logic; + SaveP : out std_logic; + Write : out std_logic + ); + end component; + + component T65_ALU + port( + Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816 + Op : in std_logic_vector(3 downto 0); + BusA : in std_logic_vector(7 downto 0); + BusB : in std_logic_vector(7 downto 0); + P_In : in std_logic_vector(7 downto 0); + P_Out : out std_logic_vector(7 downto 0); + Q : out std_logic_vector(7 downto 0) + ); + end component; + +end; diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/build_id.sv b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/build_id.sv new file mode 100644 index 00000000..1d53a3f2 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/build_id.sv @@ -0,0 +1,2 @@ +`define BUILD_DATE "171221" +`define BUILD_TIME "172231" diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/build_id.tcl b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/build_id.tcl new file mode 100644 index 00000000..be673dac --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/build_id.tcl @@ -0,0 +1,35 @@ +# ================================================================================ +# +# Build ID Verilog Module Script +# Jeff Wiencrot - 8/1/2011 +# +# Generates a Verilog module that contains a timestamp, +# from the current build. These values are available from the build_date, build_time, +# physical_address, and host_name output ports of the build_id module in the build_id.v +# Verilog source file. +# +# ================================================================================ + +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate [ clock format [ clock seconds ] -format %y%m%d ] + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + + # Create a Verilog file for output + set outputFileName "rtl/build_id.sv" + set outputFile [open $outputFileName "w"] + + # Output the Verilog source + puts $outputFile "`define BUILD_DATE \"$buildDate\"" + puts $outputFile "`define BUILD_TIME \"$buildTime\"" + close $outputFile + + # Send confirmation message to the Messages window + post_message "Generated build identification Verilog module: [pwd]/$outputFileName" + post_message "Date: $buildDate" + post_message "Time: $buildTime" +} + +# Comment out this line to prevent the process from automatically executing when the file is sourced: +generateBuildID_Verilog \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/collision.vhd b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/collision.vhd new file mode 100644 index 00000000..7720199f --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/collision.vhd @@ -0,0 +1,95 @@ +-- Collision detection logic for for Kee Games Sprint 1 +-- This is called the "Car/Playfield Comparator" in the manual and works by comparing the +-- video signals representing player and computer cars, track boundaries and oil slicks generating +-- collision signals when multiple objects appear at the same time (location) in the video. +-- Car 1 is the human player, Cars 2, 3 and Car 4 are computer controlled. +-- +-- NOTE: There is an error in the original schematic, F8 pin 5 should go to CAR1 (not inverted) and +-- F8 pin 9 to CAR2 (not inverted) while the schematic shows them connecting to the inverted signals +-- +-- Tests for the following conditions: +-- Car 1 equals Car 2 +-- Car 1 equals Car 3 or 4 +-- Car 1 equals Black Playfield (Oil slick) +-- Car 1 equals White Playfield (Track boundary) +-- +-- (c) 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity collision_detect is +port( + Clk6 : in std_logic; + Car1 : in std_logic; + Car1_n : in std_logic; + Car2 : in std_logic; + Car2_n : in std_logic; + Car3_4_n : in std_logic; + WhitePF_n : in std_logic; + BlackPF_n : in std_logic; + CollRst1_n : in std_logic; + Collisions1 : out std_logic_vector(1 downto 0) + ); +end collision_detect; + +architecture rtl of collision_detect is + +signal Col_latch_Q : std_logic_vector(2 downto 1) := (others => '0'); +signal S1_n : std_logic_vector(2 downto 1); +signal S2_n : std_logic_vector(2 downto 1); +signal R_n : std_logic_vector(2 downto 1); + + +begin + +-- Tristate buffer at E5 route collision signals to data bus 7-6 +Collisions1 <= Col_latch_Q(2 downto 1); + +-- 74LS279 quad SR latch at H6, all inputs are active low +-- Made synchronous here +H6: process(Clk6, S1_n, S2_n, R_n, Col_latch_Q) +begin + if rising_edge(Clk6) then +-- Units 1 and 3 each have an extra Set element, only half of IC is used in Sprint 1 +-- Ordered from top to bottom as drawn in the schematic + if R_n(1) = '0' then + Col_latch_Q(1) <= '0'; + elsif (S1_n(1) and S2_n(1)) = '0' then + Col_latch_Q(1) <= '1'; + else + Col_latch_Q(1) <= Col_latch_Q(1); + end if; + if R_n(2) = '0' then + Col_latch_Q(2) <= '0'; + elsif S1_n(2) = '0' then + Col_latch_Q(2) <= '1'; + else + Col_latch_Q(2) <= Col_latch_Q(2); + end if; + end if; +end process; + +-- Glue logic +S2_n(1) <= BlackPF_n or Car1_n; +S1_n(1) <= Car1 nand (Car2_n nand Car3_4_n); +R_n(1) <= CollRst1_n; + +R_n(2) <= CollRst1_n; +S1_n(2) <= Car1_n or WhitePF_n; + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/cpu_mem.vhd b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/cpu_mem.vhd new file mode 100644 index 00000000..ff20635b --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/cpu_mem.vhd @@ -0,0 +1,506 @@ +-- CPU, RAM, ROM and address decoder for Kee Games Sprint 1 +-- (c) 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity CPU_mem is +port( + CLK12 : in std_logic; + CLK6 : in std_logic; -- 6MHz on schematic + Reset_n : in std_logic; + VCount : in std_logic_vector(7 downto 0); + HCount : in std_logic_vector(8 downto 0); + Vblank_s : in std_logic; -- Vblank* on schematic + Vreset : in std_logic; + Hsync_n : in std_logic; + Test_n : in std_logic; + Attract : out std_logic; + Skid1 : out std_logic; + Skid2 : out std_logic; + NoiseReset_n : out std_logic; + CollRst1_n : out std_logic; + CollRst2_n : out std_logic; + Lamp1 : out std_logic; + SteerRst1_n : out std_logic; + PHI1_O : out std_logic; + PHI2_O : out std_logic; + DISPLAY : out std_logic_vector(7 downto 0); + IO_Adr : out std_logic_vector(9 downto 0); + Collisions1 : in std_logic_vector(1 downto 0); + Collisions2 : in std_logic_vector(1 downto 0); + Inputs : in std_logic_vector(1 downto 0) + ); +end CPU_mem; + +architecture rtl of CPU_mem is + +signal cpu_clk : std_logic; +signal PHI1 : std_logic; +signal PHI2 : std_logic; +signal Q5 : std_logic; +signal Q6 : std_logic; +signal A7_2 : std_logic; +signal A7_5 : std_logic; +signal A7_7 : std_logic; + +signal A8_6 : std_logic; + +signal H256 : std_logic; +signal H256_n : std_logic; +signal H128 : std_logic; +signal H64 : std_logic; +signal H32 : std_logic; +signal H16 : std_logic; +signal H8 : std_logic; +signal H4 : std_logic; + +signal V128 : std_logic; +signal V64 : std_logic; +signal V32 : std_logic; +signal V16 : std_logic; +signal V8 : std_logic; + +signal IRQ_n : std_logic; +signal NMI_n : std_logic; +signal RW_n : std_logic; +signal RnW : std_logic; +signal A : std_logic_vector(15 downto 0); +signal ADR : std_logic_vector(9 downto 0); +signal cpuDin : std_logic_vector(7 downto 0); +signal cpuDout : std_logic_vector(7 downto 0); +signal DBUS_n : std_logic_vector(7 downto 0); +signal DBUS : std_logic_vector(7 downto 0); + +signal ROM1_dout : std_logic_vector(7 downto 0); +signal ROM2_dout : std_logic_vector(7 downto 0); +signal ROM3_dout : std_logic_vector(7 downto 0); +signal ROM4_dout : std_logic_vector(7 downto 0); +signal ROM_dout : std_logic_vector(7 downto 0); + +signal ROM1 : std_logic; +signal ROM2 : std_logic; +signal ROM3 : std_logic; +signal ROM4 : std_logic; +signal ROM_ce : std_logic; +signal ROM_mux_in : std_logic_vector(3 downto 0); + +signal cpuRAM_dout : std_logic_vector(7 downto 0); +signal Vram_dout : std_logic_vector(7 downto 0); +signal RAM_addr : std_logic_vector(9 downto 0) := (others => '0'); +signal Vram_addr : std_logic_vector(9 downto 0) := (others => '0'); +signal scanbus : std_logic_vector(9 downto 0) := (others => '0'); +signal RAM_dout : std_logic_vector(7 downto 0); +signal RAM_we : std_logic; +signal RAM_RW_n : std_logic; +signal RAM_ce_n : std_logic; +signal RAM_n : std_logic; +signal WRAM : std_logic; +signal WRITE_n : std_logic; + +signal F2_in : std_logic_vector(3 downto 0); +signal F2_out : std_logic_vector(9 downto 0); +signal D2_in : std_logic_vector(3 downto 0); +signal D2_out : std_logic_vector(9 downto 0); +signal E8_in : std_logic_vector(3 downto 0); +signal E8_out : std_logic_vector(9 downto 0); +signal P3_8 : std_logic; + +signal Sync : std_logic; +signal Sync_n : std_logic; +signal Switch_n : std_logic; +signal Display_n : std_logic; +signal Addec_bus : std_logic_vector(7 downto 0); + +signal Timer_Reset_n : std_logic := '1'; +signal Collision1_n : std_logic := '1'; +signal Collision2_n : std_logic := '1'; +signal Attract_int : std_logic := '1'; + +signal J6_5 : std_logic; +signal J6_9 : std_logic; + +signal Coin1 : std_logic; +signal Coin2 : std_logic; +signal Input_mux : std_logic; +signal A8_8 : std_logic; +signal H9_Q_n : std_logic; +signal J9_out : std_logic_vector(7 downto 0); + +signal H8_en : std_logic; + +begin + +H8 <= HCount(3); +H16 <= HCount(4); +H32 <= HCount(5); +H64 <= HCount(6); +H128 <= HCount(7); +H256 <= HCount(8); +H256_n <= (not HCount(8)); + +V8 <= VCount(3); +V16 <= VCount(4); +V32 <= VCount(5); +V64 <= VCount(6); +V128 <= VCount(7); + + +CPU: entity work.T65 +port map( + Enable => '1', + Mode => "00", + Res_n => reset_n, + Clk => phi1, + Rdy => '1', + Abort_n => '1', + IRQ_n => '1', + NMI_n => NMI_n, + SO_n => '1', + R_W_n => RW_n, + A(15 downto 0) => A, + DI => cpuDin, + DO => cpuDout + ); + +DBUS_n <= (not cpuDout); -- Data bus to video RAM is inverted +ADR(9 downto 7) <= (A(9) or WRAM) & (A(8) or WRAM) & (A(7) or WRAM); +ADR(6 downto 0) <= A(6 downto 0); +RnW <= (not RW_n); +IO_Adr <= Adr; +NMI_n <= not (Vblank_s and Test_n); + + +-- CPU clock +H4 <= Hcount(2); +CPU_clock: process(clk12, H4, Q5, Q6) +begin + if rising_edge(clk12) then + Q5 <= H4; + Q6 <= Q5; + end if; + phi1 <= not (Q5 or Q6); --? +end process; + +PHI2 <= (not PHI1); +PHI1_O <= PHI1; +PHI2_O <= PHI2; + + +A8_6 <= not(RnW and PHI2 and H4 and WRITE_n); +A7: process(clk12, A8_6) -- Shift register chain of 4 DFF's clocked by clk12, creates a delayed WRITE_n +begin + if rising_edge(clk12) then + A7_2 <= A8_6; + A7_5 <= A7_2; + A7_7 <= A7_5; + WRITE_n <= A7_7; + end if; +end process; + + +-- Program ROMs +A1: entity work.sprom +generic map( + init_file => "rtl/roms/6290-01b1.hex", + widthad_a => 11, + width_a => 8) +port map( + clock => clk6, + address => A(10) & ADR(9 downto 0), + q => rom1_dout + ); + +--A1: entity work.prog_rom1 +--port map( +-- clock => clk6, +-- address => A(10) & ADR(9 downto 0), +-- q => rom1_dout +-- ); + +C1: entity work.sprom +generic map( + init_file => "rtl/roms/6291-01c1.hex", + widthad_a => 11, + width_a => 8) +port map( + clock => clk6, + address => A(10) & ADR(9 downto 0), + q => rom2_dout + ); + +--C1: entity work.prog_rom2 +--port map( +-- clock => clk6, +-- address => A(10) & ADR(9 downto 0), +-- q => rom2_dout +-- ); + +D1: entity work.sprom +generic map( + init_file => "rtl/roms/6442-01d1.hex", + widthad_a => 11, + width_a => 8) +port map( + clock => clk6, + address => A(10) & ADR(9 downto 0), + q => rom3_dout + ); + +--D1: entity work.prog_rom3 +--port map( +-- clock => clk6, +-- address => A(10) & ADR(9 downto 0), +-- q => rom3_dout +-- ); + +E1: entity work.sprom +generic map( + init_file => "rtl/roms/6443-01e1.hex", + widthad_a => 11, + width_a => 8) +port map( + clock => clk6, + address => A(10) & ADR(9 downto 0), + q => rom4_dout + ); + +--E1: entity work.prog_rom4 +--port map( +-- clock => clk6, +-- address => A(10) & ADR(9 downto 0), +-- q => rom4_dout +-- ); + +-- ROM data mux +ROM_mux_in <= (ROM1 & ROM2 & ROM3 & ROM4); +ROM_mux: process(ROM_mux_in, rom1_dout, rom2_dout, rom3_dout, rom4_dout) +begin + ROM_dout <= (others => '0'); + case ROM_mux_in is + when "1000" => rom_dout <= rom1_dout; + when "0100" => rom_dout <= rom2_dout; + when "0010" => rom_dout <= rom3_dout; + when "0001" => rom_dout <= rom4_dout; + when others => null; + end case; +end process; + +-- RAM +-- The original hardware multiplexes access to the RAM between the CPU and video hardware. In the FPGA it's +-- easier to use dual-ported RAM +RAM: entity work.dpram +generic map( + widthad_a => 10, + width_a => 8) +port map( + clock_a => clk6, +-- CPU side + address_a => adr(9 downto 0), + wren_a => ram_we, + data_a => DBUS_n, + q_a=> CPUram_dout, + +-- Video side + clock_b => clk6, + address_b => Vram_addr, + wren_b => '0', + data_b => x"FF", + q_b => Vram_dout + ); + +--RAM: entity work.ram1k_dp +--port map( +-- clock => clk6, +-- CPU side +-- address_a => adr(9 downto 0), +-- wren_a => ram_we, +-- data_a => DBUS_n, +-- q_a=> CPUram_dout, + +-- Video side +-- address_b => Vram_addr, +-- wren_b => '0', +-- data_b => x"FF", +-- q_b => Vram_dout +-- ); + +Vram_addr <= (V128 or H256_n) & (V64 or H256_n) & (V32 or H256_n) & (V16 and H256) & (V8 and H256) & H128 & H64 & H32 & H16 & H8; + +-- Real hardware has both WE and CE which are selected by K2 according to the state of the phase 2 clock +-- Altera block RAM has active high WE, original RAM had active low WE +ram_we <= (not Write_n) and (not Display_n) and Phi2; + +-- Rising edge of phi2 clock latches inverted output of VRAM data bus +F5: process(phi2) +begin + if rising_edge(phi2) then + display <= not Vram_dout; + end if; +end process; + + +-- Address decoder +-- A15 and A14 are not used +-- Original circuit uses a bipolar PROM in the address decoder, this could be replaced with combinational logic + +-- E2 PROM +K6: entity work.sprom +generic map( + init_file => "rtl/roms/6401-01e2.hex", + widthad_a => 5, + width_a => 8) +port map( + clock => clk12, + address => A(13 downto 9), + q => addec_bus + ); + +--E2: entity work.addec_prom +--port map( +-- clock => clk12, +-- address => A(13 downto 9), +-- q => addec_bus +-- ); + +F2_in <= addec_bus(0) & addec_bus(1) & addec_bus(2) & addec_bus(3); +WRAM <= addec_bus(4); +D2_in <= RnW & addec_bus(5) & addec_bus(6) & addec_bus(7); + +-- Decoder code could be cleaned up a bit, unused decoder states are not explicitly implemented +F2: process(F2_in) +begin + case F2_in is + when "0000" => + F2_out <= "1111111110"; + when "0001" => + F2_out <= "1111111101"; + when "0010" => + F2_out <= "1111111011"; + when "0011" => + F2_out <= "1111110111"; + when "0100" => + F2_out <= "1111101111"; + when "0101" => + F2_out <= "1111011111"; + when "0110" => + F2_out <= "1110111111"; + when "0111" => + F2_out <= "1101111111"; + when others => + F2_out <= "1111111111"; + end case; +end process; + +ROM1 <= (F2_out(0) nand F2_out(1)); +ROM2 <= (F2_out(2) nand F2_out(3)); +ROM3 <= (F2_out(4) nand F2_out(5)); +ROM4 <= (F2_out(6) nand F2_out(7)); +ROM_ce <= (ROM1 or ROM2 or ROM3 or ROM4); + +D2: process(D2_in) +begin + case D2_in is + when "0000" => + D2_out <= "1111111110"; + when "0001" => + D2_out <= "1111111101"; + when "0010" => + D2_out <= "1111111011"; + when "0011" => + D2_out <= "1111110111"; + when "0100" => + D2_out <= "1111101111"; + when "1000" => + D2_out <= "1011111111"; + when "1001" => + D2_out <= "0111111111"; + when others => + D2_out <= "1111111111"; + end case; +end process; + +RAM_n <= D2_out(0); +SYNC_n <= D2_out(1); +SYNC <= (not SYNC_n); +SWITCH_n <= D2_out(2); +COLLISION1_n <= D2_out(3); +COLLISION2_n <= D2_out(4); +DISPLAY_n <= (D2_out(0) and D2_out(8)); +P3_8 <= (D2_out(9) or WRITE_n); + +E8_in <= P3_8 & ADR(9 downto 7); + +E8: process(E8_in) +begin + case E8_in is + when "0000" => + E8_out <= "1111111110"; + when "0001" => + E8_out <= "1111111101"; + when "0010" => + E8_out <= "1111111011"; + when "0011" => + E8_out <= "1111110111"; + when "0100" => + E8_out <= "1111101111"; + when "0101" => + E8_out <= "1111011111"; + when "0110" => + E8_out <= "1110111111"; + when others => + E8_out <= "1111111111"; + end case; +end process; + +H8_en <= E8_out(0); +Timer_Reset_n <= E8_out(1); +CollRst1_n <= E8_out(2); +CollRst2_n <= E8_out(3); +SteerRst1_n <= E8_out(4); +NoiseReset_n <= E8_out(6); + +-- H8 9334 +H8_dec: process(clk6, Adr) +begin +if rising_edge(clk6) then + if (H8_en = '0') then + case Adr(6 downto 4) is + when "000" => Attract_int <= Adr(0); + when "001" => Skid1 <= Adr(0); + when "010" => null; + when "011" => LAMP1 <= Adr(0); + when "100" => null; + when "101" => null; -- "Spare" on schematic + when "110" => null; + when "111" => null; + when others => null; + end case; + end if; + end if; +end process; +Attract <= Attract_Int; + +-- CPU Din mux +cpuDin <= ROM_dout when rom_ce = '1' else + (not CPUram_dout) when Display_n = '0' else -- Remember RAM data is inverted + VCount(7) & VBlank_s & Vreset & Attract_int & "1111" when Sync_n = '0' else -- Using V128 (VCount(7)) in place of 60Hz mains reference + Collisions1 & "111111" when Collision1_n = '0' else + Inputs & "111111" when SWITCH_n = '0' else + x"FF"; + +end rtl; diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/dac.sv b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/dac.sv new file mode 100644 index 00000000..22ae8f07 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/dac.sv @@ -0,0 +1,33 @@ +// +// PWM DAC +// +// MSBI is the highest bit number. NOT amount of bits! +// +module dac #(parameter MSBI=6, parameter INV=1'b1) +( + output reg DACout, //Average Output feeding analog lowpass + input [MSBI:0] DACin, //DAC input (excess 2**MSBI) + input CLK, + input RESET +); + +reg [MSBI+2:0] DeltaAdder; //Output of Delta Adder +reg [MSBI+2:0] SigmaAdder; //Output of Sigma Adder +reg [MSBI+2:0] SigmaLatch; //Latches output of Sigma Adder +reg [MSBI+2:0] DeltaB; //B input of Delta Adder + +always @(*) DeltaB = {SigmaLatch[MSBI+2], SigmaLatch[MSBI+2]} << (MSBI+1); +always @(*) DeltaAdder = DACin + DeltaB; +always @(*) SigmaAdder = DeltaAdder + SigmaLatch; + +always @(posedge CLK or posedge RESET) begin + if(RESET) begin + SigmaLatch <= 1'b1 << (MSBI+1); + DACout <= INV; + end else begin + SigmaLatch <= SigmaAdder; + DACout <= SigmaLatch[MSBI+2] ^ INV; + end +end + +endmodule diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/dpram.vhd b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/dpram.vhd new file mode 100644 index 00000000..9ea85a26 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/dpram.vhd @@ -0,0 +1,130 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY dpram IS + GENERIC + ( + init_file : string := ""; + widthad_a : natural; + width_a : natural := 8; + outdata_reg_a : string := "UNREGISTERED"; + outdata_reg_b : string := "UNREGISTERED" + ); + PORT + ( + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + clock_a : IN STD_LOGIC ; + clock_b : IN STD_LOGIC ; + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + wren_a : IN STD_LOGIC := '1'; + wren_b : IN STD_LOGIC := '1'; + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); +END dpram; + + +ARCHITECTURE SYN OF dpram IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + SIGNAL sub_wire1 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + address_reg_b : STRING; + clock_enable_input_a : STRING; + clock_enable_input_b : STRING; + clock_enable_output_a : STRING; + clock_enable_output_b : STRING; + indata_reg_b : STRING; + init_file : STRING; + intended_device_family : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + numwords_b : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_aclr_b : STRING; + outdata_reg_a : STRING; + outdata_reg_b : STRING; + power_up_uninitialized : STRING; + read_during_write_mode_port_a : STRING; + read_during_write_mode_port_b : STRING; + widthad_a : NATURAL; + widthad_b : NATURAL; + width_a : NATURAL; + width_b : NATURAL; + width_byteena_a : NATURAL; + width_byteena_b : NATURAL; + wrcontrol_wraddress_reg_b : STRING + ); + PORT ( + wren_a : IN STD_LOGIC ; + clock0 : IN STD_LOGIC ; + wren_b : IN STD_LOGIC ; + clock1 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q_a <= sub_wire0(width_a-1 DOWNTO 0); + q_b <= sub_wire1(width_a-1 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_reg_b => "CLOCK1", + clock_enable_input_a => "BYPASS", + clock_enable_input_b => "BYPASS", + clock_enable_output_a => "BYPASS", + clock_enable_output_b => "BYPASS", + indata_reg_b => "CLOCK1", + init_file => init_file, + intended_device_family => "Cyclone III", + lpm_type => "altsyncram", + numwords_a => 2**widthad_a, + numwords_b => 2**widthad_a, + operation_mode => "BIDIR_DUAL_PORT", + outdata_aclr_a => "NONE", + outdata_aclr_b => "NONE", + outdata_reg_a => outdata_reg_a, + outdata_reg_b => outdata_reg_a, + power_up_uninitialized => "FALSE", + read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", + read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ", + widthad_a => widthad_a, + widthad_b => widthad_a, + width_a => width_a, + width_b => width_a, + width_byteena_a => 1, + width_byteena_b => 1, + wrcontrol_wraddress_reg_b => "CLOCK1" + ) + PORT MAP ( + wren_a => wren_a, + clock0 => clock_a, + wren_b => wren_b, + clock1 => clock_b, + address_a => address_a, + address_b => address_b, + data_a => data_a, + data_b => data_b, + q_a => sub_wire0, + q_b => sub_wire1 + ); + + + +END SYN; diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/hq2x.sv b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/hq2x.sv new file mode 100644 index 00000000..f17732b6 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/hq2x.sv @@ -0,0 +1,454 @@ +// +// +// Copyright (c) 2012-2013 Ludvig Strigeus +// Copyright (c) 2017 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on + +`define BITS_TO_FIT(N) ( \ + N <= 2 ? 0 : \ + N <= 4 ? 1 : \ + N <= 8 ? 2 : \ + N <= 16 ? 3 : \ + N <= 32 ? 4 : \ + N <= 64 ? 5 : \ + N <= 128 ? 6 : \ + N <= 256 ? 7 : \ + N <= 512 ? 8 : \ + N <=1024 ? 9 : 10 ) + +module hq2x_in #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input rdbuf, + output[DWIDTH:0] q, + + input [AWIDTH:0] wraddr, + input wrbuf, + input [DWIDTH:0] data, + input wren +); + + localparam AWIDTH = `BITS_TO_FIT(LENGTH); + wire [DWIDTH:0] out[2]; + assign q = out[rdbuf]; + + hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); + hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); +endmodule + + +module hq2x_out #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input [1:0] rdbuf, + output[DWIDTH:0] q, + + input [AWIDTH:0] wraddr, + input [1:0] wrbuf, + input [DWIDTH:0] data, + input wren +); + + localparam AWIDTH = `BITS_TO_FIT(LENGTH*2); + wire [DWIDTH:0] out[4]; + assign q = out[rdbuf]; + + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf2(clk,data,rdaddr,wraddr,wren && (wrbuf == 2),out[2]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf3(clk,data,rdaddr,wraddr,wren && (wrbuf == 3),out[3]); +endmodule + + +module hq2x_buf #(parameter NUMWORDS, parameter AWIDTH, parameter DWIDTH) +( + input clock, + input [DWIDTH:0] data, + input [AWIDTH:0] rdaddress, + input [AWIDTH:0] wraddress, + input wren, + output [DWIDTH:0] q +); + + altsyncram altsyncram_component ( + .address_a (wraddress), + .clock0 (clock), + .data_a (data), + .wren_a (wren), + .address_b (rdaddress), + .q_b(q), + .aclr0 (1'b0), + .aclr1 (1'b0), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_b ({(DWIDTH+1){1'b1}}), + .eccstatus (), + .q_a (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_b (1'b0)); + defparam + altsyncram_component.address_aclr_b = "NONE", + altsyncram_component.address_reg_b = "CLOCK0", + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_input_b = "BYPASS", + altsyncram_component.clock_enable_output_b = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = NUMWORDS, + altsyncram_component.numwords_b = NUMWORDS, + altsyncram_component.operation_mode = "DUAL_PORT", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.outdata_reg_b = "UNREGISTERED", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE", + altsyncram_component.widthad_a = AWIDTH+1, + altsyncram_component.widthad_b = AWIDTH+1, + altsyncram_component.width_a = DWIDTH+1, + altsyncram_component.width_b = DWIDTH+1, + altsyncram_component.width_byteena_a = 1; + +endmodule + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +module DiffCheck +( + input [17:0] rgb1, + input [17:0] rgb2, + output result +); + + wire [5:0] r = rgb1[5:1] - rgb2[5:1]; + wire [5:0] g = rgb1[11:7] - rgb2[11:7]; + wire [5:0] b = rgb1[17:13] - rgb2[17:13]; + wire [6:0] t = $signed(r) + $signed(b); + wire [6:0] gx = {g[5], g}; + wire [7:0] y = $signed(t) + $signed(gx); + wire [6:0] u = $signed(r) - $signed(b); + wire [7:0] v = $signed({g, 1'b0}) - $signed(t); + + // if y is inside (-24..24) + wire y_inside = (y < 8'h18 || y >= 8'he8); + + // if u is inside (-4, 4) + wire u_inside = (u < 7'h4 || u >= 7'h7c); + + // if v is inside (-6, 6) + wire v_inside = (v < 8'h6 || v >= 8'hfA); + assign result = !(y_inside && u_inside && v_inside); +endmodule + +module InnerBlend +( + input [8:0] Op, + input [5:0] A, + input [5:0] B, + input [5:0] C, + output [5:0] O +); + + function [8:0] mul6x3; + input [5:0] op1; + input [2:0] op2; + begin + mul6x3 = 9'd0; + if(op2[0]) mul6x3 = mul6x3 + op1; + if(op2[1]) mul6x3 = mul6x3 + {op1, 1'b0}; + if(op2[2]) mul6x3 = mul6x3 + {op1, 2'b00}; + end + endfunction + + wire OpOnes = Op[4]; + wire [8:0] Amul = mul6x3(A, Op[7:5]); + wire [8:0] Bmul = mul6x3(B, {Op[3:2], 1'b0}); + wire [8:0] Cmul = mul6x3(C, {Op[1:0], 1'b0}); + wire [8:0] At = Amul; + wire [8:0] Bt = (OpOnes == 0) ? Bmul : {3'b0, B}; + wire [8:0] Ct = (OpOnes == 0) ? Cmul : {3'b0, C}; + wire [9:0] Res = {At, 1'b0} + Bt + Ct; + assign O = Op[8] ? A : Res[9:4]; +endmodule + +module Blend +( + input [5:0] rule, + input disable_hq2x, + input [17:0] E, + input [17:0] A, + input [17:0] B, + input [17:0] D, + input [17:0] F, + input [17:0] H, + output [17:0] Result +); + + reg [1:0] input_ctrl; + reg [8:0] op; + localparam BLEND0 = 9'b1_xxx_x_xx_xx; // 0: A + localparam BLEND1 = 9'b0_110_0_10_00; // 1: (A * 12 + B * 4) >> 4 + localparam BLEND2 = 9'b0_100_0_10_10; // 2: (A * 8 + B * 4 + C * 4) >> 4 + localparam BLEND3 = 9'b0_101_0_10_01; // 3: (A * 10 + B * 4 + C * 2) >> 4 + localparam BLEND4 = 9'b0_110_0_01_01; // 4: (A * 12 + B * 2 + C * 2) >> 4 + localparam BLEND5 = 9'b0_010_0_11_11; // 5: (A * 4 + (B + C) * 6) >> 4 + localparam BLEND6 = 9'b0_111_1_xx_xx; // 6: (A * 14 + B + C) >> 4 + localparam AB = 2'b00; + localparam AD = 2'b01; + localparam DB = 2'b10; + localparam BD = 2'b11; + wire is_diff; + DiffCheck diff_checker(rule[1] ? B : H, rule[0] ? D : F, is_diff); + + always @* begin + case({!is_diff, rule[5:2]}) + 1,17: {op, input_ctrl} = {BLEND1, AB}; + 2,18: {op, input_ctrl} = {BLEND1, DB}; + 3,19: {op, input_ctrl} = {BLEND1, BD}; + 4,20: {op, input_ctrl} = {BLEND2, DB}; + 5,21: {op, input_ctrl} = {BLEND2, AB}; + 6,22: {op, input_ctrl} = {BLEND2, AD}; + + 8: {op, input_ctrl} = {BLEND0, 2'bxx}; + 9: {op, input_ctrl} = {BLEND0, 2'bxx}; + 10: {op, input_ctrl} = {BLEND0, 2'bxx}; + 11: {op, input_ctrl} = {BLEND1, AB}; + 12: {op, input_ctrl} = {BLEND1, AB}; + 13: {op, input_ctrl} = {BLEND1, AB}; + 14: {op, input_ctrl} = {BLEND1, DB}; + 15: {op, input_ctrl} = {BLEND1, BD}; + + 24: {op, input_ctrl} = {BLEND2, DB}; + 25: {op, input_ctrl} = {BLEND5, DB}; + 26: {op, input_ctrl} = {BLEND6, DB}; + 27: {op, input_ctrl} = {BLEND2, DB}; + 28: {op, input_ctrl} = {BLEND4, DB}; + 29: {op, input_ctrl} = {BLEND5, DB}; + 30: {op, input_ctrl} = {BLEND3, BD}; + 31: {op, input_ctrl} = {BLEND3, DB}; + default: {op, input_ctrl} = 11'bx; + endcase + + // Setting op[8] effectively disables HQ2X because blend will always return E. + if (disable_hq2x) op[8] = 1; + end + + // Generate inputs to the inner blender. Valid combinations. + // 00: E A B + // 01: E A D + // 10: E D B + // 11: E B D + wire [17:0] Input1 = E; + wire [17:0] Input2 = !input_ctrl[1] ? A : + !input_ctrl[0] ? D : B; + + wire [17:0] Input3 = !input_ctrl[0] ? B : D; + InnerBlend inner_blend1(op, Input1[5:0], Input2[5:0], Input3[5:0], Result[5:0]); + InnerBlend inner_blend2(op, Input1[11:6], Input2[11:6], Input3[11:6], Result[11:6]); + InnerBlend inner_blend3(op, Input1[17:12], Input2[17:12], Input3[17:12], Result[17:12]); +endmodule + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +module Hq2x #(parameter LENGTH, parameter HALF_DEPTH) +( + input clk, + input ce_x4, + input [DWIDTH:0] inputpixel, + input mono, + input disable_hq2x, + input reset_frame, + input reset_line, + input [1:0] read_y, + input [AWIDTH+1:0] read_x, + output [DWIDTH:0] outpixel +); + + +localparam AWIDTH = `BITS_TO_FIT(LENGTH); +localparam DWIDTH = HALF_DEPTH ? 8 : 17; + +wire [5:0] hqTable[256] = '{ + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 35, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 35, 35, 23, 61, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 7, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 58, 23, 15, 51, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 39, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 7, 35, 23, 15, 7, 43 +}; + +reg [17:0] Prev0, Prev1, Prev2, Curr0, Curr1, Next0, Next1, Next2; +reg [17:0] A, B, D, F, G, H; +reg [7:0] pattern, nextpatt; +reg [1:0] i; +reg [7:0] y; + +wire curbuf = y[0]; +reg prevbuf = 0; +wire iobuf = !curbuf; + +wire diff0, diff1; +DiffCheck diffcheck0(Curr1, (i == 0) ? Prev0 : (i == 1) ? Curr0 : (i == 2) ? Prev2 : Next1, diff0); +DiffCheck diffcheck1(Curr1, (i == 0) ? Prev1 : (i == 1) ? Next0 : (i == 2) ? Curr2 : Next2, diff1); + +wire [7:0] new_pattern = {diff1, diff0, pattern[7:2]}; + +wire [17:0] X = (i == 0) ? A : (i == 1) ? Prev1 : (i == 2) ? Next1 : G; +wire [17:0] blend_result; +Blend blender(hqTable[nextpatt], disable_hq2x, Curr0, X, B, D, F, H, blend_result); + +reg Curr2_addr1; +reg [AWIDTH:0] Curr2_addr2; +wire [17:0] Curr2 = HALF_DEPTH ? h2rgb(Curr2tmp) : Curr2tmp; +wire [DWIDTH:0] Curr2tmp; + +reg [AWIDTH:0] wrin_addr2; +reg [DWIDTH:0] wrpix; +reg wrin_en; + +function [17:0] h2rgb; + input [8:0] v; +begin + h2rgb = mono ? {v[5:3],v[2:0], v[5:3],v[2:0], v[5:3],v[2:0]} : {v[8:6],v[8:6],v[5:3],v[5:3],v[2:0],v[2:0]}; +end +endfunction + +function [8:0] rgb2h; + input [17:0] v; +begin + rgb2h = mono ? {3'b000, v[17:15], v[14:12]} : {v[17:15], v[11:9], v[5:3]}; +end +endfunction + +hq2x_in #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_in +( + .clk(clk), + + .rdaddr(Curr2_addr2), + .rdbuf(Curr2_addr1), + .q(Curr2tmp), + + .wraddr(wrin_addr2), + .wrbuf(iobuf), + .data(wrpix), + .wren(wrin_en) +); + +reg [1:0] wrout_addr1; +reg [AWIDTH+1:0] wrout_addr2; +reg wrout_en; +reg [DWIDTH:0] wrdata; + +hq2x_out #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_out +( + .clk(clk), + + .rdaddr(read_x), + .rdbuf(read_y), + .q(outpixel), + + .wraddr(wrout_addr2), + .wrbuf(wrout_addr1), + .data(wrdata), + .wren(wrout_en) +); + +always @(posedge clk) begin + reg [AWIDTH:0] offs; + reg old_reset_line; + reg old_reset_frame; + + wrout_en <= 0; + wrin_en <= 0; + + if(ce_x4) begin + + pattern <= new_pattern; + + if(~&offs) begin + if (i == 0) begin + Curr2_addr1 <= prevbuf; + Curr2_addr2 <= offs; + end + if (i == 1) begin + Prev2 <= Curr2; + Curr2_addr1 <= curbuf; + Curr2_addr2 <= offs; + end + if (i == 2) begin + Next2 <= HALF_DEPTH ? h2rgb(inputpixel) : inputpixel; + wrpix <= inputpixel; + wrin_addr2 <= offs; + wrin_en <= 1; + end + if (i == 3) begin + offs <= offs + 1'd1; + end + + if(HALF_DEPTH) wrdata <= rgb2h(blend_result); + else wrdata <= blend_result; + + wrout_addr1 <= {curbuf, i[1]}; + wrout_addr2 <= {offs, i[1]^i[0]}; + wrout_en <= 1; + end + + if(i==3) begin + nextpatt <= {new_pattern[7:6], new_pattern[3], new_pattern[5], new_pattern[2], new_pattern[4], new_pattern[1:0]}; + {A, G} <= {Prev0, Next0}; + {B, F, H, D} <= {Prev1, Curr2, Next1, Curr0}; + {Prev0, Prev1} <= {Prev1, Prev2}; + {Curr0, Curr1} <= {Curr1, Curr2}; + {Next0, Next1} <= {Next1, Next2}; + end else begin + nextpatt <= {nextpatt[5], nextpatt[3], nextpatt[0], nextpatt[6], nextpatt[1], nextpatt[7], nextpatt[4], nextpatt[2]}; + {B, F, H, D} <= {F, H, D, B}; + end + + i <= i + 1'b1; + if(old_reset_line && ~reset_line) begin + old_reset_frame <= reset_frame; + offs <= 0; + i <= 0; + y <= y + 1'd1; + prevbuf <= curbuf; + if(old_reset_frame & ~reset_frame) begin + y <= 0; + prevbuf <= 0; + end + end + + old_reset_line <= reset_line; + end +end + +endmodule // Hq2x diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/keyboard.sv b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/keyboard.sv new file mode 100644 index 00000000..ce182b0a --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/keyboard.sv @@ -0,0 +1,84 @@ + + +module keyboard +( + input clk, + input reset, + input ps2_kbd_clk, + input ps2_kbd_data, + + output reg[11:0] joystick +); + +reg [11:0] shift_reg = 12'hFFF; +wire[11:0] kdata = {ps2_kbd_data,shift_reg[11:1]}; +wire [7:0] kcode = kdata[9:2]; +reg release_btn = 0; + +reg [7:0] code; +reg input_strobe = 0; + +always @(negedge clk) begin + reg old_reset = 0; + + old_reset <= reset; + + if(~old_reset & reset)begin + joystick <= 0; + end + + if(input_strobe) begin + case(code) + 'h75: joystick[3] <= ~release_btn; // arrow up + 'h72: joystick[2] <= ~release_btn; // arrow down + 'h6B: joystick[1] <= ~release_btn; // arrow left + 'h74: joystick[0] <= ~release_btn; // arrow right + + 'h29: joystick[4] <= ~release_btn; // Space + 'h05: joystick[5] <= ~release_btn; // F1 + 'h06: joystick[6] <= ~release_btn; // F2 + 'h76: joystick[7] <= ~release_btn; // Escape + + 'h69: joystick[8] <= ~release_btn; // 1 + 'h72: joystick[9] <= ~release_btn; // 2 + 'h7A: joystick[10] <= ~release_btn; // 3 + 'h6B: joystick[11] <= ~release_btn; // 4 + endcase + end +end + +always @(posedge clk) begin + reg [3:0] prev_clk = 0; + reg old_reset = 0; + reg action = 0; + + old_reset <= reset; + input_strobe <= 0; + + if(~old_reset & reset)begin + prev_clk <= 0; + shift_reg <= 12'hFFF; + end else begin + prev_clk <= {ps2_kbd_clk,prev_clk[3:1]}; + if(prev_clk == 1) begin + if (kdata[11] & ^kdata[10:2] & ~kdata[1] & kdata[0]) begin + shift_reg <= 12'hFFF; + if (kcode == 8'he0) ; + // Extended key code follows + else if (kcode == 8'hf0) + // Release code follows + action <= 1; + else begin + // Cancel extended/release flags for next time + action <= 0; + release_btn <= action; + code <= kcode; + input_strobe <= 1; + end + end else begin + shift_reg <= kdata; + end + end + end +end +endmodule diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/mist_io.sv b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/mist_io.sv new file mode 100644 index 00000000..dcc7ecde --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/mist_io.sv @@ -0,0 +1,491 @@ +// +// mist_io.v +// +// mist_io for the MiST board +// http://code.google.com/p/mist-board/ +// +// Copyright (c) 2014 Till Harbaum +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////// + +// +// Use buffer to access SD card. It's time-critical part. +// Made module synchroneous with 2 clock domains: clk_sys and SPI_SCK +// (Sorgelig) +// +// for synchronous projects default value for PS2DIV is fine for any frequency of system clock. +// clk_ps2 = clk_sys/(PS2DIV*2) +// + +module mist_io #(parameter STRLEN=0, parameter PS2DIV=100) +( + + // parameter STRLEN and the actual length of conf_str have to match + input [(8*STRLEN)-1:0] conf_str, + + // Global clock. It should be around 100MHz (higher is better). + input clk_sys, + + // Global SPI clock from ARM. 24MHz + input SPI_SCK, + + input CONF_DATA0, + input SPI_SS2, + output SPI_DO, + input SPI_DI, + + output reg [7:0] joystick_0, + output reg [7:0] joystick_1, + output reg [15:0] joystick_analog_0, + output reg [15:0] joystick_analog_1, + output [1:0] buttons, + output [1:0] switches, + output scandoubler_disable, + output ypbpr, + + output reg [31:0] status, + + // SD config + input sd_conf, + input sd_sdhc, + output img_mounted, // signaling that new image has been mounted + output reg [31:0] img_size, // size of image in bytes + + // SD block level access + input [31:0] sd_lba, + input sd_rd, + input sd_wr, + output reg sd_ack, + output reg sd_ack_conf, + + // SD byte level access. Signals for 2-PORT altsyncram. + output reg [8:0] sd_buff_addr, + output reg [7:0] sd_buff_dout, + input [7:0] sd_buff_din, + output reg sd_buff_wr, + + // ps2 keyboard emulation + output ps2_kbd_clk, + output reg ps2_kbd_data, + output ps2_mouse_clk, + output reg ps2_mouse_data, + input ps2_caps_led, + + // ARM -> FPGA download + output reg ioctl_download = 0, // signal indicating an active download + output reg [7:0] ioctl_index, // menu index used to upload the file + output ioctl_wr, + output reg [23:0] ioctl_addr, + output reg [7:0] ioctl_dout +); + +reg [7:0] b_data; +reg [6:0] sbuf; +reg [7:0] cmd; +reg [2:0] bit_cnt; // counts bits 0-7 0-7 ... +reg [9:0] byte_cnt; // counts bytes +reg [7:0] but_sw; +reg [2:0] stick_idx; + +reg mount_strobe = 0; +assign img_mounted = mount_strobe; + +assign buttons = but_sw[1:0]; +assign switches = but_sw[3:2]; +assign scandoubler_disable = but_sw[4]; +assign ypbpr = but_sw[5]; + +wire [7:0] spi_dout = { sbuf, SPI_DI}; + +// this variant of user_io is for 8 bit cores (type == a4) only +wire [7:0] core_type = 8'ha4; + +// command byte read by the io controller +wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd }; + +reg spi_do; +assign SPI_DO = CONF_DATA0 ? 1'bZ : spi_do; + +wire [7:0] kbd_led = { 2'b01, 4'b0000, ps2_caps_led, 1'b1}; + +// drive MISO only when transmitting core id +always@(negedge SPI_SCK) begin + if(!CONF_DATA0) begin + // first byte returned is always core type, further bytes are + // command dependent + if(byte_cnt == 0) begin + spi_do <= core_type[~bit_cnt]; + + end else begin + case(cmd) + // reading config string + 8'h14: begin + // returning a byte from string + if(byte_cnt < STRLEN + 1) spi_do <= conf_str[{STRLEN - byte_cnt,~bit_cnt}]; + else spi_do <= 0; + end + + // reading sd card status + 8'h16: begin + if(byte_cnt == 1) spi_do <= sd_cmd[~bit_cnt]; + else if((byte_cnt >= 2) && (byte_cnt < 6)) spi_do <= sd_lba[{5-byte_cnt, ~bit_cnt}]; + else spi_do <= 0; + end + + // reading sd card write data + 8'h18: + spi_do <= b_data[~bit_cnt]; + + // reading keyboard LED status + 8'h1f: + spi_do <= kbd_led[~bit_cnt]; + + default: + spi_do <= 0; + endcase + end + end +end + +reg b_wr2,b_wr3; +always @(negedge clk_sys) begin + b_wr3 <= b_wr2; + sd_buff_wr <= b_wr3; +end + +// SPI receiver +always@(posedge SPI_SCK or posedge CONF_DATA0) begin + + if(CONF_DATA0) begin + b_wr2 <= 0; + bit_cnt <= 0; + byte_cnt <= 0; + sd_ack <= 0; + sd_ack_conf <= 0; + end else begin + b_wr2 <= 0; + + sbuf <= spi_dout[6:0]; + bit_cnt <= bit_cnt + 1'd1; + if(bit_cnt == 5) begin + if (byte_cnt == 0) sd_buff_addr <= 0; + if((byte_cnt != 0) & (sd_buff_addr != 511)) sd_buff_addr <= sd_buff_addr + 1'b1; + if((byte_cnt == 1) & ((cmd == 8'h17) | (cmd == 8'h19))) sd_buff_addr <= 0; + end + + // finished reading command byte + if(bit_cnt == 7) begin + if(~&byte_cnt) byte_cnt <= byte_cnt + 8'd1; + if(byte_cnt == 0) begin + cmd <= spi_dout; + + if(spi_dout == 8'h19) begin + sd_ack_conf <= 1; + sd_buff_addr <= 0; + end + if((spi_dout == 8'h17) || (spi_dout == 8'h18)) begin + sd_ack <= 1; + sd_buff_addr <= 0; + end + if(spi_dout == 8'h18) b_data <= sd_buff_din; + + mount_strobe <= 0; + + end else begin + + case(cmd) + // buttons and switches + 8'h01: but_sw <= spi_dout; + 8'h02: joystick_0 <= spi_dout; + 8'h03: joystick_1 <= spi_dout; + + // store incoming ps2 mouse bytes + 8'h04: begin + ps2_mouse_fifo[ps2_mouse_wptr] <= spi_dout; + ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1; + end + + // store incoming ps2 keyboard bytes + 8'h05: begin + ps2_kbd_fifo[ps2_kbd_wptr] <= spi_dout; + ps2_kbd_wptr <= ps2_kbd_wptr + 1'd1; + end + + 8'h15: status[7:0] <= spi_dout; + + // send SD config IO -> FPGA + // flag that download begins + // sd card knows data is config if sd_dout_strobe is asserted + // with sd_ack still being inactive (low) + 8'h19, + // send sector IO -> FPGA + // flag that download begins + 8'h17: begin + sd_buff_dout <= spi_dout; + b_wr2 <= 1; + end + + 8'h18: b_data <= sd_buff_din; + + // joystick analog + 8'h1a: begin + // first byte is joystick index + if(byte_cnt == 1) stick_idx <= spi_dout[2:0]; + else if(byte_cnt == 2) begin + // second byte is x axis + if(stick_idx == 0) joystick_analog_0[15:8] <= spi_dout; + else if(stick_idx == 1) joystick_analog_1[15:8] <= spi_dout; + end else if(byte_cnt == 3) begin + // third byte is y axis + if(stick_idx == 0) joystick_analog_0[7:0] <= spi_dout; + else if(stick_idx == 1) joystick_analog_1[7:0] <= spi_dout; + end + end + + // notify image selection + 8'h1c: mount_strobe <= 1; + + // send image info + 8'h1d: if(byte_cnt<5) img_size[(byte_cnt-1)<<3 +:8] <= spi_dout; + + // status, 32bit version + 8'h1e: if(byte_cnt<5) status[(byte_cnt-1)<<3 +:8] <= spi_dout; + default: ; + endcase + end + end + end +end + + +/////////////////////////////// PS2 /////////////////////////////// +// 8 byte fifos to store ps2 bytes +localparam PS2_FIFO_BITS = 3; + +reg clk_ps2; +always @(negedge clk_sys) begin + integer cnt; + cnt <= cnt + 1'd1; + if(cnt == PS2DIV) begin + clk_ps2 <= ~clk_ps2; + cnt <= 0; + end +end + +// keyboard +reg [7:0] ps2_kbd_fifo[1<= 1)&&(ps2_kbd_tx_state < 9)) begin + ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits + ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down + if(ps2_kbd_tx_byte[0]) + ps2_kbd_parity <= !ps2_kbd_parity; + end + + // transmission of parity + if(ps2_kbd_tx_state == 9) ps2_kbd_data <= ps2_kbd_parity; + + // transmission of stop bit + if(ps2_kbd_tx_state == 10) ps2_kbd_data <= 1; // stop bit is 1 + + // advance state machine + if(ps2_kbd_tx_state < 11) ps2_kbd_tx_state <= ps2_kbd_tx_state + 1'd1; + else ps2_kbd_tx_state <= 0; + end + end +end + +// mouse +reg [7:0] ps2_mouse_fifo[1<= 1)&&(ps2_mouse_tx_state < 9)) begin + ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits + ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down + if(ps2_mouse_tx_byte[0]) + ps2_mouse_parity <= !ps2_mouse_parity; + end + + // transmission of parity + if(ps2_mouse_tx_state == 9) ps2_mouse_data <= ps2_mouse_parity; + + // transmission of stop bit + if(ps2_mouse_tx_state == 10) ps2_mouse_data <= 1; // stop bit is 1 + + // advance state machine + if(ps2_mouse_tx_state < 11) ps2_mouse_tx_state <= ps2_mouse_tx_state + 1'd1; + else ps2_mouse_tx_state <= 0; + end + end +end + + +/////////////////////////////// DOWNLOADING /////////////////////////////// + +reg [7:0] data_w; +reg [23:0] addr_w; +reg rclk = 0; + +localparam UIO_FILE_TX = 8'h53; +localparam UIO_FILE_TX_DAT = 8'h54; +localparam UIO_FILE_INDEX = 8'h55; + +// data_io has its own SPI interface to the io controller +always@(posedge SPI_SCK, posedge SPI_SS2) begin + reg [6:0] sbuf; + reg [7:0] cmd; + reg [4:0] cnt; + reg [23:0] addr; + + if(SPI_SS2) cnt <= 0; + else begin + rclk <= 0; + + // don't shift in last bit. It is evaluated directly + // when writing to ram + if(cnt != 15) sbuf <= { sbuf[5:0], SPI_DI}; + + // increase target address after write + if(rclk) addr <= addr + 1'd1; + + // count 0-7 8-15 8-15 ... + if(cnt < 15) cnt <= cnt + 1'd1; + else cnt <= 8; + + // finished command byte + if(cnt == 7) cmd <= {sbuf, SPI_DI}; + + // prepare/end transmission + if((cmd == UIO_FILE_TX) && (cnt == 15)) begin + // prepare + if(SPI_DI) begin + addr <= 0; + ioctl_download <= 1; + end else begin + addr_w <= addr; + ioctl_download <= 0; + end + end + + // command 0x54: UIO_FILE_TX + if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin + addr_w <= addr; + data_w <= {sbuf, SPI_DI}; + rclk <= 1; + end + + // expose file (menu) index + if((cmd == UIO_FILE_INDEX) && (cnt == 15)) ioctl_index <= {sbuf, SPI_DI}; + end +end + +assign ioctl_wr = |ioctl_wrd; +reg [1:0] ioctl_wrd; + +always@(negedge clk_sys) begin + reg rclkD, rclkD2; + + rclkD <= rclk; + rclkD2 <= rclkD; + ioctl_wrd<= {ioctl_wrd[0],1'b0}; + + if(rclkD & ~rclkD2) begin + ioctl_dout <= data_w; + ioctl_addr <= addr_w; + ioctl_wrd <= 2'b11; + end +end + +endmodule diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/motion.vhd b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/motion.vhd new file mode 100644 index 00000000..561209eb --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/motion.vhd @@ -0,0 +1,381 @@ +-- Motion object generation circuitry for Kee Games Sprint 1 +-- This generates the four cars which are the only moving objects in the game +-- (c) 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity motion is +port( + CLK6 : in std_logic; -- 6MHz* on schematic + CLK12 : in std_logic; + PHI2 : in std_logic; + DISPLAY : in std_logic_vector(7 downto 0); + H256_s : in std_logic; -- 256H* on schematic + VCount : in std_logic_vector(7 downto 0); + HCount : in std_logic_vector(8 downto 0); + Crash_n : out std_logic; + Motor1_n : out std_logic; + Car1 : out std_logic; + Car1_n : out std_logic; + Car2 : out std_logic; + Car2_n : out std_logic; + Car3_4_n : out std_logic + ); +end motion; + +architecture rtl of motion is + +signal phi0 : std_logic; + +signal LDH1_n : std_logic; +signal LDH2_n : std_logic; +signal LDH3_n : std_logic; +signal LDH4_n : std_logic; + +signal LDV1A_n : std_logic; +signal LDV2A_n : std_logic; +signal LDV3A_n : std_logic; +signal LDV4A_n : std_logic; + +signal LDV1B_n : std_logic; +signal LDV2B_n : std_logic; +signal LDV3B_n : std_logic; +signal LDV4B_n : std_logic; + +signal Car1_Inh : std_logic; +signal Car2_Inh : std_logic; +signal Car3_Inh : std_logic; +signal Car4_Inh : std_logic; + +signal VPos_sum : std_logic_vector(7 downto 0) := x"00"; +signal N4_8 : std_logic; + +signal H256_n : std_logic; +signal H256 : std_logic; +signal H64 : std_logic; +signal H32 : std_logic; +signal H16 : std_logic; +signal H8 : std_logic; +signal H4 : std_logic; + +signal L5_reg : std_logic_vector(3 downto 0); + +signal J8_3 : std_logic; +signal J8_6 : std_logic; + +signal K8_in : std_logic_vector(3 downto 0); +signal K8_out : std_logic_vector(9 downto 0); +signal P7_in : std_logic_vector(3 downto 0); +signal P7_out : std_logic_vector(9 downto 0); + +signal Car1_Hpos : std_logic_vector(7 downto 0) := x"00"; +signal Car2_Hpos : std_logic_vector(7 downto 0) := x"00"; +signal Car3_Hpos : std_logic_vector(7 downto 0) := x"00"; +signal Car4_Hpos : std_logic_vector(7 downto 0) := x"00"; + +signal Car1_reg : std_logic_vector(15 downto 0) := x"0000"; +signal Car2_reg : std_logic_vector(15 downto 0) := x"0000"; +signal Car3_reg : std_logic_vector(15 downto 0) := x"0000"; +signal Car4_reg : std_logic_vector(15 downto 0) := x"0000"; + +signal Vid : std_logic_vector(7 downto 0); + + +begin +phi0 <= phi2; + +H4 <= Hcount(2); +H8 <= Hcount(3); +H16 <= Hcount(4); +H32 <= Hcount(5); +H64 <= Hcount(6); +H256 <= Hcount(8); +H256_n <= not(Hcount(8)); + +-- Vertical line comparator +VPos_sum <= Display + VCount; +N4_8 <= not(VPos_sum(7) and VPos_sum(6) and VPos_sum(5) and VPos_sum(4) and VPos_sum(3) and H256_n and H64 and H8); + + +-- D type flip-flops in L5 +L5: process(phi2, N4_8, VPos_sum(2 downto 0)) +begin + if rising_edge(phi2) then + L5_reg <= N4_8 & VPos_sum(2 downto 0); + end if; +end process; + + +-- Motion object PROMs - These contain the car images for all 32 possible orientations +J6: entity work.sprom +generic map( + init_file => "rtl/roms/6399-01j6.hex", + widthad_a => 9, + width_a => 4) +port map( + clock => clk6, + address => Display(7 downto 3) & L5_reg(2 downto 0) & phi2, + q => Vid(7 downto 4) + ); + +--J6: entity work.j6_prom +--port map( +-- clock => clk6, +-- address => Display(7 downto 3) & L5_reg(2 downto 0) & phi2, +-- q => Vid(7 downto 4) +-- ); + +K6: entity work.sprom +generic map( + init_file => "rtl/roms/6398-01k6.hex", + widthad_a => 9, + width_a => 4) +port map( + clock => clk6, + address => Display(7 downto 3) & L5_reg(2 downto 0) & phi2, + q => Vid(3 downto 0) + ); + +--K6: entity work.k6_prom +--port map( +-- clock => clk6, +-- address => Display(7 downto 3) & L5_reg(2 downto 0) & phi2, +-- q => Vid(3 downto 0) +-- ); + + +-- Some glue logic +J8_3 <= (H4 or L5_reg(3)); +J8_6 <= (H256 or H64 or H4); + + +-- Decoders +-- Making K8 synchronous fixes weird problem with ghost artifacts of motion objects +K8_in <= J8_3 & H32 & H16 & phi0; +K8: process(clk6, K8_in) +begin + if rising_edge(clk6) then + case K8_in is + when "0000" => + K8_out <= "1111111110"; + when "0001" => + K8_out <= "1111111101"; + when "0010" => + K8_out <= "1111111011"; + when "0011" => + K8_out <= "1111110111"; + when "0100" => + K8_out <= "1111101111"; + when "0101" => + K8_out <= "1111011111"; + when "0110" => + K8_out <= "1110111111"; + when "0111" => + K8_out <= "1101111111"; + when "1000" => + K8_out <= "1011111111"; + when "1001" => + K8_out <= "0111111111"; + when others => + K8_out <= "1111111111"; + end case; + end if; +end process; +LDV3B_n <= K8_out(7); +LDV3A_n <= K8_out(6); +LDV2B_n <= K8_out(5); +LDV2A_n <= K8_out(4); +LDV1B_n <= K8_out(3); +LDV1A_n <= K8_out(2); +LDV4B_n <= K8_out(1); +LDV4A_n <= K8_out(0); + +P7_in <= J8_6 & H32 & H16 & H8; +P7: process(P7_in) +begin + case P7_in is + when "0000" => + P7_out <= "1111111110"; + when "0001" => + P7_out <= "1111111101"; + when "0010" => + P7_out <= "1111111011"; + when "0011" => + P7_out <= "1111110111"; + when "0100" => + P7_out <= "1111101111"; + when "0101" => + P7_out <= "1111011111"; + when "0110" => + P7_out <= "1110111111"; + when "0111" => + P7_out <= "1101111111"; + when "1000" => + P7_out <= "1011111111"; + when "1001" => + P7_out <= "0111111111"; + when others => + P7_out <= "1111111111"; + end case; +end process; +Crash_n <= P7_out(7); +Motor1_n <= P7_out(5); +LDH4_n <= P7_out(4); +LDH3_n <= P7_out(3); +LDH2_n <= P7_out(2); +LDH1_n <= P7_out(1); + + +-- Car 1 Horizontal position counter +-- This combines two 74163s at locations R5 and R6 on the PCB +R5_6: process(clk6, H256_s, LDH1_n, Display) +begin + if rising_edge(clk6) then + if LDH1_n = '0' then -- preload the counter + Car1_Hpos <= Display; + elsif H256_s = '1' then -- increment the counter + Car1_Hpos <= Car1_Hpos + '1'; + end if; + if Car1_Hpos(7 downto 3) = "11111" then + Car1_Inh <= '0'; + else + Car1_Inh <= '1'; + end if; + end if; +end process; + +-- Car 1 video shift register +-- This combines two 74165s at locations M7 and N7 on the PCB +M_N7: process(clk12, Car1_Inh, LDV1A_n, LDV1B_n, Vid) +begin + if LDV1A_n = '0' then + Car1_reg(7 downto 0) <= Vid(7 downto 1) & '0'; -- Preload the LSB register + elsif LDV1B_n = '0' then + Car1_reg(15 downto 8) <= Vid(7 downto 0); -- Preload the MSB register + elsif rising_edge(clk12) then + if Car1_Inh = '0' then + Car1_reg <= '0' & Car1_reg(15 downto 1); + end if; + end if; +end process; +Car1 <= Car1_reg(0); +Car1_n <= not Car1_reg(0); + + +-- Car 2 Horizontal position counter +-- This combines two 74LS163s at locations P5 and P6 on the PCB +P5_6: process(clk6, H256_s, LDH2_n, Display) +begin + if rising_edge(clk6) then + if LDH2_n = '0' then -- preload the counter + Car2_Hpos <= Display; + elsif H256_s = '1' then -- increment the counter + Car2_Hpos <= Car2_Hpos + '1'; + end if; + if Car2_Hpos(7 downto 3) = "11111" then + Car2_Inh <= '0'; + else + Car2_Inh <= '1'; + end if; + end if; +end process; + +-- Car 2 video shift register +K_L7: process(clk12, Car2_Inh, LDV2A_n, LDV2B_n, Vid) +begin + if LDV2A_n = '0' then + Car2_reg(7 downto 0) <= Vid(7 downto 1) & '0'; -- Preload the LSB register + elsif LDV2B_n = '0' then + Car2_reg(15 downto 8) <= Vid(7 downto 0); -- Preload the MSB register + elsif rising_edge(clk12) then + if Car2_Inh = '0' then + Car2_reg <= '0' & Car2_reg(15 downto 1); + end if; + end if; +end process; +Car2 <= Car2_reg(0); +Car2_n <= not Car2_reg(0); + + +-- Car 3 Horizontal position counter +-- This combines two 74LS163s at locations N5 and N6 on the PCB +N5_6: process(clk6, H256_s, LDH3_n, Display) +begin + if rising_edge(clk6) then + if LDH3_n = '0' then -- preload the counter + Car3_Hpos <= Display; + elsif H256_s = '1' then -- increment the counter + Car3_Hpos <= Car3_Hpos + '1'; + end if; + if Car3_Hpos(7 downto 3) = "11111" then + Car3_Inh <= '0'; + else + Car3_Inh <= '1'; + end if; + end if; +end process; + +-- Car 3 video shift register +H_J7: process(clk12, Car3_Inh, LDV3A_n, LDV3B_n, Vid) +begin + if LDV3A_n = '0' then + Car3_reg(7 downto 0) <= Vid(7 downto 1) & '0'; -- Preload the LSB register + elsif LDV3B_n = '0' then + Car3_reg(15 downto 8) <= Vid(7 downto 0); -- Preload the MSB register + elsif rising_edge(clk12) then + if Car3_Inh = '0' then + Car3_reg <= '0' & Car3_reg(15 downto 1); + end if; + end if; +end process; + + +-- Car 4 Horizontal position counter +-- This combines two 74LS163s at locations M5 and M6 on the PCB +M5_6: process(clk6, H256_s, LDH4_n, Display) +begin + if rising_edge(clk6) then + if LDH4_n = '0' then -- preload the counter + Car4_Hpos <= Display; + elsif H256_s = '1' then -- increment the counter + Car4_Hpos <= Car4_Hpos + '1'; + end if; + if Car4_Hpos(7 downto 3) = "11111" then + Car4_Inh <= '0'; + else + Car4_Inh <= '1'; + end if; + end if; +end process; + +-- Car 4 video shift register +E_F7: process(clk12, Car4_Inh, LDV4A_n, LDV4B_n, Vid) +begin + if LDV4A_n = '0' then + Car4_reg(7 downto 0) <= Vid(7 downto 1) & '0'; -- Preload the LSB register + elsif LDV4B_n = '0' then + Car4_reg(15 downto 8) <= Vid(7 downto 0); -- Preload the MSB register + elsif rising_edge(clk12) then + if Car4_Inh = '0' then + Car4_reg <= '0' & Car4_reg(15 downto 1); + end if; + end if; +end process; +Car3_4_n <= not (Car3_reg(0) or Car4_reg(0)); + +end rtl; diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/osd.sv b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/osd.sv new file mode 100644 index 00000000..c62c10af --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/osd.sv @@ -0,0 +1,179 @@ +// A simple OSD implementation. Can be hooked up between a cores +// VGA output and the physical VGA pins + +module osd ( + // OSDs pixel clock, should be synchronous to cores pixel clock to + // avoid jitter. + input clk_sys, + + // SPI interface + input SPI_SCK, + input SPI_SS3, + input SPI_DI, + + // VGA signals coming from core + input [5:0] R_in, + input [5:0] G_in, + input [5:0] B_in, + input HSync, + input VSync, + + // VGA signals going to video connector + output [5:0] R_out, + output [5:0] G_out, + output [5:0] B_out +); + +parameter OSD_X_OFFSET = 10'd0; +parameter OSD_Y_OFFSET = 10'd0; +parameter OSD_COLOR = 3'd0; + +localparam OSD_WIDTH = 10'd256; +localparam OSD_HEIGHT = 10'd128; + +// ********************************************************************************* +// spi client +// ********************************************************************************* + +// this core supports only the display related OSD commands +// of the minimig +reg osd_enable; +(* ramstyle = "no_rw_check" *) reg [7:0] osd_buffer[2047:0]; // the OSD buffer itself + +// the OSD has its own SPI interface to the io controller +always@(posedge SPI_SCK, posedge SPI_SS3) begin + reg [4:0] cnt; + reg [10:0] bcnt; + reg [7:0] sbuf; + reg [7:0] cmd; + + if(SPI_SS3) begin + cnt <= 0; + bcnt <= 0; + end else begin + sbuf <= {sbuf[6:0], SPI_DI}; + + // 0:7 is command, rest payload + if(cnt < 15) cnt <= cnt + 1'd1; + else cnt <= 8; + + if(cnt == 7) begin + cmd <= {sbuf[6:0], SPI_DI}; + + // lower three command bits are line address + bcnt <= {sbuf[1:0], SPI_DI, 8'h00}; + + // command 0x40: OSDCMDENABLE, OSDCMDDISABLE + if(sbuf[6:3] == 4'b0100) osd_enable <= SPI_DI; + end + + // command 0x20: OSDCMDWRITE + if((cmd[7:3] == 5'b00100) && (cnt == 15)) begin + osd_buffer[bcnt] <= {sbuf[6:0], SPI_DI}; + bcnt <= bcnt + 1'd1; + end + end +end + +// ********************************************************************************* +// video timing and sync polarity anaylsis +// ********************************************************************************* + +// horizontal counter +reg [9:0] h_cnt; +reg [9:0] hs_low, hs_high; +wire hs_pol = hs_high < hs_low; +wire [9:0] dsp_width = hs_pol ? hs_low : hs_high; + +// vertical counter +reg [9:0] v_cnt; +reg [9:0] vs_low, vs_high; +wire vs_pol = vs_high < vs_low; +wire [9:0] dsp_height = vs_pol ? vs_low : vs_high; + +wire doublescan = (dsp_height>350); + +reg ce_pix; +always @(negedge clk_sys) begin + integer cnt = 0; + integer pixsz, pixcnt; + reg hs; + + cnt <= cnt + 1; + hs <= HSync; + + pixcnt <= pixcnt + 1; + if(pixcnt == pixsz) pixcnt <= 0; + ce_pix <= !pixcnt; + + if(hs && ~HSync) begin + cnt <= 0; + pixsz <= (cnt >> 9) - 1; + pixcnt <= 0; + ce_pix <= 1; + end +end + +always @(posedge clk_sys) begin + reg hsD, hsD2; + reg vsD, vsD2; + + if(ce_pix) begin + // bring hsync into local clock domain + hsD <= HSync; + hsD2 <= hsD; + + // falling edge of HSync + if(!hsD && hsD2) begin + h_cnt <= 0; + hs_high <= h_cnt; + end + + // rising edge of HSync + else if(hsD && !hsD2) begin + h_cnt <= 0; + hs_low <= h_cnt; + v_cnt <= v_cnt + 1'd1; + end else begin + h_cnt <= h_cnt + 1'd1; + end + + vsD <= VSync; + vsD2 <= vsD; + + // falling edge of VSync + if(!vsD && vsD2) begin + v_cnt <= 0; + vs_high <= v_cnt; + end + + // rising edge of VSync + else if(vsD && !vsD2) begin + v_cnt <= 0; + vs_low <= v_cnt; + end + end +end + +// area in which OSD is being displayed +wire [9:0] h_osd_start = ((dsp_width - OSD_WIDTH)>> 1) + OSD_X_OFFSET; +wire [9:0] h_osd_end = h_osd_start + OSD_WIDTH; +wire [9:0] v_osd_start = ((dsp_height- (OSD_HEIGHT<> 1) + OSD_Y_OFFSET; +wire [9:0] v_osd_end = v_osd_start + (OSD_HEIGHT<= h_osd_start) && (h_cnt < h_osd_end) && + (VSync != vs_pol) && (v_cnt >= v_osd_start) && (v_cnt < v_osd_end); + +reg [7:0] osd_byte; +always @(posedge clk_sys) if(ce_pix) osd_byte <= osd_buffer[{doublescan ? osd_vcnt[7:5] : osd_vcnt[6:4], osd_hcnt[7:0]}]; + +wire osd_pixel = osd_byte[doublescan ? osd_vcnt[4:2] : osd_vcnt[3:1]]; + +assign R_out = !osd_de ? R_in : {osd_pixel, osd_pixel, OSD_COLOR[2], R_in[5:3]}; +assign G_out = !osd_de ? G_in : {osd_pixel, osd_pixel, OSD_COLOR[1], G_in[5:3]}; +assign B_out = !osd_de ? B_in : {osd_pixel, osd_pixel, OSD_COLOR[0], B_in[5:3]}; + +endmodule diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/playfield.vhd b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/playfield.vhd new file mode 100644 index 00000000..350742f2 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/playfield.vhd @@ -0,0 +1,170 @@ +-- Playfield generation circuitry for Sprint 1 by Kee Games +-- (c) 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity playfield is +port( + Clk6 : in std_logic; + Display : in std_logic_vector(7 downto 0); + HCount : in std_logic_vector(8 downto 0); + VCount : in std_logic_vector(7 downto 0); + H256_s : out std_logic; + HBlank : in std_logic; + VBlank : in std_logic; + VBlank_n_s : in std_logic; -- VBLANK* on the schematic + HSync : in std_logic; + VSync : in std_logic; + CompSync_n_s : out std_logic; -- COMP SYNC* on schematic + CompBlank_s : out std_logic; -- COMP BLANK* on schematic + WhitePF_n : out std_logic; + BlackPF_n : out std_logic + ); +end playfield; + +architecture rtl of playfield is + +signal H1 : std_logic; +signal H2 : std_logic; +signal H4 : std_logic; +signal H256 : std_logic; +signal H256_n : std_logic; + +signal V1 : std_logic; +signal V2 : std_logic; +signal V4 : std_logic; + +signal char_addr : std_logic_vector(8 downto 0) := (others => '0'); +signal char_data : std_logic_vector(7 downto 0) := (others => '0'); + +signal shift_data : std_logic_vector(7 downto 0) := (others => '0'); +signal QH : std_logic; + +signal R2_reg : std_logic_vector(3 downto 0) := (others => '0'); + + +-- These signals are based off the schematic and are formatted as Designator_PinNumber +signal R7_12 : std_logic; +signal P3_3 : std_logic; +signal P2_13 : std_logic; +signal P3_6 : std_logic; +signal A6_6 : std_logic; +signal A6_3 : std_logic; + +begin + +-- Video synchronization signals +H1 <= Hcount(0); +H2 <= Hcount(1); +H4 <= Hcount(2); +H256 <= Hcount(8); +H256_n <= not(Hcount(8)); + +V1 <= Vcount(0); +V2 <= Vcount(1); +V4 <= Vcount(2); + +-- Some glue logic, may be re-written later to be cleaner and easier to follow without referring to schematic +R7_12 <= not(H1 and H2 and H4); + +P3_3 <= (H256_n or R7_12); + +P2_13 <= (HSync nor VSync); + +P3_6 <= (HBlank or VBlank); + + + +char_addr <= display(5 downto 0) & V4 & V2 & V1; + +-- Background character ROMs +R4: entity work.sprom +generic map( + init_file => "rtl/roms/6397-01r4.hex", + widthad_a => 9, + width_a => 4) +port map( + clock => clk6, + Address => char_addr, + q => char_data(3 downto 0) + ); + +--R4: entity work.Char_MSB +--port map( +-- clock => clk6, +-- Address => char_addr, +-- q => char_data(3 downto 0) +-- ); + +P4: entity work.sprom +generic map( + init_file => "rtl/roms/6396-01p4.hex", + widthad_a => 9, + width_a => 4) +port map( + clock => clk6, + Address => char_addr, + q => char_data(7 downto 4) + ); + +--P4: entity work.Char_LSB +--port map( +-- clock => clk6, +-- Address => char_addr, +-- q => char_data(7 downto 4) +-- ); + + +-- 74LS166 video shift register +R3: process(clk6, P3_3, VBlank_n_s, char_data, shift_data) +begin + if VBlank_n_s = '0' then -- Connected Clear input + shift_data <= (others => '0'); + elsif rising_edge(clk6) then + if P3_3 = '0' then -- Parallel load + shift_data <= char_data(7 downto 0); + else + shift_data <= shift_data(6 downto 0) & '0'; + end if; + end if; + QH <= shift_data(7); +end process; + + +-- 9316 counter at R2 +-- CEP and CET tied to ground, counter is used only as a synchronous latch +R2: process(clk6, R7_12, display, H256, P2_13, P3_6) +begin + if rising_edge(clk6) then + if R7_12 = '0' then + R2_reg <= (H256 & display(7) & P3_6 & P2_13); + end if; + end if; +end process; + + +H256_s <= R2_reg(3); +CompBlank_s <= R2_reg(1); +CompSync_n_s <= R2_reg(0); +A6_6 <= (R2_reg(2) and QH); +A6_3 <= ((not R2_reg(2)) and QH); + +WhitePF_n <= (not A6_6); +BlackPF_n <= (not A6_3); + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/pll.v b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/pll.v new file mode 100644 index 00000000..6a352243 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/pll.v @@ -0,0 +1,337 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.4 Build 182 03/12/2014 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2014 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll ( + inclk0, + c0, + c1, + locked); + + input inclk0; + output c0; + output c1; + output locked; + + wire [4:0] sub_wire0; + wire sub_wire2; + wire [0:0] sub_wire6 = 1'h0; + wire [0:0] sub_wire3 = sub_wire0[0:0]; + wire [1:1] sub_wire1 = sub_wire0[1:1]; + wire c1 = sub_wire1; + wire locked = sub_wire2; + wire c0 = sub_wire3; + wire sub_wire4 = inclk0; + wire [1:0] sub_wire5 = {sub_wire6, sub_wire4}; + + altpll altpll_component ( + .inclk (sub_wire5), + .clk (sub_wire0), + .locked (sub_wire2), + .activeclock (), + .areset (1'b0), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "AUTO", + altpll_component.clk0_divide_by = 125, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 224, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 125, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 56, + altpll_component.clk1_phase_shift = "0", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 37037, + altpll_component.intended_device_family = "Cyclone III", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "NORMAL", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_UNUSED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_USED", + altpll_component.port_clk2 = "PORT_UNUSED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "125" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "125" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "48.383999" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "12.096000" +// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps" +// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "224" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "56" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "48.38400000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "12.09600000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: USE_CLK1 STRING "1" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "125" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "224" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "125" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "56" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6290-01b1.hex b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6290-01b1.hex new file mode 100644 index 00000000..e99c247b --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6290-01b1.hex @@ -0,0 +1,129 @@ +:100000000620262120053FCCCCCCCCCC9344555F98 +:10001000CCCCCCCCCC95FB2223334444D94555FBE6 +:100020002222233444D9A222223444444E655FB2B2 +:1000300012222234444EA221122244444E65FB1166 +:1000400012222224544EA223222243344E6FB11195 +:1000500022222123434EA230018344334EFB11114F +:100060001111F833444EA1000E0A34444DB1111160 +:10007000111FB2A4444EA0000E6A33333311122173 +:1000800011FB12A4444EA0000E6A33233111222129 +:100090001FB112A4444EA0000E6A22221122211187 +:1000A000FB1112A4544EA0000D9D91111221111F9D +:1000B000B1111FB5544EA07007DCCCCCCCCCCCCC4D +:1000C000CCCCCB55544EA0007666666666666666F6 +:1000D00065566666644EA001666666667766666605 +:1000E00066666666655EA0007666666666667766C4 +:1000F00066666666655EA0007766666665566666D5 +:1001000066666666666ED9000776666666666666C9 +:100110006666776666FB1D888888888888888888F0 +:100120008888888888B72C214C2260043FCCCCCCAE +:10013000C9223333333223FCCCCCCC95FB3333444C +:100140004D92233333333FB3333444D9A223333472 +:1001500044E3FCCCCCC92A233334444EA2223333AB +:1001600044EFB333444D9A223334444EA222233316 +:1001700044EB23334444DA222334444EA222223374 +:1001800034E2223344445A121234444EA1111E2345 +:100190003331222334445A1217A4444EA1110E22A3 +:1001A0002311111134455A1107A4444EA1100E22F7 +:1001B00022111110A4455A1007A4444EA2000E9219 +:1001C0002111110FB3455A0007A4444EA0000ED9C7 +:1001D000111110FB3335FB0007A4444EA0000E7D27 +:1001E000888888A33333B10007A4444EA0000E775B +:1001F000666666A22222110007A4444EA0000E7774 +:10020000666666A2222211000FA4444EA0000E775B +:10021000666666A222211100FBA4444EA0000E7760 +:10022000666666D92211110FB5A4444EA0000D9741 +:100230006666666D8888888B5FB5444EA00007DCD3 +:10024000CCCCCCCCCCCCCCCCCB55444E5222722393 +:1002500060043FCCCCCCCCCC9543FCCCCCCCCCCC2F +:10026000CC95FB2223333444D93FB222233333339A +:1002700044D9A222223334444D8B222222333333F9 +:10028000444EA2222223344444E222222223333445 +:10029000444EA2222222344444E222222122334428 +:1002A000444EA11111FC944444E1111110FC9344FB +:1002B000444EA11110D9A44444E1111100A1D94424 +:1002C000444EA111077DA44445E1111070D92A4480 +:1002D000444EA11F9777A44455E11100777D9A44BD +:1002E000444EA10AE007A34455E910000077DA4420 +:1002F000444EA00DB107A33445ED900000777A4439 +:10030000444EA077100FB33444A2A00007077A44EC +:10031000444EA00711FB333333CC110800007A445C +:10032000444EA07710E22222222110E0A0007A445D +:10033000445EA00010E222222211001C10007A4428 +:10034000455EA07710D92222222222211000FB54E0 +:10035000454EA000107D911111111111100FB554CF +:10036000544EA0777077DCCCCCCCCCCCCCCB5554D5 +:10037000544E7823982460044FCCCCCCCCCCCCCC3D +:10038000CCCCCCCCCCCCCC95FB222222222222225B +:1003900022222222333344D9A222221221221233D2 +:1003A000333228222333444EA22222222222222325 +:1003B0003333D8B22233444EA222222222222222D6 +:1003C000233322222223445EA11111FCCCCCCCCCBD +:1003D000C92222111FC9455EA1111FB444455555BC +:1003E0006D911111FBFB555EA1110E34444555561C +:1003F00066DCCCCCCCB5555EA1100E3344455566B9 +:10040000666666666666666EA1000E33344556669D +:10041000666666666666666EA0000E33334589774B +:10042000766666666666666EA0000E33333E3D975E +:1004300077666667777777FBA0000E22233DCCCCEA +:10044000CCCCCCCCCCCCCCA5A0000E22222222221B +:1004500022222223334444D9A0000E222222222227 +:10046000222222223344455EA0000D922222222223 +:10047000222222222344555EA00007D91111111116 +:10048000111111222245555EA000077DCCCCCCCCA9 +:10049000CCCCCCCCCC55555E9E24BE2560043FCC44 +:1004A000CCCCCCCCCCCCCCCCCCCCCCCCCC95FB223E +:1004B00022222222233222222223333444D9A2228E +:1004C000222122222223222222223334444EA2221B +:1004D000211222222222232222222334445EA2221B +:1004E000222222222222222211222234455EA1111E +:1004F0001F8888888888888888888844555EA111E4 +:1005000007665555555D9111FB555555555EA11022 +:10051000077666666666D91FB5555566666EA10094 +:100520000777666666666EFB44555666666ED9004A +:100530000777766777666EB344456666666E1D908C +:10054000077777777776FB3334466666666E3FCCFF +:10055000CCCCC007777FB33333488888888BFB22A5 +:100560002222211077FB22222223333444D9A222D3 +:10057000222211100FA2222222223334444EA22220 +:1005800022111100FBA2222222222334445EA22245 +:100590002111100FB5D9222222222234455EA11149 +:1005A000111100FB555D911111111124555EA1111E +:1005B00011DCCCCCCCCCCCCCCCCCCCB5555EC425D1 +:1005C000E42660043FCCCCCC953FCCCCCCCCCCCC7E +:1005D000CCCCCC95FB333444D9FB222222222223DB +:1005E000333444D9A22334444DA22222222222228F +:1005F0003334444EA222334445A222222222222214 +:100600002334444EA222234445A111111F88888817 +:100610009334444EA111E34445A11111FB555555A6 +:10062000D934444EA110E34445A1111FB555556678 +:100630006D94444EA100E34445A1100E55555566F6 +:1006400066A4444EA000E33445A100075555566604 +:1006500066A4444EA000E33345A0000766665A77BF +:1006600077A4444EA000E33334A000077666FB076E +:1006700077A4444EA000E33333D90077776FB100FD +:1006800077A4444EA000E333333DCCCCCCCB110057 +:1006900007A4444EA000E22222222222222111009D +:1006A00000A4444EA000E2222222222222111100A4 +:1006B00000A4444EA000D92222222222211111009E +:1006C0000FB5444EA0007D911111111111111100AF +:1006D000FB55444EA00077DCCCCCCCCCCCCCCCCCE5 +:1006E000B555444EEA260A2860043FCCCCCCCCCC8D +:1006F000CCCCCCCCCCCCCCCCCC95FB4445555666A4 +:10070000666666666666666666D9A444455566662C +:100710006666666666666666666EA4444555666687 +:100720006666666666666666666EA344445F88882B +:100730008888888888888897777EA333444D9FB3BC +:1007400033333333333D9FB0777ED9333444DB22A8 +:10075000222223333333DB10077E1D93334442229E +:100760002222223332222110007E11D93334122268 +:100770002222222222221110000E111D9333111168 +:100780001F88888922211110000E0001E113133304 +:100790003A11111D9211111000FB000FB1133333E8 +:1007A0003D933333D888888888B700FB11103333E2 +:1007B00033DCCCCCCCCCCCCCCC950FB111072222E5 +:1007C000222222222222333444D9FB111007F9229B +:1007D0002222222222222334444EA111100FBD9244 +:1007E0002222222222222234444EA11000FB55D97B +:1007F0001111111111112224444EA100007CCCCC06 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6291-01c1.hex b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6291-01c1.hex new file mode 100644 index 00000000..e362de36 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6291-01c1.hex @@ -0,0 +1,129 @@ +:10000000CCCCCCCCCCCCCCB4444E10283029600421 +:100010003FCCCCCCCCC953FCCCCCCCCCCCCCCC9530 +:10002000FB233334444D9FB222222223334444D94C +:10003000A22233344444EB22222222223344445E5F +:10004000A22223344444E222222222222344455E77 +:10005000A22222344444E222222221111244555E7B +:10006000A11110A44444E111111F88888845555EF0 +:10007000A11107A44444E111100A11FB4455556E27 +:10008000A11007A44444E111000D9FB44455566EDD +:10009000A10007A34444E1100077EB344455666E99 +:1000A000A00007A33444E9100777E333445666FB06 +:1000B000A00007A33344ED900777E33334666FB7AE +:1000C000A00007A33333D8B00077E333333CCC959B +:1000D000A00007A2222222100007E233334444D9B1 +:1000E000A00007A2222221100000E2233344444E44 +:1000F000A00007A2222211100000E9222344444E4E +:10010000A00007A222211110000FBD922244444EEC +:10011000A00007D91111111000FB55D92245444EFA +:10012000A000077DCCCCCCCCCCCCCCCCCC55444E98 +:100130003629562A60043FCCCCCCCCCCCCCCCCCC11 +:1001400093FCCCCCCC95FB222222222223333444B4 +:10015000D8B2333444D9A222222222222223344587 +:100160005A222334444EA222222222222222345511 +:100170005A222234444EA11111F888888888855566 +:100180005A1111F4444EA1111FB4444555566666E8 +:100190006A1110E4444EA111FB444455566666664C +:1001A0006A1100E4444EA110E34444556666666655 +:1001B000FA1000E4444EA110E34444566666777F8B +:1001C000BA0000E4444EA000E344445FCCCCCCCC65 +:1001D0009A0000E4444EA000E33444FB233333444C +:1001E000DA0000E4444EA000E33344E22233333427 +:1001F0004A0000E4444EA000E33334E222233333C8 +:100200004A0000E4444EA000E2222221111F3222C3 +:10021000210000E4444EA000E2222211110E22220D +:10022000110000E4444EA000D9222111100E9221A9 +:10023000110000E4444EA0007D91111100FBD91182 +:1002400011000FB5444EA00077DCCCCCCCCCCCCC8C +:10025000CCCCCB55444E5C2A7C2B60043FCCCCCC20 +:10026000CCCCCC9543FCCCCCCCCCCC95FB444555EC +:10027000666666D94FB22223333444D9A444455626 +:100280006666666E4A2222223334444EA344456693 +:100290006666666E4A2222222334444EA3344F8877 +:1002A0008897777E4A11111FC933444EA3334A33CE +:1002B00077E0777E4A11110D9D93444EA3333DCCD8 +:1002C000CCC0077DCC911007D9A4444EA33333335F +:1002D0003333002334D910077DA4444EA2222223B5 +:1002E00023220122344D900777A4444ED9222222A2 +:1002F000222202223444D90077A4444E3E888888C2 +:100300008881077F93445A0077A4444EFB33333DE2 +:1003100093E0077EE3345A0007A4444EA22233330D +:10032000D8B0077EB3334A0007A4444EA22222224B +:100330002210077E3333310007A4444EA22222222A +:100340002110077E2222211007A4444EA1111892E9 +:100350001110077E222211100FB5444EA111E1D9D0 +:10036000111007FC91111110FB55444EA1107CCCCB +:10037000CCCCCCCCCCCCCCCCB555444E822BA22C06 +:1003800060043FCCCCCCCCCCCCCCCCCC953FCCCC32 +:10039000CC95FB222222222233333444D9FB33343E +:1003A00044D9A22222222222233334444EB22334BF +:1003B000444EA22222222222223334444E222234CC +:1003C000444EA11108888888889334444E22222400 +:1003D000444EA1100665555555D934444E2211E4BA +:1003E000444EA11007665555555D94444E2110E4C6 +:1003F000444EA100077666666666E3444E1100E44B +:10040000444ED900077766666666E3444E1000E402 +:10041000444E1D88888889777777E3444E0000E44E +:10042000444E3FB333344D977777E3344E0000E4C6 +:10043000444EFB22223344E00777E3334E0000E4CE +:10044000444EA222222334E00077E3333D0000E44F +:10045000444EA222223333210007E222210000E48D +:10046000444EA1110A2222110000E222110000E4F0 +:10047000444EA1100A222111000FC92111000FB50D +:10048000444EA1000D91111100FB4D911100FB553F +:10049000444EA00007DCCCCCCCCCCCCCCCCCB555DD +:1004A000444EA82CC82D6004333FCCCCCCCCC953CF +:1004B000FCCCCCCCCCCCCC9533FB333334445D9FDB +:1004C000B2222222233344D93FB22233344455DAB4 +:1004D000222222222233445EFB2222233445555A13 +:1004E000222222222223455EA111111F4445555A82 +:1004F000111118888884555EA11111FB444555FBE4 +:100500001110EFB55556666EA1111FB444455FB189 +:100510001100EB555566666EA1110E344445FB1172 +:10052000110FB455556666FBA1100E34444FB1113E +:1005300010FB44555F8888A5A1000E33444E11116D +:100540000FB44445FB3344D9A0000E33344E111090 +:100550007A34445FB333444EA0000E33334E11005F +:100560007A3344FB2333444EA0000E333332100061 +:100570007A3334B22233444EA0000E2222211000DE +:100580007A2222222223444EA0000E2222111000A1 +:10059000FA22221111F3444EA0000D922111000FF6 +:1005A000BD9221111FBA444EA00007D9111100FBC2 +:1005B00055D91111FBFB544EA000077DCCCCCCCCFF +:1005C000CCCCCCCCCCB5544E0093E22DEC2DF62DFA +:1005D000002E0A2E142E1E2E282E322E3C2E462E93 +:1005E000502E5A2E5E2E622E662E6A2E5A2E6E2E99 +:1005F000722EA22E6A2E5A2E762E7A2ED22E6A2E87 +:100600005A2E7A2E7E2E822E6A2E862E8A2E8E2E9E +:10061000922E6A2E962E9A2E9E2EA22E6A2E5A2E3A +:10062000A62EAA2EAE2E6A2E5A2EB22EB62EBA2E76 +:100630006A2E962EBE2EC22EA22E6A2E962E9A2E8E +:10064000C62EA22E6A2E962E9A2EC62EA22E6A2E66 +:10065000962ECA2ECE2ED22E6A2E6F6E6D6C7C7B9D +:100660007A79838393A360606162273747578A9AB8 +:10067000AABA5565758598999A9BA4B4C4D48999EA +:10068000A9B9545464745B6B7B8BBCBCCCDCB3B336 +:10069000C3D3536373836F6E6D6DBDBDCDDD959513 +:1006A000A5B5A0A0A1A28393A3B3BFBEBDBC535365 +:1006B0006373BFBEBDBC85868788B0B1B2B3B5B524 +:1006C000B6B77576777855556575A9AAABACB2B251 +:1006D000C2D260616263D205EA06FB05EA067205D2 +:1006E000EA064E06EA06C904EA060706EA064F05C8 +:1006F000EA06EA06EA06EA06EA06EA06EA06EA067A +:10070000EA06EA06EA0600FEFCFAF8F7F6F5F5F561 +:10071000F6F7F8FAFCFE0002040608090A0B0B0BB8 +:100720000A09080604020B0B0A090806040200FE67 +:10073000FCFAF8F7F6F5F5F5F6F7F8FAFCFE000224 +:10074000040608090A0B0000FFFFEFFFDFFFCFFFE1 +:10075000BEFFAEFF9EFF9EFF9DEF9DEF9DEF9DEFC5 +:100760009CEF9CEF9CEF9CEF9BDE9BDE9BDE9BDE79 +:100770009ADE9ADE9ADE9ADE99CE99CE99CE99CEFD +:1007800099CE99CE99CE71117111611162115311E7 +:100790003411252105210521F421F331F231E13114 +:1007A000E041E041D041DF32DF32CF22CF12CF0231 +:1007B000BE03BE03BEF3AEF3AEF3ADF39DF29DE216 +:1007C0009DE29CE19CE000000000000000000000B1 +:1007D0000000000000000000000000000000000019 +:1007E0000000000000000000000000000000000009 +:1007F00000000000000000000000000000000000F9 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6396-01p4.hex b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6396-01p4.hex new file mode 100644 index 00000000..28243917 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6396-01p4.hex @@ -0,0 +1,33 @@ +:1000000000000000000000000003060C0C0F0C0CA8 +:10001000000F0C0C0F0C0C0F0003060C0C0C06034D +:10002000000F0C0C0C0C0C0F000F0C0C0F0C0C0F19 +:10003000000F0C0C0F0C0C0C0003060C0C0C060330 +:10004000000C0C0C0F0C0C0C000F03030303030F2C +:100050000000000000000C07000C0C0D0F0F0D0C31 +:10006000000C0C0C0C0C0C0F000C0E0F0F0D0C0CDC +:10007000000C0E0F0F0D0C0C00070C0C0C0C0C07D9 +:10008000000F0C0C0C0F0C0C00070C0C0C0D0C07CB +:10009000000F0C0C0C0F0D0C00070C0C07000C07CC +:1000A000000F030303030303000C0C0C0C0C0C07E0 +:1000B000000C0C0C0E070301000C0C0D0F0F0E0CA6 +:1000C000000C0E0703070E0C000C0C0C07030303B7 +:1000D000000F000103070E0F0000000000000000E9 +:1000E0000000000000000000000000000000000010 +:1000F0000000000000000000000000000000000000 +:1001000000000000000000000000000000000000EF +:1001100000000000000000000000000000000000DF +:1001200000000000000000000000000000000000CF +:1001300000000000000000000000000000000000BF +:100140000000000000060600000000000006060097 +:10015000000606000006060000060600000000007B +:100160000006060000000000000000000000000083 +:10017000000000000000000000000000000000007F +:100180000003040C0C0C0603000307030303030F16 +:1001900000070C0003070E0F0007000103000C0707 +:1001A000000103060C0F0000000F0C0F00000C07ED +:1001B0000003060C0F0C0C07000F0C0001030303D7 +:1001C00000070C0E0709080700070C0C07000007C2 +:1001D000000000000000000000000000000000001F +:1001E000000000000000030700080C0C0E0F0F05B4 +:1001F0000F0F0703010000000505040F0F0B01009E +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6397-01r4.hex b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6397-01r4.hex new file mode 100644 index 00000000..72e395fe --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6397-01r4.hex @@ -0,0 +1,33 @@ +:10000000000000000000000000080C06060E0606B6 +:10001000000C06060C06060C000C06000000060C80 +:1000200000080C0606060C08000C00000800000E74 +:10003000000E00000C000000000E00000E06060E70 +:10004000000606060E060606000C00000000000C66 +:10005000000606060606060C00060C0800080C0E34 +:10006000000000000000000C00060E0E0E06060642 +:10007000000606060E0E0E06000C06060606060C08 +:10008000000C0606060C0000000C0606060E0C0A04 +:10009000000C06060E080C0E00080C000C06060CE0 +:1000A000000C000000000000000606060606060C14 +:1000B000000606060E0C0800000606060E0E0E06CA +:1000C00000060E0C080C0E06000C0C0C08000000BC +:1000D000000E0E0C0800000E0000000000000000E2 +:1000E0000000000000000000000000000000000010 +:1000F0000000000000000000000000000000000000 +:1001000000000000000000000000000000000000EF +:1001100000000000000000000000000000000000DF +:1001200000000000000000000000000000000000CF +:1001300000000000000000000000000000000000BF +:1001400000000000000606000000000000000000A3 +:10015000000000000000000000000000000000009F +:100160000006060000000000000606000000000077 +:10017000000606000006060000000000000606005B +:1001800000080C0606060408000000000000000C31 +:10019000000C060E0C08000E000E0C080C06060CD7 +:1001A000000C0C0C0C0E0C0C000C000C0606060CC3 +:1001B000000C00000C06060C000E060C08000000E7 +:1001C00000080404080E060C000C06060E060C08B7 +:1001D000000000000000000000000000000000001F +:1001E0000001070F0F0F0F01000000000C0E0F0F92 +:1001F0000505010F0F0F0F060E06040E0E0C08006A +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6398-01k6.hex b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6398-01k6.hex new file mode 100644 index 00000000..391da240 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6398-01k6.hex @@ -0,0 +1,33 @@ +:10000000000100030E0B0E0B00030E0B0E0B000085 +:10001000000700070E070E03000307090709000089 +:10002000000E000F0C070E0700030F030709000C5A +:10003000000C080F000F0E07070300010008000C5A +:100040000000000C0E0F070F00070801000C000E47 +:10005000000100000F0E030F08070C00080E000738 +:1000600000070E030F0C000F0E070C000009000024 +:100070000E070E070C030C0F080F000C080E080EDD +:100080000C0E0C0E080C0C0F0C0F080C0C0E0C0EAA +:10009000080E080E000C080F0C0F0C030E070E07BD +:1000A000000000090C000E07000F0F0C0E030007E4 +:1000B0000007080E0C000807030F0F0E00000001D8 +:1000C000000E000C08010007070F0E0F000C0000C7 +:1000D000000C0008000107030E07000F080F000CBA +:1000E000000C07090F0300030E070C07000F000E9A +:1000F00000000709070900030E030E0700070007A9 +:1001000000000E0B0E0B00030E0B0E0B0003000184 +:1001100000000C070C0700030E030E010001000095 +:1001200008000C0700070E03070300090000000089 +:1001300008000C07000F0E0707030001080C080E4B +:100140000000080E000F070F030308000E0E0F0734 +:100150000001000C0E0F030F08030E000F0E00032A +:10016000000F0E070F0E000F0C070F00000B000111 +:10017000080E080E000C0C0F0F0F000000090009FC +:10018000080C080C00080F0F0F0F0008080C080CD3 +:100190000009000900000F0F0C0F000C080E080EDC +:1001A000000100090F000C07000F0F0E0E07000FD3 +:1001B00000030F0E0E000803030F0E0F000C0001CA +:1001C0000F070E0E08000303070F000F080E0000B4 +:1001D000080E080C000103030E07000F0C070800AF +:1001E00000000000000907030E0300070C070800C9 +:1001F000000000010E010E0300030C070C070000B5 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6399-01j6.hex b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6399-01j6.hex new file mode 100644 index 00000000..74a9d0b9 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6399-01j6.hex @@ -0,0 +1,33 @@ +:1000000008000C000D070D070C000D070D07000080 +:100010000000080008070C070C000E030E03000088 +:100020000000000009000C0E0C070E000E0300017A +:100030000701030108000C0E0E070F000E0300015C +:100040000E0F070700010C0C0F0E0F000701000038 +:100050000C00070F00070C010F0C0F07030008002E +:1000600008000D00000F0E030F00070F0E070F0012 +:100070000900090000000F0F0F030300070107012B +:100080000301030101000F0F0F0F01000301030122 +:100090000701070103000F030F0F0000090009000B +:1000A0000F000E07070F0F000E03000F0D000800D2 +:1000B000080003000F070F0C0C010007070F0C00CE +:1000C000000007010F000F0E0C0C000107070E0FB8 +:1000D00000010E030F000E070C0E080003010701BC +:1000E00000010E030E000C070C0E090000000000BA +:1000F00000000E030E030C000C07080708000000A8 +:1001000000000D070D070C000D070D070C0008007F +:100110000000090E090E0C000C070E070E000E0061 +:100120000300090E0C0F0C000E070E030F000F004A +:100130000300010008000C0E0E070F000F01030062 +:100140000700030008010E000F0E0F070300000058 +:100150000E00070100030E010F0C070F000008003E +:100160000000090000030E070F00030F0C070E002C +:100170000701070103000F010F030C030E070E0711 +:100180000703070303010F030F030301070307031B +:100190000E070E070C030F030F01030007010701F1 +:1001A0000E000C07030F0F000E07000309000000EC +:1001B00008000000070F0F0C0E01000307010E00DE +:1001C000000003000F070F0E0E00080103000700D8 +:1001D00003000F010F000F070C0E080001000300C1 +:1001E00007000F000E030E070C000C0F090E030092 +:1001F0000E000E000E070C070C00090E090E000081 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6400-01m2.hex b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6400-01m2.hex new file mode 100644 index 00000000..9dbfacea --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6400-01m2.hex @@ -0,0 +1,17 @@ +:1000000000000000000000000000000000000000F0 +:1000100000000000000000000000000000000000E0 +:1000200000000000000000000000000000000000D0 +:1000300000000000000000000000000000000000C0 +:1000400000000000000000000000000000000000B0 +:1000500000000000000000000000000000000000A0 +:100060000000000000000000000000000000000090 +:100070000000000000000000000000000000000878 +:100080000A0A0A0A0A0E0000000000000000000030 +:100090000000000000000000000000000000000060 +:1000A0000000000000000000000000000000000050 +:1000B0000000000000000000000000000000000040 +:1000C0000000000000000000000000000000000030 +:1000D0000000000000000000000000000000000020 +:1000E0000808080808080808080808080808080A8E +:1000F0000A0A0B0B0B0A0A0A0A0A0A0A0A0A0A0A5D +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6401-01e2.hex b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6401-01e2.hex new file mode 100644 index 00000000..975d72ea --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6401-01e2.hex @@ -0,0 +1,3 @@ +:100000001111010141418181C1C12121E1E1E1E100 +:10001000E0E0E8E8E4E4ECECE2E2EAEAE6E6EEEE70 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6442-01d1.hex b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6442-01d1.hex new file mode 100644 index 00000000..160cbf39 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6442-01d1.hex @@ -0,0 +1,129 @@ +:10000000488A48D8A530D0038D000F2C2C0810202A +:10001000A561C992D01EA560C93FD018BABD05011F +:10002000C920B00CC9409008C9109010C918B00C74 +:1000300068AA6840A9928561A93F856078D8A27FA7 +:100040009AAD0018C9AAF0034C4E30200018A21631 +:1000500020B738A20420B738A20C20B738200337C5 +:1000600020693020F7304C6030A900853585388D07 +:10007000010C20CD3820DA3520EE3920FF37A901D8 +:10008000A21E208A38A900A651208A38A900A20EF3 +:10009000208A38A900A210208A38E630AD3000D07E +:1000A00011E635A535C90CD009A900853585384C30 +:1000B00072302C2C0830034C523A203D3AA20020DA +:1000C0008534E8E004D0F8A90085168D14008D1061 +:1000D0000C2C40081002700320FF372C000C50F14C +:1000E0008D800CA536D004A520F0AF20BA39A536F6 +:1000F000D004A520F0A460EAA2008635863820CD81 +:1001000038A20620B738A900A200208A38A90085A5 +:100110002A20DA35203D3A20FF378D800CA520F0CB +:10012000F68D310CA900A214208A382C2D0830E756 +:10013000C620A20020B738A21420B738A21220B7D8 +:1001400038A53AC940F015A900A212208A38A53A6C +:10015000C930F0038D7407A53B8D75078D000C2009 +:100160003D3AA538F00320CD38E63020D837A2013B +:10017000208534E8E004D0F88D100CA2002C00108B +:100180003009A53DF005C63D4CAF312C00103009BB +:10019000A900853D853E4CAF31A9008533A53ED0F1 +:1001A0000AA9019500853EA90F8516A910853DA5D0 +:1001B00016F00AA5304A90054A9002C616A533F0FB +:1001C000188D110CC6338A0AA8A9022C8008700267 +:1001D000A9FE187919009919002C00105004A920C3 +:1001E00085338D000DA5304A901A4A90172082372A +:1001F0008524C9F910038D110CA524187500D002AF +:10020000A9019500B5004A4A4A8522A432A5320ABE +:100210008524B9A13CA8A90018652288D0FA4A4AC9 +:100220004A38E5241002A900C9103002A90F85142C +:100230008A0AA820D837B50049FF4A4A4A4A4A4A9A +:1002400085261869038522B9190029F88524B50483 +:1002500029F838E524F0213011C91030038D110C34 +:10026000A90038E52285224C7132C9F810038D119E +:100270000CA5221875049504201035A5350AAABDD1 +:10028000CA2D8524BDCB2D8525AD2A044A29070A10 +:10029000A8B1248528C8B1248529A622B54429F00F +:1002A000852AB5404A4A4A4A290F052A852AA000CC +:1002B000B128C52AF008C8C004D0F54C0A33AD2ACD +:1002C00004186902C9BAD01AAD2904186901C9BA5B +:1002D000D00BAD28041869018D2804A9B08D29041C +:1002E000A9B08D2A04C9B0D0212C30087009A537D7 +:1002F000D005E6374C0A33A9008537E635A535C960 +:100300000CD004A906853520CD38A531F015A530CF +:100310002920F008A20220B7384C2333A202A900FA +:10032000208A38AD2804293FC53A3013AD29042965 +:100330003FC53B300AA531D006A534D002E634C60D +:100340003CD035A550D014E650A9208D3A04A9B967 +:100350008D3B04A9BA8D3C044C7133AD3C04C9B04B +:10036000D00FAD3B04C9B0F012CE3B04A9BA8D3C0E +:1003700004CE3C04A53F853C4C6A34A534F019A951 +:10038000008534E631A9B38D3B04A900A202208A7E +:1003900038A53F853C4C6A348D010C8D100CA900AA +:1003A00085168514A20220B738A20C20B738A90000 +:1003B000A20C208A38A900A216208A38AD28042968 +:1003C0000F0A0A0A0A8522AD2904290F052285226F +:1003D000A522C5543004A218100AC5553004A21A2B +:1003E0001002A21CA901208A38A520D0038D300C50 +:1003F00020EE39A908A27FA07F85268628842A209E +:10040000FF37A536D04FA520F0088D310C2C2D08D4 +:100410001043A526A628A42A88D0DE852A862BE6A6 +:1004200030A5302920F008A21620B7384C3634A960 +:1004300001A216208A38A52AA62B8D800CA07FCA7F +:10044000D0B7A07FA27FC9099002A90538E90110A1 +:10045000A8A901852AA21620B738A20C20B738A572 +:1004600020D0048D300C604CF83020D8372C400858 +:100470001002700320FF372C000C50F1201B378D29 +:10048000800C4C5F3120C934B5004A4A4A4A4A18A8 +:1004900069018522A003B50438F52C29F8F017303E +:1004A00002A0FD98187504950486260626A42699B0 +:1004B0001900A9FF8522B500186522DDA93C90032B +:1004C000BDA93C950020103560A9008522A90485AE +:1004D00023B5401869044A4A4A491F1865228522F3 +:1004E000A900852465238523B544186904090749B3 +:1004F000FF0A26240A26241865228522A5246523BE +:100500008523A000B12210070A0A0A0A0A952C6066 +:100510008622A9008552B500F0724A4A4A8524B560 +:10052000044A4A4AAA8626BD062FF02D0AAA20A709 +:1005300035A622A5281875089508A5297540101715 +:10054000C9FC3008A9018552A900F00BC9F7300792 +:10055000A9018D5200A9F79540A626BD262FF02CA3 +:100560000AAA20A735A622A52818750C950CA5293E +:100570007544100CC9E83012A9018552A9E8300A67 +:10058000C9201006A9018552A9209544A622E000A1 +:10059000F014A552F010A9209540A9509544A9C087 +:1005A0009504A90195006086258A100649FF1869FF +:1005B00001AAA90085288529A5281865248528A9C8 +:1005C0000065298529CAD0F0A525100DA90038E5B8 +:1005D000288528A900E529852960A200A920A00076 +:1005E00095409408940CE8E004D0F5A200A9019588 +:1005F00000E8E004D0F9A200A000A9C09504991970 +:1006000000C8C8E8E004D0F4A9508544A944854551 +:10061000A9388546A92C8547AD330849FF182A2AF1 +:100620002A2903A8B9A53C853C853FA9048554A97E +:10063000028555A9038556AD330849FF182A2A2A91 +:1006400029031869028522A200862486268628A509 +:1006500024F81865548524A5261865558526A528EF +:100660001865568528D8E8E422D0E4A5248554A549 +:10067000268555A5288556AD3208100DA940853A26 +:10068000853BA55685544C9D36A55629F04A4A4AC5 +:100690004A0930853AA556290F0930853BA90085BE +:1006A0003785308D100C851485158533853D853E45 +:1006B00085388534853185508D16008D000D8D006F +:1006C0000EAD2A048526AD29048527AD2804852B87 +:1006D000A901A204208A38A5268D2A04A5278D29E0 +:1006E00004A52B8D2804A52AD00BA9B08D2A048D32 +:1006F00029048D2804A9B08D3B048D3C04A9B18D3B +:100700003A0460A900852085368D300C852AA930F1 +:10071000855785588559A906855160AD2A04293F1A +:10072000207137A522F005A9B08D2A04AD2904292E +:100730003F207137A522F005A9B08D2904AD28040A +:10074000293F207137A522F005A9B08D2804AD3BC3 +:1007500004293F207137A522F005A9B98D3B04ADCE +:100760003C04293F207137A522F005A9B98D3C042E +:1007700060C9309008C93AB004A900F002A9018507 +:1007800022608626A90085322C28081010E6322C1B +:1007900029081009E6322C2A081002E632B5002991 +:1007A000F84A4AAAA9022432F001E8BD462F2C2BB0 +:1007B000083003BD862F184632B00629F04A4A4A4F +:1007C0004A290F85242632A9082424F006A52409E5 +:1007D000F08524A524A62660A200A000A533D01E83 +:1007E0002C80083019A90385222C80087004A9FDEB +:1007F0008522B919001865229919008D000E602014 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6443-01e1.hex b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6443-01e1.hex new file mode 100644 index 00000000..ae79880b --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/roms/6443-01e1.hex @@ -0,0 +1,129 @@ +:100000003038A90A85512C31081011701EA90885B5 +:1000100051A536C902F00160C636100F7004A9065A +:100020008551A536D001605002E620E620C6366034 +:10003000A90985228523852485252C4008100B508D +:1000400009A5222523C909D001608D800CA201A039 +:10005000FA88D0FD8AD0072C4008501F70052C402C +:10006000081018B522F006A9099522D018D624D078 +:1000700014E636A90995229524D00AA9099524B534 +:1000800022F002D622CA10CC30B0A000C900F00283 +:10009000A0808428BD4F3C8522BD503C8523BD7186 +:1000A0003C8524BD723C8525A000B122F0080528BE +:1000B0009124C84CAA3860BD713C8522BD723C8534 +:1000C00023A920A0009122C8C020D0F9608D800C07 +:1000D000A538D029A535D00DA22220B738E8E8E010 +:1000E00030D0F7A5350AAABD373C8524BD383C85FC +:1000F00025A000B124994800C8C006D0F618A5482C +:100100006918854EA9006549854FA901853820FFEA +:1001100037A000B14829F04A4A4A4A09A0914CA5A3 +:100120004C186901854CA900654D854DB148290FD2 +:1001300009A0914CA5481869018548A90065498521 +:1001400049A54C186901854CA900654D854DA54907 +:10015000C54BF00CA535F0BBA549C54FF00ED0B38B +:10016000A548C54AD0EEA9008538F006A548C54E79 +:10017000D0A120FF372C3008303CA5350A0AA8A2B0 +:1001800000B9D62E9522C8E8E004D0F5A200A00060 +:10019000A93C9122A001A93D9122A020A93E912233 +:1001A000A021A93F9122E8E001D00BA5248522A53A +:1001B0002585234C8E398D800C60AD6B04C9CBD066 +:1001C00026AD043EC94BD01F2C2F083001602C00F7 +:1001D0000C10FB2C000C30FBA90AA000C8D0FD3885 +:1001E000E901D0F6300160A9008520853660A900BC +:1001F000A220208A38AD2804293FC559302FF002AB +:100200001016AD2904293FC5583022F0021009AD5F +:100210002A04293FC5573015AD2804293F8559AD1B +:100220002904293F8558AD2A04293F8557A5578DB4 +:100230003B04A5588D3A04A5598D390460A200A04D +:1002400000B5409510B544991800E8C8C8E004D03E +:10025000F060A200A9019D00048D800CDD0004D097 +:10026000F59D00058D800CDD0005D0F59D00068D07 +:10027000800CDD0006D0F59D00078D800CDD0007A9 +:10028000D0F5E8D0D1186901C901D0CAA9008516F6 +:10029000A200A9108524A9058525A900857EA9208D +:1002A000857FA000A90085268522A52218717E855C +:1002B00022C8D0F68D800CE67FE626A526C904D09C +:1002C000E9A522DD2E3CF009A0008A09309124E640 +:1002D00024E8E008D0CCA9D48D6A04A9C98D6B04A8 +:1002E000A9CD8D6C04A9C58D6D04A9CC8DCC04A9B4 +:1002F000C18DCD04A9D08DCE04A9D38DCF04A9B0D2 +:100300008D7104A9B12C30087002A9B28DCA04A95C +:10031000202C33083002A9B18D6F04A9B62C330804 +:100320003008A9B27002A9B530047002A9B98D7065 +:1003300004A98A8522A90485232C31083018700B62 +:10034000A9058524A93D85254C863BA93C8524A982 +:100350003D85254C863B700BA9208524A93D85252C +:100360004C863BA9C48D8A04A9C58D8B04A9CD8D6B +:100370008C04A9CF8D8D04A200A9209D8E04E8E0F5 +:100380000CD0F84C933BA000B12409809122C8C046 +:1003900010D0F52C3208100FA200A9209DAA04E865 +:1003A000E00DD0F84CC43BA9AA8522A9048523A955 +:1003B000D58524A93C8525A000B12409809122C8B7 +:1003C000C00DD0F5A9202C30083002A93C8DEA04DC +:1003D0002C30083002A93D8DEB042C30083002A9E6 +:1003E0003E8D0A052C30083002A93F8D0B052C2CC0 +:1003F0000810034C3C308D300C8D100CA200BD2831 +:10040000088D800C30038D110CE8E003D0F0AD2B8B +:100410000830038D110C2C400830038D110C700333 +:100420008D110C2C2D0830038D110C4C033BCC513D +:100430000991382FAC4630002026214C2272239897 +:1004400024BE25E4260A283029562A7C2BA22CAD6E +:100450003CCB3CE33CFE3C193D343D4F3D5D3D7D96 +:100460003D9B3DBC3DDB3DF23DF63DFD3D043E0F79 +:100470003EA004400420046007600760076007E0B6 +:1004800004A0046007E00400047507750775076B96 +:10049000042E04400460048004A004C004E00400AE +:1004A000050C08060526384B5EA0908070202020A1 +:1004B00020202020594F555220434152204953209B +:1004C000D7C8C9D4C52020202020002020202020EB +:1004D0002020202020455854454E44454420504C6F +:1004E000415900202053434F5245202020202020F6 +:1004F000202020202020202054494D45200020206D +:100500002020202020203120434F494E20504552AA +:100510002047414D45202020002020202020202061 +:100520003220434F494E53205045522047414D45BC +:100530002020200020202020202020203220474181 +:100540004D45532050455220434F494E2020002016 +:10055000202020202020524154494E470020424C68 +:1005600041434B2043415253204452495645204178 +:1005700055544F4D41544943414C4C59002020544F +:100580005241434B53204348414E47452041555427 +:100590004F4D41544943414C4C590020204558543B +:1005A000454E44454420504C415920464F5220204E +:1005B000203020504F494E5453202000202020202E +:1005C0002020205055534820535441525420425526 +:1005D00054544F4E20202020202000202020202076 +:1005E0002020202020202047414D4520204F5645E7 +:1005F000520050524F00524F4F4B49450047524115 +:100600004E4E59004B4545202047414D455300482B +:100610004947482053434F524520202020200000C6 +:1006200000000000000000000000000000000000CA +:1006300000000000000000000000000000000000BA +:1006400000000000000000000000000000000000AA +:10065000000000000000000000000000000000009A +:10066000000000000000000000000000000000008A +:10067000000000000000000000000000000000007A +:10068000000000000000000000000000000000006A +:10069000000000000000000000000000000000005A +:1006A000000000000000000000000000000000004A +:1006B000000000000000000000000000000000003A +:1006C000000000000000000000000000000000002A +:1006D000000000000000000000000000000000001A +:1006E000000000000000000000000000000000000A +:1006F00000000000000000000000000000000000FA +:1007000000000000000000000000000000000000E9 +:1007100000000000000000000000000000000000D9 +:1007200000000000000000000000000000000000C9 +:1007300000000000000000000000000000000000B9 +:1007400000000000000000000000000000000000A9 +:100750000000000000000000000000000000000099 +:100760000000000000000000000000000000000089 +:100770000000000000000000000000000000000079 +:100780000000000000000000000000000000000069 +:100790000000000000000000000000000000000059 +:1007A0000000000000000000000000000000000049 +:1007B0000000000000000000000000000000000039 +:1007C0000000000000000000000000000000000029 +:1007D0000000000000000000000000000000000019 +:1007E0000000000000000000000000000000000009 +:1007F0000000000000000000000000303C303C30F1 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/scandoubler.sv b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/scandoubler.sv new file mode 100644 index 00000000..0213d20c --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/scandoubler.sv @@ -0,0 +1,195 @@ +// +// scandoubler.v +// +// Copyright (c) 2015 Till Harbaum +// Copyright (c) 2017 Sorgelig +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// TODO: Delay vsync one line + +module scandoubler #(parameter LENGTH, parameter HALF_DEPTH) +( + // system interface + input clk_sys, + input ce_pix, + input ce_pix_actual, + + input hq2x, + + // shifter video interface + input hs_in, + input vs_in, + input line_start, + + input [DWIDTH:0] r_in, + input [DWIDTH:0] g_in, + input [DWIDTH:0] b_in, + input mono, + + // output interface + output reg hs_out, + output vs_out, + output [DWIDTH:0] r_out, + output [DWIDTH:0] g_out, + output [DWIDTH:0] b_out +); + + +localparam DWIDTH = HALF_DEPTH ? 2 : 5; + +assign vs_out = vs_in; + +reg [2:0] phase; +reg [2:0] ce_div; +reg [7:0] pix_len = 0; +wire [7:0] pl = pix_len + 1'b1; + +reg ce_x1, ce_x4; +reg req_line_reset; +wire ls_in = hs_in | line_start; +always @(negedge clk_sys) begin + reg old_ce; + reg [2:0] ce_cnt; + + reg [7:0] pixsz2, pixsz4 = 0; + + old_ce <= ce_pix; + if(~&pix_len) pix_len <= pix_len + 1'd1; + + ce_x4 <= 0; + ce_x1 <= 0; + + // use such odd comparison to place c_x4 evenly if master clock isn't multiple 4. + if((pl == pixsz4) || (pl == pixsz2) || (pl == (pixsz2+pixsz4))) begin + phase <= phase + 1'd1; + ce_x4 <= 1; + end + + if(~old_ce & ce_pix) begin + pixsz2 <= {1'b0, pl[7:1]}; + pixsz4 <= {2'b00, pl[7:2]}; + ce_x1 <= 1; + ce_x4 <= 1; + pix_len <= 0; + phase <= phase + 1'd1; + + ce_cnt <= ce_cnt + 1'd1; + if(ce_pix_actual) begin + phase <= 0; + ce_div <= ce_cnt + 1'd1; + ce_cnt <= 0; + req_line_reset <= 0; + end + + if(ls_in) req_line_reset <= 1; + end +end + +reg ce_sd; +always @(*) begin + case(ce_div) + 2: ce_sd = !phase[0]; + 4: ce_sd = !phase[1:0]; + default: ce_sd <= 1; + endcase +end + +`define BITS_TO_FIT(N) ( \ + N <= 2 ? 0 : \ + N <= 4 ? 1 : \ + N <= 8 ? 2 : \ + N <= 16 ? 3 : \ + N <= 32 ? 4 : \ + N <= 64 ? 5 : \ + N <= 128 ? 6 : \ + N <= 256 ? 7 : \ + N <= 512 ? 8 : \ + N <=1024 ? 9 : 10 ) + +localparam AWIDTH = `BITS_TO_FIT(LENGTH); +Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x +( + .clk(clk_sys), + .ce_x4(ce_x4 & ce_sd), + .inputpixel({b_in,g_in,r_in}), + .mono(mono), + .disable_hq2x(~hq2x), + .reset_frame(vs_in), + .reset_line(req_line_reset), + .read_y(sd_line), + .read_x(sd_h_actual), + .outpixel({b_out,g_out,r_out}) +); + +reg [10:0] sd_h_actual; +always @(*) begin + case(ce_div) + 2: sd_h_actual = sd_h[10:1]; + 4: sd_h_actual = sd_h[10:2]; + default: sd_h_actual = sd_h; + endcase +end + +reg [10:0] sd_h; +reg [1:0] sd_line; +always @(posedge clk_sys) begin + + reg [11:0] hs_max,hs_rise,hs_ls; + reg [10:0] hcnt; + reg [11:0] sd_hcnt; + + reg hs, hs2, vs, ls; + + if(ce_x1) begin + hs <= hs_in; + ls <= ls_in; + + if(ls && !ls_in) hs_ls <= {hcnt,1'b1}; + + // falling edge of hsync indicates start of line + if(hs && !hs_in) begin + hs_max <= {hcnt,1'b1}; + hcnt <= 0; + if(ls && !ls_in) hs_ls <= {10'd0,1'b1}; + end else begin + hcnt <= hcnt + 1'd1; + end + + // save position of rising edge + if(!hs && hs_in) hs_rise <= {hcnt,1'b1}; + + vs <= vs_in; + if(vs && ~vs_in) sd_line <= 0; + end + + if(ce_x4) begin + hs2 <= hs_in; + + // output counter synchronous to input and at twice the rate + sd_hcnt <= sd_hcnt + 1'd1; + sd_h <= sd_h + 1'd1; + if(hs2 && !hs_in) sd_hcnt <= hs_max; + if(sd_hcnt == hs_max) sd_hcnt <= 0; + + // replicate horizontal sync at twice the speed + if(sd_hcnt == hs_max) hs_out <= 0; + if(sd_hcnt == hs_rise) hs_out <= 1; + + if(sd_hcnt == hs_ls) sd_h <= 0; + if(sd_hcnt == hs_ls) sd_line <= sd_line + 1'd1; + end +end + +endmodule diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/screech.vhd b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/screech.vhd new file mode 100644 index 00000000..251ad2ec --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/screech.vhd @@ -0,0 +1,73 @@ +-- Tire screech sound generator for Kee Games Sprint 1 +-- Identical circuit is used in a number of related Kee/Atari games +-- (c) 2017 James Sweet +-- +-- Original circuit used a 7414 Schmitt trigger oscillator operating at approximately +-- 1.2kHz producing a sawtooth with the frequency modulated slightly by the pseudo-random +-- noise generator. This is an extension of work initially done in Verilog by Jonas Elofsson. +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity tire_screech is +generic( + constant Inc1 : integer := 24; -- These constants can be adjusted to tune the frequency and modulation + constant Inc2 : integer := 34; + constant Dec1 : integer := 23; + constant Dec2 : integer := 12 + ); +port( + Clk : in std_logic; -- 750kHz from the horizontal line counter chain works well here + Noise : in std_logic; -- Output from LFSR pseudo-random noise generator + Screech_out : out std_logic -- Screech output - single bit + ); +end tire_screech; + +architecture rtl of tire_screech is + +signal Screech_count : integer range 1000 to 11000; +signal Screech_state : std_logic; + +begin + +Screech: process(Clk, Screech_state) +begin + if rising_edge(Clk) then + if screech_state = '1' then -- screech_state is 1, counter is rising + if noise = '1' then -- Noise signal from LFSR, when high increases the slope of the rising ramp + screech_count <= screech_count + inc2; + else -- When Noise is low, decreas the slope of the ramp + screech_count <= screech_count + inc1; + end if; + if screech_count > 10000 then -- Reverse the ramp direction when boundary value of 10,000 is reached + screech_state <= '0'; + end if; + elsif screech_state = '0' then -- screech_state is now low, decrement the counter (ramp down) + if noise = '1' then + screech_count <= screech_count - dec2; -- Slope is influenced by the Noise signal + else + screech_count <= screech_count - dec1; + end if; + if screech_count < 1000 then -- Reverse the ramp direction again when the lower boundary of 1,000 is crossed + screech_state <= '1'; + end if; + end if; + end if; +screech_out <= screech_state; +end process; + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sprint1.vhd b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sprint1.vhd new file mode 100644 index 00000000..7811fbef --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sprint1.vhd @@ -0,0 +1,310 @@ +-- Top level file for Kee Games Sprint 1 +-- (c) 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +-- Targeted to EP2C5T144C8 mini board but porting to nearly any FPGA should be fairly simple +-- See Sprint 1 manual for video output details. Resistor values listed here have been scaled +-- for 3.3V logic. +-- R48 1k Ohm +-- R49 1k Ohm +-- R50 680R +-- R51 330R + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + + +entity sprint1 is +port( + clk_12 : in std_logic; -- 12MHz input clock + Reset_n : in std_logic; -- Reset button (Active low) + + + VideoW_O : out std_logic; -- White video output (680 Ohm) + VideoB_O : out std_logic; -- Black video output (1.2k) + Sync_O : out std_logic; -- Composite sync output (1.2k) + + + Hs : out std_logic; + Vs : out std_logic; + Vb : out std_logic; + Hb : out std_logic; + Video : out std_logic; + Audio : out std_logic_vector(6 downto 0); + Coin1_I : in std_logic; -- Coin switches (Active low) + Coin2_I : in std_logic; + Start_I : in std_logic; -- Start button + Gas_I : in std_logic; -- Gas pedal + Gear1_I : in std_logic; -- Gear shifter, 4th gear = no other gear selected + Gear2_I : in std_logic; + Gear3_I : in std_logic; + Test_I : in std_logic; -- Self-test switch + SteerA_I : in std_logic; -- Steering wheel inputs, these are quadrature encoders + SteerB_I : in std_logic; + StartLamp_O : out std_logic -- Start button lamp + ); +end sprint1; + +architecture rtl of sprint1 is + +signal clk_6 : std_logic; +signal phi1 : std_logic; +signal phi2 : std_logic; + +signal Hcount : std_logic_vector(8 downto 0) := (others => '0'); +signal H256 : std_logic; +signal H256_s : std_logic; +signal H256_n : std_logic; +signal H128 : std_logic; +signal H64 : std_logic; +signal H32 : std_logic; +signal H16 : std_logic; +signal H8 : std_logic; +signal H8_n : std_logic; +signal H4 : std_logic; +signal H4_n : std_logic; +signal H2 : std_logic; +signal H1 : std_logic; + + + +signal Vcount : std_logic_vector(7 downto 0) := (others => '0'); +signal V128 : std_logic; +signal V64 : std_logic; +signal V32 : std_logic; +signal V16 : std_logic; +signal V8 : std_logic; +signal V4 : std_logic; +signal V2 : std_logic; +signal V1 : std_logic; + + +signal Vreset : std_logic; +signal Vblank_s : std_logic; +signal Vblank_n_s : std_logic; +signal Vblank : std_logic; +signal Hblank : std_logic; +signal Hsync : std_logic; +signal Vsync : std_logic; + +signal CompBlank_s : std_logic; +signal CompSync_n_s : std_logic; + +signal WhitePF_n : std_logic; +signal BlackPF_n : std_logic; + +signal Display : std_logic_vector(7 downto 0); + +-- Address decoder +signal addec_bus : std_logic_vector(7 downto 0); +signal RnW : std_logic; +signal Write_n : std_logic; +signal ROM1 : std_logic; +signal ROM2 : std_logic; +signal ROM3 : std_logic; +signal WRAM : std_logic; +signal RAM_n : std_logic; +signal Sync_n : std_logic; +signal Switch_n : std_logic; +signal Collision1_n : std_logic; +signal Collision2_n : std_logic; +signal Display_n : std_logic; +signal TimerReset_n : std_logic; +signal CollRst1_n : std_logic; +signal CollRst2_n : std_logic; +signal SteerRst1_n : std_logic; +signal SteerRst2_n : std_logic; +signal NoiseRst_n : std_logic; +signal Attract : std_logic; +signal Skid1 : std_logic; +signal Skid2 : std_logic; + +signal Crash_n : std_logic; +signal Motor1_n : std_logic; +signal Motor2_n : std_logic; +signal Car1 : std_logic; +signal Car1_n : std_logic; +signal Car2 : std_logic; +signal Car2_n : std_logic; +signal Car3_4_n : std_logic; + +signal NMI_n : std_logic; + +signal Adr : std_logic_vector(9 downto 0); + +signal SW1 : std_logic_vector(7 downto 0); + +signal Inputs : std_logic_vector(1 downto 0); +signal Collisions1 : std_logic_vector(1 downto 0); +signal Collisions2 : std_logic_vector(1 downto 0); + +begin +-- Configuration DIP switches, these can be brought out to external switches if desired +-- See Sprint 2 manual page 11 for complete information. Active low (0 = On, 1 = Off) +-- 1 Oil slicks (0 - Oil slicks enabled) +-- 2 Cycle tracks (0/1 - Cycle every lap/every two laps) +-- 3 4 Coins per play (00 - 1 Coin per player) +-- 5 Extended Play (0 - Extended Play enabled) +-- 6 Not used (X - Don't care) +-- 7 8 Game time (01 - 120 Seconds) +SW1 <= "11000101"; -- Config dip switches + + +Vid_sync: entity work.synchronizer +port map( + clk_12 => clk_12, + clk_6 => clk_6, + hcount => hcount, + vcount => vcount, + hsync => hsync, + hblank => hblank, + vblank_s => vblank_s, + vblank_n_s => vblank_n_s, + vblank => vblank, + vsync => vsync, + vreset => vreset + ); + + +Background: entity work.playfield +port map( + clk6 => clk_6, + display => display, + HCount => HCount, + VCount => VCount, + HBlank => HBlank, + H256_s => H256_s, + VBlank => VBlank, + VBlank_n_s => Vblank_n_s, + HSync => Hsync, + VSync => VSync, + CompSync_n_s => CompSync_n_s, + CompBlank_s => CompBlank_s, + WhitePF_n => WhitePF_n, + BlackPF_n => BlackPF_n + ); + + +Cars: entity work.motion +port map( + CLK6 => clk_6, + CLK12 => clk_12, + PHI2 => phi2, + DISPLAY => Display, + H256_s => H256_s, + VCount => VCount, + HCount => HCount, + Crash_n => Crash_n, + Motor1_n => Motor1_n, + Car1 => Car1, + Car1_n => Car1_n, + Car2 => Car2, + Car2_n => Car2_n, + Car3_4_n => Car3_4_n + ); + + +PF_Comparator: entity work.collision_detect +port map( + Clk6 => Clk_6, + Car1 => Car1, + Car1_n => Car1_n, + Car2 => Car2, + Car2_n => Car2_n, + Car3_4_n => Car3_4_n, + WhitePF_n => WhitePF_n, + BlackPF_n => BlackPF_n, + CollRst1_n => CollRst1_n, + Collisions1 => Collisions1 + ); + + +CPU: entity work.cpu_mem +port map( + Clk12 => clk_12, + Clk6 => clk_6, + Reset_n => reset_n, + VCount => VCount, + HCount => HCount, + Hsync_n => not Hsync, + Vblank_s => Vblank_s, + Vreset => Vreset, + Test_n => not Test_I, + Attract => Attract, + Skid1 => Skid1, + Skid2 => Skid2, + NoiseReset_n => NoiseRst_n, + CollRst1_n => CollRst1_n, + CollRst2_n => CollRst2_n, + SteerRst1_n => SteerRst1_n, + Lamp1 => StartLamp_O, + Phi1_o => Phi1, + Phi2_o => Phi2, + Display => Display, + IO_Adr => Adr, + Collisions1 => Collisions1, + Collisions2 => Collisions2, + Inputs => Inputs + ); + + +Input: entity work.Control_Inputs +port map( + clk6 => clk_6, + SW1 => SW1, -- DIP switches + Coin1_n => Coin1_I, + Coin2_n => Coin2_I, + Start => not Start_I, -- Active high in real hardware, inverting these makes more sense with the FPGA + Gas => not Gas_I, + Gear1 => not Gear1_I, + Gear2 => not Gear2_I, + Gear3 => not Gear3_I, + Self_Test => not Test_I, + Steering1A_n => SteerA_I, + Steering1B_n => SteerB_I, + SteerRst1_n => SteerRst1_n, + Adr => Adr, + Inputs => Inputs + ); + + +Sound: entity work.audio +port map( + Clk_6 => Clk_6, + Reset_n => Reset_n, + Motor1_n => Motor1_n, + Skid1 => Skid1, + Crash_n => Crash_n, + NoiseReset_n => NoiseRst_n, + Attract => Attract, + Display => Display, + HCount => HCount, + VCount => VCount, + Audio1 => Audio + ); + +-- Video mixing +VideoB_O <= (not(BlackPF_n and Car2_n and Car3_4_n)) nor CompBlank_s; +VideoW_O <= not(WhitePF_n and Car1_n); +Sync_O <= CompSync_n_s; + +Vb <= VBLANK; +Hb <= HBLANK; +Hs <= Hsync; +Vs <= Vsync; +Video <= (WhitePF_n and blackpf_n and car1_n and Car2_n and Car3_4_n) nor CompBlank_s; + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sprint1_mist.sv b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sprint1_mist.sv new file mode 100644 index 00000000..f367af5e --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sprint1_mist.sv @@ -0,0 +1,144 @@ +module sprint1_mist( + output LED, + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_HS, + output VGA_VS, + output AUDIO_L, + output AUDIO_R, + input SPI_SCK, + output SPI_DO, + input SPI_DI, + input SPI_SS2, + input SPI_SS3, + input CONF_DATA0, + input CLOCK_27 +); + +`include "rtl\build_id.sv" + +localparam CONF_STR = { + "Sprint1;;", + "O1,Test Mode,Off,On;", + "O34,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;", + "T6,Reset;", + "V,v1.00.",`BUILD_DATE +}; + +wire [31:0] status; +wire [1:0] buttons; +wire [1:0] switches; +wire [11:0] kbjoy; +wire [7:0] joystick_0; +wire [7:0] joystick_1; +wire scandoubler_disable; +wire ypbpr; +wire ps2_kbd_clk, ps2_kbd_data; +wire [6:0] audio; +wire video; + +wire clk_48, clk_12; +wire locked; +pll pll +( + .inclk0(CLOCK_27), + .c0(clk_48),//48.384 + .c1(clk_12),//12.096 + .locked(locked) +); + + +sprint1 sprint1 ( + .clk_12(clk_12), + .Reset_n(~(status[0] | status[6] | buttons[1])), + .VideoW_O(), + .VideoB_O(), + .Sync_O(), + .Hs(hs), + .Vs(vs), + .Vb(vb), + .Hb(hb), + .Video(video), + .Audio(audio), + .Coin1_I(~kbjoy[7]), + .Coin2_I(~kbjoy[7]), + .Start_I(~kbjoy[5]), + .Gas_I(~kbjoy[4]), +// .Gear1_I(~kbjoy[8]), +// .Gear2_I(~kbjoy[9]), +// .Gear3_I(~kbjoy[10]), + .Test_I(~status[1]), + .SteerA_I(), + .SteerB_I(), + .StartLamp_O(~LED) +); + +dac dac ( + .CLK(clk_48), + .RESET(1'b0), + .DACin(audio), + .DACout(AUDIO_L) + ); + +assign AUDIO_R = AUDIO_L; + +wire hs, vs; +wire hb, vb; +wire blankn = ~(hb | vb); +video_mixer #(.LINE_LENGTH(480), .HALF_DEPTH(1)) video_mixer +( + .clk_sys(clk_48), + .ce_pix(clk_12), + .ce_pix_actual(clk_12), + .SPI_SCK(SPI_SCK), + .SPI_SS3(SPI_SS3), + .SPI_DI(SPI_DI), + .R(blankn ? {video,video,video} : "000"), + .G(blankn ? {video,video,video} : "000"), + .B(blankn ? {video,video,video} : "000"), + .HSync(hs), + .VSync(vs), + .VGA_R(VGA_R), + .VGA_G(VGA_G), + .VGA_B(VGA_B), + .VGA_VS(VGA_VS), + .VGA_HS(VGA_HS), + .scandoubler_disable(scandoubler_disable), + .scanlines(scandoubler_disable ? 2'b00 : {status[4:3] == 3, status[4:3] == 2}), + .hq2x(status[4:3]==1), + .ypbpr_full(1), + .line_start(0), + .mono(0) +); + +mist_io #(.STRLEN(($size(CONF_STR)>>3))) mist_io +( + .clk_sys (clk_48 ), + .conf_str (CONF_STR ), + .SPI_SCK (SPI_SCK ), + .CONF_DATA0 (CONF_DATA0 ), + .SPI_SS2 (SPI_SS2 ), + .SPI_DO (SPI_DO ), + .SPI_DI (SPI_DI ), + .buttons (buttons ), + .switches (switches ), + .scandoubler_disable(scandoubler_disable), + .ypbpr (ypbpr ), + .ps2_kbd_clk (ps2_kbd_clk ), + .ps2_kbd_data (ps2_kbd_data ), + .joystick_0 (joystick_0 ), + .joystick_1 (joystick_1 ), + .status (status ) +); + +keyboard keyboard( + .clk(clk_48), + .reset(), + .ps2_kbd_clk(ps2_kbd_clk), + .ps2_kbd_data(ps2_kbd_data), + .joystick(kbjoy) + ); + + +endmodule diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sprint1_sound.vhd b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sprint1_sound.vhd new file mode 100644 index 00000000..268fe1fd --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sprint1_sound.vhd @@ -0,0 +1,195 @@ +-- Audio for Sprint 1 +-- First attempt at modeling the analog sound circuits used in Sprint 1, may be room for improvement as +-- I do not have a real board to compare. +-- (c) 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity audio is +port( + Clk_6 : in std_logic; + Reset_n : in std_logic; + Motor1_n : in std_logic; + Skid1 : in std_logic; + Crash_n : in std_logic; + NoiseReset_n : in std_logic; + Attract : in std_logic; + Display : in std_logic_vector(7 downto 0); + HCount : in std_logic_vector(8 downto 0); + VCount : in std_logic_vector(7 downto 0); + Audio1 : out std_logic_vector(6 downto 0) + ); +end audio; + +architecture rtl of audio is + +signal reset : std_logic; + +signal H4 : std_logic; +signal V2 : std_logic; + +signal Noise : std_logic; +signal Noise_Shift : std_logic_vector(15 downto 0); +signal Shift_in : std_logic; + +signal Screech_count : integer range 1000 to 11000; +signal Screech_state : std_logic; +signal Screech_snd1 : std_logic; +signal Screech1 : std_logic_vector(3 downto 0); + +signal Crash : std_logic_vector(3 downto 0); +signal Bang : std_logic_vector(3 downto 0); + +signal Mtr1_Freq : std_logic_vector(3 downto 0); +signal Motor1_speed : std_logic_vector(3 downto 0); +signal Motor1_snd : std_logic_vector(5 downto 0); + +signal ena_count : std_logic_vector(10 downto 0); +signal ena_3k : std_logic; + +signal bang_prefilter : std_logic_vector(3 downto 0); +signal bang_filter_t1 : std_logic_vector(3 downto 0); +signal bang_filter_t2 : std_logic_vector(3 downto 0); +signal bang_filter_t3 : std_logic_vector(3 downto 0); +signal bang_filtered : std_logic_vector(5 downto 0); + + +begin + +-- HCount +-- (0) 1H 3 MHz +-- (1) 2H 1.5MHz +-- (2) 4H 750 kHz +-- (3) 8H 375 kHz +-- (4) 16H 187 kHz +-- (5) 32H 93 kHz +-- (6) 64H 46 kHz +-- (7) 128H 23 kHz +-- (8) 256H 12 kHz + +reset <= (not reset_n); + +H4 <= HCount(2); +V2 <= VCount(1); + +-- Generate the 3kHz clock enable used by the filter +Enable: process(clk_6) +begin + if rising_edge(CLK_6) then + ena_count <= ena_count + "1"; + ena_3k <= '0'; + if (ena_count(10 downto 0) = "00000000000") then + ena_3k <= '1'; + end if; + end if; +end process; + + +-- LFSR that generates pseudo-random noise +Noise_gen: process(NoiseReset_n, V2) +begin + if (noisereset_n = '0') then + noise_shift <= (others => '0'); + noise <= '0'; + elsif rising_edge(V2) then + shift_in <= not(noise_shift(6) xor noise_shift(8)); + noise_shift <= shift_in & noise_shift(15 downto 1); + noise <= noise_shift(0); + end if; +end process; + + +-- Tire screech sound +Screech_gen1: entity work.tire_screech +generic map( -- These values can be tweaked to tune the screech sound + Inc1 => 24, -- Ramp increase rate when noise = 0 + Inc2 => 33, -- Ramp increase rate when noise = 1 + Dec1 => 29, -- Ramp decrease rate when noise = 0 + Dec2 => 16 -- Ramp decrease rate when noise = 1 + ) +port map( + Clk => H4, + Noise => noise, + Screech_out => screech_snd1 + ); + + +-- Convert screech from 1 bit to 4 bits wide and enable via skid1 signal +Screech_ctrl: process(screech_snd1, skid1) +begin + if (skid1 and screech_snd1) = '1' then + screech1 <= "1111"; + else + screech1 <= "0000"; + end if; +end process; + + +Crash_sound: process(crash_n, display, noise) +begin + if crash_n = '0' then + crash <= display(3 downto 0); + end if; + if noise = '1' then + bang_prefilter <= crash; + else + bang_prefilter <= "0000"; + end if; +end process; + + +---- Very simple low pass filter, borrowed from MikeJ's Asteroids code +Crash_filter: process(clk_6) +begin + if rising_edge(clk_6) then + if (ena_3k = '1') then + bang_filter_t1 <= bang_prefilter; + bang_filter_t2 <= bang_filter_t1; + bang_filter_t3 <= bang_filter_t2; + end if; + bang_filtered <= ("00" & bang_filter_t1) + + ('0' & bang_filter_t2 & '0') + + ("00" & bang_filter_t3); + end if; +end process; + + +Motor1_latch: process(Motor1_n, Display) +begin + if Motor1_n = '0' then + Motor1_speed <= Display(3 downto 0); + end if; +end process; + +Motor1: entity work.EngineSound +generic map( + Freq_tune => 50 -- Tuning pot for engine sound frequency + ) +port map( + Clk_6 => clk_6, + Ena_3k => ena_3k, + EngineData => motor1_speed, + Motor => motor1_snd + ); + + +-- Audio mixer, also mutes sound in attract mode +audio1 <= ('0' & motor1_snd) + ("00" & screech1) + ('0' & bang_filtered) when attract = '0' + else "0000000"; + + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sprom.vhd b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sprom.vhd new file mode 100644 index 00000000..a81ac959 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sprom.vhd @@ -0,0 +1,82 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY sprom IS + GENERIC + ( + init_file : string := ""; + widthad_a : natural; + width_a : natural := 8; + outdata_reg_a : string := "UNREGISTERED" + ); + PORT + ( + address : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + clock : IN STD_LOGIC ; + q : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); +END sprom; + + +ARCHITECTURE SYN OF sprom IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + address_aclr_a : STRING; + clock_enable_input_a : STRING; + clock_enable_output_a : STRING; + init_file : STRING; + intended_device_family : STRING; + lpm_hint : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_reg_a : STRING; + widthad_a : NATURAL; + width_a : NATURAL; + width_byteena_a : NATURAL + ); + PORT ( + clock0 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q <= sub_wire0(width_a-1 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_aclr_a => "NONE", + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + init_file => init_file, + intended_device_family => "Cyclone III", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 2**widthad_a, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => outdata_reg_a, + widthad_a => widthad_a, + width_a => width_a, + width_byteena_a => 1 + ) + PORT MAP ( + clock0 => clock, + address_a => address, + q_a => sub_wire0 + ); + + + +END SYN; diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sync.vhd b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sync.vhd new file mode 100644 index 00000000..6ef8fef9 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/sync.vhd @@ -0,0 +1,188 @@ +-- Video synchronizer circuit for Sprint 1 +-- Similar circuit used in many other Atari and Kee Games arcade games +-- (c) 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity synchronizer is +port( + clk_12 : in std_logic; + clk_6 : out std_logic; + hcount : out std_logic_vector(8 downto 0); + vcount : out std_logic_vector(7 downto 0); + hsync : out std_logic; + hblank : out std_logic; + vblank_s : out std_logic; + vblank_n_s : out std_logic; + vblank : out std_logic; + vsync : out std_logic; + vreset : out std_logic); +end synchronizer; + +architecture rtl of synchronizer is + +signal h_counter : std_logic_vector(9 downto 0) := (others => '0'); +signal H256 : std_logic; +signal H256_n : std_logic; +signal H128 : std_logic; +signal H64 : std_logic; +signal H32 : std_logic; +signal H16 : std_logic; +signal H8 : std_logic; +signal H8_n : std_logic; +signal H4 : std_logic; +signal H4_n : std_logic; +signal H2 : std_logic; +signal H1 : std_logic; + +signal v_counter : std_logic_vector(7 downto 0) := (others => '0'); +signal V128 : std_logic; +signal V64 : std_logic; +signal V32 : std_logic; +signal V16 : std_logic; +signal V8 : std_logic; +signal V4 : std_logic; +signal V2 : std_logic; +signal V1 : std_logic; + +signal sync_bus : std_logic_vector(3 downto 0) := (others => '0'); +signal sync_reg : std_logic_vector(3 downto 0) := (others => '0'); +signal vblank_int : std_logic := '0'; +signal vreset_n : std_logic := '0'; + +signal hblank_int : std_logic := '0'; +signal hsync_int : std_logic := '0'; +signal hsync_reset : std_logic := '0'; + + +begin + +-- Horizontal counter is 9 bits long plus additional flip flop. The last 4 bit IC in the chain resets to 0010 so total count resets to 128 +-- using only the last three count states +H_count: process(clk_12) +begin + if rising_edge(clk_12) then + if h_counter = "1111111111" then + h_counter <= "0100000000"; + else + h_counter <= h_counter + 1; + end if; + end if; +end process; + +-- Vertical counter is 8 bits, clocked by the rising edge of H256 at the end of each horizontal line +V_count: process(hsync_int) +begin + if rising_edge(Hsync_int) then + if vreset_n = '0' then + v_counter <= (others => '0'); + else + v_counter <= v_counter + '1'; + end if; + end if; +end process; + +-- Many Atari raster games use a 256 x 4 bit prom to decode vertical sync signals +-- This could be replaced by combinatorial logic +M2: entity work.sprom +generic map( + init_file => "rtl/roms/6400-01m2.hex", + widthad_a => 8, + width_a => 4) +port map( + clock => clk_12, + address => sync_reg(3) & V128 & V64 & V16 & V8 & V4 & V2 & V1, + q => sync_bus + ); + +--M2: entity work.sync_prom +--port map( +-- clock => clk_12, +-- address => sync_reg(3) & V128 & V64 & V16 & V8 & V4 & V2 & V1, +-- q => sync_bus +-- ); + +-- Register fed by the sync PROM, in the original hardware this also creates the complements of these signals +sync_register: process(hsync_int) +begin + if rising_edge(hsync_int) then + sync_reg <= sync_bus; + end if; +end process; + +-- Outputs of sync PROM +vblank_s <= sync_reg(3); +vblank_n_s <= not sync_reg(3); +vreset <= sync_reg(2); +vreset_n <= not sync_reg(2); +vblank <= sync_reg(1); +vsync <= sync_reg(0); + +-- A pair of D type flip-flops that generate the Hsync signal +Hsync_1: process(H256_n, H32) +begin + if H256_n = '0' then + hblank_int <= '0'; + else + if rising_edge(H32) then + hblank_int <= not H64; + end if; + end if; +end process; + +Hsync_2: process(hblank_int, H8) +begin + if hblank_int = '0' then + hsync_int <= '0'; + else + if rising_edge(H8) then + hsync_int <= H32; + end if; + end if; +end process; + +-- Assign various signals +clk_6 <= h_counter(0); +H1 <= h_counter(1); +H2 <= h_counter(2); +H4 <= h_counter(3); +H8 <= h_counter(4); +H16 <= h_counter(5); +H32 <= h_counter(6); +H64 <= h_counter(7); +H128 <= h_counter(8); +H256 <= h_counter(9); +H4_n <= not H4; +H8_n <= not H8; +H256_n <= not H256; + +V1 <= v_counter(0); +V2 <= v_counter(1); +V4 <= v_counter(2); +V8 <= v_counter(3); +V16 <= v_counter(4); +V32 <= v_counter(5); +V64 <= v_counter(6); +V128 <= v_counter(7); + +hcount <= h_counter(9 downto 1); +vcount <= v_counter; +hsync <= hsync_int; +hblank <= hblank_int; + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/video_mixer.sv b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/video_mixer.sv new file mode 100644 index 00000000..04cfd4ba --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/video_mixer.sv @@ -0,0 +1,242 @@ +// +// +// Copyright (c) 2017 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + +// +// LINE_LENGTH: Length of display line in pixels +// Usually it's length from HSync to HSync. +// May be less if line_start is used. +// +// HALF_DEPTH: If =1 then color dept is 3 bits per component +// For half depth 6 bits monochrome is available with +// mono signal enabled and color = {G, R} + +module video_mixer +#( + parameter LINE_LENGTH = 768, + parameter HALF_DEPTH = 0, + + parameter OSD_COLOR = 3'd4, + parameter OSD_X_OFFSET = 10'd0, + parameter OSD_Y_OFFSET = 10'd0 +) +( + // master clock + // it should be multiple by (ce_pix*4). + input clk_sys, + + // Pixel clock or clock_enable (both are accepted). + input ce_pix, + + // Some systems have multiple resolutions. + // ce_pix_actual should match ce_pix where every second or fourth pulse is enabled, + // thus half or qurter resolutions can be used without brake video sync while switching resolutions. + // For fixed single resolution (or when video sync stability isn't required) ce_pix_actual = ce_pix. + input ce_pix_actual, + + // OSD SPI interface + input SPI_SCK, + input SPI_SS3, + input SPI_DI, + + // scanlines (00-none 01-25% 10-50% 11-75%) + input [1:0] scanlines, + + // 0 = HVSync 31KHz, 1 = CSync 15KHz + input scandoubler_disable, + + // High quality 2x scaling + input hq2x, + + // YPbPr always uses composite sync + input ypbpr, + + // 0 = 16-240 range. 1 = 0-255 range. (only for YPbPr color space) + input ypbpr_full, + + // color + input [DWIDTH:0] R, + input [DWIDTH:0] G, + input [DWIDTH:0] B, + + // Monochrome mode (for HALF_DEPTH only) + input mono, + + // interlace sync. Positive pulses. + input HSync, + input VSync, + + // Falling of this signal means start of informative part of line. + // It can be horizontal blank signal. + // This signal can be used to reduce amount of required FPGA RAM for HQ2x scan doubler + // If FPGA RAM is not an issue, then simply set it to 0 for whole line processing. + // Keep in mind: due to algo first and last pixels of line should be black to avoid side artefacts. + // Thus, if blank signal is used to reduce the line, make sure to feed at least one black (or paper) pixel + // before first informative pixel. + input line_start, + + // MiST video output signals + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_VS, + output VGA_HS +); + +localparam DWIDTH = HALF_DEPTH ? 2 : 5; + +wire [DWIDTH:0] R_sd; +wire [DWIDTH:0] G_sd; +wire [DWIDTH:0] B_sd; +wire hs_sd, vs_sd; + +scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH)) scandoubler +( + .*, + .hs_in(HSync), + .vs_in(VSync), + .r_in(R), + .g_in(G), + .b_in(B), + + .hs_out(hs_sd), + .vs_out(vs_sd), + .r_out(R_sd), + .g_out(G_sd), + .b_out(B_sd) +); + +wire [DWIDTH:0] rt = (scandoubler_disable ? R : R_sd); +wire [DWIDTH:0] gt = (scandoubler_disable ? G : G_sd); +wire [DWIDTH:0] bt = (scandoubler_disable ? B : B_sd); + +generate + if(HALF_DEPTH) begin + wire [5:0] r = mono ? {gt,rt} : {rt,rt}; + wire [5:0] g = mono ? {gt,rt} : {gt,gt}; + wire [5:0] b = mono ? {gt,rt} : {bt,bt}; + end else begin + wire [5:0] r = rt; + wire [5:0] g = gt; + wire [5:0] b = bt; + end +endgenerate + +wire hs = (scandoubler_disable ? HSync : hs_sd); +wire vs = (scandoubler_disable ? VSync : vs_sd); + +reg scanline = 0; +always @(posedge clk_sys) begin + reg old_hs, old_vs; + + old_hs <= hs; + old_vs <= vs; + + if(old_hs && ~hs) scanline <= ~scanline; + if(old_vs && ~vs) scanline <= 0; +end + +wire [5:0] r_out, g_out, b_out; +always @(*) begin + case(scanlines & {scanline, scanline}) + 1: begin // reduce 25% = 1/2 + 1/4 + r_out = {1'b0, r[5:1]} + {2'b00, r[5:2]}; + g_out = {1'b0, g[5:1]} + {2'b00, g[5:2]}; + b_out = {1'b0, b[5:1]} + {2'b00, b[5:2]}; + end + + 2: begin // reduce 50% = 1/2 + r_out = {1'b0, r[5:1]}; + g_out = {1'b0, g[5:1]}; + b_out = {1'b0, b[5:1]}; + end + + 3: begin // reduce 75% = 1/4 + r_out = {2'b00, r[5:2]}; + g_out = {2'b00, g[5:2]}; + b_out = {2'b00, b[5:2]}; + end + + default: begin + r_out = r; + g_out = g; + b_out = b; + end + endcase +end + +wire [5:0] red, green, blue; +osd #(OSD_X_OFFSET, OSD_Y_OFFSET, OSD_COLOR) osd +( + .*, + + .R_in(r_out), + .G_in(g_out), + .B_in(b_out), + .HSync(hs), + .VSync(vs), + + .R_out(red), + .G_out(green), + .B_out(blue) +); + +wire [5:0] yuv_full[225] = '{ + 6'd0, 6'd0, 6'd0, 6'd0, 6'd1, 6'd1, 6'd1, 6'd1, + 6'd2, 6'd2, 6'd2, 6'd3, 6'd3, 6'd3, 6'd3, 6'd4, + 6'd4, 6'd4, 6'd5, 6'd5, 6'd5, 6'd5, 6'd6, 6'd6, + 6'd6, 6'd7, 6'd7, 6'd7, 6'd7, 6'd8, 6'd8, 6'd8, + 6'd9, 6'd9, 6'd9, 6'd9, 6'd10, 6'd10, 6'd10, 6'd11, + 6'd11, 6'd11, 6'd11, 6'd12, 6'd12, 6'd12, 6'd13, 6'd13, + 6'd13, 6'd13, 6'd14, 6'd14, 6'd14, 6'd15, 6'd15, 6'd15, + 6'd15, 6'd16, 6'd16, 6'd16, 6'd17, 6'd17, 6'd17, 6'd17, + 6'd18, 6'd18, 6'd18, 6'd19, 6'd19, 6'd19, 6'd19, 6'd20, + 6'd20, 6'd20, 6'd21, 6'd21, 6'd21, 6'd21, 6'd22, 6'd22, + 6'd22, 6'd23, 6'd23, 6'd23, 6'd23, 6'd24, 6'd24, 6'd24, + 6'd25, 6'd25, 6'd25, 6'd25, 6'd26, 6'd26, 6'd26, 6'd27, + 6'd27, 6'd27, 6'd27, 6'd28, 6'd28, 6'd28, 6'd29, 6'd29, + 6'd29, 6'd29, 6'd30, 6'd30, 6'd30, 6'd31, 6'd31, 6'd31, + 6'd31, 6'd32, 6'd32, 6'd32, 6'd33, 6'd33, 6'd33, 6'd33, + 6'd34, 6'd34, 6'd34, 6'd35, 6'd35, 6'd35, 6'd35, 6'd36, + 6'd36, 6'd36, 6'd36, 6'd37, 6'd37, 6'd37, 6'd38, 6'd38, + 6'd38, 6'd38, 6'd39, 6'd39, 6'd39, 6'd40, 6'd40, 6'd40, + 6'd40, 6'd41, 6'd41, 6'd41, 6'd42, 6'd42, 6'd42, 6'd42, + 6'd43, 6'd43, 6'd43, 6'd44, 6'd44, 6'd44, 6'd44, 6'd45, + 6'd45, 6'd45, 6'd46, 6'd46, 6'd46, 6'd46, 6'd47, 6'd47, + 6'd47, 6'd48, 6'd48, 6'd48, 6'd48, 6'd49, 6'd49, 6'd49, + 6'd50, 6'd50, 6'd50, 6'd50, 6'd51, 6'd51, 6'd51, 6'd52, + 6'd52, 6'd52, 6'd52, 6'd53, 6'd53, 6'd53, 6'd54, 6'd54, + 6'd54, 6'd54, 6'd55, 6'd55, 6'd55, 6'd56, 6'd56, 6'd56, + 6'd56, 6'd57, 6'd57, 6'd57, 6'd58, 6'd58, 6'd58, 6'd58, + 6'd59, 6'd59, 6'd59, 6'd60, 6'd60, 6'd60, 6'd60, 6'd61, + 6'd61, 6'd61, 6'd62, 6'd62, 6'd62, 6'd62, 6'd63, 6'd63, + 6'd63 +}; + +// http://marsee101.blog19.fc2.com/blog-entry-2311.html +// Y = 16 + 0.257*R + 0.504*G + 0.098*B (Y = 0.299*R + 0.587*G + 0.114*B) +// Pb = 128 - 0.148*R - 0.291*G + 0.439*B (Pb = -0.169*R - 0.331*G + 0.500*B) +// Pr = 128 + 0.439*R - 0.368*G - 0.071*B (Pr = 0.500*R - 0.419*G - 0.081*B) + +wire [18:0] y_8 = 19'd04096 + ({red, 8'd0} + {red, 3'd0}) + ({green, 9'd0} + {green, 2'd0}) + ({blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0}); +wire [18:0] pb_8 = 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0}) - ({green, 8'd0} + {green, 5'd0} + {green, 3'd0}) + ({blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0}); +wire [18:0] pr_8 = 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0}) - ({green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0}) - ({blue, 6'd0} + {blue , 3'd0}); + +wire [7:0] y = ( y_8[17:8] < 16) ? 8'd16 : ( y_8[17:8] > 235) ? 8'd235 : y_8[15:8]; +wire [7:0] pb = (pb_8[17:8] < 16) ? 8'd16 : (pb_8[17:8] > 240) ? 8'd240 : pb_8[15:8]; +wire [7:0] pr = (pr_8[17:8] < 16) ? 8'd16 : (pr_8[17:8] > 240) ? 8'd240 : pr_8[15:8]; + +assign VGA_R = ypbpr ? (ypbpr_full ? yuv_full[pr-8'd16] : pr[7:2]) : red; +assign VGA_G = ypbpr ? (ypbpr_full ? yuv_full[y -8'd16] : y[7:2]) : green; +assign VGA_B = ypbpr ? (ypbpr_full ? yuv_full[pb-8'd16] : pb[7:2]) : blue; +assign VGA_VS = (scandoubler_disable | ypbpr) ? 1'b1 : ~vs_sd; +assign VGA_HS = scandoubler_disable ? ~(HSync ^ VSync) : ypbpr ? ~(hs_sd ^ vs_sd) : ~hs_sd; + +endmodule diff --git a/Arcade_MiST/Custom Hardware/SprintOne_MiST/snapshot/sprint1.rbf b/Arcade_MiST/Custom Hardware/SprintOne_MiST/snapshot/sprint1.rbf new file mode 100644 index 0000000000000000000000000000000000000000..2fdbb6241e3ddb9721acb9cfc75ad062d97ea23b GIT binary patch literal 248468 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�LA3 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�pN(+RwK^zlDFwc*Qb8@|lURr8Fg9{uRf1?#vvy?0?H z>pW{SbMgfma?QYIZ8~_orbq{CXYKNnVYNMTx#=soZaN(_ulMFkbywMf{0HWhyKCYT zZA~>}rBTA6Kgu>9PvjoXuWWeJ$z{GZYIN#L(FP^vd_Pepix+fKnt~_&g7!ECPv}{n zG*wTnK^GS;h#5s={Os8MFwR14xsuvd<)?QMdiCfhhE8eevuWuIr&xE{$4i=9y{By> z=D56U`<5s8voHK7=;=~+hvIm|pWASXB7@RXvX*lE zw3l$aAq&X;)+uG(w8AN6ecsFn$xbQj?OQ{hQq~`S^ZDnU6w3O%Sy~@JE|{ubwU2JE zMZ1Q~ACtBm!KDl5()EM??>E~Dm~TMj#P*mke(b+?uk^O2K_59M77rWG*OUJ z&bS+9n8v8$P8wwNe&sy^&{Ec`VM#Nj?i$S5J#X2{hWOBL{#RW6u0+}I{KIFNr&v`R zUm>&=P|6r8sO*{21f!oIvQ^bK7;_A$8xoy;_&IU9%`tE1WW&2(zMva`ceUm_qtH3D zl>OmT&6pBig09z0gl}fL@C(dUMJ+J9HRv|;b$;0JK!aDSxo~2wbGkW&9(riO^z2gR zvKK8Fu#^1@cGHZ#xmj(2>TGB21ZNG-siEeSNcKcoDHmsfS~ZNT4WW#u%Yu=OuxRqD zN8*x$WEeyYm9k36RnJ-lYoe4Tu#_7f3I)rB(`O)K#vd4-9vZX@UhkU0;+ccMAAmR%Unjb!VCpUiUzPi^?Tp2oKJS7htu%v}?; z;i19)%=pC6MCG1AtIw`oQnX3}cGt+aZUws@C|=FQ#HHybPAQ96G8h}&8$YTd9j??9 z6Y<2U4;BbwMd^iad!C_BbrXI^Cd%cIeHA2i)Qt6v( x3Y@5m Inputs <= A8_8 & SW2_bank2; -- There is actually an inverter N9 fed by A8_8 so we will just account for that + when "01" => Inputs <= Coin2 & Coin1; + when "10" => Inputs <= Start2_n & Start1_n; + when "11" => Inputs <= Test_n & Slam_n; + when others => Inputs <= "11"; + end case; +end process; +-- Coin switch inputs are active-high internally but inverted on board from active-low inputs +Coin1 <= (not Coin1_n); +Coin2 <= (not Coin2_n); + + +H9: process(Adr, Select1_n, Select2_n, Serve_n, Sense1, Sense2) +begin + if Adr(4) = '0' then -- Adr(4) is connected to enable + case Adr(2 downto 0) is + when "000" => H9_Q_n <= (not Select1_n); + when "100" => H9_Q_n <= (not Sense1); + when "101" => H9_Q_n <= (not Sense2); + when "110" => H9_Q_n <= (not Serve_n); + when "111" => H9_Q_n <= (not Select2_n); + when others => H9_Q_n <= '1'; + end case; + else + H9_Q_n <= '1'; + end if; +end process; + + +-- The way the dip switches are wired in the real hardware requires some changes +-- to achieve the same result while using standard active-low switch inputs. +-- Switches are split into two banks, each bank fed from half of selector J9. +J9: process(Adr) +begin + if Adr(3) = '1' then + J9_out <= "11111111"; + else + case Adr(1 downto 0) is + when "00" => J9_out <= "11101110"; + when "01" => J9_out <= "11011101"; + when "10" => J9_out <= "10111011"; + when "11" => J9_out <= "01110111"; + end case; + end if; +end process; + +-- Re-order the dip switch signals to match the physical order of the switches +-- Bank 1 +DipSW(7) <= J9_out(7) when SW2(1) = '0' else '1'; +DipSW(6) <= J9_out(6) when SW2(3) = '0' else '1'; +DipSW(5) <= J9_out(5) when SW2(5) = '0' else '1'; +DipSW(4) <= J9_out(4) when SW2(7) = '0' else '1'; + +--Bank 2 +DipSW(3) <= J9_out(3) when SW2(0) = '0' else '1'; +DipSW(2) <= J9_out(2) when SW2(2) = '0' else '1'; +DipSW(1) <= J9_out(1) when SW2(4) = '0' else '1'; +DipSW(0) <= J9_out(0) when SW2(6) = '0' else '1'; + +-- Outputs from each switch bank are tied together, logical AND since they are active low +SW2_bank1 <= DipSW(7) and DipSW(6) and DipSW(5) and DipSW(4); +SW2_bank2 <= DipSW(3) and DipSW(2) and DipSW(1) and DipSW(0); + +-- Bank 1 of dip switches is multiplexed with player inputs connected to selector H9 +A8_8 <= SW2_bank1 and H9_Q_n; + + +-- Outputs +E8_in <= IO_wr & Adr(9 downto 7); +E8: process(E8_in) +begin + case E8_in is + when "0000" => E8_out <= "1111111110"; + when "0001" => E8_out <= "1111111101"; + when "0100" => E8_out <= "1111101111"; + when others => E8_out <= "1111111111"; + end case; +end process; + +H8_en <= E8_out(0); +TIMER_RESET_n <= E8_out(1); +INTACK_n <= E8_out(4); + +-- H8 9334 +H8_dec: process(clk6) +begin +if rising_edge(clk6) then + if (H8_en = '0') then + case Adr(6 downto 4) is + when "000" => null; + when "001" => SERV_LED_n <= Adr(0); + when "010" => null; + when "011" => LAMP1 <= Adr(0); + when "100" => LAMP2 <= Adr(0); + when "101" => MASK1_n <= Adr(0); + when "110" => MASK2_n <= Adr(0); + when "111" => COUNTER <= Adr(0); + when others => null; + end case; + end if; + end if; +end process; + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/Char_LSB.qip b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/Char_LSB.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/Char_MSB.qip b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/Char_MSB.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/T65.vhd b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/T65.vhd new file mode 100644 index 00000000..161debea --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/T65.vhd @@ -0,0 +1,551 @@ +-- **** +-- T65(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 301 more merging +-- Ver 300 Bugfixes by ehenciak added, started tidyup *bust* +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- 65xx compatible microprocessor core +-- +-- Version : 0246 +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t65/ +-- +-- Limitations : +-- +-- 65C02 and 65C816 modes are incomplete +-- Undocumented instructions are not supported +-- Some interface signals behaves incorrect +-- +-- File history : +-- +-- 0246 : First release +-- + +library IEEE; + use IEEE.std_logic_1164.all; + use IEEE.numeric_std.all; + use work.T65_Pack.all; + +-- ehenciak 2-23-2005 : Added the enable signal so that one doesn't have to use +-- the ready signal to limit the CPU. +entity T65 is + port( + Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816 + Res_n : in std_logic; + Enable : in std_logic; + Clk : in std_logic; + Rdy : in std_logic; + Abort_n : in std_logic; + IRQ_n : in std_logic; + NMI_n : in std_logic; + SO_n : in std_logic; + R_W_n : out std_logic; + Sync : out std_logic; + EF : out std_logic; + MF : out std_logic; + XF : out std_logic; + ML_n : out std_logic; + VP_n : out std_logic; + VDA : out std_logic; + VPA : out std_logic; + A : out std_logic_vector(23 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0) + ); +end T65; + +architecture rtl of T65 is + + -- Registers + signal ABC, X, Y, D : std_logic_vector(15 downto 0); + signal P, AD, DL : std_logic_vector(7 downto 0) := x"00"; + signal BAH : std_logic_vector(7 downto 0); + signal BAL : std_logic_vector(8 downto 0); + signal PBR : std_logic_vector(7 downto 0); + signal DBR : std_logic_vector(7 downto 0); + signal PC : unsigned(15 downto 0); + signal S : unsigned(15 downto 0); + signal EF_i : std_logic; + signal MF_i : std_logic; + signal XF_i : std_logic; + + signal IR : std_logic_vector(7 downto 0); + signal MCycle : std_logic_vector(2 downto 0); + + signal Mode_r : std_logic_vector(1 downto 0); + signal ALU_Op_r : std_logic_vector(3 downto 0); + signal Write_Data_r : std_logic_vector(2 downto 0); + signal Set_Addr_To_r : std_logic_vector(1 downto 0); + signal PCAdder : unsigned(8 downto 0); + + signal RstCycle : std_logic; + signal IRQCycle : std_logic; + signal NMICycle : std_logic; + + signal B_o : std_logic; + signal SO_n_o : std_logic; + signal IRQ_n_o : std_logic; + signal NMI_n_o : std_logic; + signal NMIAct : std_logic; + + signal Break : std_logic; + + -- ALU signals + signal BusA : std_logic_vector(7 downto 0); + signal BusA_r : std_logic_vector(7 downto 0); + signal BusB : std_logic_vector(7 downto 0); + signal ALU_Q : std_logic_vector(7 downto 0); + signal P_Out : std_logic_vector(7 downto 0); + + -- Micro code outputs + signal LCycle : std_logic_vector(2 downto 0); + signal ALU_Op : std_logic_vector(3 downto 0); + signal Set_BusA_To : std_logic_vector(2 downto 0); + signal Set_Addr_To : std_logic_vector(1 downto 0); + signal Write_Data : std_logic_vector(2 downto 0); + signal Jump : std_logic_vector(1 downto 0); + signal BAAdd : std_logic_vector(1 downto 0); + signal BreakAtNA : std_logic; + signal ADAdd : std_logic; + signal AddY : std_logic; + signal PCAdd : std_logic; + signal Inc_S : std_logic; + signal Dec_S : std_logic; + signal LDA : std_logic; + signal LDP : std_logic; + signal LDX : std_logic; + signal LDY : std_logic; + signal LDS : std_logic; + signal LDDI : std_logic; + signal LDALU : std_logic; + signal LDAD : std_logic; + signal LDBAL : std_logic; + signal LDBAH : std_logic; + signal SaveP : std_logic; + signal Write : std_logic; + + signal really_rdy : std_logic; + signal R_W_n_i : std_logic; + +begin + -- ehenciak : gate Rdy with read/write to make an "OK, it's + -- really OK to stop the processor now if Rdy is + -- deasserted" signal + really_rdy <= Rdy or not(R_W_n_i); + + -- ehenciak : Drive R_W_n_i off chip. + R_W_n <= R_W_n_i; + + Sync <= '1' when MCycle = "000" else '0'; + EF <= EF_i; + MF <= MF_i; + XF <= XF_i; + ML_n <= '0' when IR(7 downto 6) /= "10" and IR(2 downto 1) = "11" and MCycle(2 downto 1) /= "00" else '1'; + VP_n <= '0' when IRQCycle = '1' and (MCycle = "101" or MCycle = "110") else '1'; + VDA <= '1' when Set_Addr_To_r /= "000" else '0'; -- Incorrect !!!!!!!!!!!! + VPA <= '1' when Jump(1) = '0' else '0'; -- Incorrect !!!!!!!!!!!! + + mcode : T65_MCode + port map( + Mode => Mode_r, + IR => IR, + MCycle => MCycle, + P => P, + LCycle => LCycle, + ALU_Op => ALU_Op, + Set_BusA_To => Set_BusA_To, + Set_Addr_To => Set_Addr_To, + Write_Data => Write_Data, + Jump => Jump, + BAAdd => BAAdd, + BreakAtNA => BreakAtNA, + ADAdd => ADAdd, + AddY => AddY, + PCAdd => PCAdd, + Inc_S => Inc_S, + Dec_S => Dec_S, + LDA => LDA, + LDP => LDP, + LDX => LDX, + LDY => LDY, + LDS => LDS, + LDDI => LDDI, + LDALU => LDALU, + LDAD => LDAD, + LDBAL => LDBAL, + LDBAH => LDBAH, + SaveP => SaveP, + Write => Write + ); + + alu : T65_ALU + port map( + Mode => Mode_r, + Op => ALU_Op_r, + BusA => BusA_r, + BusB => BusB, + P_In => P, + P_Out => P_Out, + Q => ALU_Q + ); + + process (Res_n, Clk) + begin + if Res_n = '0' then + PC <= (others => '0'); -- Program Counter + IR <= "00000000"; + S <= (others => '0'); -- Dummy !!!!!!!!!!!!!!!!!!!!! + D <= (others => '0'); + PBR <= (others => '0'); + DBR <= (others => '0'); + + Mode_r <= (others => '0'); + ALU_Op_r <= "1100"; + Write_Data_r <= "000"; + Set_Addr_To_r <= "00"; + + R_W_n_i <= '1'; + EF_i <= '1'; + MF_i <= '1'; + XF_i <= '1'; + + elsif Clk'event and Clk = '1' then + if (Enable = '1') then + if (really_rdy = '1') then + R_W_n_i <= not Write or RstCycle; + + D <= (others => '1'); -- Dummy + PBR <= (others => '1'); -- Dummy + DBR <= (others => '1'); -- Dummy + EF_i <= '0'; -- Dummy + MF_i <= '0'; -- Dummy + XF_i <= '0'; -- Dummy + + if MCycle = "000" then + Mode_r <= Mode; + + if IRQCycle = '0' and NMICycle = '0' then + PC <= PC + 1; + end if; + + if IRQCycle = '1' or NMICycle = '1' then + IR <= "00000000"; + else + IR <= DI; + end if; + end if; + + ALU_Op_r <= ALU_Op; + Write_Data_r <= Write_Data; + if Break = '1' then + Set_Addr_To_r <= "00"; + else + Set_Addr_To_r <= Set_Addr_To; + end if; + + if Inc_S = '1' then + S <= S + 1; + end if; + if Dec_S = '1' and RstCycle = '0' then + S <= S - 1; + end if; + if LDS = '1' then + S(7 downto 0) <= unsigned(ALU_Q); + end if; + + if IR = "00000000" and MCycle = "001" and IRQCycle = '0' and NMICycle = '0' then + PC <= PC + 1; + end if; + -- + -- jump control logic + -- + case Jump is + when "01" => + PC <= PC + 1; + + when "10" => + PC <= unsigned(DI & DL); + + when "11" => + if PCAdder(8) = '1' then + if DL(7) = '0' then + PC(15 downto 8) <= PC(15 downto 8) + 1; + else + PC(15 downto 8) <= PC(15 downto 8) - 1; + end if; + end if; + PC(7 downto 0) <= PCAdder(7 downto 0); + + when others => null; + end case; + end if; + end if; + end if; + end process; + + PCAdder <= resize(PC(7 downto 0),9) + resize(unsigned(DL(7) & DL),9) when PCAdd = '1' + else "0" & PC(7 downto 0); + + process (Clk) + begin + if Clk'event and Clk = '1' then + if (Enable = '1') then + if (really_rdy = '1') then + if MCycle = "000" then + if LDA = '1' then + ABC(7 downto 0) <= ALU_Q; + end if; + if LDX = '1' then + X(7 downto 0) <= ALU_Q; + end if; + if LDY = '1' then + Y(7 downto 0) <= ALU_Q; + end if; + if (LDA or LDX or LDY) = '1' then + P <= P_Out; + end if; + end if; + if SaveP = '1' then + P <= P_Out; + end if; + if LDP = '1' then + P <= ALU_Q; + end if; + if IR(4 downto 0) = "11000" then + case IR(7 downto 5) is + when "000" => + P(Flag_C) <= '0'; + when "001" => + P(Flag_C) <= '1'; + when "010" => + P(Flag_I) <= '0'; + when "011" => + P(Flag_I) <= '1'; + when "101" => + P(Flag_V) <= '0'; + when "110" => + P(Flag_D) <= '0'; + when "111" => + P(Flag_D) <= '1'; + when others => + end case; + end if; + if IR = "00000000" and MCycle = "011" and RstCycle = '0' and NMICycle = '0' and IRQCycle = '0' then + P(Flag_B) <= '1'; + end if; + if IR = "00000000" and MCycle = "100" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then + P(Flag_I) <= '1'; + P(Flag_B) <= B_o; + end if; + if SO_n_o = '1' and SO_n = '0' then + P(Flag_V) <= '1'; + end if; + if RstCycle = '1' and Mode_r /= "00" then + P(Flag_1) <= '1'; + P(Flag_D) <= '0'; + P(Flag_I) <= '1'; + end if; + P(Flag_1) <= '1'; + + B_o <= P(Flag_B); + SO_n_o <= SO_n; + IRQ_n_o <= IRQ_n; + NMI_n_o <= NMI_n; + end if; + end if; + end if; + end process; + +--------------------------------------------------------------------------- +-- +-- Buses +-- +--------------------------------------------------------------------------- + + process (Res_n, Clk) + begin + if Res_n = '0' then + BusA_r <= (others => '0'); + BusB <= (others => '0'); + AD <= (others => '0'); + BAL <= (others => '0'); + BAH <= (others => '0'); + DL <= (others => '0'); + elsif Clk'event and Clk = '1' then + if (Enable = '1') then + if (Rdy = '1') then + BusA_r <= BusA; + BusB <= DI; + + case BAAdd is + when "01" => + -- BA Inc + AD <= std_logic_vector(unsigned(AD) + 1); + BAL <= std_logic_vector(unsigned(BAL) + 1); + when "10" => + -- BA Add + BAL <= std_logic_vector(resize(unsigned(BAL(7 downto 0)),9) + resize(unsigned(BusA),9)); + when "11" => + -- BA Adj + if BAL(8) = '1' then + BAH <= std_logic_vector(unsigned(BAH) + 1); + end if; + when others => + end case; + + -- ehenciak : modified to use Y register as well (bugfix) + if ADAdd = '1' then + if (AddY = '1') then + AD <= std_logic_vector(unsigned(AD) + unsigned(Y(7 downto 0))); + else + AD <= std_logic_vector(unsigned(AD) + unsigned(X(7 downto 0))); + end if; + end if; + + if IR = "00000000" then + BAL <= (others => '1'); + BAH <= (others => '1'); + if RstCycle = '1' then + BAL(2 downto 0) <= "100"; + elsif NMICycle = '1' then + BAL(2 downto 0) <= "010"; + else + BAL(2 downto 0) <= "110"; + end if; + if Set_addr_To_r = "11" then + BAL(0) <= '1'; + end if; + end if; + + + if LDDI = '1' then + DL <= DI; + end if; + if LDALU = '1' then + DL <= ALU_Q; + end if; + if LDAD = '1' then + AD <= DI; + end if; + if LDBAL = '1' then + BAL(7 downto 0) <= DI; + end if; + if LDBAH = '1' then + BAH <= DI; + end if; + end if; + end if; + end if; + end process; + + Break <= (BreakAtNA and not BAL(8)) or (PCAdd and not PCAdder(8)); + + + with Set_BusA_To select + BusA <= DI when "000", + ABC(7 downto 0) when "001", + X(7 downto 0) when "010", + Y(7 downto 0) when "011", + std_logic_vector(S(7 downto 0)) when "100", + P when "101", + (others => '-') when others; + + with Set_Addr_To_r select + A <= "0000000000000001" & std_logic_vector(S(7 downto 0)) when "01", + DBR & "00000000" & AD when "10", + "00000000" & BAH & BAL(7 downto 0) when "11", + PBR & std_logic_vector(PC(15 downto 8)) & std_logic_vector(PCAdder(7 downto 0)) when others; + + with Write_Data_r select + DO <= DL when "000", + ABC(7 downto 0) when "001", + X(7 downto 0) when "010", + Y(7 downto 0) when "011", + std_logic_vector(S(7 downto 0)) when "100", + P when "101", + std_logic_vector(PC(7 downto 0)) when "110", + std_logic_vector(PC(15 downto 8)) when others; + +------------------------------------------------------------------------- +-- +-- Main state machine +-- +------------------------------------------------------------------------- + + process (Res_n, Clk) + begin + if Res_n = '0' then + MCycle <= "001"; + RstCycle <= '1'; + IRQCycle <= '0'; + NMICycle <= '0'; + NMIAct <= '0'; + elsif Clk'event and Clk = '1' then + if (Enable = '1') then + if (really_rdy = '1') then + if MCycle = LCycle or Break = '1' then + MCycle <= "000"; + RstCycle <= '0'; + IRQCycle <= '0'; + NMICycle <= '0'; + if NMIAct = '1' then + NMICycle <= '1'; + elsif IRQ_n_o = '0' and P(Flag_I) = '0' then + IRQCycle <= '1'; + end if; + else + MCycle <= std_logic_vector(unsigned(MCycle) + 1); + end if; + + if NMICycle = '1' then + NMIAct <= '0'; + end if; + if NMI_n_o = '1' and NMI_n = '0' then + NMIAct <= '1'; + end if; + end if; + end if; + end if; + end process; + +end; diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/T65_ALU.vhd b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/T65_ALU.vhd new file mode 100644 index 00000000..b1f6d632 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/T65_ALU.vhd @@ -0,0 +1,260 @@ +-- **** +-- T65(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 300 Bugfixes by ehenciak added +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- 6502 compatible microprocessor core +-- +-- Version : 0245 +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t65/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0245 : First version +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T65_Pack.all; + +entity T65_ALU is + port( + Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 + Op : in std_logic_vector(3 downto 0); + BusA : in std_logic_vector(7 downto 0); + BusB : in std_logic_vector(7 downto 0); + P_In : in std_logic_vector(7 downto 0); + P_Out : out std_logic_vector(7 downto 0); + Q : out std_logic_vector(7 downto 0) + ); +end T65_ALU; + +architecture rtl of T65_ALU is + + -- AddSub variables (temporary signals) + signal ADC_Z : std_logic; + signal ADC_C : std_logic; + signal ADC_V : std_logic; + signal ADC_N : std_logic; + signal ADC_Q : std_logic_vector(7 downto 0); + signal SBC_Z : std_logic; + signal SBC_C : std_logic; + signal SBC_V : std_logic; + signal SBC_N : std_logic; + signal SBC_Q : std_logic_vector(7 downto 0); + +begin + + process (P_In, BusA, BusB) + variable AL : unsigned(6 downto 0); + variable AH : unsigned(6 downto 0); + variable C : std_logic; + begin + AL := resize(unsigned(BusA(3 downto 0) & P_In(Flag_C)), 7) + resize(unsigned(BusB(3 downto 0) & "1"), 7); + AH := resize(unsigned(BusA(7 downto 4) & AL(5)), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7); + +-- pragma translate_off + if is_x(std_logic_vector(AL)) then AL := "0000000"; end if; + if is_x(std_logic_vector(AH)) then AH := "0000000"; end if; +-- pragma translate_on + + if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then + ADC_Z <= '1'; + else + ADC_Z <= '0'; + end if; + + if AL(5 downto 1) > 9 and P_In(Flag_D) = '1' then + AL(6 downto 1) := AL(6 downto 1) + 6; + end if; + + C := AL(6) or AL(5); + AH := resize(unsigned(BusA(7 downto 4) & C), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7); + + ADC_N <= AH(4); + ADC_V <= (AH(4) xor BusA(7)) and not (BusA(7) xor BusB(7)); + +-- pragma translate_off + if is_x(std_logic_vector(AH)) then AH := "0000000"; end if; +-- pragma translate_on + + if AH(5 downto 1) > 9 and P_In(Flag_D) = '1' then + AH(6 downto 1) := AH(6 downto 1) + 6; + end if; + + ADC_C <= AH(6) or AH(5); + + ADC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1)); + end process; + + process (Op, P_In, BusA, BusB) + variable AL : unsigned(6 downto 0); + variable AH : unsigned(5 downto 0); + variable C : std_logic; + begin + C := P_In(Flag_C) or not Op(0); + AL := resize(unsigned(BusA(3 downto 0) & C), 7) - resize(unsigned(BusB(3 downto 0) & "1"), 6); + AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(5)), 6); + +-- pragma translate_off + if is_x(std_logic_vector(AL)) then AL := "0000000"; end if; + if is_x(std_logic_vector(AH)) then AH := "000000"; end if; +-- pragma translate_on + + if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then + SBC_Z <= '1'; + else + SBC_Z <= '0'; + end if; + + SBC_C <= not AH(5); + SBC_V <= (AH(4) xor BusA(7)) and (BusA(7) xor BusB(7)); + SBC_N <= AH(4); + + if P_In(Flag_D) = '1' then + if AL(5) = '1' then + AL(5 downto 1) := AL(5 downto 1) - 6; + end if; + AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(6)), 6); + if AH(5) = '1' then + AH(5 downto 1) := AH(5 downto 1) - 6; + end if; + end if; + + SBC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1)); + end process; + + process (Op, P_In, BusA, BusB, + ADC_Z, ADC_C, ADC_V, ADC_N, ADC_Q, + SBC_Z, SBC_C, SBC_V, SBC_N, SBC_Q) + variable Q_t : std_logic_vector(7 downto 0); + begin + -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC + -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC + P_Out <= P_In; + Q_t := BusA; + case Op(3 downto 0) is + when "0000" => + -- ORA + Q_t := BusA or BusB; + when "0001" => + -- AND + Q_t := BusA and BusB; + when "0010" => + -- EOR + Q_t := BusA xor BusB; + when "0011" => + -- ADC + P_Out(Flag_V) <= ADC_V; + P_Out(Flag_C) <= ADC_C; + Q_t := ADC_Q; + when "0101" | "1101" => + -- LDA + when "0110" => + -- CMP + P_Out(Flag_C) <= SBC_C; + when "0111" => + -- SBC + P_Out(Flag_V) <= SBC_V; + P_Out(Flag_C) <= SBC_C; + Q_t := SBC_Q; + when "1000" => + -- ASL + Q_t := BusA(6 downto 0) & "0"; + P_Out(Flag_C) <= BusA(7); + when "1001" => + -- ROL + Q_t := BusA(6 downto 0) & P_In(Flag_C); + P_Out(Flag_C) <= BusA(7); + when "1010" => + -- LSR + Q_t := "0" & BusA(7 downto 1); + P_Out(Flag_C) <= BusA(0); + when "1011" => + -- ROR + Q_t := P_In(Flag_C) & BusA(7 downto 1); + P_Out(Flag_C) <= BusA(0); + when "1100" => + -- BIT + P_Out(Flag_V) <= BusB(6); + when "1110" => + -- DEC + Q_t := std_logic_vector(unsigned(BusA) - 1); + when "1111" => + -- INC + Q_t := std_logic_vector(unsigned(BusA) + 1); + when others => + end case; + + case Op(3 downto 0) is + when "0011" => + P_Out(Flag_N) <= ADC_N; + P_Out(Flag_Z) <= ADC_Z; + when "0110" | "0111" => + P_Out(Flag_N) <= SBC_N; + P_Out(Flag_Z) <= SBC_Z; + when "0100" => + when "1100" => + P_Out(Flag_N) <= BusB(7); + if (BusA and BusB) = "00000000" then + P_Out(Flag_Z) <= '1'; + else + P_Out(Flag_Z) <= '0'; + end if; + when others => + P_Out(Flag_N) <= Q_t(7); + if Q_t = "00000000" then + P_Out(Flag_Z) <= '1'; + else + P_Out(Flag_Z) <= '0'; + end if; + end case; + + Q <= Q_t; + end process; + +end; diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/T65_MCode.vhd b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/T65_MCode.vhd new file mode 100644 index 00000000..06229751 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/T65_MCode.vhd @@ -0,0 +1,1050 @@ +-- **** +-- T65(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 301 Jump timing fixed +-- Ver 300 Bugfixes by ehenciak added +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- 65xx compatible microprocessor core +-- +-- Version : 0246 + fix +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t65/ +-- +-- Limitations : +-- +-- 65C02 +-- supported : inc, dec, phx, plx, phy, ply +-- missing : bra, ora, lda, cmp, sbc, tsb*2, trb*2, stz*2, bit*2, wai, stp, jmp, bbr*8, bbs*8 +-- +-- File history : +-- +-- 0246 : First release +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T65_Pack.all; + +entity T65_MCode is + port( + Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 + IR : in std_logic_vector(7 downto 0); + MCycle : in std_logic_vector(2 downto 0); + P : in std_logic_vector(7 downto 0); + LCycle : out std_logic_vector(2 downto 0); + ALU_Op : out std_logic_vector(3 downto 0); + Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P + Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA + Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH + Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel + BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj + BreakAtNA : out std_logic; + ADAdd : out std_logic; + AddY : out std_logic; + PCAdd : out std_logic; + Inc_S : out std_logic; + Dec_S : out std_logic; + LDA : out std_logic; + LDP : out std_logic; + LDX : out std_logic; + LDY : out std_logic; + LDS : out std_logic; + LDDI : out std_logic; + LDALU : out std_logic; + LDAD : out std_logic; + LDBAL : out std_logic; + LDBAH : out std_logic; + SaveP : out std_logic; + Write : out std_logic + ); +end T65_MCode; + +architecture rtl of T65_MCode is + + signal Branch : std_logic; + +begin + + with IR(7 downto 5) select + Branch <= not P(Flag_N) when "000", + P(Flag_N) when "001", + not P(Flag_V) when "010", + P(Flag_V) when "011", + not P(Flag_C) when "100", + P(Flag_C) when "101", + not P(Flag_Z) when "110", + P(Flag_Z) when others; + + process (IR, MCycle, P, Branch, Mode) + begin + LCycle <= "001"; + Set_BusA_To <= "001"; -- A + Set_Addr_To <= (others => '0'); + Write_Data <= (others => '0'); + Jump <= (others => '0'); + BAAdd <= "00"; + BreakAtNA <= '0'; + ADAdd <= '0'; + PCAdd <= '0'; + Inc_S <= '0'; + Dec_S <= '0'; + LDA <= '0'; + LDP <= '0'; + LDX <= '0'; + LDY <= '0'; + LDS <= '0'; + LDDI <= '0'; + LDALU <= '0'; + LDAD <= '0'; + LDBAL <= '0'; + LDBAH <= '0'; + SaveP <= '0'; + Write <= '0'; + AddY <= '0'; + + case IR(7 downto 5) is + when "100" => + --{{{ + case IR(1 downto 0) is + when "00" => + Set_BusA_To <= "011"; -- Y + Write_Data <= "011"; -- Y + when "10" => + Set_BusA_To <= "010"; -- X + Write_Data <= "010"; -- X + when others => + Write_Data <= "001"; -- A + end case; + --}}} + when "101" => + --{{{ + case IR(1 downto 0) is + when "00" => + if IR(4) /= '1' or IR(2) /= '0' then + LDY <= '1'; + end if; + when "10" => + LDX <= '1'; + when others => + LDA <= '1'; + end case; + Set_BusA_To <= "000"; -- DI + --}}} + when "110" => + --{{{ + case IR(1 downto 0) is + when "00" => + if IR(4) = '0' then + LDY <= '1'; + end if; + Set_BusA_To <= "011"; -- Y + when others => + Set_BusA_To <= "001"; -- A + end case; + --}}} + when "111" => + --{{{ + case IR(1 downto 0) is + when "00" => + if IR(4) = '0' then + LDX <= '1'; + end if; + Set_BusA_To <= "010"; -- X + when others => + Set_BusA_To <= "001"; -- A + end case; + --}}} + when others => + end case; + + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + Set_BusA_To <= "000"; -- DI + end if; + + case IR(4 downto 0) is + when "00000" | "01000" | "01010" | "11000" | "11010" => + --{{{ + -- Implied + case IR is + when "00000000" => + -- BRK + LCycle <= "110"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= "01"; -- S + Write_Data <= "111"; -- PCH + Write <= '1'; + when 2 => + Dec_S <= '1'; + Set_Addr_To <= "01"; -- S + Write_Data <= "110"; -- PCL + Write <= '1'; + when 3 => + Dec_S <= '1'; + Set_Addr_To <= "01"; -- S + Write_Data <= "101"; -- P + Write <= '1'; + when 4 => + Dec_S <= '1'; + Set_Addr_To <= "11"; -- BA + when 5 => + LDDI <= '1'; + Set_Addr_To <= "11"; -- BA + when 6 => + Jump <= "10"; -- DIDL + when others => + end case; + when "00100000" => + -- JSR + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDDI <= '1'; + Set_Addr_To <= "01"; -- S + when 2 => + Set_Addr_To <= "01"; -- S + Write_Data <= "111"; -- PCH + Write <= '1'; + when 3 => + Dec_S <= '1'; + Set_Addr_To <= "01"; -- S + Write_Data <= "110"; -- PCL + Write <= '1'; + when 4 => + Dec_S <= '1'; + when 5 => + Jump <= "10"; -- DIDL + when others => + end case; + when "01000000" => + -- RTI + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= "01"; -- S + when 2 => + Inc_S <= '1'; + Set_Addr_To <= "01"; -- S + when 3 => + Inc_S <= '1'; + Set_Addr_To <= "01"; -- S + Set_BusA_To <= "000"; -- DI + when 4 => + LDP <= '1'; + Inc_S <= '1'; + LDDI <= '1'; + Set_Addr_To <= "01"; -- S + when 5 => + Jump <= "10"; -- DIDL + when others => + end case; + when "01100000" => + -- RTS + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= "01"; -- S + when 2 => + Inc_S <= '1'; + Set_Addr_To <= "01"; -- S + when 3 => + Inc_S <= '1'; + LDDI <= '1'; + Set_Addr_To <= "01"; -- S + when 4 => + Jump <= "10"; -- DIDL + when 5 => + Jump <= "01"; + when others => + end case; + when "00001000" | "01001000" | "01011010" | "11011010" => + -- PHP, PHA, PHY*, PHX* + LCycle <= "010"; + if Mode = "00" and IR(1) = '1' then + LCycle <= "001"; + end if; + case to_integer(unsigned(MCycle)) is + when 1 => + case IR(7 downto 4) is + when "0000" => + Write_Data <= "101"; -- P + when "0100" => + Write_Data <= "001"; -- A + when "0101" => + Write_Data <= "011"; -- Y + when "1101" => + Write_Data <= "010"; -- X + when others => + end case; + Write <= '1'; + Set_Addr_To <= "01"; -- S + when 2 => + Dec_S <= '1'; + when others => + end case; + when "00101000" | "01101000" | "01111010" | "11111010" => + -- PLP, PLA, PLY*, PLX* + LCycle <= "011"; + if Mode = "00" and IR(1) = '1' then + LCycle <= "001"; + end if; + case IR(7 downto 4) is + when "0010" => + LDP <= '1'; + when "0110" => + LDA <= '1'; + when "0111" => + if Mode /= "00" then + LDY <= '1'; + end if; + when "1111" => + if Mode /= "00" then + LDX <= '1'; + end if; + when others => + end case; + case to_integer(unsigned(MCycle)) is + when 0 => + SaveP <= '1'; + when 1 => + Set_Addr_To <= "01"; -- S + when 2 => + Inc_S <= '1'; + Set_Addr_To <= "01"; -- S + when 3 => + Set_BusA_To <= "000"; -- DI + when others => + end case; + when "10100000" | "11000000" | "11100000" => + -- LDY, CPY, CPX + -- Immediate + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + when others => + end case; + when "10001000" => + -- DEY + LDY <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "011"; -- Y + when others => + end case; + when "11001010" => + -- DEX + LDX <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "010"; -- X + when others => + end case; + when "00011010" | "00111010" => + -- INC*, DEC* + if Mode /= "00" then + LDA <= '1'; -- A + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "100"; -- S + when others => + end case; + when "00001010" | "00101010" | "01001010" | "01101010" => + -- ASL, ROL, LSR, ROR + LDA <= '1'; -- A + Set_BusA_To <= "001"; -- A + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + when others => + end case; + when "10001010" | "10011000" => + -- TYA, TXA + LDA <= '1'; -- A + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + when others => + end case; + when "10101010" | "10101000" => + -- TAX, TAY + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "001"; -- A + when others => + end case; + when "10011010" => + -- TXS + case to_integer(unsigned(MCycle)) is + when 0 => + LDS <= '1'; + when 1 => + when others => + end case; + when "10111010" => + -- TSX + LDX <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "100"; -- S + when others => + end case; + + -- when "00011000" | "00111000" | "01011000" | "01111000" | "10111000" | "11011000" | "11111000" | "11001000" | "11101000" => + -- -- CLC, SEC, CLI, SEI, CLV, CLD, SED, INY, INX + -- case to_integer(unsigned(MCycle)) is + -- when 1 => + -- when others => + -- end case; + when others => + case to_integer(unsigned(MCycle)) is + when 0 => + when others => + end case; + end case; + --}}} + + when "00001" | "00011" => + --{{{ + -- Zero Page Indexed Indirect (d,x) + LCycle <= "101"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + ADAdd <= '1'; + Set_Addr_To <= "10"; -- AD + when 3 => + BAAdd <= "01"; -- DB Inc + LDBAL <= '1'; + Set_Addr_To <= "10"; -- AD + when 4 => + LDBAH <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 5 => + when others => + end case; + --}}} + + when "01001" | "01011" => + --{{{ + -- Immediate + LDA <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + when others => + end case; + + --}}} + + when "00010" | "10010" => + --{{{ + -- Immediate, KIL + LDX <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + if IR = "10100010" then + -- LDX + Jump <= "01"; + else + -- KIL !!!!!!!!!!!!!!!!!!!!!!!!!!!!! + end if; + when others => + end case; + --}}} + + when "00100" => + --{{{ + -- Zero Page + LCycle <= "010"; + case to_integer(unsigned(MCycle)) is + when 0 => + if IR(7 downto 5) = "001" then + SaveP <= '1'; + end if; + when 1 => + Jump <= "01"; + LDAD <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "10"; -- AD + when 2 => + when others => + end case; + --}}} + + when "00101" | "00110" | "00111" => + --{{{ + -- Zero Page + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + -- Read-Modify-Write + LCycle <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + LDDI <= '1'; + Write <= '1'; + Set_Addr_To <= "10"; -- AD + when 3 => + LDALU <= '1'; + SaveP <= '1'; + Write <= '1'; + Set_Addr_To <= "10"; -- AD + when 4 => + when others => + end case; + else + LCycle <= "010"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDAD <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "10"; -- AD + when 2 => + when others => + end case; + end if; + --}}} + + when "01100" => + --{{{ + -- Absolute + if IR(7 downto 6) = "01" and IR(4 downto 0) = "01100" then + -- JMP + if IR(5) = '0' then + --LCycle <= "011"; + LCycle <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDDI <= '1'; + when 2 => + Jump <= "10"; -- DIDL + when others => + end case; + else + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Jump <= "01"; + LDDI <= '1'; + LDBAL <= '1'; + when 3 => + LDBAH <= '1'; + if Mode /= "00" then + Jump <= "10"; -- DIDL + end if; + if Mode = "00" then + Set_Addr_To <= "11"; -- BA + end if; + when 4 => + LDDI <= '1'; + if Mode = "00" then + Set_Addr_To <= "11"; -- BA + BAAdd <= "01"; -- DB Inc + else + Jump <= "01"; + end if; + when 5 => + Jump <= "10"; -- DIDL + when others => + end case; + end if; + else + LCycle <= "011"; + case to_integer(unsigned(MCycle)) is + when 0 => + if IR(7 downto 5) = "001" then + SaveP <= '1'; + end if; + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + LDBAH <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 3 => + when others => + end case; + end if; + --}}} + + when "01101" | "01110" | "01111" => + --{{{ + -- Absolute + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + -- Read-Modify-Write + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 3 => + LDDI <= '1'; + Write <= '1'; + Set_Addr_To <= "11"; -- BA + when 4 => + Write <= '1'; + LDALU <= '1'; + SaveP <= '1'; + Set_Addr_To <= "11"; -- BA + when 5 => + SaveP <= '0'; -- MIKEJ was 1 + when others => + end case; + else + LCycle <= "011"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + LDBAH <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 3 => + when others => + end case; + end if; + --}}} + + when "10000" => + --{{{ + -- Relative + + -- This circuit dictates when the last + -- microcycle occurs for the branch depending on + -- whether or not the branch is taken and if a page + -- is crossed... + if (Branch = '1') then + + LCycle <= "011"; -- We're done @ T3 if branching...upper + -- level logic will stop at T2 if no page cross + -- (See the Break signal) + else + + LCycle <= "001"; + + end if; + + -- This decodes the current microcycle and takes the + -- proper course of action... + case to_integer(unsigned(MCycle)) is + + -- On the T1 microcycle, increment the program counter + -- and instruct the upper level logic to fetch the offset + -- from the Din bus and store it in the data latches. This + -- will be the last microcycle if the branch isn't taken. + when 1 => + + Jump <= "01"; -- Increments the PC by one (PC will now be PC+2) + -- from microcycle T0. + + LDDI <= '1'; -- Tells logic in top level (T65.vhd) to route + -- the Din bus to the memory data latch (DL) + -- so that the branch offset is fetched. + + -- In microcycle T2, tell the logic in the top level to + -- add the offset. If the most significant byte of the + -- program counter (i.e. the current "page") does not need + -- updating, we are done here...the Break signal at the + -- T65.vhd level takes care of that... + when 2 => + + Jump <= "11"; -- Tell the PC Jump logic to use relative mode. + + PCAdd <= '1'; -- This tells the PC adder to update itself with + -- the current offset recently fetched from + -- memory. + + -- The following is microcycle T3 : + -- The program counter should be completely updated + -- on this cycle after the page cross is detected. + -- We don't need to do anything here... + when 3 => + + + when others => null; -- Do nothing. + + end case; + --}}} + + when "10001" | "10011" => + --{{{ + -- Zero Page Indirect Indexed (d),y + LCycle <= "101"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + LDBAL <= '1'; + BAAdd <= "01"; -- DB Inc + Set_Addr_To <= "10"; -- AD + when 3 => + Set_BusA_To <= "011"; -- Y + BAAdd <= "10"; -- BA Add + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 4 => + BAAdd <= "11"; -- BA Adj + if IR(7 downto 5) = "100" then + Write <= '1'; + else + BreakAtNA <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 5 => + when others => + end case; + --}}} + + when "10100" | "10101" | "10110" | "10111" => + --{{{ + -- Zero Page, X + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + -- Read-Modify-Write + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + ADAdd <= '1'; + Set_Addr_To <= "10"; -- AD + when 3 => + LDDI <= '1'; + Write <= '1'; + Set_Addr_To <= "10"; -- AD + when 4 => + LDALU <= '1'; + SaveP <= '1'; + Write <= '1'; + Set_Addr_To <= "10"; -- AD + when 5 => + when others => + end case; + else + LCycle <= "011"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + ADAdd <= '1'; + -- Added this check for Y reg. use... + if (IR(3 downto 0) = "0110") then + AddY <= '1'; + end if; + + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "10"; -- AD + when 3 => null; + when others => + end case; + end if; + --}}} + + when "11001" | "11011" => + --{{{ + -- Absolute Y + LCycle <= "100"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + Set_BusA_To <= "011"; -- Y + BAAdd <= "10"; -- BA Add + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 3 => + BAAdd <= "11"; -- BA adj + if IR(7 downto 5) = "100" then + Write <= '1'; + else + BreakAtNA <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 4 => + when others => + end case; + --}}} + + when "11100" | "11101" | "11110" | "11111" => + --{{{ + -- Absolute X + + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + -- Read-Modify-Write + LCycle <= "110"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + Set_BusA_To <= "010"; -- X + BAAdd <= "10"; -- BA Add + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 3 => + BAAdd <= "11"; -- BA adj + Set_Addr_To <= "11"; -- BA + when 4 => + LDDI <= '1'; + Write <= '1'; + Set_Addr_To <= "11"; -- BA + when 5 => + LDALU <= '1'; + SaveP <= '1'; + Write <= '1'; + Set_Addr_To <= "11"; -- BA + when 6 => + when others => + end case; + else + LCycle <= "100"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + -- mikej + -- special case 0xBE which uses Y reg as index!! + if (IR = "10111110") then + Set_BusA_To <= "011"; -- Y + else + Set_BusA_To <= "010"; -- X + end if; + BAAdd <= "10"; -- BA Add + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 3 => + BAAdd <= "11"; -- BA adj + if IR(7 downto 5) = "100" then + Write <= '1'; + else + BreakAtNA <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 4 => + when others => + end case; + end if; + --}}} + when others => + end case; + end process; + + process (IR, MCycle) + begin + -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC + -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC + case IR(1 downto 0) is + when "00" => + --{{{ + case IR(4 downto 2) is + when "000" | "001" | "011" => + case IR(7 downto 5) is + when "110" | "111" => + -- CP + ALU_Op <= "0110"; + when "101" => + -- LD + ALU_Op <= "0101"; + when "001" => + -- BIT + ALU_Op <= "1100"; + when others => + -- NOP/ST + ALU_Op <= "0100"; + end case; + when "010" => + case IR(7 downto 5) is + when "111" | "110" => + -- IN + ALU_Op <= "1111"; + when "100" => + -- DEY + ALU_Op <= "1110"; + when others => + -- LD + ALU_Op <= "1101"; + end case; + when "110" => + case IR(7 downto 5) is + when "100" => + -- TYA + ALU_Op <= "1101"; + when others => + ALU_Op <= "----"; + end case; + when others => + case IR(7 downto 5) is + when "101" => + -- LD + ALU_Op <= "1101"; + when others => + ALU_Op <= "0100"; + end case; + end case; + --}}} + when "01" => -- OR + --{{{ + ALU_Op(3) <= '0'; + ALU_Op(2 downto 0) <= IR(7 downto 5); + --}}} + when "10" => + --{{{ + ALU_Op(3) <= '1'; + ALU_Op(2 downto 0) <= IR(7 downto 5); + case IR(7 downto 5) is + when "000" => + if IR(4 downto 2) = "110" then + -- INC + ALU_Op <= "1111"; + end if; + when "001" => + if IR(4 downto 2) = "110" then + -- DEC + ALU_Op <= "1110"; + end if; + when "100" => + if IR(4 downto 2) = "010" then + -- TXA + ALU_Op <= "0101"; + else + ALU_Op <= "0100"; + end if; + when others => + end case; + --}}} + when others => + --{{{ + case IR(7 downto 5) is + when "100" => + ALU_Op <= "0100"; + when others => + if MCycle = "000" then + ALU_Op(3) <= '0'; + ALU_Op(2 downto 0) <= IR(7 downto 5); + else + ALU_Op(3) <= '1'; + ALU_Op(2 downto 0) <= IR(7 downto 5); + end if; + end case; + --}}} + end case; + end process; + +end; diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/T65_Pack.vhd b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/T65_Pack.vhd new file mode 100644 index 00000000..e025e1bf --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/T65_Pack.vhd @@ -0,0 +1,117 @@ +-- **** +-- T65(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 300 Bugfixes by ehenciak added +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- 65xx compatible microprocessor core +-- +-- Version : 0246 +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t65/ +-- +-- Limitations : +-- +-- File history : +-- + +library IEEE; +use IEEE.std_logic_1164.all; + +package T65_Pack is + + constant Flag_C : integer := 0; + constant Flag_Z : integer := 1; + constant Flag_I : integer := 2; + constant Flag_D : integer := 3; + constant Flag_B : integer := 4; + constant Flag_1 : integer := 5; + constant Flag_V : integer := 6; + constant Flag_N : integer := 7; + + component T65_MCode + port( + Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 + IR : in std_logic_vector(7 downto 0); + MCycle : in std_logic_vector(2 downto 0); + P : in std_logic_vector(7 downto 0); + LCycle : out std_logic_vector(2 downto 0); + ALU_Op : out std_logic_vector(3 downto 0); + Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P + Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA + Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH + Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel + BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj + BreakAtNA : out std_logic; + ADAdd : out std_logic; + AddY : out std_logic; + PCAdd : out std_logic; + Inc_S : out std_logic; + Dec_S : out std_logic; + LDA : out std_logic; + LDP : out std_logic; + LDX : out std_logic; + LDY : out std_logic; + LDS : out std_logic; + LDDI : out std_logic; + LDALU : out std_logic; + LDAD : out std_logic; + LDBAL : out std_logic; + LDBAH : out std_logic; + SaveP : out std_logic; + Write : out std_logic + ); + end component; + + component T65_ALU + port( + Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816 + Op : in std_logic_vector(3 downto 0); + BusA : in std_logic_vector(7 downto 0); + BusB : in std_logic_vector(7 downto 0); + P_In : in std_logic_vector(7 downto 0); + P_Out : out std_logic_vector(7 downto 0); + Q : out std_logic_vector(7 downto 0) + ); + end component; + +end; diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/addec_prom.qip b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/addec_prom.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/greybox_tmp/cbx_args.txt b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/greybox_tmp/cbx_args.txt new file mode 100644 index 00000000..deea9283 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/greybox_tmp/cbx_args.txt @@ -0,0 +1,16 @@ +ADDRESS_ACLR_A=NONE +CLOCK_ENABLE_INPUT_A=BYPASS +CLOCK_ENABLE_OUTPUT_A=BYPASS +INIT_FILE=../roms/6400-01m2.hex +INTENDED_DEVICE_FAMILY="Cyclone III" +NUMWORDS_A=256 +OPERATION_MODE=ROM +OUTDATA_ACLR_A=NONE +OUTDATA_REG_A=UNREGISTERED +WIDTHAD_A=8 +WIDTH_A=4 +WIDTH_BYTEENA_A=1 +DEVICE_FAMILY="Cyclone III" +address_a +clock0 +q_a diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/j6_prom.qip b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/j6_prom.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/k6_prom.qip b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/k6_prom.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/prog_rom1.qip b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/prog_rom1.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/prog_rom2.qip b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/prog_rom2.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/prog_rom3.qip b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/prog_rom3.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/prog_rom4.qip b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/prog_rom4.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/ram1k_dp.qip b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/ram1k_dp.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/sync_prom.qip b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/T65/sync_prom.qip new file mode 100644 index 00000000..e69de29b diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/audio.vhd b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/audio.vhd new file mode 100644 index 00000000..635efa1f --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/audio.vhd @@ -0,0 +1,69 @@ +-- Audio for Super Breakout +-- This is a very simple circuit, tones are created by gating signals from the vertical scan counter +-- Original hardware used resistors to mix the tones, here we are mixing them digitally and using a delta-sigma +-- DAC to produce audio on a single pin +-- (c) 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity audio is +port( + Reset_n : in std_logic; + Tones_n : in std_logic; + Display : in std_logic_vector(3 downto 0); + VCount : in std_logic_vector(7 downto 0); + Audio_PWM : out std_logic_vector(7 downto 0)); +end audio; + +architecture rtl of audio is + +signal reset : std_logic; +signal V32 : std_logic; +signal V16 : std_logic; +signal V8 : std_logic; +signal V4 : std_logic; +signal tone_V4 : std_logic; +signal tone_V8 : std_logic; +signal tone_V16 : std_logic; +signal tone_V32 : std_logic; +signal tone_reg : std_logic_vector(3 downto 0); + +begin + +reset <= (not reset_n); + +V32 <= Vcount(5); +V16 <= Vcount(4); +V8 <= Vcount(3); +V4 <= Vcount(2); + +C4: process(tones_n, V4, V8, V16, V32, display) is +begin + if tones_n <= '0' then + tone_reg <= display; + end if; +end process; + +tone_V4 <= tone_reg(0) and V4; +tone_V8 <= tone_reg(1) and V8; +tone_V16 <= tone_reg(2) and V16; +tone_V32 <= tone_reg(3) and V32; + +Audio_PWM <= tone_V4 & '0' & tone_V8 & '0' & tone_V16 & '0' & tone_V32 & '0'; + + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/build_id.sv b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/build_id.sv new file mode 100644 index 00000000..1d53a3f2 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/build_id.sv @@ -0,0 +1,2 @@ +`define BUILD_DATE "171221" +`define BUILD_TIME "172231" diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/build_id.tcl b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/build_id.tcl new file mode 100644 index 00000000..be673dac --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/build_id.tcl @@ -0,0 +1,35 @@ +# ================================================================================ +# +# Build ID Verilog Module Script +# Jeff Wiencrot - 8/1/2011 +# +# Generates a Verilog module that contains a timestamp, +# from the current build. These values are available from the build_date, build_time, +# physical_address, and host_name output ports of the build_id module in the build_id.v +# Verilog source file. +# +# ================================================================================ + +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate [ clock format [ clock seconds ] -format %y%m%d ] + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + + # Create a Verilog file for output + set outputFileName "rtl/build_id.sv" + set outputFile [open $outputFileName "w"] + + # Output the Verilog source + puts $outputFile "`define BUILD_DATE \"$buildDate\"" + puts $outputFile "`define BUILD_TIME \"$buildTime\"" + close $outputFile + + # Send confirmation message to the Messages window + post_message "Generated build identification Verilog module: [pwd]/$outputFileName" + post_message "Date: $buildDate" + post_message "Time: $buildTime" +} + +# Comment out this line to prevent the process from automatically executing when the file is sourced: +generateBuildID_Verilog \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/cpu_mem.vhd b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/cpu_mem.vhd new file mode 100644 index 00000000..189a884a --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/cpu_mem.vhd @@ -0,0 +1,435 @@ +-- CPU, RAM, ROM and address decoder for Atari Super Breakout +-- 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity CPU_mem is +port( + Clk12 : in std_logic; + Clk6 : in std_logic; + Reset_n : in std_logic; + NMI_n : in std_logic; + VCount : in std_logic_vector(7 downto 0); + HCount : in std_logic_vector(8 downto 0); + Hsync_n : in std_logic; + Timer_Reset_n : in std_logic; + IntAck_n : in std_logic; + IO_wr : out std_logic; + PHI2_O : out std_logic; + Display : out std_logic_vector(7 downto 0); + IO_Adr : out std_logic_vector(9 downto 0); + Inputs : in std_logic_vector(1 downto 0) + ); +end CPU_mem; + +architecture rtl of CPU_mem is + +signal cpu_clk : std_logic; +signal PHI1 : std_logic; +signal PHI2 : std_logic; +signal Q5 : std_logic; +signal Q6 : std_logic; +signal A7_2 : std_logic; +signal A7_5 : std_logic; +signal A7_7 : std_logic; + +signal A8_6 : std_logic; + +signal H256 : std_logic; +signal H256_n : std_logic; +signal H128 : std_logic; +signal H64 : std_logic; +signal H32 : std_logic; +signal H16 : std_logic; +signal H8 : std_logic; +signal H4 : std_logic; + +signal V128 : std_logic; +signal V64 : std_logic; +signal V32 : std_logic; +signal V16 : std_logic; +signal V8 : std_logic; + +signal CPU_Reset_n : std_logic; +signal IRQ_n : std_logic; +signal RW_n : std_logic; +signal RnW : std_logic; +signal A : std_logic_vector(15 downto 0); +signal Adr : std_logic_vector(9 downto 0); +signal cpuDin : std_logic_vector(7 downto 0); +signal cpuDout : std_logic_vector(7 downto 0); +signal DBUS_n : std_logic_vector(7 downto 0); +signal DBUS : std_logic_vector(7 downto 0); + +-- No ROM 0 or 1 on the EPROM based version +signal ROM2_dout : std_logic_vector(7 downto 0); +signal ROM3_dout : std_logic_vector(7 downto 0); +signal ROM4_dout : std_logic_vector(7 downto 0); +signal ROM_dout : std_logic_vector(7 downto 0); + +signal ROM2 : std_logic; +signal ROM3 : std_logic; +signal ROM4 : std_logic; +signal ROM_ce : std_logic; +signal ROM_mux_in : std_logic_vector(2 downto 0); + +signal cpuRAM_dout : std_logic_vector(7 downto 0); +signal Vram_dout : std_logic_vector(7 downto 0); +signal RAM_addr : std_logic_vector(9 downto 0) := (others => '0'); +signal Vram_addr : std_logic_vector(9 downto 0) := (others => '0'); +signal scanbus : std_logic_vector(9 downto 0) := (others => '0'); +signal RAM_dout : std_logic_vector(7 downto 0); +signal RAM_we : std_logic; +signal RAM_RW_n : std_logic; +signal RAM_ce_n : std_logic; +signal RAM_n : std_logic; +signal WRAM : std_logic; +signal WRITE_n : std_logic; + +signal F2_in : std_logic_vector(3 downto 0); +signal F2_out : std_logic_vector(9 downto 0); +signal D2_in : std_logic_vector(3 downto 0); +signal D2_out : std_logic_vector(9 downto 0); +signal E8_in : std_logic_vector(3 downto 0); +signal E8_out : std_logic_vector(9 downto 0); + +signal Sync1 : std_logic; +signal Sync1_n : std_logic; +signal Sync2_n : std_logic; +signal Switch_n : std_logic; +signal Display_n : std_logic; +signal Addec_bus : std_logic_vector(7 downto 0); + +signal J6_5 : std_logic; +signal J6_9 : std_logic; + +signal D7 : std_logic; + + +begin + +H8 <= HCount(3); +H16 <= HCount(4); +H32 <= HCount(5); +H64 <= HCount(6); +H128 <= HCount(7); +H256 <= HCount(8); +H256_n <= (not HCount(8)); + +V8 <= VCount(3); +V16 <= VCount(4); +V32 <= VCount(5); +V64 <= VCount(6); +V128 <= VCount(7); + + +CPU: entity work.T65 +port map( + Enable => '1', + Mode => "00", + Res_n => CPU_reset_n, + Clk => phi1, + Rdy => '1', + Abort_n => '1', + IRQ_n => IRQ_n, + NMI_n => NMI_n, + SO_n => '1', + R_W_n => RW_n, + A(15 downto 0) => A, + DI => cpuDin, + DO => cpuDout + ); + +DBUS_n <= (not cpuDout); -- Data bus to video RAM is inverted +Adr(9 downto 7) <= (A(9) or WRAM) & (A(8) or WRAM) & (A(7) or WRAM); +Adr(6 downto 0) <= A(6 downto 0); +IO_Adr <= Adr; +RnW <= (not RW_n); + + +-- CPU Din mux +cpuDin <= ROM_dout when rom_ce = '1' else + (not CPUram_dout) when DISPLAY_n = '0' else -- Remember RAM data is inverted + Vcount when Sync1_n = '0' else + Inputs & "111111" when SWITCH_n = '0' else + D7 & "1111111" when Sync2_n = '0' else + x"FF"; + + +-- Watchdog timer +-- need to implement for sake of completeness +CPU_reset_n <= Reset_n; -- Bypass it for now + + +-- CPU clock +H4 <= Hcount(2); +CPU_clock: process(clk12, H4, Q5, Q6) +begin + if rising_edge(clk12) then + Q5 <= H4; + Q6 <= Q5; + end if; + phi1 <= not (Q5 or Q6); --? +end process; + +PHI2 <= (not PHI1); +PHI2_O <= PHI2; + +-- IRQ, M9 +CPU_IRQ: process(V16, INTACK_n) +begin + if INTACK_n = '1' then -- asynchronous preset + if rising_edge(V16) then + IRQ_n <= '0'; + end if; + else + IRQ_n <= '1'; + end if; +end process; + + +A8_6 <= not(RnW and PHI2 and H4 and WRITE_n); +A7: process(clk12, A8_6) -- Shift register chain of 4 DFF's clocked by clk12, creates a delayed WRITE_n +begin + if rising_edge(clk12) then + A7_2 <= A8_6; + A7_5 <= A7_2; + A7_7 <= A7_5; + WRITE_n <= A7_7; + end if; +end process; + + +-- Program ROMs +-- Note that Super Breakout only uses three ROMs, there is no ROM 1 +C1: entity work.sprom +generic map( + init_file => "rtl/roms/033453_c1.hex", + widthad_a => 11, + width_a => 8) +port map( + clock => clk6, + address => A(10) & ADR(9 downto 0), + q => rom2_dout + ); + +--C1: entity work.prog_rom2 +--port map( +-- clock => clk6, +-- address => A(10) & ADR(9 downto 0), +-- q => rom2_dout +-- ); + + +D1: entity work.sprom +generic map( + init_file => "rtl/roms/033454_d1.hex", + widthad_a => 11, + width_a => 8) +port map( + clock => clk6, + address => A(10) & ADR(9 downto 0), + q => rom3_dout + ); + +--D1: entity work.prog_rom3 +--port map( +-- clock => clk6, +-- address => A(10) & ADR(9 downto 0), +-- q => rom3_dout +-- ); + + +E1: entity work.sprom +generic map( + init_file => "rtl/roms/033455_e1.hex", + widthad_a => 11, + width_a => 8) +port map( + clock => clk6, + address => A(10) & ADR(9 downto 0), + q => rom4_dout + ); + +--E1: entity work.prog_rom4 +--port map( +-- clock => clk6, +-- address => A(10) & ADR(9 downto 0), +-- q => rom4_dout +-- ); + + +-- ROM data mux +ROM_mux_in <= (ROM2 & ROM3 & ROM4); +ROM_mux: process(ROM_mux_in, rom2_dout, rom3_dout, rom4_dout) +begin + ROM_dout <= (others => '0'); + case ROM_mux_in is + when "100" => rom_dout <= rom2_dout; + when "010" => rom_dout <= rom3_dout; + when "001" => rom_dout <= rom4_dout; + when others => null; + end case; +end process; + +-- RAM +-- The original hardware multiplexes access to the RAM between the CPU and video hardware depending on the state of +-- the phi2 clock. In the FPGA it's easier to use dual-ported RAM which is less dependent on precise timing. +RAM: entity work.dpram +generic map( + widthad_a => 10, + width_a => 8) +port map( + clock_a => clk6, +-- CPU side + address_a => adr(9 downto 0), + wren_a => ram_we, + data_a => DBUS_n, + q_a=> CPUram_dout, + +-- Video side + clock_b => clk6, + address_b => Vram_addr, + wren_b => '0', + data_b => x"FF", + q_b => Vram_dout + ); + +--RAM: entity work.ram1k_dp +--port map( +-- clock => clk6, +-- CPU side +-- address_a => adr(9 downto 0), +-- wren_a => ram_we, +-- data_a => DBUS_n, +-- q_a=> CPUram_dout, + +-- Video side +-- address_b => Vram_addr, +-- wren_b => '0', +-- data_b => x"FF", +-- q_b => Vram_dout +-- ); + +-- Data selectors at K2, J2 and H2 are not needed due to the use of dual ported RAM. Here is some glue logic that +-- drives the video side RAM address +Vram_addr <= (V128 or H256_n) & (V64 or H256_n) & (V32 or H256_n) & (V16 and H256) & (V8 and H256) & H128 & H64 & H32 & H16 & H8; + +-- Real hardware has both WE and CE which are selected by K2 according to the state of the phase 2 clock +-- Altera block RAM has active high WE, original RAM had active low WE +ram_we <= (not Write_n) and (not Display_n) and Phi2; + +-- Rising edge of phi2 clock latches inverted output of VRAM data bus. This is not strictly necessary with the dual ported RAM +F5: process(phi2) +begin + if rising_edge(phi2) then + display <= not Vram_dout; + end if; +end process; + + +-- Address decoder +-- A15 and A14 are not used +-- E2 PROM - Original circuit uses a 32 byte bipolar PROM in the address decoder, this could easily be replaced with combinational logic +E2: entity work.sprom +generic map( + init_file => "rtl/roms/006401_e2.hex", + widthad_a => 5, + width_a => 8) +port map( + clock => clk12, + address => A(13 downto 9), + q => addec_bus + ); + +--E2: entity work.addec_prom +--port map( +-- clock => clk12, +-- address => A(13 downto 9), +-- q => addec_bus +-- ); + +WRAM <= addec_bus(4); + + +-- Address Decoder -unused decoder states are not explicitly implemented +F2_in <= addec_bus(0) & addec_bus(1) & addec_bus(2) & addec_bus(3); +F2: process(F2_in) +begin + case F2_in is + when "0010" => F2_out <= "1111111011"; + when "0011" => F2_out <= "1111110111"; + when "0100" => F2_out <= "1111101111"; + when "0101" => F2_out <= "1111011111"; + when "0110" => F2_out <= "1110111111"; + when "0111" => F2_out <= "1101111111"; + when others => F2_out <= "1111111111"; + end case; +end process; + +ROM2 <= (F2_out(2) nand F2_out(3)); +ROM3 <= (F2_out(4) nand F2_out(5)); +ROM4 <= (F2_out(6) nand F2_out(7)); +ROM_ce <= (ROM2 or ROM3 or ROM4); + + +D2_in <= RnW & addec_bus(5) & addec_bus(6) & addec_bus(7); +D2: process(clk6, D2_in) +begin + if rising_edge(clk6) then + case D2_in is + when "0000" => D2_out <= "1111111110"; + when "0001" => D2_out <= "1111111101"; + when "0010" => D2_out <= "1111111011"; + when "0011" => D2_out <= "1111110111"; + when "1000" => D2_out <= "1011111111"; + when "1001" => D2_out <= "0111111111"; + when others => D2_out <= "1111111111"; + end case; + end if; +end process; + +RAM_n <= D2_out(0); +SYNC1_n <= D2_out(1); +SYNC1 <= (not SYNC1_n); +SWITCH_n <= D2_out(2); +SYNC2_n <= D2_out(3); +DISPLAY_n <= (D2_out(0) and D2_out(8)); +IO_wr <= (D2_out(9) or WRITE_n); -- IO_wr comes from P3_8 + + + +J6: process(H128, Hsync_n, Sync1_n, Sync2_n, J6_9) +begin + if Hsync_n = '0' then -- asynchronous clear + J6_5 <= '0'; + elsif rising_edge(H128) then + J6_5 <= '1'; + end if; + + if rising_edge(Sync1_n) then + J6_9 <= J6_5; + end if; + if sync2_n = '0' then + D7 <= J6_9; + else + D7 <= '1'; + end if; +end process; + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/dac.sv b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/dac.sv new file mode 100644 index 00000000..441e2cf2 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/dac.sv @@ -0,0 +1,33 @@ +// +// PWM DAC +// +// MSBI is the highest bit number. NOT amount of bits! +// +module dac #(parameter MSBI=8, parameter INV=1'b1) +( + output reg DACout, //Average Output feeding analog lowpass + input [MSBI:0] DACin, //DAC input (excess 2**MSBI) + input CLK, + input RESET +); + +reg [MSBI+2:0] DeltaAdder; //Output of Delta Adder +reg [MSBI+2:0] SigmaAdder; //Output of Sigma Adder +reg [MSBI+2:0] SigmaLatch; //Latches output of Sigma Adder +reg [MSBI+2:0] DeltaB; //B input of Delta Adder + +always @(*) DeltaB = {SigmaLatch[MSBI+2], SigmaLatch[MSBI+2]} << (MSBI+1); +always @(*) DeltaAdder = DACin + DeltaB; +always @(*) SigmaAdder = DeltaAdder + SigmaLatch; + +always @(posedge CLK or posedge RESET) begin + if(RESET) begin + SigmaLatch <= 1'b1 << (MSBI+1); + DACout <= INV; + end else begin + SigmaLatch <= SigmaAdder; + DACout <= SigmaLatch[MSBI+2] ^ INV; + end +end + +endmodule diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/dpram.vhd b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/dpram.vhd new file mode 100644 index 00000000..9ea85a26 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/dpram.vhd @@ -0,0 +1,130 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY dpram IS + GENERIC + ( + init_file : string := ""; + widthad_a : natural; + width_a : natural := 8; + outdata_reg_a : string := "UNREGISTERED"; + outdata_reg_b : string := "UNREGISTERED" + ); + PORT + ( + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + clock_a : IN STD_LOGIC ; + clock_b : IN STD_LOGIC ; + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + wren_a : IN STD_LOGIC := '1'; + wren_b : IN STD_LOGIC := '1'; + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); +END dpram; + + +ARCHITECTURE SYN OF dpram IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + SIGNAL sub_wire1 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + address_reg_b : STRING; + clock_enable_input_a : STRING; + clock_enable_input_b : STRING; + clock_enable_output_a : STRING; + clock_enable_output_b : STRING; + indata_reg_b : STRING; + init_file : STRING; + intended_device_family : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + numwords_b : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_aclr_b : STRING; + outdata_reg_a : STRING; + outdata_reg_b : STRING; + power_up_uninitialized : STRING; + read_during_write_mode_port_a : STRING; + read_during_write_mode_port_b : STRING; + widthad_a : NATURAL; + widthad_b : NATURAL; + width_a : NATURAL; + width_b : NATURAL; + width_byteena_a : NATURAL; + width_byteena_b : NATURAL; + wrcontrol_wraddress_reg_b : STRING + ); + PORT ( + wren_a : IN STD_LOGIC ; + clock0 : IN STD_LOGIC ; + wren_b : IN STD_LOGIC ; + clock1 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q_a <= sub_wire0(width_a-1 DOWNTO 0); + q_b <= sub_wire1(width_a-1 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_reg_b => "CLOCK1", + clock_enable_input_a => "BYPASS", + clock_enable_input_b => "BYPASS", + clock_enable_output_a => "BYPASS", + clock_enable_output_b => "BYPASS", + indata_reg_b => "CLOCK1", + init_file => init_file, + intended_device_family => "Cyclone III", + lpm_type => "altsyncram", + numwords_a => 2**widthad_a, + numwords_b => 2**widthad_a, + operation_mode => "BIDIR_DUAL_PORT", + outdata_aclr_a => "NONE", + outdata_aclr_b => "NONE", + outdata_reg_a => outdata_reg_a, + outdata_reg_b => outdata_reg_a, + power_up_uninitialized => "FALSE", + read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", + read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ", + widthad_a => widthad_a, + widthad_b => widthad_a, + width_a => width_a, + width_b => width_a, + width_byteena_a => 1, + width_byteena_b => 1, + wrcontrol_wraddress_reg_b => "CLOCK1" + ) + PORT MAP ( + wren_a => wren_a, + clock0 => clock_a, + wren_b => wren_b, + clock1 => clock_b, + address_a => address_a, + address_b => address_b, + data_a => data_a, + data_b => data_b, + q_a => sub_wire0, + q_b => sub_wire1 + ); + + + +END SYN; diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/hq2x.sv b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/hq2x.sv new file mode 100644 index 00000000..f17732b6 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/hq2x.sv @@ -0,0 +1,454 @@ +// +// +// Copyright (c) 2012-2013 Ludvig Strigeus +// Copyright (c) 2017 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on + +`define BITS_TO_FIT(N) ( \ + N <= 2 ? 0 : \ + N <= 4 ? 1 : \ + N <= 8 ? 2 : \ + N <= 16 ? 3 : \ + N <= 32 ? 4 : \ + N <= 64 ? 5 : \ + N <= 128 ? 6 : \ + N <= 256 ? 7 : \ + N <= 512 ? 8 : \ + N <=1024 ? 9 : 10 ) + +module hq2x_in #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input rdbuf, + output[DWIDTH:0] q, + + input [AWIDTH:0] wraddr, + input wrbuf, + input [DWIDTH:0] data, + input wren +); + + localparam AWIDTH = `BITS_TO_FIT(LENGTH); + wire [DWIDTH:0] out[2]; + assign q = out[rdbuf]; + + hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); + hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); +endmodule + + +module hq2x_out #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input [1:0] rdbuf, + output[DWIDTH:0] q, + + input [AWIDTH:0] wraddr, + input [1:0] wrbuf, + input [DWIDTH:0] data, + input wren +); + + localparam AWIDTH = `BITS_TO_FIT(LENGTH*2); + wire [DWIDTH:0] out[4]; + assign q = out[rdbuf]; + + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf2(clk,data,rdaddr,wraddr,wren && (wrbuf == 2),out[2]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf3(clk,data,rdaddr,wraddr,wren && (wrbuf == 3),out[3]); +endmodule + + +module hq2x_buf #(parameter NUMWORDS, parameter AWIDTH, parameter DWIDTH) +( + input clock, + input [DWIDTH:0] data, + input [AWIDTH:0] rdaddress, + input [AWIDTH:0] wraddress, + input wren, + output [DWIDTH:0] q +); + + altsyncram altsyncram_component ( + .address_a (wraddress), + .clock0 (clock), + .data_a (data), + .wren_a (wren), + .address_b (rdaddress), + .q_b(q), + .aclr0 (1'b0), + .aclr1 (1'b0), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_b ({(DWIDTH+1){1'b1}}), + .eccstatus (), + .q_a (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_b (1'b0)); + defparam + altsyncram_component.address_aclr_b = "NONE", + altsyncram_component.address_reg_b = "CLOCK0", + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_input_b = "BYPASS", + altsyncram_component.clock_enable_output_b = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = NUMWORDS, + altsyncram_component.numwords_b = NUMWORDS, + altsyncram_component.operation_mode = "DUAL_PORT", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.outdata_reg_b = "UNREGISTERED", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE", + altsyncram_component.widthad_a = AWIDTH+1, + altsyncram_component.widthad_b = AWIDTH+1, + altsyncram_component.width_a = DWIDTH+1, + altsyncram_component.width_b = DWIDTH+1, + altsyncram_component.width_byteena_a = 1; + +endmodule + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +module DiffCheck +( + input [17:0] rgb1, + input [17:0] rgb2, + output result +); + + wire [5:0] r = rgb1[5:1] - rgb2[5:1]; + wire [5:0] g = rgb1[11:7] - rgb2[11:7]; + wire [5:0] b = rgb1[17:13] - rgb2[17:13]; + wire [6:0] t = $signed(r) + $signed(b); + wire [6:0] gx = {g[5], g}; + wire [7:0] y = $signed(t) + $signed(gx); + wire [6:0] u = $signed(r) - $signed(b); + wire [7:0] v = $signed({g, 1'b0}) - $signed(t); + + // if y is inside (-24..24) + wire y_inside = (y < 8'h18 || y >= 8'he8); + + // if u is inside (-4, 4) + wire u_inside = (u < 7'h4 || u >= 7'h7c); + + // if v is inside (-6, 6) + wire v_inside = (v < 8'h6 || v >= 8'hfA); + assign result = !(y_inside && u_inside && v_inside); +endmodule + +module InnerBlend +( + input [8:0] Op, + input [5:0] A, + input [5:0] B, + input [5:0] C, + output [5:0] O +); + + function [8:0] mul6x3; + input [5:0] op1; + input [2:0] op2; + begin + mul6x3 = 9'd0; + if(op2[0]) mul6x3 = mul6x3 + op1; + if(op2[1]) mul6x3 = mul6x3 + {op1, 1'b0}; + if(op2[2]) mul6x3 = mul6x3 + {op1, 2'b00}; + end + endfunction + + wire OpOnes = Op[4]; + wire [8:0] Amul = mul6x3(A, Op[7:5]); + wire [8:0] Bmul = mul6x3(B, {Op[3:2], 1'b0}); + wire [8:0] Cmul = mul6x3(C, {Op[1:0], 1'b0}); + wire [8:0] At = Amul; + wire [8:0] Bt = (OpOnes == 0) ? Bmul : {3'b0, B}; + wire [8:0] Ct = (OpOnes == 0) ? Cmul : {3'b0, C}; + wire [9:0] Res = {At, 1'b0} + Bt + Ct; + assign O = Op[8] ? A : Res[9:4]; +endmodule + +module Blend +( + input [5:0] rule, + input disable_hq2x, + input [17:0] E, + input [17:0] A, + input [17:0] B, + input [17:0] D, + input [17:0] F, + input [17:0] H, + output [17:0] Result +); + + reg [1:0] input_ctrl; + reg [8:0] op; + localparam BLEND0 = 9'b1_xxx_x_xx_xx; // 0: A + localparam BLEND1 = 9'b0_110_0_10_00; // 1: (A * 12 + B * 4) >> 4 + localparam BLEND2 = 9'b0_100_0_10_10; // 2: (A * 8 + B * 4 + C * 4) >> 4 + localparam BLEND3 = 9'b0_101_0_10_01; // 3: (A * 10 + B * 4 + C * 2) >> 4 + localparam BLEND4 = 9'b0_110_0_01_01; // 4: (A * 12 + B * 2 + C * 2) >> 4 + localparam BLEND5 = 9'b0_010_0_11_11; // 5: (A * 4 + (B + C) * 6) >> 4 + localparam BLEND6 = 9'b0_111_1_xx_xx; // 6: (A * 14 + B + C) >> 4 + localparam AB = 2'b00; + localparam AD = 2'b01; + localparam DB = 2'b10; + localparam BD = 2'b11; + wire is_diff; + DiffCheck diff_checker(rule[1] ? B : H, rule[0] ? D : F, is_diff); + + always @* begin + case({!is_diff, rule[5:2]}) + 1,17: {op, input_ctrl} = {BLEND1, AB}; + 2,18: {op, input_ctrl} = {BLEND1, DB}; + 3,19: {op, input_ctrl} = {BLEND1, BD}; + 4,20: {op, input_ctrl} = {BLEND2, DB}; + 5,21: {op, input_ctrl} = {BLEND2, AB}; + 6,22: {op, input_ctrl} = {BLEND2, AD}; + + 8: {op, input_ctrl} = {BLEND0, 2'bxx}; + 9: {op, input_ctrl} = {BLEND0, 2'bxx}; + 10: {op, input_ctrl} = {BLEND0, 2'bxx}; + 11: {op, input_ctrl} = {BLEND1, AB}; + 12: {op, input_ctrl} = {BLEND1, AB}; + 13: {op, input_ctrl} = {BLEND1, AB}; + 14: {op, input_ctrl} = {BLEND1, DB}; + 15: {op, input_ctrl} = {BLEND1, BD}; + + 24: {op, input_ctrl} = {BLEND2, DB}; + 25: {op, input_ctrl} = {BLEND5, DB}; + 26: {op, input_ctrl} = {BLEND6, DB}; + 27: {op, input_ctrl} = {BLEND2, DB}; + 28: {op, input_ctrl} = {BLEND4, DB}; + 29: {op, input_ctrl} = {BLEND5, DB}; + 30: {op, input_ctrl} = {BLEND3, BD}; + 31: {op, input_ctrl} = {BLEND3, DB}; + default: {op, input_ctrl} = 11'bx; + endcase + + // Setting op[8] effectively disables HQ2X because blend will always return E. + if (disable_hq2x) op[8] = 1; + end + + // Generate inputs to the inner blender. Valid combinations. + // 00: E A B + // 01: E A D + // 10: E D B + // 11: E B D + wire [17:0] Input1 = E; + wire [17:0] Input2 = !input_ctrl[1] ? A : + !input_ctrl[0] ? D : B; + + wire [17:0] Input3 = !input_ctrl[0] ? B : D; + InnerBlend inner_blend1(op, Input1[5:0], Input2[5:0], Input3[5:0], Result[5:0]); + InnerBlend inner_blend2(op, Input1[11:6], Input2[11:6], Input3[11:6], Result[11:6]); + InnerBlend inner_blend3(op, Input1[17:12], Input2[17:12], Input3[17:12], Result[17:12]); +endmodule + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +module Hq2x #(parameter LENGTH, parameter HALF_DEPTH) +( + input clk, + input ce_x4, + input [DWIDTH:0] inputpixel, + input mono, + input disable_hq2x, + input reset_frame, + input reset_line, + input [1:0] read_y, + input [AWIDTH+1:0] read_x, + output [DWIDTH:0] outpixel +); + + +localparam AWIDTH = `BITS_TO_FIT(LENGTH); +localparam DWIDTH = HALF_DEPTH ? 8 : 17; + +wire [5:0] hqTable[256] = '{ + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 35, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 35, 35, 23, 61, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 7, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 58, 23, 15, 51, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 39, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 7, 35, 23, 15, 7, 43 +}; + +reg [17:0] Prev0, Prev1, Prev2, Curr0, Curr1, Next0, Next1, Next2; +reg [17:0] A, B, D, F, G, H; +reg [7:0] pattern, nextpatt; +reg [1:0] i; +reg [7:0] y; + +wire curbuf = y[0]; +reg prevbuf = 0; +wire iobuf = !curbuf; + +wire diff0, diff1; +DiffCheck diffcheck0(Curr1, (i == 0) ? Prev0 : (i == 1) ? Curr0 : (i == 2) ? Prev2 : Next1, diff0); +DiffCheck diffcheck1(Curr1, (i == 0) ? Prev1 : (i == 1) ? Next0 : (i == 2) ? Curr2 : Next2, diff1); + +wire [7:0] new_pattern = {diff1, diff0, pattern[7:2]}; + +wire [17:0] X = (i == 0) ? A : (i == 1) ? Prev1 : (i == 2) ? Next1 : G; +wire [17:0] blend_result; +Blend blender(hqTable[nextpatt], disable_hq2x, Curr0, X, B, D, F, H, blend_result); + +reg Curr2_addr1; +reg [AWIDTH:0] Curr2_addr2; +wire [17:0] Curr2 = HALF_DEPTH ? h2rgb(Curr2tmp) : Curr2tmp; +wire [DWIDTH:0] Curr2tmp; + +reg [AWIDTH:0] wrin_addr2; +reg [DWIDTH:0] wrpix; +reg wrin_en; + +function [17:0] h2rgb; + input [8:0] v; +begin + h2rgb = mono ? {v[5:3],v[2:0], v[5:3],v[2:0], v[5:3],v[2:0]} : {v[8:6],v[8:6],v[5:3],v[5:3],v[2:0],v[2:0]}; +end +endfunction + +function [8:0] rgb2h; + input [17:0] v; +begin + rgb2h = mono ? {3'b000, v[17:15], v[14:12]} : {v[17:15], v[11:9], v[5:3]}; +end +endfunction + +hq2x_in #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_in +( + .clk(clk), + + .rdaddr(Curr2_addr2), + .rdbuf(Curr2_addr1), + .q(Curr2tmp), + + .wraddr(wrin_addr2), + .wrbuf(iobuf), + .data(wrpix), + .wren(wrin_en) +); + +reg [1:0] wrout_addr1; +reg [AWIDTH+1:0] wrout_addr2; +reg wrout_en; +reg [DWIDTH:0] wrdata; + +hq2x_out #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_out +( + .clk(clk), + + .rdaddr(read_x), + .rdbuf(read_y), + .q(outpixel), + + .wraddr(wrout_addr2), + .wrbuf(wrout_addr1), + .data(wrdata), + .wren(wrout_en) +); + +always @(posedge clk) begin + reg [AWIDTH:0] offs; + reg old_reset_line; + reg old_reset_frame; + + wrout_en <= 0; + wrin_en <= 0; + + if(ce_x4) begin + + pattern <= new_pattern; + + if(~&offs) begin + if (i == 0) begin + Curr2_addr1 <= prevbuf; + Curr2_addr2 <= offs; + end + if (i == 1) begin + Prev2 <= Curr2; + Curr2_addr1 <= curbuf; + Curr2_addr2 <= offs; + end + if (i == 2) begin + Next2 <= HALF_DEPTH ? h2rgb(inputpixel) : inputpixel; + wrpix <= inputpixel; + wrin_addr2 <= offs; + wrin_en <= 1; + end + if (i == 3) begin + offs <= offs + 1'd1; + end + + if(HALF_DEPTH) wrdata <= rgb2h(blend_result); + else wrdata <= blend_result; + + wrout_addr1 <= {curbuf, i[1]}; + wrout_addr2 <= {offs, i[1]^i[0]}; + wrout_en <= 1; + end + + if(i==3) begin + nextpatt <= {new_pattern[7:6], new_pattern[3], new_pattern[5], new_pattern[2], new_pattern[4], new_pattern[1:0]}; + {A, G} <= {Prev0, Next0}; + {B, F, H, D} <= {Prev1, Curr2, Next1, Curr0}; + {Prev0, Prev1} <= {Prev1, Prev2}; + {Curr0, Curr1} <= {Curr1, Curr2}; + {Next0, Next1} <= {Next1, Next2}; + end else begin + nextpatt <= {nextpatt[5], nextpatt[3], nextpatt[0], nextpatt[6], nextpatt[1], nextpatt[7], nextpatt[4], nextpatt[2]}; + {B, F, H, D} <= {F, H, D, B}; + end + + i <= i + 1'b1; + if(old_reset_line && ~reset_line) begin + old_reset_frame <= reset_frame; + offs <= 0; + i <= 0; + y <= y + 1'd1; + prevbuf <= curbuf; + if(old_reset_frame & ~reset_frame) begin + y <= 0; + prevbuf <= 0; + end + end + + old_reset_line <= reset_line; + end +end + +endmodule // Hq2x diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/keyboard.sv b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/keyboard.sv new file mode 100644 index 00000000..01625319 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/keyboard.sv @@ -0,0 +1,79 @@ + + +module keyboard +( + input clk, + input reset, + input ps2_kbd_clk, + input ps2_kbd_data, + + output reg[7:0] joystick +); + +reg [11:0] shift_reg = 12'hFFF; +wire[11:0] kdata = {ps2_kbd_data,shift_reg[11:1]}; +wire [7:0] kcode = kdata[9:2]; +reg release_btn = 0; + +reg [7:0] code; +reg input_strobe = 0; + +always @(negedge clk) begin + reg old_reset = 0; + + old_reset <= reset; + + if(~old_reset & reset)begin + joystick <= 0; + end + + if(input_strobe) begin + case(code) + 'h75: joystick[3] <= ~release_btn; // arrow up + 'h72: joystick[2] <= ~release_btn; // arrow down + 'h6B: joystick[1] <= ~release_btn; // arrow left + 'h74: joystick[0] <= ~release_btn; // arrow right + + 'h29: joystick[4] <= ~release_btn; // Space + 'h05: joystick[5] <= ~release_btn; // F1 + 'h06: joystick[6] <= ~release_btn; // F2 + 'h76: joystick[7] <= ~release_btn; // Escape + endcase + end +end + +always @(posedge clk) begin + reg [3:0] prev_clk = 0; + reg old_reset = 0; + reg action = 0; + + old_reset <= reset; + input_strobe <= 0; + + if(~old_reset & reset)begin + prev_clk <= 0; + shift_reg <= 12'hFFF; + end else begin + prev_clk <= {ps2_kbd_clk,prev_clk[3:1]}; + if(prev_clk == 1) begin + if (kdata[11] & ^kdata[10:2] & ~kdata[1] & kdata[0]) begin + shift_reg <= 12'hFFF; + if (kcode == 8'he0) ; + // Extended key code follows + else if (kcode == 8'hf0) + // Release code follows + action <= 1; + else begin + // Cancel extended/release flags for next time + action <= 0; + release_btn <= action; + code <= kcode; + input_strobe <= 1; + end + end else begin + shift_reg <= kdata; + end + end + end +end +endmodule diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/mist_io.sv b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/mist_io.sv new file mode 100644 index 00000000..dcc7ecde --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/mist_io.sv @@ -0,0 +1,491 @@ +// +// mist_io.v +// +// mist_io for the MiST board +// http://code.google.com/p/mist-board/ +// +// Copyright (c) 2014 Till Harbaum +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////// + +// +// Use buffer to access SD card. It's time-critical part. +// Made module synchroneous with 2 clock domains: clk_sys and SPI_SCK +// (Sorgelig) +// +// for synchronous projects default value for PS2DIV is fine for any frequency of system clock. +// clk_ps2 = clk_sys/(PS2DIV*2) +// + +module mist_io #(parameter STRLEN=0, parameter PS2DIV=100) +( + + // parameter STRLEN and the actual length of conf_str have to match + input [(8*STRLEN)-1:0] conf_str, + + // Global clock. It should be around 100MHz (higher is better). + input clk_sys, + + // Global SPI clock from ARM. 24MHz + input SPI_SCK, + + input CONF_DATA0, + input SPI_SS2, + output SPI_DO, + input SPI_DI, + + output reg [7:0] joystick_0, + output reg [7:0] joystick_1, + output reg [15:0] joystick_analog_0, + output reg [15:0] joystick_analog_1, + output [1:0] buttons, + output [1:0] switches, + output scandoubler_disable, + output ypbpr, + + output reg [31:0] status, + + // SD config + input sd_conf, + input sd_sdhc, + output img_mounted, // signaling that new image has been mounted + output reg [31:0] img_size, // size of image in bytes + + // SD block level access + input [31:0] sd_lba, + input sd_rd, + input sd_wr, + output reg sd_ack, + output reg sd_ack_conf, + + // SD byte level access. Signals for 2-PORT altsyncram. + output reg [8:0] sd_buff_addr, + output reg [7:0] sd_buff_dout, + input [7:0] sd_buff_din, + output reg sd_buff_wr, + + // ps2 keyboard emulation + output ps2_kbd_clk, + output reg ps2_kbd_data, + output ps2_mouse_clk, + output reg ps2_mouse_data, + input ps2_caps_led, + + // ARM -> FPGA download + output reg ioctl_download = 0, // signal indicating an active download + output reg [7:0] ioctl_index, // menu index used to upload the file + output ioctl_wr, + output reg [23:0] ioctl_addr, + output reg [7:0] ioctl_dout +); + +reg [7:0] b_data; +reg [6:0] sbuf; +reg [7:0] cmd; +reg [2:0] bit_cnt; // counts bits 0-7 0-7 ... +reg [9:0] byte_cnt; // counts bytes +reg [7:0] but_sw; +reg [2:0] stick_idx; + +reg mount_strobe = 0; +assign img_mounted = mount_strobe; + +assign buttons = but_sw[1:0]; +assign switches = but_sw[3:2]; +assign scandoubler_disable = but_sw[4]; +assign ypbpr = but_sw[5]; + +wire [7:0] spi_dout = { sbuf, SPI_DI}; + +// this variant of user_io is for 8 bit cores (type == a4) only +wire [7:0] core_type = 8'ha4; + +// command byte read by the io controller +wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd }; + +reg spi_do; +assign SPI_DO = CONF_DATA0 ? 1'bZ : spi_do; + +wire [7:0] kbd_led = { 2'b01, 4'b0000, ps2_caps_led, 1'b1}; + +// drive MISO only when transmitting core id +always@(negedge SPI_SCK) begin + if(!CONF_DATA0) begin + // first byte returned is always core type, further bytes are + // command dependent + if(byte_cnt == 0) begin + spi_do <= core_type[~bit_cnt]; + + end else begin + case(cmd) + // reading config string + 8'h14: begin + // returning a byte from string + if(byte_cnt < STRLEN + 1) spi_do <= conf_str[{STRLEN - byte_cnt,~bit_cnt}]; + else spi_do <= 0; + end + + // reading sd card status + 8'h16: begin + if(byte_cnt == 1) spi_do <= sd_cmd[~bit_cnt]; + else if((byte_cnt >= 2) && (byte_cnt < 6)) spi_do <= sd_lba[{5-byte_cnt, ~bit_cnt}]; + else spi_do <= 0; + end + + // reading sd card write data + 8'h18: + spi_do <= b_data[~bit_cnt]; + + // reading keyboard LED status + 8'h1f: + spi_do <= kbd_led[~bit_cnt]; + + default: + spi_do <= 0; + endcase + end + end +end + +reg b_wr2,b_wr3; +always @(negedge clk_sys) begin + b_wr3 <= b_wr2; + sd_buff_wr <= b_wr3; +end + +// SPI receiver +always@(posedge SPI_SCK or posedge CONF_DATA0) begin + + if(CONF_DATA0) begin + b_wr2 <= 0; + bit_cnt <= 0; + byte_cnt <= 0; + sd_ack <= 0; + sd_ack_conf <= 0; + end else begin + b_wr2 <= 0; + + sbuf <= spi_dout[6:0]; + bit_cnt <= bit_cnt + 1'd1; + if(bit_cnt == 5) begin + if (byte_cnt == 0) sd_buff_addr <= 0; + if((byte_cnt != 0) & (sd_buff_addr != 511)) sd_buff_addr <= sd_buff_addr + 1'b1; + if((byte_cnt == 1) & ((cmd == 8'h17) | (cmd == 8'h19))) sd_buff_addr <= 0; + end + + // finished reading command byte + if(bit_cnt == 7) begin + if(~&byte_cnt) byte_cnt <= byte_cnt + 8'd1; + if(byte_cnt == 0) begin + cmd <= spi_dout; + + if(spi_dout == 8'h19) begin + sd_ack_conf <= 1; + sd_buff_addr <= 0; + end + if((spi_dout == 8'h17) || (spi_dout == 8'h18)) begin + sd_ack <= 1; + sd_buff_addr <= 0; + end + if(spi_dout == 8'h18) b_data <= sd_buff_din; + + mount_strobe <= 0; + + end else begin + + case(cmd) + // buttons and switches + 8'h01: but_sw <= spi_dout; + 8'h02: joystick_0 <= spi_dout; + 8'h03: joystick_1 <= spi_dout; + + // store incoming ps2 mouse bytes + 8'h04: begin + ps2_mouse_fifo[ps2_mouse_wptr] <= spi_dout; + ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1; + end + + // store incoming ps2 keyboard bytes + 8'h05: begin + ps2_kbd_fifo[ps2_kbd_wptr] <= spi_dout; + ps2_kbd_wptr <= ps2_kbd_wptr + 1'd1; + end + + 8'h15: status[7:0] <= spi_dout; + + // send SD config IO -> FPGA + // flag that download begins + // sd card knows data is config if sd_dout_strobe is asserted + // with sd_ack still being inactive (low) + 8'h19, + // send sector IO -> FPGA + // flag that download begins + 8'h17: begin + sd_buff_dout <= spi_dout; + b_wr2 <= 1; + end + + 8'h18: b_data <= sd_buff_din; + + // joystick analog + 8'h1a: begin + // first byte is joystick index + if(byte_cnt == 1) stick_idx <= spi_dout[2:0]; + else if(byte_cnt == 2) begin + // second byte is x axis + if(stick_idx == 0) joystick_analog_0[15:8] <= spi_dout; + else if(stick_idx == 1) joystick_analog_1[15:8] <= spi_dout; + end else if(byte_cnt == 3) begin + // third byte is y axis + if(stick_idx == 0) joystick_analog_0[7:0] <= spi_dout; + else if(stick_idx == 1) joystick_analog_1[7:0] <= spi_dout; + end + end + + // notify image selection + 8'h1c: mount_strobe <= 1; + + // send image info + 8'h1d: if(byte_cnt<5) img_size[(byte_cnt-1)<<3 +:8] <= spi_dout; + + // status, 32bit version + 8'h1e: if(byte_cnt<5) status[(byte_cnt-1)<<3 +:8] <= spi_dout; + default: ; + endcase + end + end + end +end + + +/////////////////////////////// PS2 /////////////////////////////// +// 8 byte fifos to store ps2 bytes +localparam PS2_FIFO_BITS = 3; + +reg clk_ps2; +always @(negedge clk_sys) begin + integer cnt; + cnt <= cnt + 1'd1; + if(cnt == PS2DIV) begin + clk_ps2 <= ~clk_ps2; + cnt <= 0; + end +end + +// keyboard +reg [7:0] ps2_kbd_fifo[1<= 1)&&(ps2_kbd_tx_state < 9)) begin + ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits + ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down + if(ps2_kbd_tx_byte[0]) + ps2_kbd_parity <= !ps2_kbd_parity; + end + + // transmission of parity + if(ps2_kbd_tx_state == 9) ps2_kbd_data <= ps2_kbd_parity; + + // transmission of stop bit + if(ps2_kbd_tx_state == 10) ps2_kbd_data <= 1; // stop bit is 1 + + // advance state machine + if(ps2_kbd_tx_state < 11) ps2_kbd_tx_state <= ps2_kbd_tx_state + 1'd1; + else ps2_kbd_tx_state <= 0; + end + end +end + +// mouse +reg [7:0] ps2_mouse_fifo[1<= 1)&&(ps2_mouse_tx_state < 9)) begin + ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits + ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down + if(ps2_mouse_tx_byte[0]) + ps2_mouse_parity <= !ps2_mouse_parity; + end + + // transmission of parity + if(ps2_mouse_tx_state == 9) ps2_mouse_data <= ps2_mouse_parity; + + // transmission of stop bit + if(ps2_mouse_tx_state == 10) ps2_mouse_data <= 1; // stop bit is 1 + + // advance state machine + if(ps2_mouse_tx_state < 11) ps2_mouse_tx_state <= ps2_mouse_tx_state + 1'd1; + else ps2_mouse_tx_state <= 0; + end + end +end + + +/////////////////////////////// DOWNLOADING /////////////////////////////// + +reg [7:0] data_w; +reg [23:0] addr_w; +reg rclk = 0; + +localparam UIO_FILE_TX = 8'h53; +localparam UIO_FILE_TX_DAT = 8'h54; +localparam UIO_FILE_INDEX = 8'h55; + +// data_io has its own SPI interface to the io controller +always@(posedge SPI_SCK, posedge SPI_SS2) begin + reg [6:0] sbuf; + reg [7:0] cmd; + reg [4:0] cnt; + reg [23:0] addr; + + if(SPI_SS2) cnt <= 0; + else begin + rclk <= 0; + + // don't shift in last bit. It is evaluated directly + // when writing to ram + if(cnt != 15) sbuf <= { sbuf[5:0], SPI_DI}; + + // increase target address after write + if(rclk) addr <= addr + 1'd1; + + // count 0-7 8-15 8-15 ... + if(cnt < 15) cnt <= cnt + 1'd1; + else cnt <= 8; + + // finished command byte + if(cnt == 7) cmd <= {sbuf, SPI_DI}; + + // prepare/end transmission + if((cmd == UIO_FILE_TX) && (cnt == 15)) begin + // prepare + if(SPI_DI) begin + addr <= 0; + ioctl_download <= 1; + end else begin + addr_w <= addr; + ioctl_download <= 0; + end + end + + // command 0x54: UIO_FILE_TX + if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin + addr_w <= addr; + data_w <= {sbuf, SPI_DI}; + rclk <= 1; + end + + // expose file (menu) index + if((cmd == UIO_FILE_INDEX) && (cnt == 15)) ioctl_index <= {sbuf, SPI_DI}; + end +end + +assign ioctl_wr = |ioctl_wrd; +reg [1:0] ioctl_wrd; + +always@(negedge clk_sys) begin + reg rclkD, rclkD2; + + rclkD <= rclk; + rclkD2 <= rclkD; + ioctl_wrd<= {ioctl_wrd[0],1'b0}; + + if(rclkD & ~rclkD2) begin + ioctl_dout <= data_w; + ioctl_addr <= addr_w; + ioctl_wrd <= 2'b11; + end +end + +endmodule diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/motion.vhd b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/motion.vhd new file mode 100644 index 00000000..bb2e85ac --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/motion.vhd @@ -0,0 +1,290 @@ +-- Motion object generation circuitry for Atari Super Breakout +-- This generates the motion objects, three balls in the case of Super Breakout +-- 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity motion is +port( + Clk6 : in std_logic; -- 6MHz on schematic + Phi2 : in std_logic; + Display : in std_logic_vector(7 downto 0); + H256_s : in std_logic; -- 256H* on schematic + VCount : in std_logic_vector(7 downto 0); + HCount : in std_logic_vector(8 downto 0); + Tones_n : out std_logic; -- Used by sound circuit, comes from decoder here + Ball1_n : out std_logic; + Ball2_n : out std_logic; -- Ball video outputs, summed by video output circuit + Ball3_n : out std_logic + ); +end motion; + +architecture rtl of motion is + +signal A : std_logic; +signal B : std_logic; +signal C : std_logic; +signal D : std_logic; +signal E : std_logic; +signal F : std_logic; +signal G : std_logic; +signal H : std_logic; +signal I : std_logic; +signal J : std_logic; +signal K : std_logic; +signal L : std_logic; +signal M : std_logic; +signal N : std_logic; + +signal phi0 : std_logic; + +signal LDH1_n : std_logic; +signal LDH2_n : std_logic; +signal LDH3_n : std_logic; + +signal LDV1A_n : std_logic; +signal LDV2A_n : std_logic; +signal LDV3A_n : std_logic; + +signal Ball1_Inh : std_logic; +signal Ball2_Inh : std_logic; +signal Ball3_Inh : std_logic; + +signal LM4_sum : std_logic_vector(7 downto 0) := (others => '0'); + +signal N4_8 : std_logic; + +signal H256_n : std_logic; +signal H256 : std_logic; +signal H64 : std_logic; +signal H32 : std_logic; +signal H16 : std_logic; +signal H8 : std_logic; +signal H4 : std_logic; + +signal L5_reg : std_logic_vector(4 downto 0) := (others => '0'); + +signal J8_3 : std_logic; +signal J8_6 : std_logic; + +signal K8_in : std_logic_vector(3 downto 0) := (others => '0'); +signal K8_out : std_logic_vector(9 downto 0) := (others => '0'); +signal D7_in : std_logic_vector(3 downto 0) := (others => '0'); +signal D7_out : std_logic_vector(9 downto 0) := (others => '0'); + +signal Ball1_Hpos : std_logic_vector(7 downto 0) := (others => '0'); +signal Ball2_Hpos : std_logic_vector(7 downto 0) := (others => '0'); +signal Ball3_Hpos : std_logic_vector(7 downto 0) := (others => '0'); + +signal Ball1_reg : std_logic_vector(7 downto 0) := (others => '0'); +signal Ball2_reg : std_logic_vector(7 downto 0) := (others => '0'); +signal Ball3_reg : std_logic_vector(7 downto 0) := (others => '0'); + +signal Vid : std_logic_vector(7 downto 0) := (others => '0'); + + +begin +phi0 <= phi2; + +H4 <= Hcount(2); +H8 <= Hcount(3); +H16 <= Hcount(4); +H32 <= Hcount(5); +H64 <= Hcount(6); +H256 <= Hcount(8); +H256_n <= not(Hcount(8)); + +LM4_sum <= Display + VCount; -- Binary adder and wide NAND gate forms the motion object comparator +N4_8 <= not(LM4_sum(7) and LM4_sum(6) and LM4_sum(5) and LM4_sum(4) and H256_n and H64 and H8); + +-- D type latches in L5 and M9 clocked by phi2 +L5: process(phi2, N4_8, LM4_sum(3 downto 0)) +begin + if rising_edge(phi2) then + L5_reg <= N4_8 & LM4_sum(3 downto 0); + end if; +end process; + +K6: entity work.sprom +generic map( + init_file => "rtl/roms/033282_k6.hex", + widthad_a => 5, + width_a => 8) +port map( + clock => clk6, + address => Display(7) & L5_reg(3 downto 0), + q => Vid + ); + +--K6: entity work.k6_prom +--port map( +-- clock => clk6, +-- address => Display(7) & L5_reg(3 downto 0), +-- q => Vid +-- ); + + +J8_3 <= (H4 or L5_reg(4)); + +J8_6 <= (H256 or H64 or H4); + +-- Decoder code could be cleaned up a bit +K8_in <= J8_3 & H32 & H16 & not phi0; +K8: process(clk6, K8_in) +begin + if rising_edge(clk6) then + case K8_in is + when "0000" => K8_out <= "1111111110"; + when "0001" => K8_out <= "1111111101"; + when "0010" => K8_out <= "1111111011"; + when "0011" => K8_out <= "1111110111"; + when "0100" => K8_out <= "1111101111"; + when "0101" => K8_out <= "1111011111"; + when "0110" => K8_out <= "1110111111"; + when "0111" => K8_out <= "1101111111"; + when "1000" => K8_out <= "1011111111"; + when "1001" => K8_out <= "0111111111"; + when others => K8_out <= "1111111111"; + end case; + LDV3A_n <= K8_out(6); + LDV2A_n <= K8_out(4); + LDV1A_n <= K8_out(2); + end if; +end process; + + +D7_in <= J8_6 & H32 & H16 & H8; +D7: process(D7_in) +begin + case D7_in is + when "0000" => D7_out <= "1111111110"; + when "0001" => D7_out <= "1111111101"; + when "0010" => D7_out <= "1111111011"; + when "0011" => D7_out <= "1111110111"; + when "0100" => D7_out <= "1111101111"; + when "0101" => D7_out <= "1111011111"; + when "0110" => D7_out <= "1110111111"; + when "0111" => D7_out <= "1101111111"; + when "1000" => D7_out <= "1011111111"; + when "1001" => D7_out <= "0111111111"; + when others => D7_out <= "1111111111"; + end case; +end process; + +Tones_n <= D7_out(2); +LDH1_n <= D7_out(1); +LDH2_n <= D7_out(3); +LDH3_n <= D7_out(5); + + +-- Ball 1 Horizontal ball position counter +-- This combines two 74LS163s at locations R5 and R6 on the PCB +R5_6: process(clk6, H256_s, LDH1_n, Display) +begin + if rising_edge(clk6) then + if LDH1_n = '0' then -- preload the counter + Ball1_Hpos <= Display; + elsif H256_s = '1' then -- increment the counter + Ball1_Hpos <= Ball1_Hpos + '1'; + end if; + end if; +end process; +D <= Ball1_Hpos(7); +C <= Ball1_Hpos(6); +B <= Ball1_Hpos(5); +A <= Ball1_Hpos(4); +Ball1_Inh <= not(A and B and C and D); + +-- Ball 1 video shift register +N7: process(clk6, Ball1_Inh, LDV1A_n, Vid) +begin + if LDV1A_n = '0' then + Ball1_reg <= Vid; -- Preload the register with a line from the motion object PROM + elsif rising_edge(clk6) then + if Ball1_Inh = '0' then + Ball1_reg <= '0' & Ball1_reg(7 downto 1); + end if; + end if; +end process; +Ball1_n <= not Ball1_reg(0); + + +-- Ball 2 Horizontal ball position counter +-- This combines two 74LS163s at locations P5 and P6 on the PCB +P5_6: process(clk6, H256_s, LDH2_n, Display) +begin + if rising_edge(clk6) then + if LDH2_n = '0' then -- preload the counter + Ball2_Hpos <= Display; + elsif H256_s = '1' then -- increment the counter + Ball2_Hpos <= Ball2_Hpos + '1'; + end if; + end if; +end process; +J <= Ball2_Hpos(7); +H <= Ball2_Hpos(6); +F <= Ball2_Hpos(5); +E <= Ball2_Hpos(4); +Ball2_Inh <= not(E and F and H and J); + +-- Ball 2 video shift register +L7: process(clk6, Ball2_Inh, LDV2A_n, Vid) +begin + if LDV2A_n = '0' then + Ball2_reg <= Vid; -- Preload the register with a line from the motion object PROM + elsif rising_edge(clk6) then + if Ball2_Inh = '0' then + Ball2_reg <= '0' & Ball2_reg(7 downto 1); + end if; + end if; +end process; +Ball2_n <= not Ball2_reg(0); + + +-- Ball 3 Horizontal ball position counter +-- This combines two 74LS163s at locations N5 and N6 on the PCB +N5_6: process(clk6, H256_s, LDH3_n, Display) +begin + if rising_edge(clk6) then + if LDH3_n = '0' then -- preload the counter + Ball3_Hpos <= Display; + elsif H256_s = '1' then -- increment the counter + Ball3_Hpos <= Ball3_Hpos + '1'; + end if; + end if; +end process; +N <= Ball3_Hpos(7); +M <= Ball3_Hpos(6); +L <= Ball3_Hpos(5); +K <= Ball3_Hpos(4); +Ball3_Inh <= not(K and L and M and N); + +-- Ball 3 video shift register +J7: process(clk6, Ball3_Inh, LDV3A_n, Vid) +begin + if LDV3A_n = '0' then + Ball3_reg <= Vid; -- Preload the register with a line from the motion object PROM + elsif rising_edge(clk6) then + if Ball3_Inh = '0' then + Ball3_reg <= '0' & Ball3_reg(7 downto 1); + end if; + end if; +end process; +Ball3_n <= not Ball3_reg(0); + +end rtl; diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/osd.sv b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/osd.sv new file mode 100644 index 00000000..c62c10af --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/osd.sv @@ -0,0 +1,179 @@ +// A simple OSD implementation. Can be hooked up between a cores +// VGA output and the physical VGA pins + +module osd ( + // OSDs pixel clock, should be synchronous to cores pixel clock to + // avoid jitter. + input clk_sys, + + // SPI interface + input SPI_SCK, + input SPI_SS3, + input SPI_DI, + + // VGA signals coming from core + input [5:0] R_in, + input [5:0] G_in, + input [5:0] B_in, + input HSync, + input VSync, + + // VGA signals going to video connector + output [5:0] R_out, + output [5:0] G_out, + output [5:0] B_out +); + +parameter OSD_X_OFFSET = 10'd0; +parameter OSD_Y_OFFSET = 10'd0; +parameter OSD_COLOR = 3'd0; + +localparam OSD_WIDTH = 10'd256; +localparam OSD_HEIGHT = 10'd128; + +// ********************************************************************************* +// spi client +// ********************************************************************************* + +// this core supports only the display related OSD commands +// of the minimig +reg osd_enable; +(* ramstyle = "no_rw_check" *) reg [7:0] osd_buffer[2047:0]; // the OSD buffer itself + +// the OSD has its own SPI interface to the io controller +always@(posedge SPI_SCK, posedge SPI_SS3) begin + reg [4:0] cnt; + reg [10:0] bcnt; + reg [7:0] sbuf; + reg [7:0] cmd; + + if(SPI_SS3) begin + cnt <= 0; + bcnt <= 0; + end else begin + sbuf <= {sbuf[6:0], SPI_DI}; + + // 0:7 is command, rest payload + if(cnt < 15) cnt <= cnt + 1'd1; + else cnt <= 8; + + if(cnt == 7) begin + cmd <= {sbuf[6:0], SPI_DI}; + + // lower three command bits are line address + bcnt <= {sbuf[1:0], SPI_DI, 8'h00}; + + // command 0x40: OSDCMDENABLE, OSDCMDDISABLE + if(sbuf[6:3] == 4'b0100) osd_enable <= SPI_DI; + end + + // command 0x20: OSDCMDWRITE + if((cmd[7:3] == 5'b00100) && (cnt == 15)) begin + osd_buffer[bcnt] <= {sbuf[6:0], SPI_DI}; + bcnt <= bcnt + 1'd1; + end + end +end + +// ********************************************************************************* +// video timing and sync polarity anaylsis +// ********************************************************************************* + +// horizontal counter +reg [9:0] h_cnt; +reg [9:0] hs_low, hs_high; +wire hs_pol = hs_high < hs_low; +wire [9:0] dsp_width = hs_pol ? hs_low : hs_high; + +// vertical counter +reg [9:0] v_cnt; +reg [9:0] vs_low, vs_high; +wire vs_pol = vs_high < vs_low; +wire [9:0] dsp_height = vs_pol ? vs_low : vs_high; + +wire doublescan = (dsp_height>350); + +reg ce_pix; +always @(negedge clk_sys) begin + integer cnt = 0; + integer pixsz, pixcnt; + reg hs; + + cnt <= cnt + 1; + hs <= HSync; + + pixcnt <= pixcnt + 1; + if(pixcnt == pixsz) pixcnt <= 0; + ce_pix <= !pixcnt; + + if(hs && ~HSync) begin + cnt <= 0; + pixsz <= (cnt >> 9) - 1; + pixcnt <= 0; + ce_pix <= 1; + end +end + +always @(posedge clk_sys) begin + reg hsD, hsD2; + reg vsD, vsD2; + + if(ce_pix) begin + // bring hsync into local clock domain + hsD <= HSync; + hsD2 <= hsD; + + // falling edge of HSync + if(!hsD && hsD2) begin + h_cnt <= 0; + hs_high <= h_cnt; + end + + // rising edge of HSync + else if(hsD && !hsD2) begin + h_cnt <= 0; + hs_low <= h_cnt; + v_cnt <= v_cnt + 1'd1; + end else begin + h_cnt <= h_cnt + 1'd1; + end + + vsD <= VSync; + vsD2 <= vsD; + + // falling edge of VSync + if(!vsD && vsD2) begin + v_cnt <= 0; + vs_high <= v_cnt; + end + + // rising edge of VSync + else if(vsD && !vsD2) begin + v_cnt <= 0; + vs_low <= v_cnt; + end + end +end + +// area in which OSD is being displayed +wire [9:0] h_osd_start = ((dsp_width - OSD_WIDTH)>> 1) + OSD_X_OFFSET; +wire [9:0] h_osd_end = h_osd_start + OSD_WIDTH; +wire [9:0] v_osd_start = ((dsp_height- (OSD_HEIGHT<> 1) + OSD_Y_OFFSET; +wire [9:0] v_osd_end = v_osd_start + (OSD_HEIGHT<= h_osd_start) && (h_cnt < h_osd_end) && + (VSync != vs_pol) && (v_cnt >= v_osd_start) && (v_cnt < v_osd_end); + +reg [7:0] osd_byte; +always @(posedge clk_sys) if(ce_pix) osd_byte <= osd_buffer[{doublescan ? osd_vcnt[7:5] : osd_vcnt[6:4], osd_hcnt[7:0]}]; + +wire osd_pixel = osd_byte[doublescan ? osd_vcnt[4:2] : osd_vcnt[3:1]]; + +assign R_out = !osd_de ? R_in : {osd_pixel, osd_pixel, OSD_COLOR[2], R_in[5:3]}; +assign G_out = !osd_de ? G_in : {osd_pixel, osd_pixel, OSD_COLOR[1], G_in[5:3]}; +assign B_out = !osd_de ? B_in : {osd_pixel, osd_pixel, OSD_COLOR[0], B_in[5:3]}; + +endmodule diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/paddle.vhd b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/paddle.vhd new file mode 100644 index 00000000..efedbe21 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/paddle.vhd @@ -0,0 +1,101 @@ +-- Paddle input circuitry for Atari Super Breakout +-- This interfaces the player control knob that moves the paddle. The original hardware +-- used an analog potentiometer that was read by comparing the voltage of a ramp generated +-- by a charging capacitor against the voltage from the pot wiper. That could be duplicated +-- with external circuitry but here an optical encoder will be used. The hardware included +-- two channels but Super Breakout only made use of one. +-- 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; + +entity paddle is +port( + CLK6 : in std_logic; + Enc_A : in std_logic; + Enc_B : in std_logic; + Mask1_n : in std_logic; + Mask2_n : in std_logic; + Vblank : in std_logic; + Sense1 : out std_logic; + Sense2 : out std_logic; + NMI_n : out std_logic + ); +end paddle; + +architecture rtl of paddle is + +signal sense1_int : std_logic; +signal sense2_int : std_logic; +signal comp1_n: std_logic; +signal ramp: integer range 0 to 100000; +signal position: integer range 0 to 160000; +signal pad_pos: integer range 400 to 2500; + + +begin + +-- Ramp is reset by Vblank pulse and begins to rise. Originally an analog comparator compared the pot position +-- against the ramp voltage, the output of this comparator going high when the ramp voltage rises above the pot value +-- Since this ramp counter is clocked at 6MHz, position output from encoder interface is multiplied +Ramp_Compare: process(clk6, Vblank) +begin + if rising_edge(clk6) then + if Vblank = '1' then + comp1_n <= '0'; + ramp <= 0; + else + ramp <= ramp + 1; + end if; + + if ramp > (pad_pos * 35) then + comp1_n <= '1'; + end if; + end if; +end process; + +-- Logic gates in IC at M10 +sense1_int <= not(comp1_n and mask1_n); +NMI_n <= sense1_int and sense2_int; + +Sense1 <= Sense1_int; +Sense2 <= Sense2_int; + +-- The original hardware has support for two pots however the game code only supports one so hardwire this high +sense2_int <= '1'; + +-- If the pulse from the ramp comparator comes too soon after Vblank the paddle interrupt is triggered too +-- early and this causes problems so make the minimum position 500. +pad_pos <= (position + 500); + + +-- Interface for the quadrature encoder. The optical encoder used in the prototype has a very high resolution, it +-- will be necessary to adjust values for other encoders +encoder: entity work.quadrature_decoder + generic map( + positions => 2000, --size of the position counter (i.e. number of positions counted) + debounce_time => 500, --number of clock cycles required to register a new position = debounce_time + 2 + set_origin_debounce_time => 50_000) --number of clock cycles required to register a new set_origin_n value = set_origin_debounce_time + 2 + port map( + clk => clk6, --system clock + a => Enc_a, --quadrature encoded signal a + b => Enc_b, --quadrature encoded signal b + set_origin_n => '1', --active-low synchronous clear of position counter + direction => open, --direction of last change, 1 = positive, 0 = negative + position => position + ); + +end rtl; diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/paddle_analog.vhd b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/paddle_analog.vhd new file mode 100644 index 00000000..5292ab50 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/paddle_analog.vhd @@ -0,0 +1,53 @@ +-- Paddle interface using analog potentiometer for Super Breakout arcade game by Atari +-- (c) 2017 James Sweet +-- +-- Use this file if you want to use a potentiometer as used in the original arcade machine +-- instead of an encoder to control the paddle. An external analog comparator and ramp generator +-- circuit is required, see schematic in Super Breakout manual. +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + + +library IEEE; +use IEEE.STD_LOGIC_1164.all; + +entity paddle_analog is +port( + Pot_Comp1_n : in std_logic; + Pot_Comp2_n : in std_logic; + Mask1_n : in std_logic; + Mask2_n : in std_logic; + Vblank : in std_logic; + Sense1 : out std_logic; + Sense2 : out std_logic; + NMI_n : out std_logic + ); +end paddle_analog; + +architecture rtl of paddle_analog is + +signal sense1_int : std_logic; +signal sense2_int : std_logic; + +begin + +sense1 <= sense1_int; +sense2 <= sense2_int; + +-- Logic gates in IC at M10 +-- These should be a 74LS132 with Schmitt trigger inputs, may not work reliably using FPGA pins directly +sense1_int <= not(Pot_Comp1_n and mask1_n); +sense2_int <= not(Pot_Comp2_n and mask2_n); +NMI_n <= sense1_int and sense2_int; + +end rtl; diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/playfield.vhd b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/playfield.vhd new file mode 100644 index 00000000..78b1bd1b --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/playfield.vhd @@ -0,0 +1,148 @@ +-- Playfield generation circuitry for Atari Super Breakout +-- Several other games use a virtually identical circuit +-- (c)2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity playfield is +port( + Clk6 : in std_logic; + Display : in std_logic_vector(7 downto 0); + HCount : in std_logic_vector(8 downto 0); + VCount : in std_logic_vector(7 downto 0); + H256_s : out std_logic; -- 256H* on schematic + HBlank : in std_logic; + VBlank : in std_logic; + VBlank_n_s : in std_logic; -- VBLANK* on the schematic + HSync : in std_logic; + VSync : in std_logic; + CompSync_n_s : out std_logic; -- COMP SYNC* on schematic + CompBlank_s : out std_logic; -- COMP BLANK* on schematic + Playfield_n : out std_logic + ); +end playfield; + +architecture rtl of playfield is + +signal H1 : std_logic; +signal H2 : std_logic; +signal H4 : std_logic; +signal H256 : std_logic; +signal H256_n : std_logic; + +signal V1 : std_logic; +signal V2 : std_logic; +signal V4 : std_logic; + +signal char_addr : std_logic_vector(8 downto 0) := (others => '0'); +signal char_data : std_logic_vector(7 downto 0) := (others => '0'); +signal shift_data : std_logic_vector(7 downto 0) := (others => '0'); +signal QH : std_logic := '0'; +signal R7_12 : std_logic := '0'; +signal P3_3 : std_logic := '0'; +signal Display7_s : std_logic := '0'; + +begin +-- Video synchronization signals +H1 <= Hcount(0); +H2 <= Hcount(1); +H4 <= Hcount(2); +H256 <= Hcount(8); +H256_n <= not(Hcount(8)); + +V1 <= Vcount(0); +V2 <= Vcount(1); +V4 <= Vcount(2); + + +-- Some glue logic, some signals could be renamed to be easier to follow without referring to schematic +R7_12 <= not(H1 and H2 and H4); -- 3-input NAND gate at R7 +P3_3 <= (H256_n or R7_12); -- OR gate at P3 +char_addr <= display(5 downto 0) & V4 & V2 & V1; + +-- Background character ROMs +R4: entity work.sprom +generic map( + init_file => "rtl/roms/033281_r4.hex", + widthad_a => 9, + width_a => 4) +port map( + clock => clk6, + Address => char_addr, + q => char_data(3 downto 0) + ); + +--R4: entity work.Char_MSB +--port map( +-- clock => clk6, +-- Address => char_addr, +-- q => char_data(3 downto 0) +-- ); + +P4: entity work.sprom +generic map( + init_file => "rtl/roms/033280_p4.hex", + widthad_a => 9, + width_a => 4) +port map( + clock => clk6, + Address => char_addr, + q => char_data(7 downto 4) + ); + +--P4: entity work.Char_LSB +--port map( +-- clock => clk6, +-- Address => char_addr, +-- q => char_data(7 downto 4) +-- ); + + +-- 74LS166 video shift register +R3: process(clk6, P3_3, VBlank_n_s, char_data) +begin + if VBlank_n_s = '0' then -- Connected Clear input + shift_data <= (others => '0'); + elsif rising_edge(clk6) then + if P3_3 = '0' then -- Parallel load + shift_data <= char_data; + else + shift_data <= shift_data(6 downto 0) & '0'; + end if; + end if; + QH <= shift_data(7); +end process; + + +-- 9316 counter at R2 +-- CEP and CET tied to ground, counter is used only as a synchronous latch +R2: process(clk6, R7_12, display(7), H256, Hblank, Vblank, Hsync, Vsync) +begin + if rising_edge(clk6) then + if R7_12 = '0' then + H256_s <= H256; + Display7_s <= display(7); + CompBlank_s <= (Hblank or Vblank); + CompSync_n_s <= not(Hsync or Vsync); + end if; + end if; +end process; + +Playfield_n <= not(QH and Display7_s); + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/pll.v b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/pll.v new file mode 100644 index 00000000..6a352243 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/pll.v @@ -0,0 +1,337 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.4 Build 182 03/12/2014 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2014 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll ( + inclk0, + c0, + c1, + locked); + + input inclk0; + output c0; + output c1; + output locked; + + wire [4:0] sub_wire0; + wire sub_wire2; + wire [0:0] sub_wire6 = 1'h0; + wire [0:0] sub_wire3 = sub_wire0[0:0]; + wire [1:1] sub_wire1 = sub_wire0[1:1]; + wire c1 = sub_wire1; + wire locked = sub_wire2; + wire c0 = sub_wire3; + wire sub_wire4 = inclk0; + wire [1:0] sub_wire5 = {sub_wire6, sub_wire4}; + + altpll altpll_component ( + .inclk (sub_wire5), + .clk (sub_wire0), + .locked (sub_wire2), + .activeclock (), + .areset (1'b0), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "AUTO", + altpll_component.clk0_divide_by = 125, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 224, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 125, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 56, + altpll_component.clk1_phase_shift = "0", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 37037, + altpll_component.intended_device_family = "Cyclone III", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "NORMAL", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_UNUSED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_USED", + altpll_component.port_clk2 = "PORT_UNUSED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "125" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "125" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "48.383999" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "12.096000" +// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps" +// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "224" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "56" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "48.38400000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "12.09600000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: USE_CLK1 STRING "1" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "125" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "224" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "125" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "56" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/quadrature_decoder.vhd b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/quadrature_decoder.vhd new file mode 100644 index 00000000..4e347271 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/quadrature_decoder.vhd @@ -0,0 +1,103 @@ +-------------------------------------------------------------------------------- +-- +-- FileName: quadrature_decoder.vhd +-- Dependencies: None +-- Design Software: Quartus II 64-bit Version 13.1.0 Build 162 SJ Web Edition +-- +-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY +-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY +-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL +-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF +-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS +-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), +-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS. +-- +-- Version History +-- Version 1.0 9/7/2017 Scott Larson +-- Initial Public Release +-- +-------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +ENTITY quadrature_decoder IS + GENERIC( + positions : INTEGER := 16; --size of the position counter (i.e. number of positions counted) + debounce_time : INTEGER := 50_000; --number of clock cycles required to register a new position = debounce_time + 2 + set_origin_debounce_time : INTEGER := 500_000); --number of clock cycles required to register a new set_origin_n value = set_origin_debounce_time + 2 + PORT( + clk : IN STD_LOGIC; --system clock + a : IN STD_LOGIC; --quadrature encoded signal a + b : IN STD_LOGIC; --quadrature encoded signal b + set_origin_n : IN STD_LOGIC; --active-low synchronous clear of position counter + direction : OUT STD_LOGIC; --direction of last change, 1 = positive, 0 = negative + position : BUFFER INTEGER RANGE 0 TO positions-1 := 0); --current position relative to index or initial value +END quadrature_decoder; + +ARCHITECTURE logic OF quadrature_decoder IS + SIGNAL a_new : STD_LOGIC_VECTOR(1 DOWNTO 0); --synchronizer/debounce registers for encoded signal a + SIGNAL b_new : STD_LOGIC_VECTOR(1 DOWNTO 0); --synchronizer/debounce registers for encoded signal b + SIGNAL a_prev : STD_LOGIC; --last previous stable value of encoded signal a + SIGNAL b_prev : STD_LOGIC; --last previous stable value of encoded signal b + SIGNAL debounce_cnt : INTEGER RANGE 0 TO debounce_time; --timer to remove glitches and validate stable values of inputs + SIGNAL set_origin_n_new : STD_LOGIC_VECTOR(1 DOWNTO 0); --synchronizer/debounce registers for the set_origin_n input + SIGNAL set_origin_n_int : STD_LOGIC; --last debounced value of set_origin_n signal + SIGNAL set_origin_cnt : INTEGER RANGE 0 TO set_origin_debounce_time; --debounce counter for set_origin_n signal +BEGIN + + PROCESS(clk) + BEGIN + IF(clk'EVENT AND clk = '1') THEN --rising edge of system clock + + --synchronize and debounce a and b inputs + a_new <= a_new(0) & a; --shift in new values of 'a' + b_new <= b_new(0) & b; --shift in new values of 'b' + IF(((a_new(0) XOR a_new(1)) OR (b_new(0) XOR b_new(1))) = '1') THEN --a input or b input is changing + debounce_cnt <= 0; --clear debounce counter + ELSIF(debounce_cnt = debounce_time) THEN --debounce time is met + a_prev <= a_new(1); --update value of a_prev + b_prev <= b_new(1); --update value of b_prev + ELSE --debounce time is not yet met + debounce_cnt <= debounce_cnt + 1; --increment debounce counter + END IF; + + --synchronize and debounce set_origin_n input + set_origin_n_new <= set_origin_n_new(0) & set_origin_n; --shift in new values of set_origin_n + IF((set_origin_n_new(0) XOR set_origin_n_new(1)) = '1') THEN --set_origin_n input is changing + set_origin_cnt <= 0; --clear debounce counter + ELSIF(set_origin_cnt = set_origin_debounce_time) THEN --debounce time is met + set_origin_n_int <= set_origin_n_new(1); --update value of set_origin_n_int + ELSE --debounce time is not yet met + set_origin_cnt <= set_origin_cnt + 1; --increment debounce counter + END IF; + + --determine direction and position + IF(set_origin_n_int = '0') THEN --inital position is being set + position <= 0; --clear position counter + ELSIF(debounce_cnt = debounce_time --debounce time for a and b is met + AND ((a_prev XOR a_new(1)) OR (b_prev XOR b_new(1))) = '1') THEN --AND the new value is different than the previous value + direction <= b_prev XOR a_new(1); --update the direction + IF((b_prev XOR a_new(1)) = '1') THEN --clockwise direction + IF(position < positions-1) THEN --not at position limit + position <= position + 1; --advance position counter + ELSE --at position limit + --position <= 0; --roll over position counter to zero + null; + END IF; + ELSE --counter-clockwise direction + IF(position > 0) THEN --not at position limit + position <= position - 1; --decrement position counter + ELSE --at position limit + --position <= positions-1; --roll over position counter maximum + null; + END IF; + END IF; + END IF; + + END IF; + END PROCESS; + +END logic; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/006400_m2.hex b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/006400_m2.hex new file mode 100644 index 00000000..9dbfacea --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/006400_m2.hex @@ -0,0 +1,17 @@ +:1000000000000000000000000000000000000000F0 +:1000100000000000000000000000000000000000E0 +:1000200000000000000000000000000000000000D0 +:1000300000000000000000000000000000000000C0 +:1000400000000000000000000000000000000000B0 +:1000500000000000000000000000000000000000A0 +:100060000000000000000000000000000000000090 +:100070000000000000000000000000000000000878 +:100080000A0A0A0A0A0E0000000000000000000030 +:100090000000000000000000000000000000000060 +:1000A0000000000000000000000000000000000050 +:1000B0000000000000000000000000000000000040 +:1000C0000000000000000000000000000000000030 +:1000D0000000000000000000000000000000000020 +:1000E0000808080808080808080808080808080A8E +:1000F0000A0A0B0B0B0A0A0A0A0A0A0A0A0A0A0A5D +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/006401_e2.hex b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/006401_e2.hex new file mode 100644 index 00000000..975d72ea --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/006401_e2.hex @@ -0,0 +1,3 @@ +:100000001111010141418181C1C12121E1E1E1E100 +:10001000E0E0E8E8E4E4ECECE2E2EAEAE6E6EEEE70 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033280_p4.hex b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033280_p4.hex new file mode 100644 index 00000000..743eadb7 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033280_p4.hex @@ -0,0 +1,33 @@ +:1000000000000000000000000F0F0202020F0F00AE +:100010000F0F0909090F060003070C08080C04005C +:100020000F0F08080C0703000F0F09090908080043 +:100030000F0F01010101000003070C08090F0F0059 +:100040000F0F0101010F0F0008080F0F0808000033 +:10005000040C0808080F07000F0F03070E0C080018 +:100060000F0F0808080808000F0F0103010F0F0009 +:100070000F0F0103070F0F00070F0808080F0700F5 +:100080000F0F020202030100070F080A0E070B0000 +:100090000F0F02060F0D0900040D0909090F0600D4 +:1000A00000000F0F00000000070F0808080F0700EE +:1000B0000103070E070301000F0F0703070F0F00CF +:1000C0000C0E0703070E0C0000010F0F01000000CB +:1000D0000C0E0F0B090808000000000000000000D3 +:1000E0000000000000000000000000000000000010 +:1000F0000000000000000000000000000000000000 +:1001000000000000000000000300000000000000EC +:1001100003030000000000000303030000000000D0 +:1001200003030303000000000303030303000000B4 +:100130000303030303030000030303030303030098 +:100140000303030303030303000303030303030382 +:10015000000003030303030300000003030303037E +:10016000000000000303030300000000000303037A +:100170000000000000000303000000000000000376 +:1001800003070C080807030008080F0F0808000001 +:100190000C0E0F0B0B090800040C0909090F0600CF +:1001A000030302020F0F0200040C0808080F0700E7 +:1001B000070F0909090F060000000E0F01000000DB +:1001C0000609090B0B0E0600000909090D070300BB +:1001D000000000000000000003000F0F0F0F0F0FC2 +:1001E00003030F0F0F0F0F0F00000F0F0F0F0F0F55 +:1001F00000000F0F0F0F0F0F0F0F0F0F0F0F0F0F2D +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033281_r4.hex b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033281_r4.hex new file mode 100644 index 00000000..000d461b --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033281_r4.hex @@ -0,0 +1,33 @@ +:100000000000000000000000080C0602060C0800BA +:100010000E0E0202020E0C00080C0602020604007C +:100020000E0E0202060C08000E0E02020202000072 +:100030000E0E020202020200080C06020202020078 +:100040000E0E0000000E0E0002020E0E0202000054 +:1000500000000000000E0E000E0E00080C0602004C +:100060000E0E0000000000000E0E0C080C0E0E001C +:100070000E0E0C08000E0E000C0E0202020E0C00FA +:100080000E0E0202020E0C000C0E0202020E0C00FA +:100090000E0E0202020E0C000C0E020206040000FC +:1000A00002020E0E020200000E0E0000000E0E00F4 +:1000B0000E0E0000000E0E000E0E0008000E0E00C8 +:1000C000060E0C080C0E06000E0E00000E0E0000B0 +:1000D0000202020A0E0E06000000000000000000EE +:1000E0000000000000000000000000000000000010 +:1000F0000000000000000000000000000000000000 +:1001000000000000000000000F00000000000000E0 +:100110000F0F0000000000000F0F0F000000000094 +:100120000F0F0F0F000000000F0F0F0F0F00000048 +:100130000F0F0F0F0F0F00000F0F0F0F0F0F0F00FC +:100140000F0F0F0F0F0F0F0F000F0F0F0F0F0F0FCE +:1001500000000F0F0F0F0F0F0000000F0F0F0F0FFA +:10016000000000000F0F0F0F00000000000F0F0F26 +:100170000000000000000F0F000000000000000F52 +:10018000080C0202060C080000040E0E000000001D +:10019000040602020A0E0C000002020A0E06020009 +:1001A00000080C060E0E00000E0E0A0A0A0A0000D5 +:1001B000080C060202020000060602020A0E0600F1 +:1001C0000C0E0A02020C00000C0E0202020E0C00C1 +:1001D00000000000000000000F000F0F0F0F0F0FB6 +:1001E0000F0F0F0F0F0F0F0F00000F0F0F0F0F0F3D +:1001F00000000C0C0C0C0C0C0C0C0C0C0C0C0C0C57 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033282_k6.hex b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033282_k6.hex new file mode 100644 index 00000000..0e7a352d --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033282_k6.hex @@ -0,0 +1,3 @@ +:10000000E0E0E00000000000000000000000000050 +:1000100000000000000000000000000000000000E0 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033453_c1.hex b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033453_c1.hex new file mode 100644 index 00000000..dfc82906 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033453_c1.hex @@ -0,0 +1,129 @@ +:10000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +:10001000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0 +:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 +:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0 +:10004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 +:10005000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0 +:10006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0 +:10007000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90 +:10008000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80 +:10009000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70 +:1000A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60 +:1000B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50 +:1000C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40 +:1000D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF30 +:1000E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20 +:1000F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10 +:10010000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +:10011000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF +:10012000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF +:10013000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF +:10014000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF +:10015000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF +:10016000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F +:10017000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F +:10018000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F +:10019000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F +:1001A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F +:1001B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F +:1001C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F +:1001D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F +:1001E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F +:1001F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0F +:10020000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE +:10021000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEE +:10022000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDE +:10023000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCE +:10024000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBE +:10025000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAE +:10026000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E +:10027000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E +:10028000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E +:10029000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E +:1002A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E +:1002B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E +:1002C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3E +:1002D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E +:1002E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E +:1002F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0E +:10030000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD +:10031000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED +:10032000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDD +:10033000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD +:10034000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD +:10035000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD +:10036000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9D +:10037000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D +:10038000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7D +:10039000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D +:1003A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D +:1003B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D +:1003C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3D +:1003D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2D +:1003E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1D +:1003F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0D +:100400004C8D3CA201A406A503F01BB525D92700FD +:100410009011992700D007B520D922009005B5206A +:10042000992200CA10E5204F348D300C8D400CE627 +:1004300004A9398539A9398538A206A903853E2042 +:10044000B035202F36A503D004A50ED0D920C9364B +:1004500020082F202432205231A505D0E8A503F032 +:10046000C5A9088511850020C9362C2E083006A59F +:1004700000293FD0F2A9008511E60220F234A5023E +:10048000C50390ADA9008502A9042C32081002A969 +:1004900002C504B09A4C032C206933A538291F38B3 +:1004A000E90F1002A9004A8538A5060A0A0A05388C +:1004B000A8A92D8539A93B8538B1381024B52A1053 +:1004C00003200B3AC940AD5B339003AD5C33853AF2 +:1004D000B52AC980A53A9003200B3A952AA9099517 +:1004E0002BA503F053B138297F8538186509C92039 +:1004F0009002A9208509F8A53818A40588F0076599 +:100500003888F0026538A4027920009920009027ED +:10051000A900792500992500C50AD01BA5021869F4 +:1005200001A80A0A2517D00F9805178517A9108565 +:10053000078508E60EE60ED8C60D600101030385A7 +:10054000858787000001038587000000000103857F +:10055000870000A900853EA21EA9398539A93985E1 +:100560003820B035A9568538A9398539A91FAA85FB +:100570003E4CB035A503F00AA502D06CA504C90114 +:10058000D066A500290FD060AD28082AAD2F082914 +:10059000802A2AC9039002A902C506F0098506A986 +:1005A0000085404C8231AD3208850AAD330829C040 +:1005B000260A260A05062A2A2AAABDE92D850AF056 +:1005C00027A944204937A50A4A4A4A4AF00320AAE3 +:1005D0003EA000913AA50A20AA3EA020913AA9B0D7 +:1005E000A040913AA060913A6000020406091216F8 +:1005F0002000020406081012150002030407091166 +:1006000014A537C902B005A2024C973660A512C9DD +:10061000249004C964900BA51B4A9006E605182A8D +:10062000851BA514C9249004C964900BA51D4A908C +:1006300006E605182A851D60A506C901F0C3B0CDE0 +:10064000A503D004A50BD025A000A52BC9089008B0 +:10065000A91CC53790028537A537C9079067C930EF +:10066000B00DC914900529014C6D2E2903D056A94F +:10067000048539853BA906853CA2248638863AE65E +:100680003AA539C9079006A538C960B036B13A9184 +:1006900038E638E63AA53A291FC91F90F0A50C297B +:1006A00004D0049138F00EA5382920D004A9BFD079 +:1006B00002A9BE9138A53818653CAA90BEE639E675 +:1006C0003BD0B8E60C60A50FD00B2C31087006307B +:1006D00004A904850EA5002907F008C904D0038DDC +:1006E000700C60A50FF0FB2C310850083008E60EA6 +:1006F000E60E1000E60EE60EC60F8D710CA50EC9B3 +:100700001E90DFA91E850E60A204B51910034CE3EC +:100710002FB518C9E8B010C91AB01DB52AC9409044 +:1007200017C9C0B013D00AB52AC9409004C9C090F7 +:100730000720013A952AE608B510D023B52A301FC4 +:10074000200B3A952AA9238536B5192901F002E62E +:1007500005B51929809519A503F004A9088516B5D2 +:1007600010C9F09015B5192901D002C605A98095C8 +:1007700019A506C902D00320382EB5192902D05C6C +:10078000206933A000B138C9BEF00FC9BFD04DA554 +:100790003838E9208538B002C639B5192901D03971 +:1007A000A506F008B51909029519D012A536300E24 +:1007B000A538291F38E53620AD39C904901EA53863 +:1007C000291F8536A503D004A50BD00DA000A900D4 +:1007D0009138A020913820982C20EB2F863F20764E +:1007E00032A63FCACA30034C0A2F60A506C901F0E1 +:1007F0000EB010A536C91ED006B52AC980B0034C6C +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033454_d1.hex b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033454_d1.hex new file mode 100644 index 00000000..ae94647e --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033454_d1.hex @@ -0,0 +1,129 @@ +:10000000823060B5192901F0F6B518290FC906909C +:100010005DC90CB059A000B5102907C904B52AB0B4 +:1000200005200B3AA00248B518290FC909900968A4 +:1000300020013A48980960A8206933A53838E92199 +:100040008538B002C639B138291FD04E683043C94F +:1000500040902F843A9829600901A8B138291FF0EF +:1000600031A53A29020920A8B138291FD02DA506AB +:10007000C902D00EB5102907C904900EB52AC9804F +:10008000B007B52A200B3A952A60B52AC98090F9A5 +:10009000B0F0B52A20013A952A6068B52A1869801F +:1000A000952A60A503D01BA5002940F016A50EC90E +:1000B00004B010AD310829C0F0090A2A2A094020ED +:1000C000493760A9C1204937A606B5271522F0187F +:1000D000A940204937A53A8538A53B8539A9B0857F +:1000E0003AA606E8E820F23560A204A505F062B55C +:1000F00019305AB52B8538B52A48863E20143A491E +:10010000FF18690120B539A63EA53A18753095301B +:10011000A53B7510C9F09006B42A3002A9009510CD +:10012000B52B853868863E20113A49FF18690120B1 +:10013000B539A63EA53A1875319531A53B7518C954 +:10014000E89002A9E8C919B002A9199518CACA10FD +:100150009E60A503F00EA5004A90094A9007A511DC +:100160002903851160A900A609F004C6090904A69F +:1001700008F004C6080902A607F004C607090185AD +:1001800011608D800CA9808519851B851DA90085AE +:100190001120532DA602F640A506F00BC901F0214F +:1001A000C902F0244C8D3CA968850DA9398539A96F +:1001B000738538A21EA91B853E20B035A2164CAC13 +:1001C00035A968850D4CA235A960850D20A235A9F9 +:1001D00001851B851DA9398539A9908538A218A9E3 +:1001E00017853E20B035A9D7852CA929852EA95879 +:1001F000851AA9A0851CA93C85128514A904852D02 +:10020000852F60B13A9138A900913AA020B13A9176 +:1002100038A900913AA000E638E63AA53A291FC964 +:100220001FD0E060A50DD042A506F03EC902D0283F +:10023000A505C901D034A202B5191006A204B5194A +:1002400030168519A9809519B5108510B51885182F +:10025000B52B852BB52A852AA204B5193008B52AF5 +:100260003004B5103005CACA10F060A602B540C906 +:1002700003B0F74C9431A503D020A50129E0D01597 +:10028000B510C9E09013B52A100F200B3A952AA596 +:1002900037C9309042A900850560B51930FBA50625 +:1002A000C901D00AB510C9B59004C9BF900AB510EC +:1002B000C9DD90E5C9E7B0E1A51E186904D518901D +:1002C000D8A51649FF186901853E18651ED518B0D6 +:1002D000C8B52AC98090C2E637D004A9808537E620 +:1002E00007A5374A4AC9049002A903A8B52BC90833 +:1002F000B005B96533952BA503D004A900F014A56A +:100300003E386A186901651E38F518853CA901B0A8 +:1003100002A900853EB52BC9089004A902D01DA5ED +:100320003729FCC90C9004A900F011853DA53C209B +:10033000AD39C903A900B002A902053D053EA8B91F +:100340005933952AB5192901F002E605B519298016 +:100350009519A98085364C382E1C642858285830A9 +:10036000501070107005060607B5101869084A4A43 +:100370004A491F8538A9048539A900853AB5181856 +:10038000690F090749FF0A263A0A263A186538858F +:1003900038A53A6539853960A902853A8538A904B6 +:1003A000853B8539A9BD8D62078D6707A21AA0001C +:1003B000A506C901D002A005843CA53A186920858C +:1003C0003A9002E63BA900A8913AA43C913ACAD0DF +:1003D000E9A516F079A51E49FF4A4A4AAACACAA544 +:1003E0003818692085389002E639CAD0F2A51E294E +:1003F0000749FF853B1869B0A0009138A43C9138AB +:10040000A53818692085389002E639A51618653B8D +:10041000F03CC909901A38E908853BA9A89138A091 +:10042000009138A5381869208538A53B9002E63937 +:100430001869A0AAA538C960900BA539C907D005CD +:100440008A18691AAA8AA0009138A43C913860A938 +:1004500080851985478548A9008540854185168591 +:10046000038505850285048501A50ED014A50BF032 +:1004700004C60BD00BC6061004A90285064C8231B7 +:1004800060A90E8516A5170A0A851720C93620749B +:100490002DA5002910D0088D300C8D400CF010A532 +:1004A0000EC902900A8D310CC90490038D410C2CA9 +:1004B00080083022A50EC90490D138E904850EA920 +:1004C000028503A902850BA9008520852185258544 +:1004D0002685404C823170B3A50EC90290ADC60E80 +:1004E000C60EA9018503A5172908F0D7A904851709 +:1004F000D0D1A503C902B00160A900850DA60CA545 +:10050000468646850CA61BA547851B8647A61DA5C6 +:1005100048851D864820E631A000843BA949853ADC +:10052000A9278538A9048539A207A900853CB13AD5 +:10053000853DB138C9BED00338B00118663CE638F5 +:10054000CA10EFA53C913AA207C638263DB00AA9C9 +:10055000009138A0209138D00CE60DA9BE9138A9A1 +:10056000BFA0209138A000CA10DFE63AA53818696C +:100570000885389002E639291FC91FD0ABA5381865 +:10058000692885389002E639A539C907909AA538B7 +:10059000C9609094A504C901D007C502D0034C825C +:1005A0003160A9398539A9738538A21AA913853E06 +:1005B000A904853B8A853A48A96020493768AACAB8 +:1005C0003004E43EB0EA60A0B0C502D00EAAA50394 +:1005D000F008A5002910D002A0008A843AAAD00A07 +:1005E000A9608538A9048539D008A9068539A9A04C +:1005F0008538A900A0209138A0009138B525F016C3 +:1006000029F0F0084A4A4A4A053A9138B525290F97 +:10061000053AA0209138B52029F04A4A4A4A053ABD +:10062000A0409138B520290F053AA060913860A507 +:1006300003F022A90E8516A9C120493720C936200A +:10064000742D2C2E08300EA50029108D110CF0EC05 +:100650008D100CD0E7A90085378D110CA9C4204955 +:1006600037A900A8913AA020913AA040913AA06001 +:10067000913AA500098029E1850020C936A50FD04F +:1006800004A500D0F5A504C901D004A900850CA2D9 +:1006900000860786088609E60520E239C920B002EF +:1006A000A920C9E09002A9E0951820E2392938C9AB +:1006B00020F0F71869A0952AA9809510A90295192C +:1006C000A904952BA980853660AD000CC9D8B0F976 +:1006D000AD000CC9D890F9E600D002E6018D800C7F +:1006E000A516186915853EA51FC53EB004A63E9007 +:1006F0001CC9E89004A2E7D014AA38E51EA820ADD2 +:1007000039C902900AD006CA981002E8E8861E206D +:10071000E930209833A503F006A504290F09B08D10 +:10072000A005A90020C735A901A603F004C503F060 +:100730000320C73520E23920C62E20A3308D510C6E +:10074000ADC00830034CB13C60A200A000863C86DE +:100750003D182A263C2A263D4AAA2940D026BDD14A +:1007600037853ABDD237853B8A0A0A8538AD3008CD +:1007700029C04A4A4A4A4A0538AABDA9378538BD20 +:10078000AA378539B138F020A63CF004A900F0065C +:10079000A63DF0020980A200813AA53A1869208599 +:1007A0003A9002E63BC810DC60DB37E837F93709DE +:1007B000381338243839384D386138723887389BC7 +:1007C00038AD38BE38D338E738FA380939183929FE +:1007D00039A104A104A104A1048404204849474884 +:1007E0002053434F52452000424553544520505515 +:1007F0004E4B545A41484C20004D45494C4C4555B0 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033455_e1.hex b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033455_e1.hex new file mode 100644 index 00000000..09d17ca8 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/033455_e1.hex @@ -0,0 +1,129 @@ +:10000000522053434F5245200020205245434F5227 +:100010004420003120434F494E203220504C41595A +:100020004552530031204D55454E5A4520322053FC +:100030005049454C4552202000203120504945432D +:10004000452032204A4F5545555253200031204615 +:10005000494348412032204A554741444F52455375 +:10006000003120434F494E20203120504C4159450A +:10007000520031204D55454E5A45202031205350D5 +:1000800049454C45522000203120504945434520E8 +:100090002031204A4F5545555220003120464943D2 +:1000A00048412031204A554741444F5200322043B5 +:1000B0004F494E53203120504C4159455200322077 +:1000C0004D55454E5A454E203120535049454C45DB +:1000D0005220002032205049454345532031204AC8 +:1000E0004F55455552200032204649434841532040 +:1000F00031204A554741444F520020202020424F92 +:100100004E555320464F52200020465245494553F4 +:1001100020535049454C20005041525449452047F6 +:100120005241545549544520005041525449444F7E +:100130002047524154495320003D202020202020B8 +:1001400020202020202020202020202020202020AF +:10015000202020203D003E7F7F7F7F7F7F7F7F7F2D +:100160007F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F9F +:100170007F3F003D3E3F3E3F3E3F3E3F3E3F3E3F96 +:100180003E3F3E3F3E3F3E3F3E3F3E3F3E3F3D00C7 +:100190003D3E3F3E3F3E3F202020203E3F3E3F3EF3 +:1001A0003F202020203E3F3E3F3E3F3D001005497E +:1001B000FF18690160853CA900853D853A853BA50E +:1001C0003C1004A9FF853D4638B003D00E6018A549 +:1001D0003A653C853AA53B653D853B063C263D4C52 +:1001E000C739061326151002E613A5132902F006D7 +:1001F000A51349018513A5150513D002E613A51310 +:100200006038E940200B3A1869406049FF186901DD +:100210006038E9404A4AAABD1B3A60000D192531F1 +:100220003C47515B636A71767A7E7F7F7F7E7A7608 +:10023000716A635B51473C3125190D00F3E7DBCF51 +:10024000C4B9AFA59D968F8A868281818182868A74 +:100250008F969DA5AFB9C4CFDBE7F3000000000087 +:10026000000000000000000000000000000000008E +:10027000000000000000000000000000000000007E +:10028000000000000000000000000000000000006E +:10029000000000000000000000000000000000005E +:1002A000000000000000000000000000000000004E +:1002B000000000000000000000000000000000003E +:1002C000000000000000000000000000000000002E +:1002D000000000000000000000000000000000001E +:1002E000000000000000000000000000000000000E +:1002F00000000000000000000000000000000000FE +:1003000000000000000000000000000000000000ED +:1003100000000000000000000000000000000000DD +:1003200000000000000000000000000000000000CD +:1003300000000000000000000000000000000000BD +:1003400000000000000000000000000000000000AD +:10035000000000000000000000000000000000009D +:10036000000000000000000000000000000000008D +:10037000000000000000000000000000000000007D +:10038000000000000000000000000000000000006D +:10039000000000000000000000000000000000005D +:1003A000000000000000000000000000000000004D +:1003B000000000000000000000000000000000003D +:1003C000000000000000000000000000000000002D +:1003D000000000000000000000000000000000001D +:1003E000000000000000000000000000000000000D +:1003F00000000000000000000000000000000000FD +:10040000488D000E58AD000C2920F00268408A4843 +:10041000D8BABD0501C92C9045C944B041AD4008CA +:10042000A2012A26432A2642B542D00CB544F01830 +:10043000D644D014E60FD01029FCC9F8D00AB54430 +:10044000F002E60FA9209544CA10DDADC00829408E +:10045000D008854285438544854568AA68404C8D0F +:100460003C48D8AD000C49FF38E948B006A90085E2 +:100470001FF0121006A9FF851FD00A851FAD0010BE +:1004800049FF2A261F8D500C8D600C6840D8A27F32 +:100490009AA9008D500C8D600C8D700CAA9500E807 +:1004A000D0FBA9FF851B851DADC0081004584C0367 +:1004B0002C78A2008E500C8E600C8A1869049D0066 +:1004C000041869019D00051869019D00061869015D +:1004D0009D00078D800CE8D0E18A1869045D000456 +:1004E000D0338A1869055D0005D02A8A1869065D2F +:1004F0000006D0218A1869075D0007D0188D800C8E +:10050000E8D0D68A9D00049D00059D00069D000749 +:10051000E8D0F1F032386AF023A2089002A20186F6 +:1005200011A200A000E8D0FD8D800CC8D0F7861184 +:10053000E8D0FD8D800CC8D0F718F0DA8D800C2C37 +:10054000C00810F84C8D3CA90085118D310C8D41EF +:100550000C8D100CA9E4853AA904853BA92C853F94 +:10056000A200A9048538A900853EA8A955513EC816 +:10057000D0FB8D800CE63FC638D0F2DDA43EF03CC7 +:100580005DA43E853C4A4A4A4A20AA3EC63A913A70 +:10059000A53C20AA3EA020913AA000E63AA9928D5F +:1005A0006404A98F8D8404A98D8DA4048A09B09157 +:1005B0003AA53A186960853A9002E63BE8E005D032 +:1005C000A1A53BC904D006A53AC9E4F010A98291BF +:1005D0003AA020A981913AA040A984913AA9008526 +:1005E0003CADC0088538AD2E088539AD8008853A08 +:1005F000AD28082AAD2F086A29C0853BAD40088583 +:100600003DAD000CC9FAB0F9AD000CC9FA90F9E69D +:10061000008D800C8D510CA51F20AA3E8DC005A514 +:100620001F4A4A4A4A20AA3E8DA005A611A53CD0E1 +:1006300011A500291FD0128A0A290FD002A901AAE8 +:10064000D007A5002901D051AAADC00845382940DE +:10065000F002A281AD2E0845392980F002A282ADB8 +:100660008008453A29C0F002A284AD28082AAD2F9F +:10067000086A29C0C53B853BF00D0A2A2AAAA910A1 +:100680004ACA10FC0980AAAD4008453D29C0F002C5 +:10069000A28886118A1002853C2CC00830034C01C8 +:1006A0003E4C8D3C92D8D234AA16290F09B0C9BA53 +:1006B000900338E9396000000000000000000000ED +:1006C000000000000000000000000000000000002A +:1006D000000000000000000000000000000000001A +:1006E000000000000000000000000000000000000A +:1006F00000000000000000000000000000000000FA +:1007000000000000000000000000000000000000E9 +:1007100000000000000000000000000000000000D9 +:1007200000000000000000000000000000000000C9 +:1007300000000000000000000000000000000000B9 +:1007400000000000000000000000000000000000A9 +:100750000000000000000000000000000000000099 +:100760000000000000000000000000000000000089 +:100770000000000000000000000000000000000079 +:100780000000000000000000000000000000000069 +:100790000000000000000000000000000000000059 +:1007A0000000000000000000000000000000000049 +:1007B0000000000000000000000000000000000039 +:1007C0000000000000000000000000000000000029 +:1007D0000000000000000000000000000000000019 +:1007E0000000000000000000000000000000000009 +:1007F00000000000000000000000613C8D3C003C57 +:00000001FF diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/roms.rar b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/roms/roms.rar new file mode 100644 index 0000000000000000000000000000000000000000..4340f581bc61f39f2a0c59d129ce1093087163ec GIT binary patch literal 35063 zcmeFZ1yCjJmZpolySux)yL;j8Ubwp!?(PnSQ)uB(xVyW%yIrdO(`V*%pN@N{r{~U0 zL=!=I6j8kZRXfZ+2GBXa`>JsU?uIu~rpHW2X-6Jr~w)WlcDUp0+XYde3XQ!7UN_|hYylrCKh=}ifp2I z9|jM^twZr#uTUUyeIh*A5@of!*AD{4 zeg|+e!;<{K^Za50i?DPNoa(xuzWs6`r)z^RBFl4dUTU@{3tOh!=a3IXc=%n9VyJ8x z#u7q-46SD0sgmtakUQFCP`7O*v8sC4mw89Dx{~2zKvKW6?CmcQ?TJ*6h30x@gv6rSHZp;B(t|3)%i&u%84 zC7`WVtI*ZN?h4Ak)+Frs)xqg`Sm4a+uH_X^^=)rHlq7l zzO(gG7V6Is!Ng7l?!(9_pv))cf*Q%AvyjbIizUGtQ zzOYM&2Sla`=}OHbg0YYq*mZp$Mftl6{1-d^Lg2A#RC2dGtUNlur-zBfq z9(sWqv@hXR3pyk;H`R9(5SnU1fmDITwz6Ph%q+P<%L zqDQmiA)AYMypG*NV1f){LvicP@{>ewLvZfz*vX5%afPgTG`NsMh!1V(-bUsEW*XoH z<1)2LU?4G@f(MD4!Ve3{2qHSP&3lzh&2qE$r+K+N9>$TMJ+v|~6dzH@J73RiwRzdE z8nQ_389E>u8l>`Q*lpoZAF!|BJ_>!S!CxM!=^9!`6nzn(udtj$+~JE~Em2YhhBoq| zNgIRs7VcY*rL&hB{p0q!3PQzA^fd33C`Wy|KtsEi-W3>Va9NShI(CVe9vm5^g=iFT zULJ``EyUPjcc6<>_;Hdccfw&U$`!f$;DDRh1|VHxuJ0O<1j@EM{nt+dMtqt#PNWH0~g&)i+Yr*F!j&yTJGu(`n@nUwK5ez-!LG3!OvFgZF4n7jdVJ{ z4$n5Yj}O=~T9M}A+!RGII?Cs$4~&`Fuc=)+T+^gw;n;84~s9(0G94EtrZGp z_1F5M1JW`fiwO>zNb@tM2`FwP)-(AgPK3u)M0&FfSiuZQNJ_}q?7%}%Ufbr^TYdL&&si#Esbl&g<&B8g6Aeu2~A>Nc_L;IQA@62$z{Z_2IGGFV2+ zTp;^0xwmnt0tG=Ai(pk1AO_&n}57I2!wcd4&v6Y+41RnWI zQf!y;>bv+BEmAg*l8 z66k*F8(wTbz$rVk5d`C2$1Q17%|oipc_j?Jg-%jUmVNZAl5w%!oI7anbj+Impa!@# z4P{KpLI`?u5=>^WdYdpr^`~Y?N=|fU2Ku3Sx4ZLI9t3*0TAZzUz7(0VI(rUHJQcOf zyE`c?j7+YRmQA{F=YIB;#=h)(kMz+seX8ddA9ANy=GnJ2G*v}KzE=*y z41t$nzV$owk-6e@ zGhU-i!r$OowuNA`Gi*)=jDfcY5mHRT z@4;<)T$MasjA!w`PBB9ccZm7;KLoJl&f72^5WG2 zDt@Fq3|?~BDE3nKEck$%p3ot)&oKz;eP17aNd6c!#`rA1)PJkRpXK-Ws{&IwX

A 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 K4MG$i;(q`-)_u$X literal 0 HcmV?d00001 diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/scandoubler.sv b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/scandoubler.sv new file mode 100644 index 00000000..0213d20c --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/scandoubler.sv @@ -0,0 +1,195 @@ +// +// scandoubler.v +// +// Copyright (c) 2015 Till Harbaum +// Copyright (c) 2017 Sorgelig +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// TODO: Delay vsync one line + +module scandoubler #(parameter LENGTH, parameter HALF_DEPTH) +( + // system interface + input clk_sys, + input ce_pix, + input ce_pix_actual, + + input hq2x, + + // shifter video interface + input hs_in, + input vs_in, + input line_start, + + input [DWIDTH:0] r_in, + input [DWIDTH:0] g_in, + input [DWIDTH:0] b_in, + input mono, + + // output interface + output reg hs_out, + output vs_out, + output [DWIDTH:0] r_out, + output [DWIDTH:0] g_out, + output [DWIDTH:0] b_out +); + + +localparam DWIDTH = HALF_DEPTH ? 2 : 5; + +assign vs_out = vs_in; + +reg [2:0] phase; +reg [2:0] ce_div; +reg [7:0] pix_len = 0; +wire [7:0] pl = pix_len + 1'b1; + +reg ce_x1, ce_x4; +reg req_line_reset; +wire ls_in = hs_in | line_start; +always @(negedge clk_sys) begin + reg old_ce; + reg [2:0] ce_cnt; + + reg [7:0] pixsz2, pixsz4 = 0; + + old_ce <= ce_pix; + if(~&pix_len) pix_len <= pix_len + 1'd1; + + ce_x4 <= 0; + ce_x1 <= 0; + + // use such odd comparison to place c_x4 evenly if master clock isn't multiple 4. + if((pl == pixsz4) || (pl == pixsz2) || (pl == (pixsz2+pixsz4))) begin + phase <= phase + 1'd1; + ce_x4 <= 1; + end + + if(~old_ce & ce_pix) begin + pixsz2 <= {1'b0, pl[7:1]}; + pixsz4 <= {2'b00, pl[7:2]}; + ce_x1 <= 1; + ce_x4 <= 1; + pix_len <= 0; + phase <= phase + 1'd1; + + ce_cnt <= ce_cnt + 1'd1; + if(ce_pix_actual) begin + phase <= 0; + ce_div <= ce_cnt + 1'd1; + ce_cnt <= 0; + req_line_reset <= 0; + end + + if(ls_in) req_line_reset <= 1; + end +end + +reg ce_sd; +always @(*) begin + case(ce_div) + 2: ce_sd = !phase[0]; + 4: ce_sd = !phase[1:0]; + default: ce_sd <= 1; + endcase +end + +`define BITS_TO_FIT(N) ( \ + N <= 2 ? 0 : \ + N <= 4 ? 1 : \ + N <= 8 ? 2 : \ + N <= 16 ? 3 : \ + N <= 32 ? 4 : \ + N <= 64 ? 5 : \ + N <= 128 ? 6 : \ + N <= 256 ? 7 : \ + N <= 512 ? 8 : \ + N <=1024 ? 9 : 10 ) + +localparam AWIDTH = `BITS_TO_FIT(LENGTH); +Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x +( + .clk(clk_sys), + .ce_x4(ce_x4 & ce_sd), + .inputpixel({b_in,g_in,r_in}), + .mono(mono), + .disable_hq2x(~hq2x), + .reset_frame(vs_in), + .reset_line(req_line_reset), + .read_y(sd_line), + .read_x(sd_h_actual), + .outpixel({b_out,g_out,r_out}) +); + +reg [10:0] sd_h_actual; +always @(*) begin + case(ce_div) + 2: sd_h_actual = sd_h[10:1]; + 4: sd_h_actual = sd_h[10:2]; + default: sd_h_actual = sd_h; + endcase +end + +reg [10:0] sd_h; +reg [1:0] sd_line; +always @(posedge clk_sys) begin + + reg [11:0] hs_max,hs_rise,hs_ls; + reg [10:0] hcnt; + reg [11:0] sd_hcnt; + + reg hs, hs2, vs, ls; + + if(ce_x1) begin + hs <= hs_in; + ls <= ls_in; + + if(ls && !ls_in) hs_ls <= {hcnt,1'b1}; + + // falling edge of hsync indicates start of line + if(hs && !hs_in) begin + hs_max <= {hcnt,1'b1}; + hcnt <= 0; + if(ls && !ls_in) hs_ls <= {10'd0,1'b1}; + end else begin + hcnt <= hcnt + 1'd1; + end + + // save position of rising edge + if(!hs && hs_in) hs_rise <= {hcnt,1'b1}; + + vs <= vs_in; + if(vs && ~vs_in) sd_line <= 0; + end + + if(ce_x4) begin + hs2 <= hs_in; + + // output counter synchronous to input and at twice the rate + sd_hcnt <= sd_hcnt + 1'd1; + sd_h <= sd_h + 1'd1; + if(hs2 && !hs_in) sd_hcnt <= hs_max; + if(sd_hcnt == hs_max) sd_hcnt <= 0; + + // replicate horizontal sync at twice the speed + if(sd_hcnt == hs_max) hs_out <= 0; + if(sd_hcnt == hs_rise) hs_out <= 1; + + if(sd_hcnt == hs_ls) sd_h <= 0; + if(sd_hcnt == hs_ls) sd_line <= sd_line + 1'd1; + end +end + +endmodule diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/sprom.vhd b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/sprom.vhd new file mode 100644 index 00000000..a81ac959 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/sprom.vhd @@ -0,0 +1,82 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY sprom IS + GENERIC + ( + init_file : string := ""; + widthad_a : natural; + width_a : natural := 8; + outdata_reg_a : string := "UNREGISTERED" + ); + PORT + ( + address : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + clock : IN STD_LOGIC ; + q : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); +END sprom; + + +ARCHITECTURE SYN OF sprom IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + address_aclr_a : STRING; + clock_enable_input_a : STRING; + clock_enable_output_a : STRING; + init_file : STRING; + intended_device_family : STRING; + lpm_hint : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_reg_a : STRING; + widthad_a : NATURAL; + width_a : NATURAL; + width_byteena_a : NATURAL + ); + PORT ( + clock0 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q <= sub_wire0(width_a-1 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_aclr_a => "NONE", + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + init_file => init_file, + intended_device_family => "Cyclone III", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 2**widthad_a, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => outdata_reg_a, + widthad_a => widthad_a, + width_a => width_a, + width_byteena_a => 1 + ) + PORT MAP ( + clock0 => clock, + address_a => address, + q_a => sub_wire0 + ); + + + +END SYN; diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/super_breakout.vhd b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/super_breakout.vhd new file mode 100644 index 00000000..6eda769b --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/super_breakout.vhd @@ -0,0 +1,254 @@ +-- Top level file for FPGA implementation of Super Breakout arcade game by Atari +-- (c) 2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +-- Targeted to EP2C5T144C8 mini board but porting to nearly any FPGA should be fairly simple +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity super_breakout is +port( + clk_12 : in std_logic; -- 50MHz input clock + Reset_n : in std_logic; -- Reset (Active low) + Coin1_I : in std_logic; -- Coin switches + Coin2_I : in std_logic; + Start1_I : in std_logic; -- Player start buttons + Start2_I : in std_logic; + Serve_I : in std_logic; + Select1_I : in std_logic; -- Select inputs from game type select knob + Select2_I : in std_logic; + Test_I : in std_logic; -- Self test switch + Slam_I : in std_logic; -- Slam switch + Enc_A : in std_logic; -- Rotary encoder, used in place of a pot to control the paddle + Enc_B : in std_logic; + Pot_Comp1_I : in std_logic; -- If you want to use a pot instead, this goes to the output of the comparator + VBlank_O : out std_logic; -- VBlank signal to reset the ramp genrator used by the pot reading circuitry + Lamp1_O : out std_logic; -- Player start button lamps (Active high to control incandescent lamps via SCR or transistors) + Lamp2_O : out std_logic; + Serve_LED_O : out std_logic; -- Serve button LED (Active low) + Counter_O : out std_logic; -- Coin counter output (Active high) + Audio_O : out std_logic_vector(7 downto 0); -- PWM audio, low pass filter is desirable but not really necessary for the simple SFX in this game + Video_O : out std_logic; -- Video output, sum this through a 470R resistor to composite video + HS : out std_logic; + VS : out std_logic; + HB : out std_logic; + VB : out std_logic; + CompSync_O : out std_logic); -- Composite sync, sum this through a 1k resistor to composite video +end super_breakout; + +architecture rtl of super_breakout is + +signal clk_6 : std_logic; +signal phi2 : std_logic; + +signal reset_h : std_logic; + +signal NMI_n : std_logic; +signal Timer_Reset_n : std_logic; +signal IntAck_n : std_logic; +signal IO_wr : std_logic; +signal Adr : std_logic_vector(9 downto 0); +signal Inputs : std_logic_vector(1 downto 0); + +-- Video timing signals +signal Hcount : std_logic_vector(8 downto 0) := (others => '0'); +signal H256 : std_logic; +signal H256_s : std_logic; +signal H256_n : std_logic; +signal H128 : std_logic; +signal H64 : std_logic; +signal H32 : std_logic; +signal H16 : std_logic; +signal H8 : std_logic; +signal H8_n : std_logic; +signal H4 : std_logic; +signal H4_n : std_logic; +signal H2 : std_logic; +signal H1 : std_logic; + +signal Vcount : std_logic_vector(7 downto 0) := (others => '0'); +signal V128 : std_logic; +signal V64 : std_logic; +signal V32 : std_logic; +signal V16 : std_logic; +signal V8 : std_logic; +signal V4 : std_logic; +signal V2 : std_logic; +signal V1 : std_logic; + +signal Hsync : std_logic; +signal Vsync : std_logic; +signal Vblank : std_logic; +signal Vreset : std_logic; +signal Vblank_s : std_logic; +signal Vblank_n_s : std_logic; +signal HBlank : std_logic; +signal CompBlank_s : std_logic; +signal CompSync_n_s : std_logic; + +-- Video output signals +signal Playfield_n : std_logic; +signal Ball1_n : std_logic := '1'; +signal Ball2_n : std_logic := '1'; +signal Ball3_n : std_logic := '1'; + +signal Display : std_logic_vector(7 downto 0); + +signal Tones_n : std_logic; + +signal SW2 : std_logic_vector(7 downto 0) := (others => '0'); +signal Mask1_n : std_logic; +signal Mask2_n : std_logic; +signal Sense1 : std_logic; +signal Sense2 : std_logic; + +begin +-- Configuration DIP switches, these can be brought out to external switches if desired +-- See Super Breakout manual page 13 for complete information. Active low (0 = On, 1 = Off) +-- 1 2 Language (00 - English) +-- 3 4 Coins per play (10 - 1 Coin, 1 Play) +-- 5 3/5 Balls (1 - 3 Balls) +-- 6 7 8 Bonus play (011 - 600 Progressive, 400 Cavity, 600 Double) + +SW2 <= "00101011"; + +-- Video mixer +Video_O <= not(Playfield_n and Ball1_n and Ball2_n and Ball3_n); +CompSync_O <= CompSync_n_s; +HS <= Hsync; +VS <= Vsync; +HB <= Hblank; +VB <= Vblank; + +Reset_h <= (not Reset_n); -- Some components need an active-high reset +Vblank_O <= Vblank; -- Resets ramp in analog paddle circuit (if used) + + +Vid_sync: entity work.synchronizer +port map( + clk_12 => clk_12, + clk_6 => clk_6, + hcount => hcount, + vcount => vcount, + hsync => hsync, + hblank => hblank, + vblank_s => vblank_s, + vblank_n_s => vblank_n_s, + vblank => vblank, + vsync => vsync, + vreset => vreset + ); + +PF: entity work.playfield +port map( + Clk6 => clk_6, + Display => Display, + HCount => HCount, + VCount => VCount, + H256_s => H256_s, + HBlank => HBlank, + VBlank => VBlank, + VBlank_n_s => VBlank_n_s, + HSync => HSync, + VSync => VSync, + CompSync_n_s => CompSync_n_s, + CompBlank_s => CompBlank_s, + Playfield_n => Playfield_n + ); + +Ball_motion: entity work.motion +port map( + Clk6 => clk_6, + PHI2 => phi2, + Display => Display, + H256_s => H256_s, + VCount => VCount, + HCount => HCount, + Tones_n => Tones_n, + Ball1_n => Ball1_n, + Ball2_n => Ball2_n, + Ball3_n => Ball3_n + ); + +Sounds: entity work.audio +port map( + Reset_n => Reset_n, + Tones_n => Tones_n, + Display => Display(3 downto 0), + VCount => VCount, + Audio_PWM => Audio_O + ); + +Knob: entity work.paddle +port map( + Clk6 => Clk_6, + Enc_A => Enc_A, + Enc_B => Enc_B, + Mask1_n => Mask1_n, + Mask2_n => Mask2_n, + Vblank => Vblank, + Sense1 => Sense1, + Sense2 => Sense2, + NMI_n => NMI_n + ); + +CPU: entity work.cpu_mem +port map( + Clk12 => Clk_12, + Clk6 => Clk_6, + Reset_n => Reset_n, + NMI_n => NMI_n, + VCount => VCount, + HCount => HCount, + Hsync_n => not Hsync, + Timer_Reset_n => Timer_Reset_n, + IntAck_n => IntAck_n, + IO_wr => IO_wr, + Phi2_o => Phi2, + Display => Display, + IO_Adr => Adr, + Inputs => Inputs + ); + +Input_Output: entity work.IO +port map( + clk6 => clk_6, + SW2 => SW2, -- DIP switches + Coin1_n => Coin1_I, + Coin2_n => Coin2_I, + Start1_n => Start1_I, + Start2_n => Start2_I, + Select1_n => Select1_I, + Select2_n => Select2_I, + Serve_n => Serve_I, + Test_n => Test_I, + Slam_n => Slam_I, + Sense1 => Sense1, + Sense2 => Sense2, + Mask1_n => Mask1_n, + Mask2_n => Mask2_n, + Timer_Reset_n => Timer_Reset_n, + IntAck_n => IntAck_n, + IO_wr => IO_wr, + Lamp1 => Lamp1_O, + Lamp2 => Lamp2_O, + Serv_LED_n => Serve_LED_O, + Counter => Counter_O, + Adr => Adr, + Inputs => Inputs + ); + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/super_breakout_mist.sv b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/super_breakout_mist.sv new file mode 100644 index 00000000..20f01e14 --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/super_breakout_mist.sv @@ -0,0 +1,147 @@ +module super_breakout_mist( + output LED, + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_HS, + output VGA_VS, + output AUDIO_L, + output AUDIO_R, + input SPI_SCK, + output SPI_DO, + input SPI_DI, + input SPI_SS2, + input SPI_SS3, + input CONF_DATA0, + input CLOCK_27 +); + +`include "rtl\build_id.sv" + +localparam CONF_STR = { + "S. Breakout;;", + "O1,Test Mode,Off,On;", + "O34,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;", + "T6,Reset;", + "V,v1.00.",`BUILD_DATE +}; + +wire [31:0] status; +wire [1:0] buttons; +wire [1:0] switches; +wire [9:0] kbjoy; +wire [7:0] joystick_0; +wire [7:0] joystick_1; +wire scandoubler_disable; +wire ypbpr; +wire ps2_kbd_clk, ps2_kbd_data; +wire [7:0] audio; +wire video; + +wire clk_48, clk_12; +wire locked; +pll pll +( + .inclk0(CLOCK_27), + .c0(clk_48),//48.384 + .c1(clk_12),//12.096 + .locked(locked) +); + + +super_breakout super_breakout ( + .clk_12(clk_12), + .Reset_n(~(status[0] | status[6] | buttons[1])), + .CompSync_O(), + .HS(hs), + .VS(vs), + .VB(vb), + .HB(hb), + .Video_O(video), + .Audio_O(audio), + .Coin1_I(~kbjoy[7]), + .Coin2_I(~kbjoy[7]), + .Start1_I(~kbjoy[5]), + .Start2_I(~kbjoy[6]), + .Select1_I(), + .Select2_I(), + .Enc_A(), + .Enc_B(), + .Pot_Comp1_I(), + .Slam_I(), + .Serve_I(~kbjoy[4]), + .Test_I(~status[1]), + .Lamp1_O(~LED), + .Lamp2_O(), + .Serve_LED_O(), + .Counter_O() + ); + +dac dac ( + .CLK(clk_48), + .RESET(1'b0), + .DACin(audio), + .DACout(AUDIO_L) + ); + +assign AUDIO_R = AUDIO_L; + +wire hs, vs; +wire hb, vb; +wire blankn = ~(hb | vb); +video_mixer #(.LINE_LENGTH(480), .HALF_DEPTH(1)) video_mixer +( + .clk_sys(clk_48), + .ce_pix(clk_12), + .ce_pix_actual(clk_12), + .SPI_SCK(SPI_SCK), + .SPI_SS3(SPI_SS3), + .SPI_DI(SPI_DI), + .R(blankn ? {video,video,video} : "000"), + .G(blankn ? {video,video,video} : "000"), + .B(blankn ? {video,video,video} : "000"), + .HSync(hs), + .VSync(vs), + .VGA_R(VGA_R), + .VGA_G(VGA_G), + .VGA_B(VGA_B), + .VGA_VS(VGA_VS), + .VGA_HS(VGA_HS), + .scandoubler_disable(scandoubler_disable), + .scanlines(scandoubler_disable ? 2'b00 : {status[4:3] == 3, status[4:3] == 2}), + .hq2x(status[4:3]==1), + .ypbpr_full(1), + .line_start(0), + .mono(1) +); + +mist_io #(.STRLEN(($size(CONF_STR)>>3))) mist_io +( + .clk_sys (clk_48 ), + .conf_str (CONF_STR ), + .SPI_SCK (SPI_SCK ), + .CONF_DATA0 (CONF_DATA0 ), + .SPI_SS2 (SPI_SS2 ), + .SPI_DO (SPI_DO ), + .SPI_DI (SPI_DI ), + .buttons (buttons ), + .switches (switches ), + .scandoubler_disable(scandoubler_disable), + .ypbpr (ypbpr ), + .ps2_kbd_clk (ps2_kbd_clk ), + .ps2_kbd_data (ps2_kbd_data ), + .joystick_0 (joystick_0 ), + .joystick_1 (joystick_1 ), + .status (status ) +); + +keyboard keyboard( + .clk(clk_48), + .reset(), + .ps2_kbd_clk(ps2_kbd_clk), + .ps2_kbd_data(ps2_kbd_data), + .joystick(kbjoy) + ); + + +endmodule diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/sync.vhd b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/sync.vhd new file mode 100644 index 00000000..0e15e09c --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/sync.vhd @@ -0,0 +1,190 @@ +-- Video synchronizer circuit for Super Breakout +-- Similar circuit used in many other Atari and Kee Games arcade games +-- (c)2017 James Sweet +-- +-- This is free software: you can redistribute +-- it and/or modify it under the terms of the GNU General +-- Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your +-- option) any later version. +-- +-- This is distributed in the hope that it will +-- be useful, but WITHOUT ANY WARRANTY; without even the +-- implied warranty of MERCHANTABILITY or FITNESS FOR A +-- PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity synchronizer is +port( + clk_12 : in std_logic; + clk_6 : out std_logic; + hcount : out std_logic_vector(8 downto 0); + vcount : out std_logic_vector(7 downto 0); + hsync : out std_logic; + hblank : out std_logic; + vblank_s : out std_logic; + vblank_n_s : out std_logic; + vblank : out std_logic; + vsync : out std_logic; + vreset : out std_logic); +end synchronizer; + +architecture rtl of synchronizer is + +signal h_counter : std_logic_vector(9 downto 0) := (others => '0'); +signal H256 : std_logic; +signal H256_n : std_logic; +signal H128 : std_logic; +signal H64 : std_logic; +signal H32 : std_logic; +signal H16 : std_logic; +signal H8 : std_logic; +signal H8_n : std_logic; +signal H4 : std_logic; +signal H4_n : std_logic; +signal H2 : std_logic; +signal H1 : std_logic; + +signal v_counter : std_logic_vector(7 downto 0) := (others => '0'); +signal V128 : std_logic; +signal V64 : std_logic; +signal V32 : std_logic; +signal V16 : std_logic; +signal V8 : std_logic; +signal V4 : std_logic; +signal V2 : std_logic; +signal V1 : std_logic; + +signal sync_bus : std_logic_vector(3 downto 0) := (others => '0'); +signal sync_reg : std_logic_vector(3 downto 0) := (others => '0'); +signal vblank_int : std_logic := '0'; +signal vreset_n : std_logic := '0'; + +signal hblank_int : std_logic := '0'; +signal hsync_int : std_logic := '0'; +signal hsync_reset : std_logic := '0'; + + +begin + +-- Horizontal counter is 9 bits long plus additional flip flop. The last 4 bit IC in the chain resets to 0010 so total count resets to 128 +-- using only the last three count states +H_count: process(clk_12) +begin + if rising_edge(clk_12) then + if h_counter = "1111111111" then + h_counter <= "0100000000"; + else + h_counter <= h_counter + 1; + end if; + end if; +end process; + +-- Vertical counter is 8 bits, clocked by the rising edge of H256 at the end of each horizontal line +V_count: process(hsync_int) +begin + if rising_edge(Hsync_int) then + if vreset_n = '0' then + v_counter <= (others => '0'); + else + v_counter <= v_counter + '1'; + end if; + end if; +end process; + +-- Many Atari raster games use a 256 x 4 bit prom to decode vertical sync signals +-- This could be replaced with combinatorial logic +M2: entity work.sprom +generic map( + init_file => "rtl/roms/006400_m2.hex", + widthad_a => 8, + width_a => 4) +port map( + clock => clk_12, + address => sync_reg(3) & V128 & V64 & V16 & V8 & V4 & V2 & V1, + q => sync_bus + ); + + + +--M2: entity work.sync_prom +--port map( +-- clock => clk_12, +-- address => sync_reg(3) & V128 & V64 & V16 & V8 & V4 & V2 & V1, +-- q => sync_bus +-- ); + +-- Register fed by the sync PROM, in the original hardware this also creates the complements of these signals +sync_register: process(hsync_int) +begin + if rising_edge(hsync_int) then + sync_reg <= sync_bus; + end if; +end process; + +-- Outputs of sync PROM +vblank_s <= sync_reg(3); +vblank_n_s <= not sync_reg(3); +vreset <= sync_reg(2); +vreset_n <= not sync_reg(2); +vblank <= sync_reg(1); +vsync <= sync_reg(0); + +-- A pair of D type flip-flops that generate the Hsync signal +R1_a: process(H256_n, H32) +begin + if H256_n = '0' then + hblank_int <= '0'; + else + if rising_edge(H32) then + hblank_int <= not H64; + end if; + end if; +end process; + +R1_b: process(hblank_int, H8) +begin + if hblank_int = '0' then + hsync_int <= '0'; + else + if rising_edge(H8) then + hsync_int <= H32; + end if; + end if; +end process; + +-- Assign various signals +clk_6 <= h_counter(0); +H1 <= h_counter(1); +H2 <= h_counter(2); +H4 <= h_counter(3); +H8 <= h_counter(4); +H16 <= h_counter(5); +H32 <= h_counter(6); +H64 <= h_counter(7); +H128 <= h_counter(8); +H256 <= h_counter(9); +H4_n <= not H4; +H8_n <= not H8; +H256_n <= not H256; + +V1 <= v_counter(0); +V2 <= v_counter(1); +V4 <= v_counter(2); +V8 <= v_counter(3); +V16 <= v_counter(4); +V32 <= v_counter(5); +V64 <= v_counter(6); +V128 <= v_counter(7); + +hcount <= h_counter(9 downto 1); +vcount <= v_counter; +hsync <= hsync_int; +hblank <= hblank_int; + +end rtl; \ No newline at end of file diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/video_mixer.sv b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/video_mixer.sv new file mode 100644 index 00000000..04cfd4ba --- /dev/null +++ b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/rtl/video_mixer.sv @@ -0,0 +1,242 @@ +// +// +// Copyright (c) 2017 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + +// +// LINE_LENGTH: Length of display line in pixels +// Usually it's length from HSync to HSync. +// May be less if line_start is used. +// +// HALF_DEPTH: If =1 then color dept is 3 bits per component +// For half depth 6 bits monochrome is available with +// mono signal enabled and color = {G, R} + +module video_mixer +#( + parameter LINE_LENGTH = 768, + parameter HALF_DEPTH = 0, + + parameter OSD_COLOR = 3'd4, + parameter OSD_X_OFFSET = 10'd0, + parameter OSD_Y_OFFSET = 10'd0 +) +( + // master clock + // it should be multiple by (ce_pix*4). + input clk_sys, + + // Pixel clock or clock_enable (both are accepted). + input ce_pix, + + // Some systems have multiple resolutions. + // ce_pix_actual should match ce_pix where every second or fourth pulse is enabled, + // thus half or qurter resolutions can be used without brake video sync while switching resolutions. + // For fixed single resolution (or when video sync stability isn't required) ce_pix_actual = ce_pix. + input ce_pix_actual, + + // OSD SPI interface + input SPI_SCK, + input SPI_SS3, + input SPI_DI, + + // scanlines (00-none 01-25% 10-50% 11-75%) + input [1:0] scanlines, + + // 0 = HVSync 31KHz, 1 = CSync 15KHz + input scandoubler_disable, + + // High quality 2x scaling + input hq2x, + + // YPbPr always uses composite sync + input ypbpr, + + // 0 = 16-240 range. 1 = 0-255 range. (only for YPbPr color space) + input ypbpr_full, + + // color + input [DWIDTH:0] R, + input [DWIDTH:0] G, + input [DWIDTH:0] B, + + // Monochrome mode (for HALF_DEPTH only) + input mono, + + // interlace sync. Positive pulses. + input HSync, + input VSync, + + // Falling of this signal means start of informative part of line. + // It can be horizontal blank signal. + // This signal can be used to reduce amount of required FPGA RAM for HQ2x scan doubler + // If FPGA RAM is not an issue, then simply set it to 0 for whole line processing. + // Keep in mind: due to algo first and last pixels of line should be black to avoid side artefacts. + // Thus, if blank signal is used to reduce the line, make sure to feed at least one black (or paper) pixel + // before first informative pixel. + input line_start, + + // MiST video output signals + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_VS, + output VGA_HS +); + +localparam DWIDTH = HALF_DEPTH ? 2 : 5; + +wire [DWIDTH:0] R_sd; +wire [DWIDTH:0] G_sd; +wire [DWIDTH:0] B_sd; +wire hs_sd, vs_sd; + +scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH)) scandoubler +( + .*, + .hs_in(HSync), + .vs_in(VSync), + .r_in(R), + .g_in(G), + .b_in(B), + + .hs_out(hs_sd), + .vs_out(vs_sd), + .r_out(R_sd), + .g_out(G_sd), + .b_out(B_sd) +); + +wire [DWIDTH:0] rt = (scandoubler_disable ? R : R_sd); +wire [DWIDTH:0] gt = (scandoubler_disable ? G : G_sd); +wire [DWIDTH:0] bt = (scandoubler_disable ? B : B_sd); + +generate + if(HALF_DEPTH) begin + wire [5:0] r = mono ? {gt,rt} : {rt,rt}; + wire [5:0] g = mono ? {gt,rt} : {gt,gt}; + wire [5:0] b = mono ? {gt,rt} : {bt,bt}; + end else begin + wire [5:0] r = rt; + wire [5:0] g = gt; + wire [5:0] b = bt; + end +endgenerate + +wire hs = (scandoubler_disable ? HSync : hs_sd); +wire vs = (scandoubler_disable ? VSync : vs_sd); + +reg scanline = 0; +always @(posedge clk_sys) begin + reg old_hs, old_vs; + + old_hs <= hs; + old_vs <= vs; + + if(old_hs && ~hs) scanline <= ~scanline; + if(old_vs && ~vs) scanline <= 0; +end + +wire [5:0] r_out, g_out, b_out; +always @(*) begin + case(scanlines & {scanline, scanline}) + 1: begin // reduce 25% = 1/2 + 1/4 + r_out = {1'b0, r[5:1]} + {2'b00, r[5:2]}; + g_out = {1'b0, g[5:1]} + {2'b00, g[5:2]}; + b_out = {1'b0, b[5:1]} + {2'b00, b[5:2]}; + end + + 2: begin // reduce 50% = 1/2 + r_out = {1'b0, r[5:1]}; + g_out = {1'b0, g[5:1]}; + b_out = {1'b0, b[5:1]}; + end + + 3: begin // reduce 75% = 1/4 + r_out = {2'b00, r[5:2]}; + g_out = {2'b00, g[5:2]}; + b_out = {2'b00, b[5:2]}; + end + + default: begin + r_out = r; + g_out = g; + b_out = b; + end + endcase +end + +wire [5:0] red, green, blue; +osd #(OSD_X_OFFSET, OSD_Y_OFFSET, OSD_COLOR) osd +( + .*, + + .R_in(r_out), + .G_in(g_out), + .B_in(b_out), + .HSync(hs), + .VSync(vs), + + .R_out(red), + .G_out(green), + .B_out(blue) +); + +wire [5:0] yuv_full[225] = '{ + 6'd0, 6'd0, 6'd0, 6'd0, 6'd1, 6'd1, 6'd1, 6'd1, + 6'd2, 6'd2, 6'd2, 6'd3, 6'd3, 6'd3, 6'd3, 6'd4, + 6'd4, 6'd4, 6'd5, 6'd5, 6'd5, 6'd5, 6'd6, 6'd6, + 6'd6, 6'd7, 6'd7, 6'd7, 6'd7, 6'd8, 6'd8, 6'd8, + 6'd9, 6'd9, 6'd9, 6'd9, 6'd10, 6'd10, 6'd10, 6'd11, + 6'd11, 6'd11, 6'd11, 6'd12, 6'd12, 6'd12, 6'd13, 6'd13, + 6'd13, 6'd13, 6'd14, 6'd14, 6'd14, 6'd15, 6'd15, 6'd15, + 6'd15, 6'd16, 6'd16, 6'd16, 6'd17, 6'd17, 6'd17, 6'd17, + 6'd18, 6'd18, 6'd18, 6'd19, 6'd19, 6'd19, 6'd19, 6'd20, + 6'd20, 6'd20, 6'd21, 6'd21, 6'd21, 6'd21, 6'd22, 6'd22, + 6'd22, 6'd23, 6'd23, 6'd23, 6'd23, 6'd24, 6'd24, 6'd24, + 6'd25, 6'd25, 6'd25, 6'd25, 6'd26, 6'd26, 6'd26, 6'd27, + 6'd27, 6'd27, 6'd27, 6'd28, 6'd28, 6'd28, 6'd29, 6'd29, + 6'd29, 6'd29, 6'd30, 6'd30, 6'd30, 6'd31, 6'd31, 6'd31, + 6'd31, 6'd32, 6'd32, 6'd32, 6'd33, 6'd33, 6'd33, 6'd33, + 6'd34, 6'd34, 6'd34, 6'd35, 6'd35, 6'd35, 6'd35, 6'd36, + 6'd36, 6'd36, 6'd36, 6'd37, 6'd37, 6'd37, 6'd38, 6'd38, + 6'd38, 6'd38, 6'd39, 6'd39, 6'd39, 6'd40, 6'd40, 6'd40, + 6'd40, 6'd41, 6'd41, 6'd41, 6'd42, 6'd42, 6'd42, 6'd42, + 6'd43, 6'd43, 6'd43, 6'd44, 6'd44, 6'd44, 6'd44, 6'd45, + 6'd45, 6'd45, 6'd46, 6'd46, 6'd46, 6'd46, 6'd47, 6'd47, + 6'd47, 6'd48, 6'd48, 6'd48, 6'd48, 6'd49, 6'd49, 6'd49, + 6'd50, 6'd50, 6'd50, 6'd50, 6'd51, 6'd51, 6'd51, 6'd52, + 6'd52, 6'd52, 6'd52, 6'd53, 6'd53, 6'd53, 6'd54, 6'd54, + 6'd54, 6'd54, 6'd55, 6'd55, 6'd55, 6'd56, 6'd56, 6'd56, + 6'd56, 6'd57, 6'd57, 6'd57, 6'd58, 6'd58, 6'd58, 6'd58, + 6'd59, 6'd59, 6'd59, 6'd60, 6'd60, 6'd60, 6'd60, 6'd61, + 6'd61, 6'd61, 6'd62, 6'd62, 6'd62, 6'd62, 6'd63, 6'd63, + 6'd63 +}; + +// http://marsee101.blog19.fc2.com/blog-entry-2311.html +// Y = 16 + 0.257*R + 0.504*G + 0.098*B (Y = 0.299*R + 0.587*G + 0.114*B) +// Pb = 128 - 0.148*R - 0.291*G + 0.439*B (Pb = -0.169*R - 0.331*G + 0.500*B) +// Pr = 128 + 0.439*R - 0.368*G - 0.071*B (Pr = 0.500*R - 0.419*G - 0.081*B) + +wire [18:0] y_8 = 19'd04096 + ({red, 8'd0} + {red, 3'd0}) + ({green, 9'd0} + {green, 2'd0}) + ({blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0}); +wire [18:0] pb_8 = 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0}) - ({green, 8'd0} + {green, 5'd0} + {green, 3'd0}) + ({blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0}); +wire [18:0] pr_8 = 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0}) - ({green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0}) - ({blue, 6'd0} + {blue , 3'd0}); + +wire [7:0] y = ( y_8[17:8] < 16) ? 8'd16 : ( y_8[17:8] > 235) ? 8'd235 : y_8[15:8]; +wire [7:0] pb = (pb_8[17:8] < 16) ? 8'd16 : (pb_8[17:8] > 240) ? 8'd240 : pb_8[15:8]; +wire [7:0] pr = (pr_8[17:8] < 16) ? 8'd16 : (pr_8[17:8] > 240) ? 8'd240 : pr_8[15:8]; + +assign VGA_R = ypbpr ? (ypbpr_full ? yuv_full[pr-8'd16] : pr[7:2]) : red; +assign VGA_G = ypbpr ? (ypbpr_full ? yuv_full[y -8'd16] : y[7:2]) : green; +assign VGA_B = ypbpr ? (ypbpr_full ? yuv_full[pb-8'd16] : pb[7:2]) : blue; +assign VGA_VS = (scandoubler_disable | ypbpr) ? 1'b1 : ~vs_sd; +assign VGA_HS = scandoubler_disable ? ~(HSync ^ VSync) : ypbpr ? ~(hs_sd ^ vs_sd) : ~hs_sd; + +endmodule diff --git a/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/snapshot/SuperBreakout.rbf b/Arcade_MiST/Custom Hardware/SuperBreakout_MiST/snapshot/SuperBreakout.rbf new file mode 100644 index 0000000000000000000000000000000000000000..111dab4a2cefd4bce91f129b747c04975bef34fa GIT binary patch literal 239690 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 h)$ygr2#g8~`RG