From: Michael Gernoth Date: Tue, 29 Apr 2008 08:07:07 +0000 (+0200) Subject: galaxians X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/fpga-games/commitdiff_plain/782690d0b2046d5fa0ae296c2fb3f411d668b5dc galaxians --- 782690d0b2046d5fa0ae296c2fb3f411d668b5dc diff --git a/galaxian/build_roms b/galaxian/build_roms new file mode 100755 index 0000000..a8371f8 --- /dev/null +++ b/galaxian/build_roms @@ -0,0 +1,13 @@ +#!/bin/sh +set -x + +./romgen/romgen roms/1h.bin GALAXIAN_1H 11 l r e >roms/galaxian_1h.vhd +./romgen/romgen roms/1k.bin GALAXIAN_1K 11 l r e >roms/galaxian_1k.vhd +./romgen/romgen roms/7l GALAXIAN_7L 11 l r e >roms/galaxian_7l.vhd +./romgen/romgen roms/galmidw.u GALAXIAN_U 11 l r e >roms/galaxian_u.vhd +./romgen/romgen roms/galmidw.v GALAXIAN_V 11 l r e >roms/galaxian_v.vhd +./romgen/romgen roms/galmidw.w GALAXIAN_W 11 l r e >roms/galaxian_w.vhd +./romgen/romgen roms/galmidw.y GALAXIAN_Y 11 l r e >roms/galaxian_y.vhd +./romgen/romgen roms/6l.bpr GALAXIAN_6L 5 b r e >roms/galaxian_6l.vhd + +#./romgen mc_wav_2.bin GALAXIAN_WAV 18 l r e >roms/galaxian_wav.vhd diff --git a/galaxian/build_xst b/galaxian/build_xst new file mode 100755 index 0000000..4f203ca --- /dev/null +++ b/galaxian/build_xst @@ -0,0 +1,30 @@ +#/bin/sh + +set -x + +name=galaxian +rom_path=roms/ +echo use build_xst /xil to skip synthesis stage. + +rm -rf build/ +mkdir -p build +cd build/ + +cp -r ../src . +cp -r ../t80_ip . +cp ../roms/*.vhd . +cp ../${name}.ucf ${name}.ucf +cp ../${name}.ut . +cp ../${name}.scr . +cp ../${name}.prj . +echo "work" >${name}.lso + +xst -ifn ${name}.scr -ofn ${name}.srp + +ngdbuild -nt on -uc ${name}.ucf ${name}.ngc ${name}.ngd +map -pr b ${name}.ngd -o ${name}.ncd ${name}.pcf +par -w -ol high ${name}.ncd ${name}.ncd ${name}.pcf +trce -v 10 -o ${name}.twr ${name}.ncd ${name}.pcf +bitgen ${name}.ncd ${name}.bit -w -f ${name}.ut + +echo Done diff --git a/galaxian/doc/altera_fpga_galaxian.txt b/galaxian/doc/altera_fpga_galaxian.txt new file mode 100644 index 0000000..95875bc --- /dev/null +++ b/galaxian/doc/altera_fpga_galaxian.txt @@ -0,0 +1,174 @@ +************************************************************************************************** +* 2004- 9-24 Katsumi Degawa * +* ALTERA(CYCLONE)-FPGA-GALAXIAN ‚ւ悤‚±‚» * +* * +************************************************************************************************** +y@ ‚Í‚¶‚߂Ɂ@ z +@@‚±‚ÌALTERA(CYCLONE)-FPGA-GALAXIAN‚́A1980”N‘ã‚ɏ‰‚ß‚É”­•\‚³‚ê@ƒQ[ƒ€ƒZƒ“ƒ^[‚È‚Ç‚ÅŠˆ–ôH +@‚µ‚Ä‚¢‚½@Šî”‚Ɖñ˜H}‚ðŒ³‚ÉVerilogHDL‚Ő݌v‚µAFPGA‚Å“®ì‚·‚é‚悤‚É‚µ‚½‚à‚Ì‚Å‚·B + +y@•ÏX“_Fv2.50@z + +@@1.T80_IP‚ł́A1.5MHz“®ì‚Å‚µ‚½‚ª@V2.50‚©‚ç@3.0MHz‚Å“®ì‚µ‚Ä‚¢‚Ü‚·. + +@@2.V1.xx‚ł́AƒfƒoƒCƒX‚âCPU_IP‚É‚æ‚Á‚Ä•ª‚©‚ê‚Ä‚¢‚½ƒtƒ@ƒCƒ‹‚ðˆê‚‚ɑ‡‚µ‚Ü‚µ‚½B + +@@@‚½‚¾‚µ@ƒfƒoƒCƒX‚É‚æ‚è\’z•û–@‚ªˆÙ‚Ȃ邽‚߁@ƒfƒoƒCƒX•Ê‚̃eƒLƒXƒg‚ðŽQÆ‚µ‚ĉº‚³‚¢B + +y@•K—v‚ÈHARD@z +@1.@ALTERA@CPLD.FPGAŠJ”­Tool@¢Quartus II 4.0 SP1 Web Edition£@‚ª“®ì‚·‚éPC +@@@ *OS‚́AWINDOWS2000@or@WINDOWS@XP + +@2.@ALTERA BYTE BLASTER-MV Parallel Port Download Cable –”‚́AEPCS4(Config-ROM)‚ɏ‘‚«ž‚ޏꍇ‚́A +@@@ALTERA BYTE BLASTER-‡U Parallel Port Download Cable@‚ª•K—vB + +@3.@ALTERA FPGA DEVICE + +y@•K—v‚ÈSOFT@z +@1.@ALTERA_Quartus‡U_WebEdition_ver4.0 +@@@‰º‹LURL‚æ‚è@ƒ_ƒEƒ“ƒ[ƒh‚µ‚Ä‚­‚¾‚³‚¢B‹N“®‚·‚邽‚߂ɂ́Aƒ‰ƒCƒZƒ“ƒX‚ª•K—v‚É‚È‚é‚Ì‚ÅFree‚Ì +@@@ƒ‰ƒCƒZƒ“ƒX‚ðŽæ“¾‚µ‚Ä‚­‚¾‚³‚¢B +@@@http://www.altera.com/products/software/pld/products/quartus2/sof-quarwebmain.html + +@2.@bhc.exe /* Binary data <-> Intel Hex data Converter Ver 1.0.3 */ + ‰º‹LURL‚æ‚è@ƒ_ƒEƒ“ƒ[ƒh‚µ‚Ä‚­‚¾‚³‚¢B ‰ð“€Œã@bhc.exe‚ð"\make_rom"ƒtƒHƒ‹ƒ_‚ɃRƒs[ ‚·‚éB +@@@http://www.vector.co.jp/soft/win95/util/se057995.html@ + +y@GALAXIAN ROM-\’z@z +@1.@GALAXIAN Šî”‚ÌROMƒf[ƒ^‚ð‰º‹LFile–¼‚ŃRƒs[‚·‚éB + +@@ IC(ROM) @ @@ADDERSS (SIZE)@@@@@File-Name + 7H @0x0000 - 0x07FF(0x0800) galmidw.u + 0x0800 - 0x0FFF(0x0800) galmidw.v + 0x1000 - 0x17FF(0x0800) galmidw.w + 0x1800 - 0x1FFF(0x0800) galmidw.y + 7L @0x2000 - 0x27FF(0x0800) 7l + 1K (0x0800) 1k.bin + 1H (0x0800) 1h.bin + 6L (0x0020) 6l.bpr + + @@@@@@@@@@@@@@@* File–¼‚́AƒA[ƒP[ƒhƒGƒ~ƒ…ƒŒ[ƒ^[‚Æ‚µ‚čłà—L–¼‚È +@@@@@@@@@@@@@@@@@@M.A.M.E(http://www.mame.net/)‚ɍ‡‚킹‚Ä‚¢‚Ü‚·. + +@2.@1.‚ÌROM-File‚ð"\make_rom"ƒtƒHƒ‹ƒ_‚ɃRƒs[‚·‚éB +@3.@make_rom.bat ‚ðŽÀs + + address map + -------------------------------------------------- + 0x00000 - 0x007FF galmidw.u CPU-ROM + 0x00800 - 0x00FFF galmidw.v CPU-ROM + 0x01000 - 0x017FF galmidw.w CPU-ROM + 0x01800 - 0x01FFF galmidw.y CPU-ROM + 0x02000 - 0x027FF 7l CPU-ROM + 0x04000 - 0x047FF 1k.bin VID-ROM + 0x05000 - 0x057FF 1h.bin VID-ROM + 0x10000 - 0x3FFFF mc_wav_2.bin Sound(Wav)Data + +@4.@galaxian_sf.bin@‚ðROM ‚Ƀ_ƒEƒ“ƒ[ƒh‚·‚éB +@@@@ROM ‚́A—e—Ê‚ª@2Mbit@ˆÈã‚ÌEP-ROM@or@EEP-ROM@‚ðŽg—p‚·‚éB + 5.@galaxian_prjƒtƒHƒ‹ƒ_‰º‚Ɂ@6l.hex@‚ªo—ˆ‚Ä‚¢‚邱‚Æ‚ðŠm”F‚µ‚Ä‚­‚¾‚³‚¢B +@@@@ +y@ALTERA-FPGA-DATA(mc_top.pof)‚̍쐬•ƒ_ƒEƒ“ƒ[ƒh@z +‚PDgalaxian_prjƒtƒHƒ‹ƒ_‚́hmc_top.quartush‚ðƒ_ƒuƒ‹ƒNƒŠƒbƒN‚µ‚ÄQuartus‡U‚ð‹N“®‚µ‚Ä‚­‚¾‚³‚¢B +@@FPGA-GALAXIAN ‚É•K—v‚ÈFile‚ð‰º‹L‚É‹LÚ‚µ‚Ü‚·B + + VERILOG_FILE = src\mc_top.v; + VERILOG_FILE = src\mc_clock.v; + VERILOG_FILE = src\mc_adec.v; + VERILOG_FILE = src\mc_inport.v; + VERILOG_FILE = src\mc_hv_count.v; + VERILOG_FILE = src\mc_ld_pls.v; + VERILOG_FILE = src\mc_video.v; + VERILOG_FILE = src\mc_missile.v; + VERILOG_FILE = src\mc_stars.v; + VERILOG_FILE = src\mc_col_pal.v; + VERILOG_FILE = src\mc_vedio_mix.v; + VERILOG_FILE = src\mc_vga_if_alt.v; + VERILOG_FILE = src\mc_sound_a.v; + VERILOG_FILE = src\mc_sound_b.v; + VERILOG_FILE = src\mc_logic.v; + VERILOG_FILE = src\mc_bram_if_alt.v; + VERILOG_FILE = src\psPAD_conf.v; + VERILOG_FILE = src\psPAD_top.v; + VERILOG_FILE = src\fpga_arcade_if.v; + VERILOG_FILE = src\alt_ram_256_5.v; + VERILOG_FILE = src\alt_ram_256_8.v; + VERILOG_FILE = src\alt_ram_1024_8.v; + VERILOG_FILE = src\alt_rom_6l.v; + VERILOG_FILE = src\dac.v; + VERILOG_FILE = src\z80ip.v; + VHDL_FILE = t80_ip\T80_Pack.vhd; + VHDL_FILE = t80_ip\T80_ALU.VHD; + VHDL_FILE = t80_ip\T80_MCode.vhd; + VHDL_FILE = t80_ip\T80_Reg.vhd; + VHDL_FILE = t80_ip\T80.VHD; + VHDL_FILE = t80_ip\T80as.vhd; + +‚QDFPGA‚ÌIN/OUT‚ÌPIN”z’u‚̐ݒè‚ð‚µ‚Ä‚­‚¾‚³‚¢B + +‚RDplaystation‚̃Rƒ“ƒgƒ[ƒ‰‚ðŽg—p‚·‚éê‡‚́Amc_conf.v ‚́@h`define PSPAD_USEh‚Ì +@@ƒRƒƒ“ƒgƒAƒEƒg‚ðŠO‚µ‚ĉº‚³‚¢. +@@@@@//@`define PSPAD_USE@@Ë@`define PSPAD_USE + +‚SDƒ‚ƒjƒ^‚́APC—p‚ÌVGAƒ‚ƒjƒ^‚𐄏§‚µ‚Ü‚·.@‚µ‚©‚µ16KH‚š(H).60Hz(V)‚ÌRGBƒ‚ƒjƒ^‚àŽg—p‚·‚é +@@‚±‚Æ‚ªo—ˆ‚Ü‚·.@‚±‚̏ꍇAmc_conf.v ‚́@h`define VGA_USEh‚ðƒRƒƒ“ƒgƒAƒEƒg‚µ‚ĉº‚³‚¢. +@@@@@@`define VGA_USE@@Ë@// `define VGA_USE + +‚TDQuartus‡UËProcessingËStart Compilation ‚ðƒNƒŠƒbƒN‚µ‚ăRƒ“ƒpƒCƒ‹‚ðŽÀs +@@@@@@@ +@@Fitting‚ª¬Œ÷‚·‚é‚Ɖº‹LƒƒbƒZ[ƒW‚ª•\Ž¦‚³‚ê‚Ü‚·B ++---------------------------------------------------------------+ +; Fitter Summary ; ++-----------------------+---------------------------------------+ +; Fitter Status ; Successful - Sat Sep 18 12:34:48 2004 ; +; Revision Name ; mc_top ; +; Top-level Entity Name ; mc_top ; +; Family ; Cyclone ; +; Device ; EP1C12Q240C8 ; +; Total logic elements ; 3,046 / 12,060 ( 23 % ) ; +; Total pins ; 59 / 173 ( 34 % ) ; +; Total memory bits ; 24,064 / 239,616 ( 10 % ) ; +; Total PLLs ; 0 / 2 ( 0 % ) ; ++-----------------------+---------------------------------------+ + +‚UDQuartus‡U‚É‚æ‚Á‚ж¬‚³‚ꂽhmc_top.pofh‚ðƒ_ƒEƒ“ƒ[ƒh‚µ‚ÄŠ®—¹‚Å‚·B + +y@FPGA-MoonCresta ƒRƒ“ƒgƒ[ƒ‹@z +@y I_PSW[4:0] z +@LEFT 1P/2P : LEFT (I_SW[2]) +@RIGHT 1P/2P : RIGHT (I_SW[3]) +@UP 1P/2P : UP (I_SW[0]) ... NOT USE +@DOWN 1P/2P : DOWN (I_SW[1]) ... NOT USE +@FIRE@1P/2P : JP (I_SW[4]) +@START 1P : LEFT + JP +@START 2P : RIGHT + JP +@COIN1 : LEFT + RIGHT + UP (and DOWN off) + + y PS_PAD z +@LEFT 1P/2P : LEFT@iRight Joystickj +@RIGHT 1P/2P : RIGHT iRight Joystickj +@UP 1P/2P : UP iRight Joystickj ... NOT USE +@DOWN 1P/2P : DOWN iRight Joystickj ... NOT USE +@FIRE@1P/2P : « +@START 1P : START +@START 2P : SELCT +@COIN1 : › + + Enjoy! +@ +y@’˜ìŒ •–ƐӁ@z +@fpga-galaxian@‚Ì’˜ìŒ ‚́AKatsumi Degawa ‚É‘®‚µ‚Ü‚·. +@fpga-mooncresta‚Ì’˜ìŒ ‚́AKatsumi Degawa ‚É‘®‚µ‚Ü‚·. +@pspad@@@ ‚Ì’˜ìŒ ‚́AKatsumi Degawa ‚É‘®‚µ‚Ü‚·. +@T80(Z80_IP)@@‚Ì’˜ìŒ ‚́ADaniel WallnerŽ ‚É‘®‚µ‚Ü‚·. + +@–{ƒ\[ƒXƒtƒ@ƒCƒ‹‚ðŽg—p‚µ‚½‚±‚Æ‚É‚æ‚萶‚¶‚½‚¢‚©‚È‚éáŠQA‘¹ŠQ‚É‚¨‚¢‚čìŽÒ‚͈êØÓ”C‚𕉂í + ‚È‚¢‚à‚Ì‚Æ‚µ‚Ü‚·B +@ŠeŽ©‚̐ӔC‚É‚¨‚¢‚ÄŽg—p‚µ‚Ä‚­‚¾‚³‚¢B + +y@˜A—æ@z +@‚²ˆÓŒ©A‚²—v–]“™‚ ‚è‚܂肽‚琥”ñˆÈ‰º‚Ì‚Ü‚Å‚²˜A—‚ð‚¨Šè‚¢‚µ‚Ü‚·B +@‚½‚¾‚µROMƒCƒ[ƒW“™‚Ì‚²Ž¿–â‚́A‚¨“š‚¦‚Å‚«‚Ü‚¹‚ñB + + E-mail : office_dsan@infoseek.jp + diff --git a/galaxian/doc/xilinx_fpga_galaxian.txt b/galaxian/doc/xilinx_fpga_galaxian.txt new file mode 100644 index 0000000..30c92ef --- /dev/null +++ b/galaxian/doc/xilinx_fpga_galaxian.txt @@ -0,0 +1,173 @@ +************************************************************************************************** +* 2004- 9-24 Katsumi Degawa * +* XILINX(SPARTAN‡UE)-FPGA-GALAXIAN ‚ւ悤‚±‚» * +* * +************************************************************************************************** +y@ ‚Í‚¶‚߂Ɂ@ z + ‚±‚ÌXILINX(SPARTAN‡UE)-FPGA-MOONCRESTA‚́A1980”N‘ã‚ɏ‰‚ß‚É”­•\‚³‚ê@ƒQ[ƒ€ƒZƒ“ƒ^[‚È‚Ç‚ÅŠˆ–ôH +@ ‚µ‚Ä‚¢‚½@Šî”‚Ɖñ˜H}‚ðŒ³‚ÉVerilogHDL‚Ő݌v‚µAFPGA‚Å“®ì‚·‚é‚悤‚É‚µ‚½‚à‚Ì‚Å‚·B + +y@•ÏX“_Fv2.50@z + +@@1.T80_IP‚ł́A1.5MHz“®ì‚Å‚µ‚½‚ª@V2.50‚©‚ç@3.0MHz‚Å“®ì‚µ‚Ä‚¢‚Ü‚·. + +@@2.V1.xx‚ł́AƒfƒoƒCƒX‚âCPU_IP‚É‚æ‚Á‚Ä•ª‚©‚ê‚Ä‚¢‚½ƒtƒ@ƒCƒ‹‚ðˆê‚‚ɑ‡‚µ‚Ü‚µ‚½B + +@@@‚½‚¾‚µ@ƒfƒoƒCƒX‚É‚æ‚è\’z•û–@‚ªˆÙ‚Ȃ邽‚߁@ƒfƒoƒCƒX•Ê‚̃eƒLƒXƒg‚ðŽQÆ‚µ‚ĉº‚³‚¢B + +y@•K—v‚ÈHARD@z +@1.@XILINX@CPLD.FPGAŠJ”­Tool@¢XILINX ISE6.2SP3 Webpack£@‚ª“®ì‚·‚éPC +@@@*OS‚́AWINDOWS2000@or@WINDOWS@XP + +@2.@Xilinx Parallel Port Download Cable + +@3.@XILINX FPGA DEVICE + +y@•K—v‚ÈSOFT@z +@1.@XILINX ISE6.2SP3 Webpack +@@@‰º‹LURL‚æ‚è@ƒ_ƒEƒ“ƒ[ƒh‚µ‚Ä‚­‚¾‚³‚¢B@“o˜^‚ª•K—vB + http://www.xilinx.co.jp/xlnx/xil_prodcat_landingpage.jsp?title=ISE+WebPack + +y@GALAXIAN ROM-\’z@z +@1.@GALAXIAN Šî”‚ÌROMƒf[ƒ^‚ð‰º‹LFile–¼‚ŃRƒs[‚·‚éB + +@@ IC(ROM) @ @@ADDERSS (SIZE)@@@@@File-Name + 7H @0x0000 - 0x07FF(0x0800) galmidw.u + 0x0800 - 0x0FFF(0x0800) galmidw.v + 0x1000 - 0x17FF(0x0800) galmidw.w + 0x1800 - 0x1FFF(0x0800) galmidw.y + 7L @0x2000 - 0x27FF(0x0800) 7l + 1K (0x0800) 1k.bin + 1H (0x0800) 1h.bin + 6L (0x0020) 6l.bpr + + @@@@@@@@@@@@@@@* File–¼‚́AƒA[ƒP[ƒhƒGƒ~ƒ…ƒŒ[ƒ^[‚Æ‚µ‚čłà—L–¼‚È +@@@@@@@@@@@@@@@@@@M.A.M.E(http://www.mame.net/)‚ɍ‡‚킹‚Ä‚¢‚Ü‚·. + +@2.@1.‚ÌROM-File‚ð"\make_rom"ƒtƒHƒ‹ƒ_‚ɃRƒs[‚·‚éB +@3.@make_rom.bat ‚ðŽÀs + + address map + -------------------------------------------------- + 0x00000 - 0x007FF galmidw.u CPU-ROM + 0x00800 - 0x00FFF galmidw.v CPU-ROM + 0x01000 - 0x017FF galmidw.w CPU-ROM + 0x01800 - 0x01FFF galmidw.y CPU-ROM + 0x02000 - 0x027FF 7l CPU-ROM + 0x04000 - 0x047FF 1k.bin VID-ROM + 0x05000 - 0x057FF 1h.bin VID-ROM + 0x10000 - 0x3FFFF mc_wav_2.bin Sound(Wav)Data + +@4.@galaxian_sf.bin@‚ðROM ‚Ƀ_ƒEƒ“ƒ[ƒh‚·‚éB +@@@@ROM ‚́A—e—Ê‚ª@2Mbit@ˆÈã‚ÌEP-ROM@or@EEP-ROM@‚ðŽg—p‚·‚éB + + 5.@mooncrst_prjƒtƒHƒ‹ƒ_‰º‚Ɂ@mc_top.ucf & mc_top_pad.ucf@‚ªo—ˆ‚Ä‚¢‚邱‚Æ‚ð + Šm”F‚µ‚Ä‚­‚¾‚³‚¢B +@@@@ +y@XILINX-FPGA-DATA(mc_top.bit or mc_top.mcs)‚̍쐬•ƒ_ƒEƒ“ƒ[ƒh@z +‚PDFPGA-GALAXIAN ‚É•K—v‚ÈFile‚ð‰º‹L‚É‹LÚ‚µ‚Ü‚·B + + VERILOG_FILE = src\mc_top.v;@@ + VERILOG_FILE = src\mc_top_pad.v; + VERILOG_FILE = src\mc_clock.v; + VERILOG_FILE = src\mc_adec.v; + VERILOG_FILE = src\mc_inport.v; + VERILOG_FILE = src\mc_hv_count.v; + VERILOG_FILE = src\mc_video.v; + VERILOG_FILE = src\mc_ld_pls.v; + VERILOG_FILE = src\mc_missile.v; + VERILOG_FILE = src\mc_stars.v; + VERILOG_FILE = src\mc_vedio_mix.v; + VERILOG_FILE = src\mc_col_pal.v; + VERILOG_FILE = src\mc_sound_a.v; + VERILOG_FILE = src\mc_sound_b.v; + VERILOG_FILE = src\mc_vga_if_xlinx.v; + VERILOG_FILE = src\mc_logic.v; + VERILOG_FILE = src\mc_bram_if_xlinx.v; + VERILOG_FILE = src\z80ip_b.v; + VERILOG_FILE = src\psPAD_conf.v; + VERILOG_FILE = src\psPAD_top.v; + VERILOG_FILE = src\fpga_arcade_if.v; + VERILOG_FILE = src\fpga_arcade_if_x.v; + VERILOG_FILE = src\dac.v; + VERILOG_FILE = src\z80ip.v; + VHDL_FILE = t80_ip\T80_Pack.vhd; + VHDL_FILE = t80_ip\T80_ALU.VHD; + VHDL_FILE = t80_ip\T80_MCode.vhd; + VHDL_FILE = t80_ip\T80_RegX.vhd; + VHDL_FILE = t80_ip\T80.VHD; + VHDL_FILE = t80_ip\T80as.vhd; + +‚QDPIN assign‚ð•ÏX‚·‚éê‡‚́Ahmc_top.ucf & mc_top_pad.ucfh‚ð•ÒW‚µ‚Ä‚­‚¾‚³‚¢. + +‚RDƒ‚ƒjƒ^‚́APC—p‚ÌVGAƒ‚ƒjƒ^‚𐄏§‚µ‚Ü‚·.@‚µ‚©‚µ16KH‚š(H).60Hz(V)‚ÌRGBƒ‚ƒjƒ^‚àŽg—p‚·‚é +@@‚±‚Æ‚ªo—ˆ‚Ü‚·.@‚±‚̏ꍇAmc_top.v ‚́@h`define VGA_USEh‚ðƒRƒƒ“ƒgƒAƒEƒg‚µ‚ĉº‚³‚¢. +@@@@@@`define VGA_USE@@Ë@// `define VGA_USE + +‚SDplaystation‚̃Rƒ“ƒgƒ[ƒ‰‚ðŽg—p‚·‚éê‡‚́Amc_conf.v ‚́@h`define PSPAD_USEh‚Ì +@@ƒRƒƒ“ƒgƒAƒEƒg‚ðŠO‚µ‚ĉº‚³‚¢. +@@@@@//@`define PSPAD_USE@@Ë@`define PSPAD_USE + +‚TDZ80_IP‚ÌNGC FILE‚̐¶¬ +@y@T80it80as.ngcjz +@@(1)@t80_ip.npl‚©‚çProject Navigator‹N“®‚·‚éB +@@(2)@t80as‚Ìsynthesise ‚ðŽÀs‚·‚éB +@@(3)@prjƒtƒHƒ‹ƒ_‰º‚Ét80as.ngc‚ªo—ˆ‚Ä‚¢‚邱‚Æ‚ðŠm”F‚·‚éB + +‚UDPSPAD_IP‚ÌNGC FILE‚̐¶¬ +@@*PLAYSTATIONƒRƒ“ƒgƒ[ƒ‰‚ðŽg—p‚·‚éê‡‚É•K—v‚Å‚·. +@@(1)@ps_pad_ip.npl‚©‚çProject Navigator‹N“®‚·‚éB +@@(2)@fpga_arcade_if‚Ìsynthesise ‚ðŽÀs‚·‚éB +@@(3)@prjƒtƒHƒ‹ƒ_‰º‚Éfpga_arcade_if.ngc‚ªo—ˆ‚Ä‚¢‚邱‚Æ‚ðŠm”F‚·‚éB + +‚VDmc_top.bit.mc_top.mcs‚̍쐬 +@@(1)@galaxian_prj_v25.npl‚©‚çProject Navigator‹N“®‚·‚éB + PLAYSTATIONƒRƒ“ƒgƒ[ƒ‰‚ðŽg—p‚·‚éê‡‚́A +@@@@ galaxian_prj_v25_p.npl‚©‚çProject Navigator‹N“®‚·‚éB +@@(2)@Generate Programming File ‚ðŽÀs‚·‚éB + (3)@prjƒtƒHƒ‹ƒ_‰º‚É mc_top.bit‚ªo—ˆ‚Ä‚¢‚邱‚Æ‚ðŠm”F‚·‚éB +@@(4)@ƒRƒ“ƒtƒBƒMƒ…ƒŒ[ƒVƒ‡ƒ“ROM‚ðŽg—p‚·‚éê‡‚ͤGenerate PROM,ACE or JTAG File +@@@@ ‚ðŽÀs‚µ‚ā@mc_top.mcs@ƒtƒ@ƒCƒ‹‚ðì¬‚µ‚ĉº‚³‚¢. + +‚WD¶¬‚³‚ꂽhmc_top.bith–”‚ͤhmc_top.mcsh‚ðƒ_ƒEƒ“ƒ[ƒh‚µ‚ÄŠ®—¹‚Å‚·B + +y@FPGA-MoonCresta ƒRƒ“ƒgƒ[ƒ‹@z +@y I_PSW[4:0] z +@LEFT 1P/2P : LEFT (I_SW[2]) +@RIGHT 1P/2P : RIGHT (I_SW[3]) +@UP 1P/2P : UP (I_SW[0]) ... NOT USE +@DOWN 1P/2P : DOWN (I_SW[1]) ... NOT USE +@FIRE@1P/2P : JP (I_SW[4]) +@START 1P : LEFT + JP +@START 2P : RIGHT + JP +@COIN1 : LEFT + RIGHT + UP (and DOWN off) + + y PS_PAD z +@LEFT 1P/2P : LEFT@iRight Joystickj +@RIGHT 1P/2P : RIGHT iRight Joystickj +@UP 1P/2P : UP iRight Joystickj ... NOT USE +@DOWN 1P/2P : DOWN iRight Joystickj ... NOT USE +@FIRE@1P/2P : « +@START 1P : START +@START 2P : SELCT +@COIN1 : › + + Enjoy! +@ +y@’˜ìŒ •–ƐӁ@z +@fpga-mooncrst@‚Ì’˜ìŒ ‚́AKatsumi Degawa ‚É‘®‚µ‚Ü‚·. + fpga-galaxian@‚Ì’˜ìŒ ‚́AKatsumi Degawa ‚É‘®‚µ‚Ü‚·. +@pspad@@@ ‚Ì’˜ìŒ ‚́AKatsumi Degawa ‚É‘®‚µ‚Ü‚·. +@T80(Z80_IP)@@‚Ì’˜ìŒ ‚́ADaniel WallnerŽ ‚É‘®‚µ‚Ü‚·. + binucf.exe ‚Ì’˜ìŒ ‚Í Tatsuyuki Satoh Ž‚É‘®‚µ‚Ü‚·. + +@–{ƒ\[ƒXƒtƒ@ƒCƒ‹‚ðŽg—p‚µ‚½‚±‚Æ‚É‚æ‚萶‚¶‚½‚¢‚©‚È‚éáŠQA‘¹ŠQ‚É‚¨‚¢‚čìŽÒ‚͈êØÓ”C‚𕉂í + ‚È‚¢‚à‚Ì‚Æ‚µ‚Ü‚·B +@ŠeŽ©‚̐ӔC‚É‚¨‚¢‚ÄŽg—p‚µ‚Ä‚­‚¾‚³‚¢B + +y@˜A—æ@z +@‚²ˆÓŒ©A‚²—v–]“™‚ ‚è‚܂肽‚琥”ñˆÈ‰º‚Ì‚Ü‚Å‚²˜A—‚ð‚¨Šè‚¢‚µ‚Ü‚·B +@‚½‚¾‚µROMƒCƒ[ƒW“™‚Ì‚²Ž¿–â‚́A‚¨“š‚¦‚Å‚«‚Ü‚¹‚ñB + + E-mail : office_dsan@infoseek.jp@ + diff --git a/galaxian/galaxian.cmd b/galaxian/galaxian.cmd new file mode 100644 index 0000000..8081ef1 --- /dev/null +++ b/galaxian/galaxian.cmd @@ -0,0 +1,8 @@ +setMode -bs +setMode -bs +setCable -port auto +Identify +identifyMPM +assignFile -p 1 -file "build/galaxian.bit" +Program -p 1 +exit diff --git a/galaxian/galaxian.prj b/galaxian/galaxian.prj new file mode 100644 index 0000000..a81077d --- /dev/null +++ b/galaxian/galaxian.prj @@ -0,0 +1,37 @@ +verilog work "src/dac.v" +verilog work "src/mc_adec.v" +verilog work "src/mc_clock.v" +verilog work "src/mc_col_pal.v" +verilog work "src/mc_hv_count.v" +verilog work "src/mc_ld_pls.v" +verilog work "src/mc_logic.v" +verilog work "src/mc_missile.v" +verilog work "src/mc_sound_a.v" +verilog work "src/mc_sound_b.v" +verilog work "src/mc_stars.v" +verilog work "src/mc_top.v" +verilog work "src/mc_vedio_mix.v" +verilog work "src/mc_video.v" +verilog work "src/mc_vga_if.v" +verilog work "src/mc_bram_if.v" +verilog work "src/mc_inport.v" +verilog work "src/mc_conf.v" +verilog work "src/roms.v" +verilog work "src/dcm.v" +#verilog work "src/t80as.v" +verilog work "src/z80ip.v" +verilog work "src/fpga_arcade_if_x.v" +vhdl work "t80_ip/T80.vhd" +vhdl work "t80_ip/T80_ALU.vhd" +vhdl work "t80_ip/T80_MCode.vhd" +vhdl work "t80_ip/T80_Pack.vhd" +vhdl work "t80_ip/T80_Reg.vhd" +vhdl work "t80_ip/T80as.vhd" +vhdl work "galaxian_1h.vhd" +vhdl work "galaxian_1k.vhd" +vhdl work "galaxian_6l.vhd" +vhdl work "galaxian_7l.vhd" +vhdl work "galaxian_u.vhd" +vhdl work "galaxian_v.vhd" +vhdl work "galaxian_w.vhd" +vhdl work "galaxian_y.vhd" diff --git a/galaxian/galaxian.scr b/galaxian/galaxian.scr new file mode 100644 index 0000000..b2f292f --- /dev/null +++ b/galaxian/galaxian.scr @@ -0,0 +1,10 @@ +run +-ifn galaxian.prj +-ifmt mixed +-ofn galaxian.ngc +-ofmt NGC +-p XC3SD1800A-FG676-4 +-opt_mode Area +-opt_level 1 +-top mc_top +-keep_hierarchy yes diff --git a/galaxian/galaxian.ucf b/galaxian/galaxian.ucf new file mode 100644 index 0000000..1f840ca --- /dev/null +++ b/galaxian/galaxian.ucf @@ -0,0 +1,73 @@ +### UCF file for FPGA-MOONCRST on XC2S200E +# +#---------- MasterClock 18.432MHz ---------- +NET "I_CLK_125M" LOC = "F13" | IOSTANDARD = LVCMOS33; +#------------------------------------------- +#---------- SW I/F ------------------------- +NET "I_PSW<0>" LOC = "K19" | IOSTANDARD = LVTTL | PULLUP; +NET "I_PSW<1>" LOC = "F22" | IOSTANDARD = LVTTL | PULLUP; +NET "I_PSW<2>" LOC = "G22" | IOSTANDARD = LVTTL | PULLUP; +NET "I_PSW<3>" LOC = "K18" | IOSTANDARD = LVTTL | PULLUP; +NET "I_PSW<4>" LOC = "F23" | IOSTANDARD = LVTTL | PULLUP; +#------------------------------------------- +#--------- EEPROM I/F ---------------------- +#NET "I_ROM_DB<0>" LOC = "P70"; +#NET "I_ROM_DB<1>" LOC = "P68"; +#NET "I_ROM_DB<2>" LOC = "P63"; +#NET "I_ROM_DB<3>" LOC = "P58"; +#NET "I_ROM_DB<4>" LOC = "P60"; +#NET "I_ROM_DB<5>" LOC = "P62"; +#NET "I_ROM_DB<6>" LOC = "P57"; +#NET "I_ROM_DB<7>" LOC = "P59"; +#NET "O_ROM_AB<0>" LOC = "P71"; +#NET "O_ROM_AB<1>" LOC = "P74"; +#NET "O_ROM_AB<2>" LOC = "P73"; +#NET "O_ROM_AB<3>" LOC = "P75"; +#NET "O_ROM_AB<4>" LOC = "P81"; +#NET "O_ROM_AB<5>" LOC = "P82"; +#NET "O_ROM_AB<6>" LOC = "P84"; +#NET "O_ROM_AB<7>" LOC = "P86"; +#NET "O_ROM_AB<8>" LOC = "P89"; +#NET "O_ROM_AB<9>" LOC = "P87"; +#NET "O_ROM_AB<10>" LOC = "P64"; +#NET "O_ROM_AB<11>" LOC = "P83"; +#NET "O_ROM_AB<12>" LOC = "P88"; +#NET "O_ROM_AB<13>" LOC = "P95"; +#NET "O_ROM_AB<14>" LOC = "P97"; +#NET "O_ROM_AB<15>" LOC = "P93"; +#NET "O_ROM_AB<16>" LOC = "P96"; +#NET "O_ROM_AB<17>" LOC = "P98"; +#NET "O_ROM_AB<18>" LOC = "P94"; +#NET "O_ROM_CSn" LOC = "P61"; +#NET "O_ROM_OEn" LOC = "P69"; +#NET "O_ROM_WEn" LOC = "P100"; +#------------------------------------------- +#--------- SOUND I/F ----------------------- +NET "O_SOUND_OUT_L" LOC = "AA22" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8; +NET "O_SOUND_OUT_R" LOC = "V19" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8; +#------------------------------------------- +#--------- VIDEO I/F ----------------------- +NET "O_VGA_R<4>" LOC = "V18" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; +NET "O_VGA_R<3>" LOC = "F24" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; +NET "O_VGA_R<2>" LOC = "F25" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; +NET "O_VGA_R<1>" LOC = "K20" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; +NET "O_VGA_R<0>" LOC = "L20" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; +NET "O_VGA_G<4>" LOC = "T17" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; +NET "O_VGA_G<3>" LOC = "J22" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; +NET "O_VGA_G<2>" LOC = "J23" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; +NET "O_VGA_G<1>" LOC = "M18" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; +NET "O_VGA_G<0>" LOC = "M19" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; +NET "O_VGA_B<4>" LOC = "Y25" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; +NET "O_VGA_B<3>" LOC = "G24" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; +NET "O_VGA_B<2>" LOC = "G23" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; +NET "O_VGA_B<1>" LOC = "K21" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; +NET "O_VGA_B<0>" LOC = "L22" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; + +NET "O_VGA_H_SYNCn" LOC = "K26" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; +NET "O_VGA_V_SYNCn" LOC = "K25" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; + + +#------------------------------------------- +# +#---------- Build-in ROM ------------------------------------------------------------------------------- +#INST "col_rom00" INIT_00 = c6077600f007f6000700000007a0c00007c4c0003f07d8003fc01600f6000000; diff --git a/galaxian/galaxian.ut b/galaxian/galaxian.ut new file mode 100644 index 0000000..01ec7f9 --- /dev/null +++ b/galaxian/galaxian.ut @@ -0,0 +1,4 @@ +-g DonePin:PULLUP +-g TdoPin:PULLNONE +-g StartUpClk:JTAGCLK +-g DriveDone:Yes diff --git a/galaxian/romgen/romgen.cpp b/galaxian/romgen/romgen.cpp new file mode 100644 index 0000000..5271add --- /dev/null +++ b/galaxian/romgen/romgen.cpp @@ -0,0 +1,504 @@ +#include +#include +#include +#include +#include +using namespace std; + +#define MAX_ROM_SIZE 0x4000 + +int main(int argc, char* argv[]) + +{ + cerr << "romgen by MikeJ version 3.00\n"; + // read file + + string buffer; + FILE *fin; + + if(argc < 5) + { + cerr << "\nUsage: romgen \n"; + cerr << " {registered} {enable}\n"; + cerr << "\n"; + cerr << "Now uses bit_vector generics for compatibilty with Xilinx UniSim library\n"; + cerr << "\n"; + cerr << "for the format paramater use :\n"; + cerr << " a - rtl model rom array \n"; + cerr << " c - rtl model case statement \n"; + cerr << " b - Xilinx block ram4 (registered output always)\n"; + cerr << " l - Xilinx block ram16 (registered output always)\n"; + cerr << " d - Xilinx distributed ram [not supported yet]\n"; + cerr << "\n"; + cerr << "for the registered paramater (optional) use :\n"; + cerr << " r - registered output (combinatorial otherwise) \n"; + cerr << "\n"; + cerr << "for the enable paramater (optional) use :\n"; + cerr << " e - clock enable generated \n"; + cerr << "\n"; + cerr << "note, generated roms are always 8 bits wide\n"; + cerr << " max 12 address bits for block ram4s\n"; + cerr << " max 14 address bits for block ram16s\n"; + cerr << "for example romgen fred.bin fred_rom 12 c r\n\n"; + return -1; + } + + fin = fopen(argv[1],"rb"); + if (fin == NULL) { + cerr << "ERROR : Could not open input file " << argv[1] <<"\n"; + return -1; + } + + char rom_type = 0; + char option_1 = 0; + char option_2 = 0; + sscanf(argv[4],"%c",&rom_type); + if (argc > 5) sscanf(argv[5],"%c",&option_1); + if (argc > 6) sscanf(argv[6],"%c",&option_2); + + bool format_case = false; + bool format_array = false; + bool format_block = false; + bool format_dist = false; + bool format_clock = false; + bool format_ram16 = false; + bool format_ena = false; + + cerr << "INFO : creating entity : " << argv[2] << "\n"; + + if (option_1 != 0) { + if ((option_1 == 'r') || (option_1 == 'R')) + format_clock = true; + else if ((option_1 == 'e') || (option_1 == 'E')) + format_ena = true; + else { + cerr << "ERROR : output option not supported\n"; + return -1; + } + } + + // lazy ... + if (option_2 != 0) { + if ((option_2 == 'r') || (option_2 == 'R')) + format_clock = true; + else if ((option_2 == 'e') || (option_2 == 'E')) + format_ena = true; + else { + cerr << "ERROR : output option not supported\n"; + return -1; + } + } + + if ((rom_type == 'c') || (rom_type == 'C')) { + cerr << "INFO : rtl model, case statement \n"; format_case = true; } + else if ((rom_type == 'a') || (rom_type == 'A')) { + cerr << "INFO : rtl model, rom array \n"; format_array = true; } + else if ((rom_type == 'b') || (rom_type == 'B')) { + cerr << "INFO : block4 ram, registered \n"; format_block = true; format_clock = true; } + else if ((rom_type == 'l') || (rom_type == 'L')) { + cerr << "INFO : block16 ram, registered \n"; format_block = true; format_clock = true; format_ram16 = true; } + //else if ((rom_type == 'd') || (rom_type == 'D')) { + // cerr << "INFO : distributed ram, combinatorial; \n"; format_dist = true; } + else { + cerr << "ERROR : format not supported\n"; + return -1; + } + if (format_clock == true) + cerr << "INFO : registered output\n\n"; + else + cerr << "INFO : combinatorial output\n\n"; + + + // calc number of address bits required + int addr_bits; + int max_addr_bits = 16; + int rom_inits = 16; + + if (format_block == true) { + if (format_ram16 == true) { + max_addr_bits = 14; + rom_inits = 64; + } + else + max_addr_bits = 12; + } + + sscanf(argv[3],"%d",&addr_bits); + if (addr_bits < 1 || addr_bits > max_addr_bits) { + cerr << "ERROR : illegal rom size, number of address bits must be between 1 and " << max_addr_bits << "\n"; + return -1; + } + // ram b16s + // for 14 bits use ram_b16_s1 x data_width + // for 13 bits use ram_b16_s2 x data_width/2 + // for 12 bits use ram_b16_s4 x data_width/4 + // for<=11 bits use ram_b16_s8 x data_width/8 + + // ram b4s + // for 12 bits use ram_b4_s1 x data_width + // for 11 bits use ram_b4_s2 x data_width/2 + // for 10 bits use ram_b4_s4 x data_width/4 + // for <=9 bits use ram_b4_s8 x data_width/8 + int rom_size = (int) pow(2,addr_bits); + + int number_of_block_rams = 1; + int block_ram_width = 8; + int block_ram_pwidth = 0; + int block_ram_abits = 9; + + if (format_ram16 == true) { + block_ram_abits = 11; // default + block_ram_pwidth = 1; + // ram16s + switch (addr_bits) { + case 14 : number_of_block_rams = 8; block_ram_width = 1; block_ram_pwidth = 0; block_ram_abits = 14; break; + case 13 : number_of_block_rams = 4; block_ram_width = 2; block_ram_pwidth = 0; block_ram_abits = 13; break; + case 12 : number_of_block_rams = 2; block_ram_width = 4; block_ram_pwidth = 0; block_ram_abits = 12; break; + default : ; + } + } + else { + // ram4s + switch (addr_bits) { + case 12 : number_of_block_rams = 8; block_ram_width = 1; block_ram_abits = 12; break; + case 11 : number_of_block_rams = 4; block_ram_width = 2; block_ram_abits = 11; break; + case 10 : number_of_block_rams = 2; block_ram_width = 4; block_ram_abits = 10; break; + default : ; + } + } + + //printf("block ram w : %d ",block_ram_width); + //printf("block ram n : %d ",number_of_block_rams); + + + // process + int mem[MAX_ROM_SIZE]; + string line; + + int i,j,k; + + + int addr = 0; + int offset = 0; + int mask = 0; + unsigned int data = 0; + + // clear mem + for (i = 0; i < MAX_ROM_SIZE; i++) mem[i] = 0; + + // process file + data = getc(fin); + while (!feof(fin) && (addr < rom_size)) { + if (addr >= MAX_ROM_SIZE) { + cerr << "ERROR : file too large\n"; + return -1; + } + + mem[addr] = data; + // debug + //if (addr % 16 == 0) printf("%04x : ",addr); + //printf("%02x ",data); + //if (addr % 16 == 15) printf("\n"); + // end debug + addr ++; + data = getc(fin); + } + fclose(fin); + + + printf("-- generated with romgen v3.0 by MikeJ\n"); + printf("library ieee;\n"); + printf(" use ieee.std_logic_1164.all;\n"); + printf(" use ieee.std_logic_unsigned.all;\n"); + printf(" use ieee.numeric_std.all;\n"); + printf("\n"); + printf("library UNISIM;\n"); + printf(" use UNISIM.Vcomponents.all;\n"); + printf("\n"); + printf("entity %s is\n",argv[2]); + printf(" port (\n"); + if (format_clock == true) printf(" CLK : in std_logic;\n"); + if (format_ena == true) printf(" ENA : in std_logic;\n"); + printf(" ADDR : in std_logic_vector(%d downto 0);\n",addr_bits - 1); + printf(" DATA : out std_logic_vector(7 downto 0)\n"); + printf(" );\n"); + printf("end;\n"); + printf("\n"); + printf("architecture RTL of %s is\n",argv[2]); + printf("\n"); + + // if blockram + //{{{ + if (format_block == true) { + printf(" function romgen_str2bv (str : string) return bit_vector is\n"); + printf(" variable result : bit_vector (str'length*4-1 downto 0);\n"); + printf(" begin\n"); + printf(" for i in 0 to str'length-1 loop\n"); + printf(" case str(str'high-i) is\n"); + for (i = 0; i<16; i++) + printf(" when '%01X' => result(i*4+3 downto i*4) := x\042%01X\042;\n",i,i); + printf(" when others => null;\n"); + printf(" end case;\n"); + printf(" end loop;\n"); + printf(" return result;\n"); + printf(" end romgen_str2bv;\n"); + printf("\n"); + + // xilinx block ram component + if (block_ram_pwidth != 0) { + for (i = 0; i< 8; i++) + printf(" attribute INITP_%02X : string;\n",i); + printf("\n"); + } + + for (i = 0; i< rom_inits; i++) + printf(" attribute INIT_%02X : string;\n",i); + printf("\n"); + + if (format_ram16 == true) + printf(" component RAMB16_S%d\n",block_ram_width + block_ram_pwidth); + else + printf(" component RAMB4_S%d\n",block_ram_width); + + printf(" --pragma translate_off\n"); + printf(" generic (\n"); + if (block_ram_pwidth != 0) { + for (i = 0; i< 8; i++) { + printf(" INITP_%02X : bit_vector (255 downto 0) := x\0420000000000000000000000000000000000000000000000000000000000000000\042",i); + printf(";\n"); + } + printf("\n"); + } + + for (i = 0; i< rom_inits; i++) { + printf(" INIT_%02X : bit_vector (255 downto 0) := x\0420000000000000000000000000000000000000000000000000000000000000000\042",i); + if (i< (rom_inits - 1)) printf(";"); + printf("\n"); + } + printf(" );\n"); + printf(" --pragma translate_on\n"); + printf(" port (\n"); + printf(" DO : out std_logic_vector (%d downto 0);\n",block_ram_width -1); + if (block_ram_pwidth != 0) + printf(" DOP : out std_logic_vector (%d downto 0);\n",block_ram_pwidth -1); + printf(" ADDR : in std_logic_vector (%d downto 0);\n",block_ram_abits -1); + printf(" CLK : in std_logic;\n"); + printf(" DI : in std_logic_vector (%d downto 0);\n",block_ram_width -1); + if (block_ram_pwidth != 0) + printf(" DIP : in std_logic_vector (%d downto 0);\n",block_ram_pwidth -1); + printf(" EN : in std_logic;\n"); + if (format_ram16 == true) + printf(" SSR : in std_logic;\n"); + else + printf(" RST : in std_logic;\n"); + printf(" WE : in std_logic \n"); + printf(" );\n"); + printf(" end component;\n"); + printf("\n"); + printf(" signal rom_addr : std_logic_vector(%d downto 0);\n",block_ram_abits - 1); + printf("\n"); + } + //}}} + //{{{ + if (format_array == true) { + printf("\n"); + printf(" type ROM_ARRAY is array(0 to %d) of std_logic_vector(7 downto 0);\n",rom_size - 1); + printf(" constant ROM : ROM_ARRAY := (\n"); + for (i = 0; i < rom_size; i ++ ) { + if (i % 8 == 0) printf(" "); + printf("x\042%02X\042",mem[i]); + if (i < (rom_size - 1)) printf(","); + if (i == (rom_size - 1)) printf(" "); + if (i % 8 == 7) printf(" -- 0x%04X\n",i - 7); + } + printf(" );\n"); + printf("\n"); + } // end array + //}}} + //{{{ + if (format_case == true) { + printf(" signal rom_addr : std_logic_vector(11 downto 0);\n"); + printf("\n"); + } + //}}} + + printf("begin\n"); + printf("\n"); + // + if ((format_block == true) || (format_case == true)) { + printf(" p_addr : process(ADDR)\n"); + printf(" begin\n"); + printf(" rom_addr <= (others => '0');\n"); + printf(" rom_addr(%d downto 0) <= ADDR;\n",addr_bits - 1); + printf(" end process;\n"); + printf("\n"); + } + // + //{{{ + if (format_block == true) { + for (k = 0; k < number_of_block_rams; k ++){ + printf(" rom%d : if true generate\n",k); + + for (j = 0; j < rom_inits; j++) { + printf(" attribute INIT_%02X of inst : label is \042",j); + switch (block_ram_width) { + + case 1 : // width 1 + mask = 0x1 << (k); + for (i = 0; i < 256; i+=8) { + data = ((mem[(j*256) + (255 - i)] & mask) >> k); + data <<= 1; + data += ((mem[(j*256) + (254 - i)] & mask) >> k); + data <<= 1; + data += ((mem[(j*256) + (253 - i)] & mask) >> k); + data <<= 1; + data += ((mem[(j*256) + (252 - i)] & mask) >> k); + data <<= 1; + data += ((mem[(j*256) + (251 - i)] & mask) >> k); + data <<= 1; + data += ((mem[(j*256) + (250 - i)] & mask) >> k); + data <<= 1; + data += ((mem[(j*256) + (249 - i)] & mask) >> k); + data <<= 1; + data += ((mem[(j*256) + (248 - i)] & mask) >> k); + printf("%02X",data); + } + break; + + case 2 : // width 2 + mask = 0x3 << (k * 2); + for (i = 0; i < 128; i+=4) { + data = ((mem[(j*128) + (127 - i)] & mask) >> k * 2); + data <<= 2; + data += ((mem[(j*128) + (126 - i)] & mask) >> k * 2); + data <<= 2; + data += ((mem[(j*128) + (125 - i)] & mask) >> k * 2); + data <<= 2; + data += ((mem[(j*128) + (124 - i)] & mask) >> k * 2); + printf("%02X",data); + } + break; + + case 4 : // width 4 + mask = 0xF << (k * 4); + for (i = 0; i < 64; i+=2) { + data = ((mem[(j*64) + (63 - i)] & mask) >> k * 4); + data <<= 4; + data += ((mem[(j*64) + (62 - i)] & mask) >> k * 4); + + printf("%02X",data); + } + break; + + + case 8 : // width 8 + for (i = 0; i < 32; i++) { + data = ((mem[(j*32) + (31 - i)])); + printf("%02X",data); + } + break; + } // end switch + + printf("\042;\n"); + } + + printf(" begin\n"); + if (format_ram16 == true) + printf(" inst : RAMB16_S%d\n",block_ram_width + block_ram_pwidth); + else + printf(" inst : RAMB4_S%d\n",block_ram_width); + + printf(" --pragma translate_off\n"); + printf(" generic map (\n"); + + if (block_ram_pwidth != 0) { + for (i = 0; i< 8; i++) { + printf(" INITP_%02X => x\0420000000000000000000000000000000000000000000000000000000000000000\042",i); + printf(",\n"); + } + printf("\n"); + } + + for (i = 0; i< rom_inits; i++) { + printf(" INIT_%02X => romgen_str2bv(inst'INIT_%02X)",i,i); + if (i< (rom_inits - 1)) printf(","); + printf("\n"); + } + printf(" )\n"); + printf(" --pragma translate_on\n"); + printf(" port map (\n"); + printf(" DO => DATA(%d downto %d),\n",((k+1) * block_ram_width)-1,k*block_ram_width); + if (block_ram_pwidth != 0) + printf(" DOP => open,\n"); + printf(" ADDR => rom_addr,\n"); + printf(" CLK => CLK,\n"); + printf(" DI => \042"); + for (i = 0; i < block_ram_width -1; i++) printf("0"); + printf("0\042,\n"); + if (block_ram_pwidth != 0) { + printf(" DIP => \042"); + for (i = 0; i < block_ram_pwidth -1; i++) printf("0"); + printf("0\042,\n"); + } + if (format_ena == true) + printf(" EN => ENA,\n"); + else + printf(" EN => '1',\n"); + // + if (format_ram16 == true) + printf(" SSR => '0',\n"); + else + printf(" RST => '0',\n"); + printf(" WE => '0'\n"); + printf(" );\n"); + printf(" end generate;\n"); + } + } // end block ram + //}}} + + //{{{ + if (format_array == true) { + if (format_clock == true) + printf(" p_rom : process\n"); + else + printf(" p_rom : process(ADDR)\n"); + printf(" begin\n"); + if (format_clock == true) + printf(" wait until rising_edge(CLK);\n"); + if (format_ena == true) + printf(" if (ENA = '1') then\n "); + printf(" DATA <= ROM(to_integer(unsigned(ADDR)));\n"); + if (format_ena == true) + printf(" end if;\n"); + printf(" end process;\n"); + //}}} + } // end array + + //{{{ + if (format_case == true) { + if (format_clock == true) + printf(" p_rom : process\n"); + else + printf(" p_rom : process(rom_addr)\n"); + printf(" begin\n"); + if (format_clock == true) + printf(" wait until rising_edge(CLK);\n"); + if (format_ena == true) + printf(" if (ENA = '1') then\n"); + + printf(" DATA <= (others => '0');\n"); + printf(" case rom_addr is\n"); + for (i = 0; i < rom_size; i ++ ) { + printf(" when x\042%03X\042 => DATA <= x\042%02X\042;\n",i,mem[i]); + } + printf(" when others => DATA <= (others => '0');\n"); + printf(" end case;\n"); + if (format_ena == true) + printf(" end if;\n"); + printf(" end process;\n"); + //}}} + } // end case + printf("end RTL;\n"); + + return 0; +} diff --git a/galaxian/src/altera/alt_ram_1024_8.v b/galaxian/src/altera/alt_ram_1024_8.v new file mode 100644 index 0000000..419b4d3 --- /dev/null +++ b/galaxian/src/altera/alt_ram_1024_8.v @@ -0,0 +1,126 @@ +// megafunction wizard: %RAM: 1-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: alt_ram_1024_8.v +// Megafunction Name(s): +// altsyncram +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// ************************************************************ + + +//Copyright (C) 1991-2003 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + + +module alt_ram_1024_8 ( + address, + clock, + data, + wren, + q); + + input [9:0] address; + input clock; + input [7:0] data; + input wren; + output [7:0] q; + + wire [7:0] sub_wire0; + wire [7:0] q = sub_wire0[7:0]; + + altsyncram altsyncram_component ( + .wren_a (wren), + .clock0 (clock), + .address_a (address), + .data_a (data), + .q_a (sub_wire0)); + defparam + altsyncram_component.intended_device_family = "Cyclone", + altsyncram_component.width_a = 8, + altsyncram_component.widthad_a = 10, + altsyncram_component.numwords_a = 1024, + altsyncram_component.operation_mode = "SINGLE_PORT", + altsyncram_component.outdata_reg_a = "UNREGISTERED", + altsyncram_component.indata_aclr_a = "NONE", + altsyncram_component.wrcontrol_aclr_a = "NONE", + altsyncram_component.address_aclr_a = "NONE", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.width_byteena_a = 1, + altsyncram_component.ram_block_type = "AUTO", + altsyncram_component.lpm_type = "altsyncram"; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: WidthData NUMERIC "8" +// Retrieval info: PRIVATE: WidthAddr NUMERIC "10" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: PRIVATE: SingleClock NUMERIC "1" +// Retrieval info: PRIVATE: UseDQRAM NUMERIC "1" +// Retrieval info: PRIVATE: RegData NUMERIC "1" +// Retrieval info: PRIVATE: RegAddr NUMERIC "1" +// Retrieval info: PRIVATE: RegOutput NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +// Retrieval info: PRIVATE: AclrByte NUMERIC "0" +// Retrieval info: PRIVATE: AclrData NUMERIC "0" +// Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0" +// Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +// Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +// Retrieval info: PRIVATE: Clken NUMERIC "0" +// Retrieval info: PRIVATE: BlankMemory NUMERIC "1" +// Retrieval info: PRIVATE: MIFfilename STRING "" +// Retrieval info: PRIVATE: UseLCs NUMERIC "0" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +// Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "10" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "1024" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT" +// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" +// Retrieval info: CONSTANT: INDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: WRCONTROL_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: CONSTANT: RAM_BLOCK_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: USED_PORT: address 0 0 10 0 INPUT NODEFVAL address[9..0] +// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL q[7..0] +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock +// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL data[7..0] +// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL wren +// Retrieval info: CONNECT: @address_a 0 0 10 0 address 0 0 10 0 +// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +// Retrieval info: CONNECT: @data_a 0 0 8 0 data 0 0 8 0 +// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0 +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all diff --git a/galaxian/src/altera/alt_ram_1024_8_8.v b/galaxian/src/altera/alt_ram_1024_8_8.v new file mode 100644 index 0000000..05e6a2a --- /dev/null +++ b/galaxian/src/altera/alt_ram_1024_8_8.v @@ -0,0 +1,245 @@ +// megafunction wizard: %RAM: 2-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: alt_ram_1024_8_8.v +// Megafunction Name(s): +// altsyncram +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 4.0 Build 214 3/25/2004 SP 1 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2004 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module alt_ram_1024_8_8 ( + data_a, + wren_a, + address_a, + data_b, + address_b, + wren_b, + clock_a, + enable_a, + clock_b, + enable_b, + q_a, + q_b); + + input [7:0] data_a; + input wren_a; + input [9:0] address_a; + input [7:0] data_b; + input [9:0] address_b; + input wren_b; + input clock_a; + input enable_a; + input clock_b; + input enable_b; + output [7:0] q_a; + output [7:0] q_b; + + wire [7:0] sub_wire0; + wire [7:0] sub_wire1; + wire [7:0] q_a = sub_wire0[7:0]; + wire [7:0] q_b = sub_wire1[7:0]; + + altsyncram altsyncram_component ( + .clocken0 (enable_a), + .clocken1 (enable_b), + .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) + // synopsys translate_off +, + .rden_b (), + .aclr0 (), + .aclr1 (), + .byteena_a (), + .byteena_b (), + .addressstall_a (), + .addressstall_b () + // synopsys translate_on + +); + defparam + altsyncram_component.intended_device_family = "Cyclone", + altsyncram_component.operation_mode = "BIDIR_DUAL_PORT", + altsyncram_component.width_a = 8, + altsyncram_component.widthad_a = 10, + altsyncram_component.numwords_a = 1024, + altsyncram_component.width_b = 8, + altsyncram_component.widthad_b = 10, + altsyncram_component.numwords_b = 1024, + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.width_byteena_a = 1, + altsyncram_component.width_byteena_b = 1, + altsyncram_component.outdata_reg_a = "UNREGISTERED", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_reg_b = "UNREGISTERED", + altsyncram_component.indata_aclr_a = "NONE", + altsyncram_component.wrcontrol_aclr_a = "NONE", + altsyncram_component.address_aclr_a = "NONE", + altsyncram_component.indata_reg_b = "CLOCK1", + altsyncram_component.address_reg_b = "CLOCK1", + altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1", + altsyncram_component.indata_aclr_b = "NONE", + altsyncram_component.wrcontrol_aclr_b = "NONE", + altsyncram_component.address_aclr_b = "NONE", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.ram_block_type = "AUTO"; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0" +// Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "3" +// Retrieval info: PRIVATE: UseDPRAM NUMERIC "1" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: PRIVATE: VarWidth NUMERIC "0" +// Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "8" +// Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "8" +// Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "8" +// Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "8" +// Retrieval info: PRIVATE: MEMSIZE NUMERIC "8192" +// Retrieval info: PRIVATE: Clock NUMERIC "5" +// Retrieval info: PRIVATE: rden 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: Clock_A NUMERIC "0" +// Retrieval info: PRIVATE: Clock_B NUMERIC "0" +// Retrieval info: PRIVATE: REGdata NUMERIC "1" +// Retrieval info: PRIVATE: REGwraddress NUMERIC "1" +// Retrieval info: PRIVATE: REGwren NUMERIC "1" +// Retrieval info: PRIVATE: REGrdaddress NUMERIC "0" +// Retrieval info: PRIVATE: REGrren NUMERIC "0" +// Retrieval info: PRIVATE: REGq NUMERIC "0" +// Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "1" +// Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "1" +// Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "0" +// Retrieval info: PRIVATE: CLRdata NUMERIC "0" +// Retrieval info: PRIVATE: CLRwren NUMERIC "0" +// Retrieval info: PRIVATE: CLRwraddress NUMERIC "0" +// Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0" +// Retrieval info: PRIVATE: CLRrren NUMERIC "0" +// Retrieval info: PRIVATE: CLRq NUMERIC "0" +// Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0" +// Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: enable NUMERIC "1" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0" +// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +// Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2" +// Retrieval info: PRIVATE: BlankMemory NUMERIC "1" +// Retrieval info: PRIVATE: MIFfilename STRING "" +// Retrieval info: PRIVATE: UseLCs NUMERIC "0" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_0 STRING "wren_a;wren_b;rden_b;data_a;data_b" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_1 STRING "address_a;address_b;clock0;clock1;clocken0" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_2 STRING "clocken1;aclr0;aclr1;byteena_a;byteena_b" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_3 STRING "addressstall_a;addressstall_b;q_a;q_b" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "BIDIR_DUAL_PORT" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "10" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "1024" +// Retrieval info: CONSTANT: WIDTH_B NUMERIC "8" +// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "10" +// Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "1024" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_B NUMERIC "1" +// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" +// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED" +// Retrieval info: CONSTANT: INDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: WRCONTROL_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: INDATA_REG_B STRING "CLOCK1" +// Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK1" +// Retrieval info: CONSTANT: WRCONTROL_WRADDRESS_REG_B STRING "CLOCK1" +// Retrieval info: CONSTANT: INDATA_ACLR_B STRING "NONE" +// Retrieval info: CONSTANT: WRCONTROL_ACLR_B STRING "NONE" +// Retrieval info: CONSTANT: ADDRESS_ACLR_B STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE" +// Retrieval info: CONSTANT: RAM_BLOCK_TYPE STRING "AUTO" +// Retrieval info: USED_PORT: data_a 0 0 8 0 INPUT NODEFVAL data_a[7..0] +// Retrieval info: USED_PORT: wren_a 0 0 0 0 INPUT VCC wren_a +// 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: address_a 0 0 10 0 INPUT NODEFVAL address_a[9..0] +// Retrieval info: USED_PORT: data_b 0 0 8 0 INPUT NODEFVAL data_b[7..0] +// Retrieval info: USED_PORT: address_b 0 0 10 0 INPUT NODEFVAL address_b[9..0] +// Retrieval info: USED_PORT: wren_b 0 0 0 0 INPUT VCC wren_b +// Retrieval info: USED_PORT: clock_a 0 0 0 0 INPUT NODEFVAL clock_a +// Retrieval info: USED_PORT: enable_a 0 0 0 0 INPUT VCC enable_a +// Retrieval info: USED_PORT: clock_b 0 0 0 0 INPUT NODEFVAL clock_b +// Retrieval info: USED_PORT: enable_b 0 0 0 0 INPUT VCC enable_b +// Retrieval info: CONNECT: @data_a 0 0 8 0 data_a 0 0 8 0 +// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren_a 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: CONNECT: @address_a 0 0 10 0 address_a 0 0 10 0 +// Retrieval info: CONNECT: @data_b 0 0 8 0 data_b 0 0 8 0 +// Retrieval info: CONNECT: @address_b 0 0 10 0 address_b 0 0 10 0 +// Retrieval info: CONNECT: @wren_b 0 0 0 0 wren_b 0 0 0 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 clock_a 0 0 0 0 +// Retrieval info: CONNECT: @clocken0 0 0 0 0 enable_a 0 0 0 0 +// Retrieval info: CONNECT: @clock1 0 0 0 0 clock_b 0 0 0 0 +// Retrieval info: CONNECT: @clocken1 0 0 0 0 enable_b 0 0 0 0 +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: GEN_FILE: TYPE_NORMAL alt_ram_1024_8_8.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL alt_ram_1024_8_8.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL alt_ram_1024_8_8.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL alt_ram_1024_8_8.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL alt_ram_1024_8_8_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL alt_ram_1024_8_8_bb.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL alt_ram_1024_8_8_waveforms.html FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL alt_ram_1024_8_8_wave*.jpg FALSE diff --git a/galaxian/src/altera/alt_ram_256_5.v b/galaxian/src/altera/alt_ram_256_5.v new file mode 100644 index 0000000..383724a --- /dev/null +++ b/galaxian/src/altera/alt_ram_256_5.v @@ -0,0 +1,133 @@ +// megafunction wizard: %RAM: 1-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: alt_ram_256_5.v +// Megafunction Name(s): +// altsyncram +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// ************************************************************ + + +//Copyright (C) 1991-2003 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + + +module alt_ram_256_5 ( + address, + inclock, + outclock, + data, + wren, + q); + + input [7:0] address; + input inclock; + input outclock; + input [4:0] data; + input wren; + output [4:0] q; + + wire [4:0] sub_wire0; + wire [4:0] q = sub_wire0[4:0]; + + altsyncram altsyncram_component ( + .wren_a (wren), + .clock0 (inclock), + .clock1 (outclock), + .address_a (address), + .data_a (data), + .q_a (sub_wire0)); + defparam + altsyncram_component.intended_device_family = "Cyclone", + altsyncram_component.width_a = 5, + altsyncram_component.widthad_a = 8, + altsyncram_component.numwords_a = 256, + altsyncram_component.operation_mode = "SINGLE_PORT", + altsyncram_component.outdata_reg_a = "CLOCK1", + altsyncram_component.indata_aclr_a = "NONE", + altsyncram_component.wrcontrol_aclr_a = "NONE", + altsyncram_component.address_aclr_a = "NONE", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.width_byteena_a = 1, + altsyncram_component.ram_block_type = "AUTO", + altsyncram_component.use_eab = "ON", + altsyncram_component.lpm_type = "altsyncram"; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: WidthData NUMERIC "5" +// Retrieval info: PRIVATE: WidthAddr NUMERIC "8" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: PRIVATE: SingleClock NUMERIC "0" +// Retrieval info: PRIVATE: UseDQRAM NUMERIC "1" +// Retrieval info: PRIVATE: RegData NUMERIC "1" +// Retrieval info: PRIVATE: RegAddr NUMERIC "1" +// Retrieval info: PRIVATE: RegOutput NUMERIC "1" +// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +// Retrieval info: PRIVATE: AclrByte NUMERIC "0" +// Retrieval info: PRIVATE: AclrData NUMERIC "0" +// Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0" +// Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +// Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +// Retrieval info: PRIVATE: Clken NUMERIC "0" +// Retrieval info: PRIVATE: BlankMemory NUMERIC "1" +// Retrieval info: PRIVATE: MIFfilename STRING "" +// Retrieval info: PRIVATE: UseLCs NUMERIC "0" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +// Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "5" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "8" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "256" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT" +// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK1" +// Retrieval info: CONSTANT: INDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: WRCONTROL_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: CONSTANT: RAM_BLOCK_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: USE_EAB STRING "ON" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: USED_PORT: address 0 0 8 0 INPUT NODEFVAL address[7..0] +// Retrieval info: USED_PORT: q 0 0 5 0 OUTPUT NODEFVAL q[4..0] +// Retrieval info: USED_PORT: inclock 0 0 0 0 INPUT NODEFVAL inclock +// Retrieval info: USED_PORT: outclock 0 0 0 0 INPUT NODEFVAL outclock +// Retrieval info: USED_PORT: data 0 0 5 0 INPUT NODEFVAL data[4..0] +// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL wren +// Retrieval info: CONNECT: @address_a 0 0 8 0 address 0 0 8 0 +// Retrieval info: CONNECT: q 0 0 5 0 @q_a 0 0 5 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 inclock 0 0 0 0 +// Retrieval info: CONNECT: @clock1 0 0 0 0 outclock 0 0 0 0 +// Retrieval info: CONNECT: @data_a 0 0 5 0 data 0 0 5 0 +// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0 +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all diff --git a/galaxian/src/altera/alt_ram_256_8.v b/galaxian/src/altera/alt_ram_256_8.v new file mode 100644 index 0000000..3e40926 --- /dev/null +++ b/galaxian/src/altera/alt_ram_256_8.v @@ -0,0 +1,126 @@ +// megafunction wizard: %RAM: 1-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: alt_ram_256_8.v +// Megafunction Name(s): +// altsyncram +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// ************************************************************ + + +//Copyright (C) 1991-2003 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + + +module alt_ram_256_8 ( + address, + clock, + data, + wren, + q); + + input [7:0] address; + input clock; + input [7:0] data; + input wren; + output [7:0] q; + + wire [7:0] sub_wire0; + wire [7:0] q = sub_wire0[7:0]; + + altsyncram altsyncram_component ( + .wren_a (wren), + .clock0 (clock), + .address_a (address), + .data_a (data), + .q_a (sub_wire0)); + defparam + altsyncram_component.intended_device_family = "Cyclone", + altsyncram_component.width_a = 8, + altsyncram_component.widthad_a = 8, + altsyncram_component.numwords_a = 256, + altsyncram_component.operation_mode = "SINGLE_PORT", + altsyncram_component.outdata_reg_a = "UNREGISTERED", + altsyncram_component.indata_aclr_a = "NONE", + altsyncram_component.wrcontrol_aclr_a = "NONE", + altsyncram_component.address_aclr_a = "NONE", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.width_byteena_a = 1, + altsyncram_component.ram_block_type = "AUTO", + altsyncram_component.lpm_type = "altsyncram"; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: WidthData NUMERIC "8" +// Retrieval info: PRIVATE: WidthAddr NUMERIC "8" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: PRIVATE: SingleClock NUMERIC "1" +// Retrieval info: PRIVATE: UseDQRAM NUMERIC "1" +// Retrieval info: PRIVATE: RegData NUMERIC "1" +// Retrieval info: PRIVATE: RegAddr NUMERIC "1" +// Retrieval info: PRIVATE: RegOutput NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +// Retrieval info: PRIVATE: AclrByte NUMERIC "0" +// Retrieval info: PRIVATE: AclrData NUMERIC "0" +// Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0" +// Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +// Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +// Retrieval info: PRIVATE: Clken NUMERIC "0" +// Retrieval info: PRIVATE: BlankMemory NUMERIC "1" +// Retrieval info: PRIVATE: MIFfilename STRING "" +// Retrieval info: PRIVATE: UseLCs NUMERIC "0" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +// Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "8" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "256" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT" +// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" +// Retrieval info: CONSTANT: INDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: WRCONTROL_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: CONSTANT: RAM_BLOCK_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: USED_PORT: address 0 0 8 0 INPUT NODEFVAL address[7..0] +// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL q[7..0] +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock +// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL data[7..0] +// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL wren +// Retrieval info: CONNECT: @address_a 0 0 8 0 address 0 0 8 0 +// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +// Retrieval info: CONNECT: @data_a 0 0 8 0 data 0 0 8 0 +// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0 +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all diff --git a/galaxian/src/altera/alt_ram_256_8_8.v b/galaxian/src/altera/alt_ram_256_8_8.v new file mode 100644 index 0000000..3e0da8a --- /dev/null +++ b/galaxian/src/altera/alt_ram_256_8_8.v @@ -0,0 +1,245 @@ +// megafunction wizard: %RAM: 2-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: alt_ram_256_8_8.v +// Megafunction Name(s): +// altsyncram +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 4.0 Build 214 3/25/2004 SP 1 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2004 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module alt_ram_256_8_8 ( + data_a, + wren_a, + address_a, + data_b, + address_b, + wren_b, + clock_a, + enable_a, + clock_b, + enable_b, + q_a, + q_b); + + input [7:0] data_a; + input wren_a; + input [7:0] address_a; + input [7:0] data_b; + input [7:0] address_b; + input wren_b; + input clock_a; + input enable_a; + input clock_b; + input enable_b; + output [7:0] q_a; + output [7:0] q_b; + + wire [7:0] sub_wire0; + wire [7:0] sub_wire1; + wire [7:0] q_a = sub_wire0[7:0]; + wire [7:0] q_b = sub_wire1[7:0]; + + altsyncram altsyncram_component ( + .clocken0 (enable_a), + .clocken1 (enable_b), + .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) + // synopsys translate_off +, + .rden_b (), + .aclr0 (), + .aclr1 (), + .byteena_a (), + .byteena_b (), + .addressstall_a (), + .addressstall_b () + // synopsys translate_on + +); + defparam + altsyncram_component.intended_device_family = "Cyclone", + altsyncram_component.operation_mode = "BIDIR_DUAL_PORT", + altsyncram_component.width_a = 8, + altsyncram_component.widthad_a = 8, + altsyncram_component.numwords_a = 256, + altsyncram_component.width_b = 8, + altsyncram_component.widthad_b = 8, + altsyncram_component.numwords_b = 256, + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.width_byteena_a = 1, + altsyncram_component.width_byteena_b = 1, + altsyncram_component.outdata_reg_a = "UNREGISTERED", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_reg_b = "UNREGISTERED", + altsyncram_component.indata_aclr_a = "NONE", + altsyncram_component.wrcontrol_aclr_a = "NONE", + altsyncram_component.address_aclr_a = "NONE", + altsyncram_component.indata_reg_b = "CLOCK1", + altsyncram_component.address_reg_b = "CLOCK1", + altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1", + altsyncram_component.indata_aclr_b = "NONE", + altsyncram_component.wrcontrol_aclr_b = "NONE", + altsyncram_component.address_aclr_b = "NONE", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.ram_block_type = "AUTO"; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0" +// Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "3" +// Retrieval info: PRIVATE: UseDPRAM NUMERIC "1" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: PRIVATE: VarWidth NUMERIC "0" +// Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "8" +// Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "8" +// Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "8" +// Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "8" +// Retrieval info: PRIVATE: MEMSIZE NUMERIC "2048" +// Retrieval info: PRIVATE: Clock NUMERIC "5" +// Retrieval info: PRIVATE: rden 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: Clock_A NUMERIC "0" +// Retrieval info: PRIVATE: Clock_B NUMERIC "0" +// Retrieval info: PRIVATE: REGdata NUMERIC "1" +// Retrieval info: PRIVATE: REGwraddress NUMERIC "1" +// Retrieval info: PRIVATE: REGwren NUMERIC "1" +// Retrieval info: PRIVATE: REGrdaddress NUMERIC "0" +// Retrieval info: PRIVATE: REGrren NUMERIC "0" +// Retrieval info: PRIVATE: REGq NUMERIC "0" +// Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "1" +// Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "1" +// Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "0" +// Retrieval info: PRIVATE: CLRdata NUMERIC "0" +// Retrieval info: PRIVATE: CLRwren NUMERIC "0" +// Retrieval info: PRIVATE: CLRwraddress NUMERIC "0" +// Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0" +// Retrieval info: PRIVATE: CLRrren NUMERIC "0" +// Retrieval info: PRIVATE: CLRq NUMERIC "0" +// Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0" +// Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: enable NUMERIC "1" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0" +// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +// Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2" +// Retrieval info: PRIVATE: BlankMemory NUMERIC "1" +// Retrieval info: PRIVATE: MIFfilename STRING "" +// Retrieval info: PRIVATE: UseLCs NUMERIC "0" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_0 STRING "wren_a;wren_b;rden_b;data_a;data_b" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_1 STRING "address_a;address_b;clock0;clock1;clocken0" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_2 STRING "clocken1;aclr0;aclr1;byteena_a;byteena_b" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_3 STRING "addressstall_a;addressstall_b;q_a;q_b" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "BIDIR_DUAL_PORT" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "8" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "256" +// Retrieval info: CONSTANT: WIDTH_B NUMERIC "8" +// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "8" +// Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "256" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_B NUMERIC "1" +// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" +// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED" +// Retrieval info: CONSTANT: INDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: WRCONTROL_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: INDATA_REG_B STRING "CLOCK1" +// Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK1" +// Retrieval info: CONSTANT: WRCONTROL_WRADDRESS_REG_B STRING "CLOCK1" +// Retrieval info: CONSTANT: INDATA_ACLR_B STRING "NONE" +// Retrieval info: CONSTANT: WRCONTROL_ACLR_B STRING "NONE" +// Retrieval info: CONSTANT: ADDRESS_ACLR_B STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE" +// Retrieval info: CONSTANT: RAM_BLOCK_TYPE STRING "AUTO" +// Retrieval info: USED_PORT: data_a 0 0 8 0 INPUT NODEFVAL data_a[7..0] +// Retrieval info: USED_PORT: wren_a 0 0 0 0 INPUT VCC wren_a +// 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: address_a 0 0 8 0 INPUT NODEFVAL address_a[7..0] +// Retrieval info: USED_PORT: data_b 0 0 8 0 INPUT NODEFVAL data_b[7..0] +// Retrieval info: USED_PORT: address_b 0 0 8 0 INPUT NODEFVAL address_b[7..0] +// Retrieval info: USED_PORT: wren_b 0 0 0 0 INPUT VCC wren_b +// Retrieval info: USED_PORT: clock_a 0 0 0 0 INPUT NODEFVAL clock_a +// Retrieval info: USED_PORT: enable_a 0 0 0 0 INPUT VCC enable_a +// Retrieval info: USED_PORT: clock_b 0 0 0 0 INPUT NODEFVAL clock_b +// Retrieval info: USED_PORT: enable_b 0 0 0 0 INPUT VCC enable_b +// Retrieval info: CONNECT: @data_a 0 0 8 0 data_a 0 0 8 0 +// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren_a 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: CONNECT: @address_a 0 0 8 0 address_a 0 0 8 0 +// Retrieval info: CONNECT: @data_b 0 0 8 0 data_b 0 0 8 0 +// Retrieval info: CONNECT: @address_b 0 0 8 0 address_b 0 0 8 0 +// Retrieval info: CONNECT: @wren_b 0 0 0 0 wren_b 0 0 0 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 clock_a 0 0 0 0 +// Retrieval info: CONNECT: @clocken0 0 0 0 0 enable_a 0 0 0 0 +// Retrieval info: CONNECT: @clock1 0 0 0 0 clock_b 0 0 0 0 +// Retrieval info: CONNECT: @clocken1 0 0 0 0 enable_b 0 0 0 0 +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: GEN_FILE: TYPE_NORMAL alt_ram_256_8_8.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL alt_ram_256_8_8.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL alt_ram_256_8_8.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL alt_ram_256_8_8.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL alt_ram_256_8_8_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL alt_ram_256_8_8_bb.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL alt_ram_256_8_8_waveforms.html FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL alt_ram_256_8_8_wave*.jpg FALSE diff --git a/galaxian/src/altera/alt_rom_6l.v b/galaxian/src/altera/alt_rom_6l.v new file mode 100644 index 0000000..e466f69 --- /dev/null +++ b/galaxian/src/altera/alt_rom_6l.v @@ -0,0 +1,103 @@ +// megafunction wizard: %ROM: 1-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: alt_rom_6l.v +// Megafunction Name(s): +// altsyncram +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// ************************************************************ + + +//Copyright (C) 1991-2003 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + + +module alt_rom_6l ( + address, + clock, + q); + + input [4:0] address; + input clock; + output [7:0] q; + + wire [7:0] sub_wire0; + wire [7:0] q = sub_wire0[7:0]; + + altsyncram altsyncram_component ( + .clock0 (clock), + .address_a (address), + .q_a (sub_wire0)); + defparam + altsyncram_component.intended_device_family = "Cyclone", + altsyncram_component.width_a = 8, + altsyncram_component.widthad_a = 5, + altsyncram_component.numwords_a = 32, + altsyncram_component.operation_mode = "ROM", + altsyncram_component.outdata_reg_a = "UNREGISTERED", + altsyncram_component.address_aclr_a = "NONE", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.width_byteena_a = 1, + altsyncram_component.init_file = "6l.hex", + altsyncram_component.lpm_type = "altsyncram"; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: WidthData NUMERIC "8" +// Retrieval info: PRIVATE: WidthAddr NUMERIC "5" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: PRIVATE: SingleClock NUMERIC "1" +// Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" +// Retrieval info: PRIVATE: RegAddr NUMERIC "1" +// Retrieval info: PRIVATE: RegOutput NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +// Retrieval info: PRIVATE: AclrByte NUMERIC "0" +// Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +// Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +// Retrieval info: PRIVATE: Clken NUMERIC "0" +// Retrieval info: PRIVATE: MIFfilename STRING "6l.hex" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "5" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "32" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" +// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" +// Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: CONSTANT: INIT_FILE STRING "6l.hex" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: USED_PORT: address 0 0 5 0 INPUT NODEFVAL address[4..0] +// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL q[7..0] +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock +// Retrieval info: CONNECT: @address_a 0 0 5 0 address 0 0 5 0 +// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all diff --git a/galaxian/src/dac.v b/galaxian/src/dac.v new file mode 100644 index 0000000..c7e4648 --- /dev/null +++ b/galaxian/src/dac.v @@ -0,0 +1,50 @@ +// +// XAPP154 based SigmaDeltaPCM Module +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +// See the xapp154.pdf on Xilinx application note. +// +// + +`timescale 100 ps / 10 ps +`define MSBI 7 // Most significant Bit of DAC input +//This is a Delta-Sigma Digital to Analog Converter + +module dac(DACout, DACin, Clk, Reset); +output DACout; // This is the average output that feeds low pass filter +reg DACout; // for optimum performance, ensure that this ff is in IOB +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 @(SigmaLatch) DeltaB = {SigmaLatch[`MSBI+2], SigmaLatch[`MSBI+2]} << (`MSBI+1); + +always @(DACin or DeltaB) DeltaAdder = DACin + DeltaB; + +always @(DeltaAdder or SigmaLatch) SigmaAdder = DeltaAdder + SigmaLatch; + +always @(posedge Clk or posedge Reset) +begin + if(Reset) + begin + SigmaLatch <= #1 1'b1 << (`MSBI+1); + DACout <= #1 1'b0; + end + else + begin +// SigmaLatch <== #1 SigmaAdder; + SigmaLatch <= #1 SigmaAdder; + DACout <= #1 SigmaLatch[`MSBI+2]; + end +end +endmodule + diff --git a/galaxian/src/dcm.v b/galaxian/src/dcm.v new file mode 100644 index 0000000..13f9f5f --- /dev/null +++ b/galaxian/src/dcm.v @@ -0,0 +1,70 @@ +// Module dcm +// Generated by Xilinx Architecture Wizard +// Written for synthesis tool: XST +// Period Jitter (unit interval) for block DCM_SP_INST = 0.02 UI +// Period Jitter (Peak-to-Peak) for block DCM_SP_INST = 0.89 ns +`timescale 1ns / 1ps + +module dcm(CLKIN_IN, + RST_IN, + CLKFX_OUT, + CLKIN_IBUFG_OUT, + CLK0_OUT, + LOCKED_OUT); + + input CLKIN_IN; + input RST_IN; + output CLKFX_OUT; + output CLKIN_IBUFG_OUT; + output CLK0_OUT; + output LOCKED_OUT; + + wire CLKFB_IN; + wire CLKFX_BUF; + wire CLKIN_IBUFG; + wire CLK0_BUF; + wire GND_BIT; + + assign GND_BIT = 0; + assign CLKIN_IBUFG_OUT = CLKIN_IBUFG; + assign CLK0_OUT = CLKFB_IN; + BUFG CLKFX_BUFG_INST (.I(CLKFX_BUF), + .O(CLKFX_OUT)); + IBUFG CLKIN_IBUFG_INST (.I(CLKIN_IN), + .O(CLKIN_IBUFG)); + BUFG CLK0_BUFG_INST (.I(CLK0_BUF), + .O(CLKFB_IN)); + DCM_SP DCM_SP_INST (.CLKFB(CLKFB_IN), + .CLKIN(CLKIN_IBUFG), + .DSSEN(GND_BIT), + .PSCLK(GND_BIT), + .PSEN(GND_BIT), + .PSINCDEC(GND_BIT), + .RST(RST_IN), + .CLKDV(), + .CLKFX(CLKFX_BUF), + .CLKFX180(), + .CLK0(CLK0_BUF), + .CLK2X(), + .CLK2X180(), + .CLK90(), + .CLK180(), + .CLK270(), + .LOCKED(LOCKED_OUT), + .PSDONE(), + .STATUS()); + defparam DCM_SP_INST.CLK_FEEDBACK = "1X"; + defparam DCM_SP_INST.CLKDV_DIVIDE = 2.0; + defparam DCM_SP_INST.CLKFX_DIVIDE = 27; + defparam DCM_SP_INST.CLKFX_MULTIPLY = 4; + defparam DCM_SP_INST.CLKIN_DIVIDE_BY_2 = "FALSE"; + defparam DCM_SP_INST.CLKIN_PERIOD = 8.000; + defparam DCM_SP_INST.CLKOUT_PHASE_SHIFT = "NONE"; + defparam DCM_SP_INST.DESKEW_ADJUST = "SYSTEM_SYNCHRONOUS"; + defparam DCM_SP_INST.DFS_FREQUENCY_MODE = "LOW"; + defparam DCM_SP_INST.DLL_FREQUENCY_MODE = "LOW"; + defparam DCM_SP_INST.DUTY_CYCLE_CORRECTION = "TRUE"; + defparam DCM_SP_INST.FACTORY_JF = 16'hC080; + defparam DCM_SP_INST.PHASE_SHIFT = 0; + defparam DCM_SP_INST.STARTUP_WAIT = "FALSE"; +endmodule diff --git a/galaxian/src/fpga_arcade_if.v b/galaxian/src/fpga_arcade_if.v new file mode 100644 index 0000000..11ef8ab --- /dev/null +++ b/galaxian/src/fpga_arcade_if.v @@ -0,0 +1,121 @@ +//------------------------------------------------------------------- +// +// PLAYSTATION CONTROLLER-FPGA ARCADE GAME INTERFACE TOP +// +// Version : 2.01 +// +// Copyright(c) 2003 - 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +// 2004-4-29 fpga mooncrst use k .degawa +//------------------------------------------------------------------- + +`timescale 100ps/10ps +`include "src/mc_conf.v" + +module fpga_arcade_if( + +CLK_18M432, +I_RSTn, +psCLK, +psSEL, +psTXD, +psRXD, +ps_PSW, +I_VIB_SW + +); + +input CLK_18M432,I_RSTn; +input I_VIB_SW; +input psRXD; +output psCLK,psSEL,psTXD; +output [8:0]ps_PSW; + +reg [5:0]clk_reg; +wire CLK_288K; + +assign CLK_288K = clk_reg[5]; +always@(posedge CLK_18M432) clk_reg <= clk_reg+1; + +wire [7:0]RX_DATA_1,RX_DATA_2; +wire [7:0]RX_DATA_3,RX_DATA_4; +//wire [7:0]RX_DATA_5,RX_DATA_6; + +reg [1:0]XY_pos; + +assign ps_PSW[0] = 1'b1; // UP +assign ps_PSW[1] = 1'b1; // DOWN +assign ps_PSW[2] = XY_pos[0]; // LEFT +assign ps_PSW[3] = XY_pos[1]; // RIGHT +assign ps_PSW[4] = RX_DATA_2[5]; // CREDIT1 (MARU-BOTAN) +assign ps_PSW[5] = RX_DATA_2[4]; // CREDIT2 (SANKAKU-BOTAN) +assign ps_PSW[6] = RX_DATA_1[3]; // START 1P (START-BOTAN) +assign ps_PSW[7] = RX_DATA_1[0]; // START 2P (SELCT-BOTAN) +assign ps_PSW[8] = RX_DATA_1[6]; + +always@(posedge CLK_288K) +begin + if(RX_DATA_3<=8'h5F&&RX_DATA_3>=8'h00) + XY_pos <= 2'b10; + else if(RX_DATA_3<=8'hFF&&RX_DATA_3>=8'hA0) + XY_pos <= 2'b01; + else + XY_pos <= 2'b11; +end + +// Dualshock +`ifdef Dualshock +psPAD_top pspad( + +.I_CLK250K(CLK_288K), +.I_RSTn(I_RSTn), +.I_VIB_SW({I_VIB_SW,1'b0}), +.O_psCLK(psCLK), +.O_psSEL(psSEL), +.O_psTXD(psTXD), +.I_psRXD(psRXD), +.O_RXD_1(RX_DATA_1), +.O_RXD_2(RX_DATA_2), +.O_RXD_3(RX_DATA_3), +.O_RXD_4(RX_DATA_4), +.O_RXD_5(), +.O_RXD_6(), +.I_CONF_SW(), +.I_MODE_SW(), +.I_MODE_EN(), +.I_VIB_DAT(8'hFF) +); +`else +psPAD_top pspad( + +.I_CLK250K(CLK_288K), +.I_RSTn(I_RSTn), +.I_VIB_SW(I_VIB_SW), +.O_psCLK(psCLK), +.O_psSEL(psSEL), +.O_psTXD(psTXD), +.I_psRXD(psRXD), +.O_RXD_1(RX_DATA_1), +.O_RXD_2(RX_DATA_2), +.O_RXD_3(RX_DATA_3), +.O_RXD_4(RX_DATA_4), +.O_RXD_5(), +.O_RXD_6(), +.I_CONF_SW(), +.I_MODE_SW(), +.I_MODE_EN(), +.I_VIB_DAT() +); +`endif + +endmodule + + + + diff --git a/galaxian/src/fpga_arcade_if_x.v b/galaxian/src/fpga_arcade_if_x.v new file mode 100644 index 0000000..cbc9401 --- /dev/null +++ b/galaxian/src/fpga_arcade_if_x.v @@ -0,0 +1,37 @@ +//------------------------------------------------------------------- +// +// PLAYSTATION CONTROLLER-FPGA ARCADE GAME INTERFACE TOP +// +// Version : 2.02 +// +// Copyright(c) 2003 - 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +// Xilinx Net I/F +//------------------------------------------------------------------- + +module fpga_arcade_if( + +CLK_18M432, +I_RSTn, +psCLK, +psSEL, +psTXD, +psRXD, +ps_PSW, +I_VIB_SW + +); + +input CLK_18M432,I_RSTn; +input I_VIB_SW; +input psRXD; +output psCLK,psSEL,psTXD; +output [8:0]ps_PSW; + +endmodule \ No newline at end of file diff --git a/galaxian/src/mc_adec.v b/galaxian/src/mc_adec.v new file mode 100644 index 0000000..75f3b28 --- /dev/null +++ b/galaxian/src/mc_adec.v @@ -0,0 +1,274 @@ +//--------------------------------------------------------------------- +// FPGA GALAXIAN ADDRESS DECDER +// +// Version : 2.01 +// +// Copyright(c) 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +// 2004- 4-30 galaxian modify by K.DEGAWA +// 2004- 5- 6 first release. +// 2004- 8-23 Improvement with T80-IP. +//--------------------------------------------------------------------- +// +//GALAXIAN Address Map +// +// Address Item(R..read-mode W..wight-mode) Parts +//0000 - 1FFF CPU-ROM..R ( 7H or 7K ) +//2000 - 3FFF CPU-ROM..R ( 7L ) +//4000 - 47FF CPU-RAM..RW ( 7N & 7P ) +//5000 - 57FF VID-RAM..RW +//5800 - 5FFF OBJ-RAM..RW +//6000 - SW0..R LAMP......W +//6800 - SW1..R SOUND.....W +//7000 - DIP..R +//7001 NMI_ON....W +//7004 STARS_ON..W +//7006 H_FLIP....W +//7007 V-FLIP....W +//7800 WDR..R PITCH.....W +// +//W MODE +//6000 - 6002 +//6003 COIN CNTR +//6004 - 6007 SOUND CONTROL(OSC) +// +//6800 SOUND CONTROL(FS1) +//6801 SOUND CONTROL(FS2) +//6802 SOUND CONTROL(FS3) +//6803 SOUND CONTROL(HIT) +//6805 SOUND CONTROL(SHOT) +//6806 SOUND CONTROL(VOL1) +//6807 SOUND CONTROL(VOL2) +// + +module mc_adec( + +I_CLK_12M, +I_CLK_6M, +I_CPU_CLK, +I_RSTn, + +I_CPU_A, +I_CPU_D, +I_MREQn, +I_RFSHn, +I_RDn, +I_WRn, +I_H_BL, +I_V_BLn, + +O_WAITn, +O_NMIn, +O_CPU_ROM_CSn, +O_CPU_RAM_RDn, +O_CPU_RAM_WRn, +O_CPU_RAM_CSn, +O_OBJ_RAM_RDn, +O_OBJ_RAM_WRn, +O_OBJ_RAM_RQn, +O_VID_RAM_RDn, +O_VID_RAM_WRn, +O_SW0_OEn, +O_SW1_OEn, +O_DIP_OEn, +O_WDR_OEn, +O_LAMP_WEn, +O_SOUND_WEn, +O_PITCHn, +O_H_FLIP, +O_V_FLIP, +O_BD_G, +O_STARS_ON + +); + + +input I_CLK_12M; +input I_CLK_6M; +input I_CPU_CLK; +input I_RSTn; + +input [15:0]I_CPU_A; +input I_CPU_D; +input I_MREQn; +input I_RFSHn; +input I_RDn; +input I_WRn; +input I_H_BL; +input I_V_BLn; + +output O_WAITn; +output O_NMIn; +output O_CPU_ROM_CSn; +output O_CPU_RAM_RDn; +output O_CPU_RAM_WRn; +output O_CPU_RAM_CSn; +output O_OBJ_RAM_RDn; +output O_OBJ_RAM_WRn; +output O_OBJ_RAM_RQn; +output O_VID_RAM_RDn; +output O_VID_RAM_WRn; +output O_SW0_OEn; +output O_SW1_OEn; +output O_DIP_OEn; +output O_WDR_OEn; +output O_LAMP_WEn; +output O_SOUND_WEn; +output O_PITCHn; +output O_H_FLIP; +output O_V_FLIP; +output O_BD_G; +output O_STARS_ON; + + +wire [3:0]W_8E1_Q; +wire [3:0]W_8E2_Q; +wire [7:0]W_8P_Q,W_8N_Q,W_8M_Q; +reg [7:0]W_9N_Q; +wire W_NMI_ONn = W_9N_Q[1]; // galaxian +//------ CPU WAITn ---------------------------------------------- + +reg W_6S1_Q,W_6S1_Qn; +reg W_6S2_Qn; + +//assign O_WAITn = W_6S1_Qn; +assign O_WAITn = 1'b1 ; // No Wait + +always@(posedge I_CPU_CLK or negedge I_V_BLn) +begin + if(I_V_BLn == 1'b0)begin + W_6S1_Q <= 1'b0; + W_6S1_Qn <= 1'b1; + end + else begin + W_6S1_Q <= ~(I_H_BL | W_8P_Q[2]); + W_6S1_Qn <= I_H_BL | W_8P_Q[2]; + end +end + +always@(negedge I_CPU_CLK) +begin + W_6S2_Qn <= ~W_6S1_Q; +end +//------ CPU NMIn ----------------------------------------------- +wire W_V_BL = ~I_V_BLn; +reg O_NMIn; +always@(posedge W_V_BL or negedge W_NMI_ONn) +begin + if(~W_NMI_ONn) + O_NMIn <= 1'b1; + else + O_NMIn <= 1'b0; +end +//----------------------------------------------------------------- +logic_74xx139 U_8E1( + +.I_G(I_MREQn), +.I_Sel(I_CPU_A[15:14]), +.O_Q(W_8E1_Q) + +); + +//-------- CPU_ROM CS 0000 - 3FFF --------------------------- +logic_74xx139 U_8E2( + +.I_G(I_RDn), +.I_Sel({W_8E1_Q[0],I_CPU_A[13]}), +.O_Q(W_8E2_Q) + +); + +assign O_CPU_ROM_CSn = W_8E2_Q[0]&W_8E2_Q[1] ; // 0000 - 3FFF +//----------------------------------------------------------------- +// ADDRESS +// W_8E1_Q[0] = 0000 - 3FFF ---- CPU_ROM_USE +// W_8E1_Q[1] = 4000 - 7FFF ---- GALAXIAN USE *1 +// W_8E1_Q[2] = 8000 - BFFF ---- MOONCREST USE +// W_8E1_Q[3] = C000 - FFFF + +logic_74xx138 U_8P( + +.I_G1(I_RFSHn), +.I_G2a(W_8E1_Q[1]), // <= *1 +.I_G2b(W_8E1_Q[1]), // <= *1 +.I_Sel(I_CPU_A[13:11]), +.O_Q(W_8P_Q) + +); + +logic_74xx138 U_8N( + +.I_G1(1'b1), +.I_G2a(I_RDn), +.I_G2b(W_8E1_Q[1]), // <= *1 +.I_Sel(I_CPU_A[13:11]), +.O_Q(W_8N_Q) + +); + +logic_74xx138 U_8M( + +//.I_G1(W_6S2_Qn), +.I_G1(1'b1), // No Wait +.I_G2a(I_WRn), +.I_G2b(W_8E1_Q[1]), // <= *1 +.I_Sel(I_CPU_A[13:11]), +.O_Q(W_8M_Q) + +); + +assign O_BD_G = ~(W_8E1_Q[0]&W_8P_Q[0]); // +assign O_OBJ_RAM_RQn = W_8P_Q[3]; // + +assign O_CPU_RAM_CSn = W_8N_Q[0]&W_8M_Q[0]; // +assign O_CPU_RAM_RDn = W_8N_Q[0]; // +assign O_CPU_RAM_WRn = W_8M_Q[0]; // +assign O_VID_RAM_RDn = W_8N_Q[2]; // +assign O_OBJ_RAM_RDn = W_8N_Q[3]; // +assign O_SW0_OEn = W_8N_Q[4]; // +assign O_SW1_OEn = W_8N_Q[5]; // +assign O_DIP_OEn = W_8N_Q[6]; // +assign O_WDR_OEn = W_8N_Q[7]; // + +assign O_VID_RAM_WRn = W_8M_Q[2]; // +assign O_OBJ_RAM_WRn = W_8M_Q[3]; // +assign O_LAMP_WEn = W_8M_Q[4]; // +assign O_SOUND_WEn = W_8M_Q[5]; // + +assign O_PITCHn = W_8M_Q[7]; // + +//--- Parts 9N --------- + +always@(posedge I_CLK_12M or negedge I_RSTn) +begin + if(I_RSTn == 1'b0)begin + W_9N_Q <= 0; + end + else begin + if(W_8M_Q[6] == 1'b0)begin + case(I_CPU_A[2:0]) + 3'h0 : W_9N_Q[0] <= I_CPU_D; + 3'h1 : W_9N_Q[1] <= I_CPU_D; + 3'h2 : W_9N_Q[2] <= I_CPU_D; + 3'h3 : W_9N_Q[3] <= I_CPU_D; + 3'h4 : W_9N_Q[4] <= I_CPU_D; + 3'h5 : W_9N_Q[5] <= I_CPU_D; + 3'h6 : W_9N_Q[6] <= I_CPU_D; + 3'h7 : W_9N_Q[7] <= I_CPU_D; + endcase + end + end +end + +assign O_STARS_ON = W_9N_Q[4]; // +assign O_H_FLIP = W_9N_Q[6]; // +assign O_V_FLIP = W_9N_Q[7]; // + + +endmodule \ No newline at end of file diff --git a/galaxian/src/mc_bram_if.v b/galaxian/src/mc_bram_if.v new file mode 100644 index 0000000..8476f25 --- /dev/null +++ b/galaxian/src/mc_bram_if.v @@ -0,0 +1,321 @@ +//=============================================================================== +// FPGA MOONCRESTA & GALAXIAN +// FPGA BLOCK RAM I/F (ALTERA-CYCLONE & XILINX SPARTAN2E) +// +// Version : 2.50 +// +// Copyright(c) 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +// mc_col_rom(6L) added by k.Degawa +// +// 2004- 5- 6 first release. +// 2004- 8-23 Improvement with T80-IP. K.Degawa +// 2004- 9-18 added Xilinx Device K.Degawa +//================================================================================ +`include "src/mc_conf.v" + +// mc_top.v use +module mc_cpu_ram ( + +I_CLK, +I_ADDR, +I_D, +I_WE, +I_OE, +O_D + +); + +input I_CLK; +input [9:0]I_ADDR; +input [7:0]I_D; +input I_WE; +input I_OE; +output [7:0]O_D; + +wire [7:0]W_D; +assign O_D = I_OE ? W_D : 8'h00 ; + +`ifdef DEVICE_CYCLONE +alt_ram_1024_8 CPURAM_ALT( + +.clock(I_CLK), +.address(I_ADDR), +.data(I_D), +.wren(I_WE), +.q(W_D) + +); +`endif +`ifdef DEVICE_SPARTAN2E +RAMB4_S4 CPURAM_X1( + +.CLK(I_CLK), +.ADDR(I_ADDR[9:0]), +.DI(I_D[7:4]), +.DO(W_D[7:4]), +.EN(1'b1), +.WE(I_WE), +.RST(1'b0) + +); + +RAMB4_S4 CPURAM_X0( + +.CLK(I_CLK), +.ADDR(I_ADDR[9:0]), +.DI(I_D[3:0]), +.DO(W_D[3:0]), +.EN(1'b1), +.WE(I_WE), +.RST(1'b0) + +); +`endif + +endmodule + +// mc_video.v use +module mc_obj_ram( + +I_CLKA, +I_ADDRA, +I_WEA, +I_CEA, +I_DA, +O_DA, + +I_CLKB, +I_ADDRB, +I_WEB, +I_CEB, +I_DB, +O_DB + +); + +input I_CLKA,I_CLKB; +input [7:0]I_ADDRA,I_ADDRB; +input I_WEA,I_WEB; +input I_CEA,I_CEB; +input [7:0]I_DA,I_DB; +output [7:0]O_DA,O_DB; + +`ifdef DEVICE_CYCLONE +alt_ram_256_8_8 OBJRAM( + +.clock_a(I_CLKA), +.address_a(I_ADDRA), +.wren_a(I_WEA), +.enable_a(I_CEA), +.data_a(I_DA), +.q_a(O_DA), + +.clock_b(I_CLKB), +.address_b(I_ADDRB), +.wren_b(I_WEB), +.enable_b(I_CEB), +.data_b(I_DB), +.q_b(O_DB) + +); +`endif +`ifdef DEVICE_SPARTAN2E +RAMB4_S8_S8 OBJRAM( + +.CLKA(I_CLKA), +.ADDRA({1'b0,I_ADDRA[7:0]}), +.DIA(I_DA), +.DOA(O_DA), +.ENA(I_CEA), +.WEA(I_WEA), +.RSTA(1'b0), + +.CLKB(I_CLKB), +.ADDRB({1'b0,I_ADDRB[7:0]}), +.DIB(I_DB), +.DOB(O_DB), +.ENB(I_CEB), +.WEB(I_WEB), +.RSTB(1'b0) +); +`endif + +endmodule + + +// mc_video.v use +module mc_vid_ram ( + +I_CLKA, +I_ADDRA, +I_DA, +I_WEA, +I_CEA, +O_DA, + +I_CLKB, +I_ADDRB, +I_DB, +I_WEB, +I_CEB, +O_DB + +); + +input I_CLKA,I_CLKB; +input [9:0]I_ADDRA,I_ADDRB; +input [7:0]I_DA,I_DB; +input I_WEA,I_WEB; +input I_CEA,I_CEB; +output [7:0]O_DA,O_DB; + +`ifdef DEVICE_CYCLONE +alt_ram_1024_8_8 VIDRAM( + +.clock_a(I_CLKA), +.address_a(I_ADDRA), +.data_a(I_DA), +.wren_a(I_WEA), +.enable_a(I_CEA), +.q_a(O_DA), + +.clock_b(I_CLKB), +.address_b(I_ADDRB), +.data_b(I_DB), +.wren_b(I_WEB), +.enable_b(I_CEB), +.q_b(O_DB) + +); +`endif +`ifdef DEVICE_SPARTAN2E +RAMB4_S4_S4 VIDRAM_X1( + +.CLKA(I_CLKA), +.ADDRA(I_ADDRA[9:0]), +.DIA(I_DA[7:4]), +.DOA(O_DA[7:4]), +.ENA(I_CEA), +.WEA(I_WEA), +.RSTA(1'b0), + +.CLKB(I_CLKB), +.ADDRB(I_ADDRB[9:0]), +.DIB(I_DB[7:4]), +.DOB(O_DB[7:4]), +.ENB(I_CEB), +.WEB(I_WEB), +.RSTB(1'b0) + +); + +RAMB4_S4_S4 VIDRAM_X0( + +.CLKA(I_CLKA), +.ADDRA(I_ADDRA[9:0]), +.DIA(I_DA[3:0]), +.DOA(O_DA[3:0]), +.ENA(I_CEA), +.WEA(I_WEA), +.RSTA(1'b0), + +.CLKB(I_CLKB), +.ADDRB(I_ADDRB[9:0]), +.DIB(I_DB[3:0]), +.DOB(O_DB[3:0]), +.ENB(I_CEB), +.WEB(I_WEB), +.RSTB(1'b0) + +); +`endif + +endmodule + +// mc_video.v use +module mc_lram( + +I_CLK, +I_ADDR, +I_WE, +I_D, +O_Dn + +); + +input I_CLK; +input [7:0]I_ADDR; +input [4:0]I_D; +input I_WE; +output [4:0]O_Dn; +wire [4:0]W_D; + +`ifdef DEVICE_CYCLONE +assign O_Dn = ~W_D; + +alt_ram_256_5 LRAM( + +.inclock(I_CLK), +.outclock(~I_CLK), +.address(I_ADDR), +.data(I_D), +.wren(I_WE), +.q(W_D) + +); +`endif +`ifdef DEVICE_SPARTAN2E +reg [4:0]O_Dn; +always@(negedge I_CLK) O_Dn <= ~W_D[4:0] ; + +RAMB4_S8 LRAM( + +.CLK(I_CLK), +.ADDR({1'b0,I_ADDR[7:0]}), +.DI({3'b000,I_D}), +.DO(W_D), +.EN(1'b1), +.WE(I_WE), +.RST(1'b0) + +); +`endif + +endmodule + +// mc_col_pal.v use +`ifdef DEVICE_CYCLONE +module mc_col_rom( + +I_CLK, +I_ADDR, +I_OEn, +O_DO + +); + +input I_CLK; +input [4:0]I_ADDR; +input I_OEn; +output [7:0]O_DO; +wire [7:0]W_DO; + +assign O_DO = I_OEn ? 8'h00 : W_DO ; +alt_rom_6l U_6L( + +.clock(I_CLK), +.address(I_ADDR), +.q(W_DO) + +); + + +endmodule +`endif diff --git a/galaxian/src/mc_clock.v b/galaxian/src/mc_clock.v new file mode 100644 index 0000000..43cadb4 --- /dev/null +++ b/galaxian/src/mc_clock.v @@ -0,0 +1,63 @@ +//--------------------------------------------------------------------- +// FPGA MOONCRESTA CLOCK GEN +// +// Version : 1.00 +// +// Copyright(c) 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +//--------------------------------------------------------------------- + + + +module mc_clock( + +I_CLK_18M, +O_CLK_12M, +O_CLK_06M, +O_CLK_06Mn + +); + +input I_CLK_18M; +output O_CLK_12M; +output O_CLK_06M; +output O_CLK_06Mn; + +// 2/3 clock divider(duty 33%) +reg [1:0] clk_ff1,clk_ff2; +//I_CLK 1010101010101010101 +//c_ff10 0011110011110011110 +//c_ff11 0011000011000011000 +//c_ff20 0000110000110000110 +//c_ff21 0110000110000110000 +//O_12M 0000110110110110110 +always @(posedge I_CLK_18M) +begin + clk_ff1[0] <= ~clk_ff1[0] | clk_ff1[1]; + clk_ff1[1] <= ~clk_ff1[0] & ~clk_ff1[1]; + clk_ff2[0] <= clk_ff1[0] & clk_ff1[1]; +end +always @(negedge I_CLK_18M) + clk_ff2[1] <= ~clk_ff1[0] & ~clk_ff1[1]; + +// 2/3 clock (duty 66%) +assign O_CLK_12M = clk_ff2[0]| clk_ff2[1]; + +// 1/3 clock divider (duty 50%) +reg CLK_6M , CLK_6Mn; +always @(posedge O_CLK_12M) +begin + CLK_6Mn <= CLK_6M; + CLK_6M <= ~CLK_6M; +end +assign O_CLK_06M = CLK_6M; +assign O_CLK_06Mn = CLK_6Mn; + + +endmodule \ No newline at end of file diff --git a/galaxian/src/mc_col_pal.v b/galaxian/src/mc_col_pal.v new file mode 100644 index 0000000..136f5e7 --- /dev/null +++ b/galaxian/src/mc_col_pal.v @@ -0,0 +1,108 @@ +//=============================================================================== +// FPGA MOONCRESTA COLOR-PALETTE +// +// Version : 2.00 +// +// Copyright(c) 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +// 2004- 9-18 added Xilinx Device. K.Degawa +//================================================================================ +`include "src/mc_conf.v" + +module mc_col_pal( + +I_CLK_12M, +I_CLK_6M, +I_VID, +I_COL, +I_C_BLnX, + +O_C_BLX, +O_STARS_OFFn, +O_R, +O_G, +O_B + +); + +input I_CLK_12M; +input I_CLK_6M; +input [1:0]I_VID; +input [2:0]I_COL; +input I_C_BLnX; + +output O_C_BLX; +output O_STARS_OFFn; +output [2:0]O_R; +output [2:0]O_G; +output [1:0]O_B; + +//--- Parts 6M -------------------------------------------------------- +wire [6:0]W_6M_DI = {I_COL[2:0],I_VID[1:0],~(I_VID[0]|I_VID[1]),I_C_BLnX}; +reg [6:0]W_6M_DO; + +wire W_6M_CLR = W_6M_DI[0]|W_6M_DO[0]; +assign O_C_BLX = ~(W_6M_DI[0]|W_6M_DO[0]); +assign O_STARS_OFFn = W_6M_DO[1]; + +always@(posedge I_CLK_6M or negedge W_6M_CLR) +begin + if(W_6M_CLR==1'b0) + W_6M_DO <= 7'h00; + else + W_6M_DO <= W_6M_DI; +end +//--- COL ROM -------------------------------------------------------- +wire [4:0]W_COL_ROM_A = W_6M_DO[6:2]; +wire [7:0]W_COL_ROM_DO; +wire W_COL_ROM_OEn = W_6M_DO[1]; + +`ifdef DEVICE_CYCLONE +mc_col_rom COL_ROM( + +.I_CLK(I_CLK_12M), +.I_ADDR(W_COL_ROM_A), +.O_DO(W_COL_ROM_DO), +.I_OEn(W_COL_ROM_OEn) + +); +`endif +`ifdef DEVICE_SPARTAN2E +GALAXIAN_6L COL_ROM( +.CLK(I_CLK_12M), +.ADDR(W_COL_ROM_A), +.DATA(W_COL_ROM_DO), +.ENA(1'b1) +); +//RAMB4_S8 col_rom00( +// +//.CLK(I_CLK_12M), +//.ADDR({4'b0000,W_COL_ROM_A[4:0]}), +//.DI(8'h00), +//.DO(W_COL_ROM_DO), +//.EN(1'b1), +//.WE(1'b0), +//.RST(1'b0) +// +//); +`endif +//--- VID OUT -------------------------------------------------------- +assign O_R[0] = W_COL_ROM_DO[2]; +assign O_R[1] = W_COL_ROM_DO[1]; +assign O_R[2] = W_COL_ROM_DO[0]; + +assign O_G[0] = W_COL_ROM_DO[5]; +assign O_G[1] = W_COL_ROM_DO[4]; +assign O_G[2] = W_COL_ROM_DO[3]; + +assign O_B[0] = W_COL_ROM_DO[7]; +assign O_B[1] = W_COL_ROM_DO[6]; + + +endmodule diff --git a/galaxian/src/mc_conf.v b/galaxian/src/mc_conf.v new file mode 100644 index 0000000..eb9be47 --- /dev/null +++ b/galaxian/src/mc_conf.v @@ -0,0 +1,35 @@ +//=============================================================================== +// FPGA MOONCRESTA CONFIG FILE +// +// Version : 1.00 +// +// Copyright(c) 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +//================================================================================ +//- Device selct ---------------------------------------------------------------- +// `define DEVICE_CYCLONE // ALTERA DEVICE +`define DEVICE_SPARTAN2E // XILINX DEVICE +//-------------------------------------------------------------------------------- +//- Video out Format ------------------------------------------------------------ + `define VGA_USE + +//-------------------------------------------------------------------------------- +//- include the playstation control(DUALSHOCK) interface module ----------------- +//`define PSPAD_USE + `define Dualshock // default +//-------------------------------------------------------------------------------- + + + + + + + + + diff --git a/galaxian/src/mc_hv_count.v b/galaxian/src/mc_hv_count.v new file mode 100644 index 0000000..aa34b40 --- /dev/null +++ b/galaxian/src/mc_hv_count.v @@ -0,0 +1,127 @@ +//--------------------------------------------------------------------- +// FPGA MOONCRESTA H & V COUNTER +// +// Version : 2.00 +// +// Copyright(c) 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +// 2004- 9-22 +//--------------------------------------------------------------------- +// MoonCrest hv_count +// H_CNT 0 - 255 , 384 - 511 Total 384 count +// V_CNT 0 - 255 , 504 - 511 Total 264 count +//----------------------------------------------------------------------------------------- +// H_CNT[0],H_CNT[1],H_CNT[2],H_CNT[3],H_CNT[4],H_CNT[5],H_CNT[6],H_CNT[7],H_CNT[8], +// 1 H 2 H 4H 8H 16 H 32H 64 H 128 H 256 H +//----------------------------------------------------------------------------------------- +// V_CNT[0], V_CNT[1], V_CNT[2], V_CNT[3], V_CNT[4], V_CNT[5], V_CNT[6], V_CNT[7] +// 1 V 2 V 4 V 8 V 16 V 32 V 64 V 128 V +//----------------------------------------------------------------------------------------- + +module mc_hv_count( + +I_CLK, // 6MHz +I_RSTn, + +O_H_CNT, +O_H_SYNC, +O_H_BL, +O_V_CNT, +O_V_SYNC, +O_V_BLn, +O_V_BL2n, +O_C_BLn + +); + +input I_CLK,I_RSTn; +output [8:0]O_H_CNT; +output O_H_SYNC; +output O_H_BL; +output O_V_BL2n; +output [7:0]O_V_CNT; +output O_V_SYNC; +output O_V_BLn; + +output O_C_BLn; + +//------- H_COUNT ---------------------------------------- +reg [8:0]H_CNT; +always@(posedge I_CLK) +begin + H_CNT <= H_CNT==255 ? 384 : H_CNT +1 ; +end +assign O_H_CNT = H_CNT[8:0]; + +//------- H_SYNC ---------------------------------------- + +reg H_SYNCn; +wire H_SYNC = ~H_SYNCn; +always@(posedge H_CNT[4] or negedge H_CNT[8]) +begin + if(H_CNT[8]==1'b0) H_SYNCn <= 1'b1; + else H_SYNCn <= ~(~H_CNT[6]& H_CNT[5]); +end + +assign O_H_SYNC = H_SYNC; +//------- H_BL ------------------------------------------ + +reg H_BL; + +always@(posedge I_CLK) +begin + case(H_CNT[8:0]) + 387:H_BL<=1'b1; + 503:H_BL<=1'b0; + default:; + endcase +end + +assign O_H_BL = H_BL; +//------- V_COUNT ---------------------------------------- +reg [8:0]V_CNT; +always@(posedge H_SYNC or negedge I_RSTn) +begin + if(I_RSTn==1'b0) + V_CNT <= 0; + else + V_CNT <= V_CNT==255 ? 504 : V_CNT +1 ; +end +assign O_V_CNT = V_CNT[7:0]; +assign O_V_SYNC = V_CNT[8]; + +//------- V_BLn ------------------------------------------ + +reg V_BLn; +always@(posedge H_SYNC) +begin + case(V_CNT[7:0]) + 239: V_BLn <= 0; + 15: V_BLn <= 1; + default:; + endcase +end + +reg V_BL2n; +always@(posedge H_SYNC) +begin + case(V_CNT[7:0]) + 239: V_BL2n <= 0; + 16: V_BL2n <= 1; + default:; + endcase +end + +assign O_V_BLn = V_BLn; +assign O_V_BL2n = V_BL2n; +//------- C_BLn ------------------------------------------ + +assign O_C_BLn = ~(~V_BLn | H_CNT[8]); + +endmodule \ No newline at end of file diff --git a/galaxian/src/mc_inport.v b/galaxian/src/mc_inport.v new file mode 100644 index 0000000..0310d55 --- /dev/null +++ b/galaxian/src/mc_inport.v @@ -0,0 +1,84 @@ +//--------------------------------------------------------------------- +// FPGA MOONCRESTA INPORT +// +// Version : 1.01 +// +// Copyright(c) 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +// 2004-4-30 galaxian modify by K.DEGAWA +//--------------------------------------------------------------------- + +// DIP SW 0 1 2 3 4 5 +//--------------------------------------------------------------- +// COIN CHUTE +// 1 COIN/1 PLAY 1'b0 1'b0 +// 2 COIN/1 PLAY 1'b1 1'b0 +// 1 COIN/2 PLAY 1'b0 1'b1 +// FREE PLAY 1'b1 1'b1 +// BOUNS +// 1'b0 1'b0 +// 1'b1 1'b0 +// 1'b0 1'b1 +// 1'b1 1'b1 +// LIVES +// 2 1'b0 +// 3 1'b1 + +module mc_inport( + +I_COIN1, // ACTIVE HI +I_COIN2, // ACTIVE HI +I_1P_LE, // ACTIVE HI +I_1P_RI, // ACTIVE HI +I_1P_SH, // ACTIVE HI +I_2P_LE, +I_2P_RI, +I_2P_SH, +I_1P_START, // ACTIVE HI +I_2P_START, // ACTIVE HI + +I_SW0_OEn, +I_SW1_OEn, +I_DIP_OEn, + +O_D + +); + +input I_COIN1; +input I_COIN2; +input I_1P_LE; +input I_1P_RI; +input I_1P_SH; +input I_2P_LE; +input I_2P_RI; +input I_2P_SH; +input I_1P_START; +input I_2P_START; + +input I_SW0_OEn; +input I_SW1_OEn; +input I_DIP_OEn; + +output [7:0]O_D; + +wire W_TABLE = 0; // UP TYPE = 0; + +wire [5:0]W_DIP_D = {1'b0,1'b1,1'b0,1'b0,1'b0,1'b0}; +wire [7:0]W_SW0_DI = { 1'b0, 1'b0, W_TABLE, I_1P_SH, I_1P_RI, I_1P_LE, I_COIN2, I_COIN1}; +wire [7:0]W_SW1_DI = {W_DIP_D[1],W_DIP_D[0], 1'b0, I_2P_SH, I_2P_RI, I_2P_LE,I_2P_START,I_1P_START}; +wire [7:0]W_DIP_DI = { 1'b0, 1'b0, 1'b0, 1'b0,W_DIP_D[5],W_DIP_D[4],W_DIP_D[3],W_DIP_D[2]}; + +wire [7:0]W_SW0_DO = I_SW0_OEn ? 8'h00 : W_SW0_DI; +wire [7:0]W_SW1_DO = I_SW1_OEn ? 8'h00 : W_SW1_DI; +wire [7:0]W_DIP_DO = I_DIP_OEn ? 8'h00 : W_DIP_DI; + +assign O_D = W_SW0_DO | W_SW1_DO | W_DIP_DO ; + +endmodule \ No newline at end of file diff --git a/galaxian/src/mc_ld_pls.v b/galaxian/src/mc_ld_pls.v new file mode 100644 index 0000000..51a2934 --- /dev/null +++ b/galaxian/src/mc_ld_pls.v @@ -0,0 +1,111 @@ +//=============================================================================== +// FPGA MOONCRESTA VIDEO-LD_PLS_GEN +// +// Version : 2.00 +// +// Copyright(c) 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +// 2004- 9-22 The problem which missile didn't sometimes come out from was improved. +//================================================================================ + + +module mc_ld_pls( + +I_CLK_6M, +I_H_CNT, +I_3D_DI, + +O_LDn, +O_CNTRLDn, +O_CNTRCLRn, +O_COLLn, +O_VPLn, +O_OBJDATALn, +O_MLDn, +O_SLDn + +); + +input I_CLK_6M; +input [8:0]I_H_CNT; +input I_3D_DI; + +output O_LDn; +output O_CNTRLDn; +output O_CNTRCLRn; +output O_COLLn; +output O_VPLn; +output O_OBJDATALn; +output O_MLDn; +output O_SLDn; + +reg W_5C_Q; +always@(posedge I_CLK_6M) + W_5C_Q <= I_H_CNT[0]; + +// Parts 4D +wire W_4D1_G = ~(I_H_CNT[0]&I_H_CNT[1]&I_H_CNT[2]); +wire [3:0]W_4D1_Q; +wire [3:0]W_4D2_Q; + +logic_74xx139 U_4D1( + +.I_G(W_4D1_G), +.I_Sel({I_H_CNT[8],I_H_CNT[3]}), +.O_Q(W_4D1_Q) + +); + +logic_74xx139 U_4D2( + +.I_G(W_5C_Q), +.I_Sel(I_H_CNT[2:1]), +.O_Q(W_4D2_Q) + +); + +// Parts 4C +wire [3:0]W_4C1_Q; +wire [3:0]W_4C2_Q; + +logic_74xx139 U_4C1( + +.I_G(W_4D2_Q[1]), +.I_Sel({I_H_CNT[8],I_H_CNT[3]}), +.O_Q(W_4C1_Q) + +); + +reg W_4C1_Q3; +always@(negedge I_CLK_6M) // 2004-9-22 added + W_4C1_Q3 <= W_4C1_Q[3]; + +reg W_4C2_B; +always@(posedge W_4C1_Q3) + W_4C2_B <= I_3D_DI; + +logic_74xx139 U_4C2( + +.I_G(W_4D1_Q[3]), +.I_Sel({W_4C2_B,~(I_H_CNT[6]&I_H_CNT[5]&I_H_CNT[4]&I_H_CNT[3])}), +.O_Q(W_4C2_Q) + +); + +assign O_LDn = W_4D1_G; +assign O_CNTRLDn = W_4D1_Q[2]; +assign O_CNTRCLRn = W_4D1_Q[0]; +assign O_COLLn = W_4D2_Q[2]; +assign O_VPLn = W_4D2_Q[0]; +assign O_OBJDATALn = W_4C1_Q[2]; +assign O_MLDn = W_4C2_Q[0]; +assign O_SLDn = W_4C2_Q[1]; + + +endmodule diff --git a/galaxian/src/mc_logic.v b/galaxian/src/mc_logic.v new file mode 100644 index 0000000..6bc57fe --- /dev/null +++ b/galaxian/src/mc_logic.v @@ -0,0 +1,90 @@ +//=============================================================================== +// FPGA MOONCRESTA LOGIC IP MODULE +// +// Version : 1.00 +// +// Copyright(c) 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +//================================================================================ + + +//================================================ +// 74xx138 +// 3-to-8 line decoder +//================================================ +module logic_74xx138( + +I_G1, +I_G2a, +I_G2b, +I_Sel, +O_Q + +); + +input I_G1,I_G2a,I_G2b; +input [2:0]I_Sel; +output [7:0]O_Q; + +reg [7:0]O_Q; +wire [2:0]I_G = {I_G1,I_G2a,I_G2b}; +always@(I_G or I_Sel or O_Q) +begin + if(I_G == 3'b100 )begin + case(I_Sel) + 3'b000: O_Q = 8'b11111110; + 3'b001: O_Q = 8'b11111101; + 3'b010: O_Q = 8'b11111011; + 3'b011: O_Q = 8'b11110111; + 3'b100: O_Q = 8'b11101111; + 3'b101: O_Q = 8'b11011111; + 3'b110: O_Q = 8'b10111111; + 3'b111: O_Q = 8'b01111111; + endcase + end + else begin + O_Q = 8'b11111111; + end +end + +endmodule + +//================================================ +// 74xx139 +// 2-to-4 line decoder +//================================================ +module logic_74xx139( + +I_G, +I_Sel, +O_Q + +); + +input I_G; +input [1:0]I_Sel; +output [3:0]O_Q; + +reg [3:0]O_Q; +always@(I_G or I_Sel or O_Q) +begin + if(I_G == 1'b0 )begin + case(I_Sel) + 2'b00: O_Q = 4'b1110; + 2'b01: O_Q = 4'b1101; + 2'b10: O_Q = 4'b1011; + 2'b11: O_Q = 4'b0111; + endcase + end + else begin + O_Q = 4'b1111; + end +end + +endmodule diff --git a/galaxian/src/mc_missile.v b/galaxian/src/mc_missile.v new file mode 100644 index 0000000..1a4e548 --- /dev/null +++ b/galaxian/src/mc_missile.v @@ -0,0 +1,101 @@ +//=============================================================================== +// FPGA MOONCRESTA VIDEO-MISSILE +// +// Version : 2.00 +// +// Copyright(c) 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +// 2004- 9-22 The problem which missile didn't sometimes come out from was improved. +//================================================================================ + + +module mc_missile( + +I_CLK_18M, +I_CLK_6M, +I_C_BLn_X, +I_MLDn, +I_SLDn, +I_HPOS, + +O_MISSILEn, +O_SHELLn + +); + +input I_CLK_6M,I_CLK_18M; +input I_C_BLn_X; +input I_MLDn; +input I_SLDn; +input [7:0]I_HPOS; + +output O_MISSILEn; +output O_SHELLn; + +reg [7:0]W_45R_Q; + +always@(posedge I_CLK_6M) +begin + if(I_MLDn==1'b0) + W_45R_Q <= I_HPOS; + else begin + if(I_C_BLn_X) + W_45R_Q <= W_45R_Q +1; + else + W_45R_Q <= W_45R_Q ; + end +end + +reg W_5P1_Q; +reg W_5P1_CLK; + +always@(posedge I_CLK_18M) + W_5P1_CLK <= ~((&W_45R_Q[7:2])&W_5P1_Q); + +always@(posedge W_5P1_CLK or negedge I_MLDn) +begin + if(I_MLDn==1'b0) + W_5P1_Q <= 1'b1; + else + W_5P1_Q <= 1'b0; +end + +assign O_MISSILEn = W_5P1_CLK; + +reg [7:0]W_45S_Q; +always@(posedge I_CLK_6M) +begin + if(I_SLDn==1'b0) + W_45S_Q <= I_HPOS; + else begin + if(I_C_BLn_X) + W_45S_Q <= W_45S_Q +1; + else + W_45S_Q <= W_45S_Q ; + end +end + +reg W_5P2_Q; +reg W_5P2_CLK; + +always@(posedge I_CLK_18M) + W_5P2_CLK <= ~((&W_45S_Q[7:2])&W_5P2_Q); + +always@(posedge W_5P2_CLK or negedge I_SLDn) +begin + if(I_SLDn==1'b0) + W_5P2_Q <= 1'b1; + else + W_5P2_Q <= 1'b0; +end + +assign O_SHELLn = W_5P2_CLK; + + +endmodule \ No newline at end of file diff --git a/galaxian/src/mc_sound_a.v b/galaxian/src/mc_sound_a.v new file mode 100644 index 0000000..74336ed --- /dev/null +++ b/galaxian/src/mc_sound_a.v @@ -0,0 +1,82 @@ +//=============================================================================== +// FPGA MOONCRESTA SOUND I/F +// +// Version : 1.00 +// +// Copyright(c) 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +//================================================================================ + + +module mc_sound_a( + +I_CLK_12M, +I_CLK_6M, +I_H_CNT1, +I_BD, +I_PITCHn, +I_VOL1, +I_VOL2, + +O_SDAT, +O_DO + +); + +input I_CLK_12M; +input I_CLK_6M; +input I_H_CNT1; +input [7:0]I_BD; +input I_PITCHn; +input I_VOL1; +input I_VOL2; + +output [3:0]O_DO; +output [7:0]O_SDAT; + +reg W_PITCHn; +reg W_89K_LDn; +reg [7:0]W_89K_Q; +reg [7:0]W_89K_LDATA; +reg [3:0]W_6T_Q; + +always@(posedge I_CLK_12M) +begin + W_PITCHn <= I_PITCHn; + W_89K_LDn <= ~(&W_89K_Q[7:0]); +end + +// Parts 9J +always@(posedge W_PITCHn) W_89K_LDATA <= I_BD; + +always@(posedge I_H_CNT1) +begin + if(~W_89K_LDn) + W_89K_Q <= W_89K_LDATA; + else + W_89K_Q <= W_89K_Q + 1; +end + +always@(negedge W_89K_LDn) W_6T_Q <= W_6T_Q + 1; +assign O_DO = W_6T_Q; + +reg [7:0]W_SDAT0; +reg [7:0]W_SDAT2; +reg [7:0]W_SDAT3; +always@(posedge I_CLK_6M) +begin + W_SDAT0 <= W_6T_Q[0]==1'b0 ? 8'd0 : 8'd42 ; + W_SDAT2 <= W_6T_Q[2]==1'b0 ? 8'd0 : I_VOL1 ? 8'd105 : 8'd57 ; + W_SDAT3 <= W_6T_Q[3]==1'b0 ? 8'd0 : I_VOL2 ? 8'd72 : 8'd0 ; +end + +assign O_SDAT = W_SDAT0 + W_SDAT2 + W_SDAT3 + 8'd20 ; + + +endmodule \ No newline at end of file diff --git a/galaxian/src/mc_sound_b.v b/galaxian/src/mc_sound_b.v new file mode 100644 index 0000000..9cd2f2c --- /dev/null +++ b/galaxian/src/mc_sound_b.v @@ -0,0 +1,220 @@ +//=============================================================================== +// FPGA MOONCRESTA WAVE SOUND +// +// Version : 1.00 +// +// Copyright(c) 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +//================================================================================ + + +module mc_sound_b( + +I_CLK1, +I_CLK2, +I_RSTn, +I_SW, + +O_WAV_A0, +O_WAV_A1, +O_WAV_A2, +I_WAV_D0, +I_WAV_D1, +I_WAV_D2, + +O_SDAT + +); + +input I_CLK1; // 18MHz +input I_CLK2; // 6MHz +input I_RSTn; +input [2:0]I_SW; +output [7:0]O_SDAT; +output [18:0]O_WAV_A0; +output [18:0]O_WAV_A1; +output [18:0]O_WAV_A2; +input [7:0]I_WAV_D0; +input [7:0]I_WAV_D1; +input [7:0]I_WAV_D2; + +parameter sample_time = 1670/2; // sample time 22050Hz +//parameter sample_time = 1670; // sample time 11025Hz +parameter fire_cnt = 14'h3FF0; +parameter hit_cnt = 16'hA830; +parameter effect_cnt = 16'hBFC0; + +reg [9:0]sample; +reg sample_pls; + +always@(posedge I_CLK1 or negedge I_RSTn) +begin + if(I_RSTn == 1'b0)begin + sample <= 0; + sample_pls <= 0; + end + else begin + sample <= (sample == sample_time-1)? 0 : sample+1; + sample_pls <= (sample == sample_time-1)? 1 : 0 ; + end +end + +//----------- FIRE SOUND ------------------------------------------ +reg [13:0]fire_ad; +reg [1:0]s0_trg_ff; +reg s0_trg; +reg s0_play; + +always@(posedge I_CLK1 or negedge I_RSTn) +begin + if(I_RSTn == 1'b0)begin + s0_trg_ff <= 0; + s0_trg <= 0; + end + else begin + s0_trg_ff[0] <= I_SW[0]; + s0_trg_ff[1] <= s0_trg_ff[0]; + s0_trg <= ~s0_trg_ff[1]&s0_trg_ff[0]&~s0_play; + end +end + +always@(posedge I_CLK1 or negedge I_RSTn) +begin + if(I_RSTn == 1'b0) + s0_play <= 0; + else begin + if(fire_ad <= fire_cnt-1) + s0_play <= 1; + else + s0_play <= 0; + end +end + +always@(posedge I_CLK1 or negedge I_RSTn) +begin + if(I_RSTn == 1'b0) + fire_ad <= fire_cnt; + else begin + if(s0_trg) fire_ad <= 0; + else begin + if(sample_pls)begin + if(fire_ad <= fire_cnt) + fire_ad <= fire_ad +1 ; + else + fire_ad <= fire_ad ; + end + end + end +end +//----------- HIT SOUND ------------------------------------------ +reg [15:0]hit_ad; +reg [1:0]s1_trg_ff; +reg s1_trg; +reg s1_play; + +always@(posedge I_CLK1 or negedge I_RSTn) +begin + if(I_RSTn == 1'b0)begin + s1_trg_ff <= 0; + s1_trg <= 0; + end + else begin + s1_trg_ff[0] <= I_SW[1]; + s1_trg_ff[1] <= s1_trg_ff[0]; + s1_trg <= ~s1_trg_ff[1]&s1_trg_ff[0]&~s1_play; + end +end + +always@(posedge I_CLK1 or negedge I_RSTn) +begin + if(I_RSTn == 1'b0) + s1_play <= 0; + else begin + if(hit_ad <= hit_cnt-1) + s1_play <= 1; + else + s1_play <= 0; + end +end + +always@(posedge I_CLK1 or negedge I_RSTn) +begin + if(I_RSTn == 1'b0) + hit_ad <= hit_cnt; + else begin + if(s1_trg) hit_ad <= 0; + else begin + if(sample_pls)begin + if(hit_ad <= hit_cnt) + hit_ad <= hit_ad +1 ; + else + hit_ad <= hit_ad ; + end + end + end +end +//----------- EFFICT SOUND --------------------------------------- +reg [15:0]effect_ad; + +always@(posedge I_CLK1 or negedge I_RSTn) +begin + if(I_RSTn == 1'b0) + effect_ad <= effect_cnt; + else begin + if(I_SW[2])begin + if(sample_pls)begin + if(effect_ad >= effect_cnt) + effect_ad <= 0; + else + effect_ad <= effect_ad + 1; + end + end + else begin + effect_ad <= effect_cnt; + end + end +end + +assign O_WAV_A0 = {3'h1,2'h0,fire_ad}; +assign O_WAV_A1 = {3'h1,4'h4+hit_ad[15:12],hit_ad[11:0]}; +assign O_WAV_A2 = {3'h2,effect_ad}; + +wire [7:0]W_WAV_D0 = I_WAV_D0; +wire [7:0]W_WAV_D1 = I_WAV_D1; +wire [7:0]W_WAV_D2 = I_WAV_D2; + +// sound mix +wire [8:0]mix0 = W_WAV_D0 + W_WAV_D1 ; +reg [8:0]mix_0; +always@(posedge I_CLK1) +begin + if(mix0 >= 9'h17F) // POS Limiter + mix_0 <= 9'h0FF; + else if(mix0 <= 9'h080)// NEG Limiter + mix_0 <= 9'h000; + else + mix_0 <= mix0 - 9'h080; +end + +wire [8:0]mix1 = mix0[7:0] + W_WAV_D2 ; +reg [8:0]mix_1; +always@(posedge I_CLK1) +begin + if(mix1 >= 9'h17F) // POS Limiter + mix_1 <= 9'h0FF; + else if(mix1 <= 9'h080)// NEG Limiter + mix_1 <= 9'h000; + else + mix_1 <= mix1 - 9'h080; +end + +assign O_SDAT = mix_1[7:0]; + + +endmodule diff --git a/galaxian/src/mc_stars.v b/galaxian/src/mc_stars.v new file mode 100644 index 0000000..d2a5326 --- /dev/null +++ b/galaxian/src/mc_stars.v @@ -0,0 +1,108 @@ +//=============================================================================== +// FPGA MOONCRESTA STARS +// +// Version : 2.00 +// +// Copyright(c) 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +// 2004- 9-22 +//================================================================================ + + +module mc_stars( + +I_CLK_18M, +I_CLK_6M, +I_H_FLIP, +I_V_SYNC, +I_8HF, +I_256HnX, +I_1VF, +I_2V, +I_STARS_ON, +I_STARS_OFFn, + +O_R, +O_G, +O_B, +O_NOISE + +); + +input I_CLK_18M; +input I_CLK_6M; +input I_H_FLIP; +input I_V_SYNC; +input I_8HF; +input I_256HnX; +input I_1VF; +input I_2V; +input I_STARS_ON; +input I_STARS_OFFn; + +output [2:0]O_R; +output [2:0]O_G; +output [1:0]O_B; +output O_NOISE; + +wire W_V_SYNCn = ~I_V_SYNC; + +wire CLK_1C = ~(I_CLK_18M & I_CLK_6M & W_V_SYNCn & I_256HnX); + +reg W_1C_Q1,W_1C_Q2; +always@(posedge CLK_1C or negedge W_V_SYNCn) +begin + if(W_V_SYNCn==1'b0)begin + W_1C_Q1 <= 1'b0; + W_1C_Q2 <= 1'b0; + end + else begin + W_1C_Q1 <= 1'b1; + W_1C_Q2 <= W_1C_Q1; + end +end + +wire CLK_1AB = ~(CLK_1C |(~(I_H_FLIP|W_1C_Q2))) ; + +reg [15:0]W_1AB_Q; +reg W_2D_Qn; +wire W_3B = W_2D_Qn^W_1AB_Q[4]; + +always@(posedge CLK_1AB or negedge I_STARS_ON) +begin + if(I_STARS_ON==1'b0)begin + W_1AB_Q <= 0; + W_2D_Qn <= 1'b1; + end + else begin + W_1AB_Q <= {W_1AB_Q[14:0],W_3B}; + W_2D_Qn <= ~W_1AB_Q[15]; + end +end + +wire W_2A = ~(& W_1AB_Q[7:0]); +wire W_4P = ~(( I_8HF ^ I_1VF ) & W_2D_Qn & I_STARS_OFFn); + +assign O_R[2] = 1'b0 ; +assign O_R[1] = (W_2A|W_4P) ? 1'b0 : W_1AB_Q[8] ; +assign O_R[0] = (W_2A|W_4P) ? 1'b0 : W_1AB_Q[9] ; + +assign O_G[2] = 1'b0 ; +assign O_G[1] = (W_2A|W_4P) ? 1'b0 : W_1AB_Q[10] ; +assign O_G[0] = (W_2A|W_4P) ? 1'b0 : W_1AB_Q[11] ; + +assign O_B[1] = (W_2A|W_4P) ? 1'b0 : W_1AB_Q[12] ; +assign O_B[0] = (W_2A|W_4P) ? 1'b0 : W_1AB_Q[13] ; + +reg noise; +always@(posedge I_2V) noise <= W_2D_Qn ; +assign O_NOISE = noise ; + + +endmodule \ No newline at end of file diff --git a/galaxian/src/mc_top.v b/galaxian/src/mc_top.v new file mode 100644 index 0000000..58bc3c0 --- /dev/null +++ b/galaxian/src/mc_top.v @@ -0,0 +1,724 @@ +//=============================================================================== +// FPGA GALAXIAN TOP +// +// Version : 2.50 +// +// Copyright(c) 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +// 2004- 4-30 galaxian modify by K.DEGAWA +// 2004- 5- 6 first release. +// 2004- 8-23 Improvement with T80-IP. +// 2004- 9-18 The description of ALTERA(CYCLONE) and XILINX(SPARTAN2E) was made one. +// 2004- 9-22 The problem which missile didn't sometimes come out from was improved. +//================================================================================ + +`include "src/mc_conf.v" + +module mc_top( + +// FPGA_USE +I_CLK_125M, + +`ifdef PSPAD_USE +// PS_PAD interface +psCLK, +psSEL, +psTXD, +psRXD, +`endif + +// ROM IF +//O_ROM_AB, +//I_ROM_DB, +//O_ROM_OEn, +//O_ROM_CSn, +//O_ROM_WEn, + +// INPORT SW IF +I_PSW, + +// SOUND OUT +O_SOUND_OUT_L, +O_SOUND_OUT_R, + +// VGA (VIDEO) IF +O_VGA_R, +O_VGA_G, +O_VGA_B, +O_VGA_H_SYNCn, +O_VGA_V_SYNCn + +); + +// FPGA_USE +input I_CLK_125M; + +// CPU ADDRESS BUS +wire [15:0]W_A; +// CPU IF +wire W_CPU_RDn; +wire W_CPU_WRn; +wire W_CPU_MREQn; +wire W_CPU_RFSHn; +wire W_CPU_BUSAKn; +wire W_CPU_IORQn; +wire W_CPU_M1n; +wire W_CPU_CLK; +wire W_CPU_HRDWR_RESETn; +wire W_CPU_WAITn; +wire W_CPU_NMIn; + +`ifdef PSPAD_USE +// PS_PAD interface +input psRXD; +output psTXD,psCLK,psSEL; +`endif + +// ROM IF +//output [18:0]O_ROM_AB; +//input [7:0]I_ROM_DB; +//output O_ROM_OEn; +//output O_ROM_CSn; +//output O_ROM_WEn; + +// INPORT SW IF +input [4:0]I_PSW; + +// SOUND OUT +output O_SOUND_OUT_L; +output O_SOUND_OUT_R; + +// VGA (VIDEO) IF +output [4:0]O_VGA_R; +output [4:0]O_VGA_G; +output [4:0]O_VGA_B; +output O_VGA_H_SYNCn; +output O_VGA_V_SYNCn; + +wire W_RESETn = |I_PSW[3:0]; +//------ CLOCK GEN --------------------------- +wire I_CLK_18432M; +wire W_CLK_12M,WB_CLK_12M; +wire W_CLK_6M,WB_CLK_6M; +wire W_STARS_CLK; + +dcm clockgen( +.CLKIN_IN(I_CLK_125M), +.RST_IN(W_RESETn), +.CLKFX_OUT(I_CLK_18432M) +); + +//------ H&V COUNTER ------------------------- +wire [8:0]W_H_CNT; +wire [7:0]W_V_CNT; +wire W_H_BL; +wire W_V_BLn; +wire W_C_BLn; +wire W_H_SYNC; +wire W_V_SYNC; + +//------ CPU RAM ---------------------------- +wire [7:0]W_CPU_RAM_DO; + +//------ ADDRESS DECDER ---------------------- +wire W_CPU_ROM_CSn; +wire W_CPU_RAM_RDn; +wire W_CPU_RAM_WRn; +wire W_CPU_RAM_CSn; +wire W_OBJ_RAM_RDn; +wire W_OBJ_RAM_WRn; +wire W_OBJ_RAM_RQn; +wire W_VID_RAM_RDn; +wire W_VID_RAM_WRn; +wire W_SW0_OEn; +wire W_SW1_OEn; +wire W_DIP_OEn; +wire W_WDR_OEn; +wire W_LAMP_WEn; +wire W_SOUND_WEn; +wire W_PITCHn; +wire W_H_FLIP; +wire W_V_FLIP; +wire W_BD_G; +wire W_STARS_ON; + +wire W_VID_RDn = W_OBJ_RAM_RDn & W_VID_RAM_RDn ; +wire W_SW_OEn = W_SW0_OEn & W_SW1_OEn & W_DIP_OEn ; +//------- INPORT ----------------------------- +wire [7:0]W_SW_DO; +//------- VIDEO ----------------------------- +wire [7:0]W_VID_DO; +//-------------------------------------------- + +mc_clock MC_CLK( + +.I_CLK_18M(I_CLK_18432M), +.O_CLK_12M(WB_CLK_12M), +.O_CLK_06M(WB_CLK_6M) + +); + +`ifdef DEVICE_CYCLONE +assign W_CLK_12M = WB_CLK_12M; +assign W_CLK_6M = WB_CLK_6M; +`endif +`ifdef DEVICE_SPARTAN2E +BUFG BUFG_12MHz( .I(WB_CLK_12M),.O(W_CLK_12M) ); +BUFG BUFG_6MHz ( .I(WB_CLK_6M ),.O(W_CLK_6M ) ); +`endif +//--- DATA I/F ------------------------------------- +reg [7:0]W_CPU_ROM_DO; +wire [7:0]W_CPU_ROM_DOB = W_CPU_ROM_CSn ? 8'h00: W_CPU_ROM_DO ; + +wire [7:0]W_BDO = W_SW_DO | W_VID_DO | W_CPU_RAM_DO | W_CPU_ROM_DOB ; +wire [7:0]W_BDI; + +//--- CPU I/F ------------------------------------- +reg [3:0]rst_count; +always@(posedge W_H_CNT[0] or negedge W_RESETn) +begin + if(! W_RESETn) rst_count <= 0; + else begin + if( rst_count == 15) + rst_count <= rst_count; + else + rst_count <= rst_count+1; + end +end + +assign W_CPU_RESETn = W_RESETn; +assign W_CPU_CLK = W_H_CNT[0]; + +Z80IP CPU( + +.CLK(W_CPU_CLK), +.RESET_N(W_CPU_RESETn), +.INT_N(1'b1), +.NMI_N(W_CPU_NMIn), +.ADRS(W_A), +.DOUT(W_BDI), +.DINP(W_BDO), +.M1_N(), +.MREQ_N(W_CPU_MREQn), +.IORQ_N(), +.RD_N(W_CPU_RDn ), +.WR_N(W_CPU_WRn ), +.WAIT_N(W_CPU_WAITn), +.BUSWO(), +.RFSH_N(W_CPU_RFSHn), +.HALT_N() + +); + +wire W_CPU_RAM_CLK = W_CLK_12M & ~W_CPU_RAM_CSn; + +mc_cpu_ram MC_CPU_RAM( + +.I_CLK(W_CPU_RAM_CLK), +.I_ADDR(W_A[9:0]), +.I_D(W_BDI), +.I_WE(~W_CPU_WRn), +.I_OE(~W_CPU_RAM_RDn ), +.O_D(W_CPU_RAM_DO) + +); + + +mc_adec MC_ADEC( + +.I_CLK_12M(W_CLK_12M), +.I_CLK_6M(W_CLK_6M), +.I_CPU_CLK(W_H_CNT[0]), +.I_RSTn(W_RESETn), + +.I_CPU_A(W_A), +.I_CPU_D(W_BDI[0]), +.I_MREQn(W_CPU_MREQn), +.I_RFSHn(W_CPU_RFSHn), +.I_RDn(W_CPU_RDn), +.I_WRn(W_CPU_WRn), +.I_H_BL(W_H_BL), +.I_V_BLn(W_V_BLn), + +.O_WAITn(W_CPU_WAITn), +.O_NMIn(W_CPU_NMIn), +.O_CPU_ROM_CSn(W_CPU_ROM_CSn), +.O_CPU_RAM_RDn(W_CPU_RAM_RDn), +.O_CPU_RAM_WRn(W_CPU_RAM_WRn), +.O_CPU_RAM_CSn(W_CPU_RAM_CSn), +.O_OBJ_RAM_RDn(W_OBJ_RAM_RDn), +.O_OBJ_RAM_WRn(W_OBJ_RAM_WRn), +.O_OBJ_RAM_RQn(W_OBJ_RAM_RQn), +.O_VID_RAM_RDn(W_VID_RAM_RDn), +.O_VID_RAM_WRn(W_VID_RAM_WRn), +.O_SW0_OEn(W_SW0_OEn), +.O_SW1_OEn(W_SW1_OEn), +.O_DIP_OEn(W_DIP_OEn), +.O_WDR_OEn(W_WDR_OEn), +.O_LAMP_WEn(W_LAMP_WEn), +.O_SOUND_WEn(W_SOUND_WEn), +.O_PITCHn(W_PITCHn), +.O_H_FLIP(W_H_FLIP), +.O_V_FLIP(W_V_FLIP), +.O_BD_G(W_BD_G), +.O_STARS_ON(W_STARS_ON) + +); + +//-------- SOUND I/F ----------------------------- +//--- Parts 9L --------- +reg [7:0]W_9L_Q; +always@(posedge W_CLK_12M or negedge W_RESETn) +begin + if(W_RESETn == 1'b0)begin + W_9L_Q <= 0; + end + else begin + if(W_SOUND_WEn == 1'b0)begin + case(W_A[2:0]) + 3'h0 : W_9L_Q[0] <= W_BDI[0]; + 3'h1 : W_9L_Q[1] <= W_BDI[0]; + 3'h2 : W_9L_Q[2] <= W_BDI[0]; + 3'h3 : W_9L_Q[3] <= W_BDI[0]; + 3'h4 : W_9L_Q[4] <= W_BDI[0]; + 3'h5 : W_9L_Q[5] <= W_BDI[0]; + 3'h6 : W_9L_Q[6] <= W_BDI[0]; + 3'h7 : W_9L_Q[7] <= W_BDI[0]; + endcase + end + end +end +wire W_VOL1 = W_9L_Q[6]; +wire W_VOL2 = W_9L_Q[7]; +wire W_FIRE = W_9L_Q[5]; +wire W_HIT = W_9L_Q[3]; +wire W_FS3 = W_9L_Q[2]; +wire W_FS2 = W_9L_Q[1]; +wire W_FS1 = W_9L_Q[0]; +//--------------------------------------------------- +//---- CPU DATA WATCH ------------------------------- +wire ZMWR = W_CPU_MREQn | W_CPU_WRn ; + +reg [1:0]on_game; +always @(posedge W_CPU_CLK) +begin + if(~ZMWR)begin + if(W_A == 16'h4007)begin + if(W_BDI == 8'h00) + on_game[0] <= 1; + else + on_game[0] <= 0; + end + if(W_A == 16'h4005)begin + if(W_BDI == 8'h03 || W_BDI == 8'h04 ) + on_game[1] <= 1; + else + on_game[1] <= 0; + end + end +end + +`ifdef PSPAD_USE +reg died; +always @(posedge W_CPU_CLK) +begin + if(~ZMWR)begin + if(W_A == 16'h4206)begin + if(W_BDI == 8'h00) + died <= 0; + else + died <= 1; + end + end +end +//---- PS_PAD Interface ----------------------------- +wire [8:0]ps_PSW; +wire VIB_SW = died & (&on_game[1:0]); + +fpga_arcade_if pspad( + +.CLK_18M432(I_CLK_18432M), +.I_RSTn(W_RESETn), +.psCLK(psCLK), +.psSEL(psSEL), +.psTXD(psTXD), +.psRXD(psRXD), +.ps_PSW(ps_PSW), +.I_VIB_SW(VIB_SW) + +); +`endif +//---- SW Interface --------------------------------- +`ifdef PSPAD_USE +wire L1 = I_PSW[2] & ps_PSW[2]; +wire R1 = I_PSW[3] & ps_PSW[3]; +wire U1 = I_PSW[0]; +wire D1 = I_PSW[1]; +wire J1 = I_PSW[4] & ps_PSW[8]; + +wire S1 = (U1|J1) & ps_PSW[6]; +wire S2 = (D1|J1) & ps_PSW[7]; + +wire C1 = (L1|R1|U1|~D1) & ps_PSW[4]; +`else +wire L1 = I_PSW[2]; +wire R1 = I_PSW[3]; +wire U1 = I_PSW[0]; +wire D1 = I_PSW[1]; +wire J1 = I_PSW[4]; + +wire S1 = U1|J1; +wire S2 = D1|J1; + +wire C1 = L1|R1|U1|~D1; +`endif +wire C2 = L1|R1|~U1|D1; + +wire L2 = L1; +wire R2 = R1; +wire U2 = U1; +wire D2 = D1; +wire J2 = J1; + +mc_inport MC_INPORT( + +.I_COIN1(~C1), // ACTIVE HI +.I_COIN2(~C2), // ACTIVE HI +.I_1P_LE(~L1), // ACTIVE HI +.I_1P_RI(~R1), // ACTIVE HI +.I_1P_SH(~J1), // ACTIVE HI +.I_2P_LE(~L2), // ACTIVE HI +.I_2P_RI(~R2), // ACTIVE HI +.I_2P_SH(~J2), // ACTIVE HI +.I_1P_START(~S1), // ACTIVE HI +.I_2P_START(~S2), // ACTIVE HI + +.I_SW0_OEn(W_SW0_OEn), +.I_SW1_OEn(W_SW1_OEn), +.I_DIP_OEn(W_DIP_OEn), + +.O_D(W_SW_DO) + +); + +//----------------------------------------------------------------------------- +//------- ROM ------------------------------------------------------- +reg [18:0]ROM_A; +wire [10:0]W_OBJ_ROM_A; +reg [7:0]W_OBJ_ROM_A_D; +reg [7:0]W_OBJ_ROM_B_D; + +wire [18:0]W_WAV_A0,W_WAV_A1,W_WAV_A2; +reg [7:0]W_WAV_D0,W_WAV_D1,W_WAV_D2; + +wire [7:0]ROM_D; // = I_ROM_DB; +//assign O_ROM_AB = ROM_A; + +//assign O_ROM_OEn = 1'b0; +//assign O_ROM_CSn = 1'b0; +//assign O_ROM_WEn = 1'b1; + +galaxian_roms ROMS( +.I_CLK_18432M(I_CLK_18432M), +.I_CLK_12M(WB_CLK_12M), +.I_ADDR(ROM_A), +.O_DATA(ROM_D) +); + + +reg [1:0]clk_d; +reg [4:0]seq; +always @(posedge I_CLK_18432M) +begin + // 24 phase generator + clk_d[0] <= W_H_CNT[0] & W_H_CNT[1] & W_H_CNT[2]; + clk_d[1] <= clk_d[0]; + seq <= (~clk_d[1] & clk_d[0]) ? 0 : seq+1; + case(seq) + 0:begin + //sound + ROM_A <= W_WAV_A0; + W_CPU_ROM_DO <= ROM_D; + end + 2:begin + //sound + ROM_A <= W_WAV_A1; + W_WAV_D0 <= ROM_D; + end + 4:begin + //sound + ROM_A <= {3'h0,W_A[15:0]}; + W_WAV_D1 <= ROM_D; + end + 6:begin + //sound + ROM_A <= W_WAV_A2; + W_CPU_ROM_DO <= ROM_D; + end + 8:W_WAV_D2 <= ROM_D; //sound + 10:ROM_A <= {3'h0,W_A[15:0]}; + 12:W_CPU_ROM_DO <= ROM_D; + 16:ROM_A <= {3'h0,W_A[15:0]}; + 18:begin + ROM_A <= {3'h0,4'h4,1'b0,W_OBJ_ROM_A}; + W_CPU_ROM_DO <= ROM_D; + end + 20:begin + ROM_A <= {3'h0,4'h5,1'b0,W_OBJ_ROM_A}; + W_OBJ_ROM_A_D <= ROM_D; + end + 22:begin + ROM_A <= {3'h0,W_A[15:0]}; + W_OBJ_ROM_B_D <= ROM_D; + end + default:; + endcase +end +//----------------------------------------------------------------------------- + +wire W_V_BL2n; + +mc_hv_count MC_HV( + +.I_CLK(WB_CLK_6M), +.I_RSTn(W_RESETn), + +.O_H_CNT(W_H_CNT), +.O_H_SYNC(W_H_SYNC), +.O_H_BL(W_H_BL), +.O_V_CNT(W_V_CNT), +.O_V_SYNC(W_V_SYNC), +.O_V_BL2n(W_V_BL2n), +.O_V_BLn(W_V_BLn), +.O_C_BLn(W_C_BLn) + +); + +//------ VIDEO ----------------------------- +wire W_8HF; +wire W_1VF; +wire W_C_BLnX; +wire W_256HnX; +wire W_MISSILEn; +wire W_SHELLn; +wire [1:0]W_VID; +wire [2:0]W_COL; + +mc_video MC_VID( +.I_CLK_18M(I_CLK_18432M), +.I_CLK_12M(W_CLK_12M), +.I_CLK_6M(W_CLK_6M), +.I_H_CNT(W_H_CNT), +.I_V_CNT(W_V_CNT), +.I_H_FLIP(W_H_FLIP), +.I_V_FLIP(W_V_FLIP), +.I_V_BLn(W_V_BLn), +.I_C_BLn(W_C_BLn), + +.I_A(W_A[9:0]), +.I_OBJ_SUB_A(3'b000), +.I_BD(W_BDI), +.I_OBJ_RAM_RQn(W_OBJ_RAM_RQn), +.I_OBJ_RAM_RDn(W_OBJ_RAM_RDn), +.I_OBJ_RAM_WRn(W_OBJ_RAM_WRn), +.I_VID_RAM_RDn(W_VID_RAM_RDn), +.I_VID_RAM_WRn(W_VID_RAM_WRn), + +.O_OBJ_ROM_A(W_OBJ_ROM_A), +.I_OBJ_ROM_A_D(W_OBJ_ROM_A_D), +.I_OBJ_ROM_B_D(W_OBJ_ROM_B_D), + +.O_C_BLnX(W_C_BLnX), +.O_8HF(W_8HF), +.O_256HnX(W_256HnX), +.O_1VF(W_1VF), +.O_MISSILEn(W_MISSILEn), +.O_SHELLn(W_SHELLn), +.O_BD(W_VID_DO), +.O_VID(W_VID), +.O_COL(W_COL) + +); + +wire W_C_BLX; +wire W_STARS_OFFn; +wire [2:0]W_VIDEO_R; +wire [2:0]W_VIDEO_G; +wire [1:0]W_VIDEO_B; + +mc_col_pal MC_COL_PAL( + +.I_CLK_12M(W_CLK_12M), +.I_CLK_6M(W_CLK_6M), +.I_VID(W_VID), +.I_COL(W_COL), +.I_C_BLnX(W_C_BLnX), + +.O_C_BLX(W_C_BLX), +.O_STARS_OFFn(W_STARS_OFFn), +.O_R(W_VIDEO_R), +.O_G(W_VIDEO_G), +.O_B(W_VIDEO_B) + +); + +wire [2:0]W_STARS_R; +wire [2:0]W_STARS_G; +wire [1:0]W_STARS_B; + +mc_stars MC_STARS( + +.I_CLK_18M(I_CLK_18432M), +`ifdef DEVICE_CYCLONE +.I_CLK_6M(~WB_CLK_6M), +`endif +`ifdef DEVICE_SPARTAN2E +.I_CLK_6M(WB_CLK_6M), +`endif +.I_H_FLIP(W_H_FLIP), +.I_V_SYNC(W_V_SYNC), +.I_8HF(W_8HF), +.I_256HnX(W_256HnX), +.I_1VF(W_1VF), +.I_2V(W_V_CNT[1]), +.I_STARS_ON(W_STARS_ON), +.I_STARS_OFFn(W_STARS_OFFn), + +.O_R(W_STARS_R), +.O_G(W_STARS_G), +.O_B(W_STARS_B), +.O_NOISE() + +); + +wire [2:0]W_R; +wire [2:0]W_G; +wire [1:0]W_B; + +mc_vedio_mix MIX( + +.I_VID_R(W_VIDEO_R), +.I_VID_G(W_VIDEO_G), +.I_VID_B(W_VIDEO_B), +.I_STR_R(W_STARS_R), +.I_STR_G(W_STARS_G), +.I_STR_B(W_STARS_B), + +.I_C_BLnXX(~W_C_BLX), +.I_C_BLX(W_C_BLX | ~W_V_BL2n), +.I_MISSILEn(W_MISSILEn), +.I_SHELLn(W_SHELLn), + +.O_R(W_R), +.O_G(W_G), +.O_B(W_B) + +); + +`ifdef VGA_USE +mc_vga_if VGA( + +// input +.I_CLK_1(W_CLK_6M), +.I_CLK_2(W_CLK_12M), +.I_R(W_R), +.I_G(W_G), +.I_B(W_B), +.I_H_SYNC(W_H_SYNC), +.I_V_SYNC(W_V_SYNC), +// output +.O_R(O_VGA_R), +.O_G(O_VGA_G), +.O_B(O_VGA_B), +.O_H_SYNCn(O_VGA_H_SYNCn), +.O_V_SYNCn(O_VGA_V_SYNCn) + +); + +`else + +assign O_VGA_R[2:0] = W_R; +assign O_VGA_R[4:3] = 1'b0; + +assign O_VGA_G[2:0] = W_G; +assign O_VGA_G[4:3] = 1'b0; + +assign O_VGA_B[1:0] = W_B; +assign O_VGA_B[4:2] = 1'b0; + +//assign O_VGA_H_SYNCn = W_H_SYNC | W_V_SYNC ; // AKIDUKI LCD USED +assign O_VGA_H_SYNCn = ~W_H_SYNC ; +assign O_VGA_V_SYNCn = ~W_V_SYNC ; + +`endif + +wire [7:0]W_SDAT_A; + +mc_sound_a MC_SOUND_A( + +.I_CLK_12M(W_CLK_12M), +.I_CLK_6M(W_CLK_6M), +.I_H_CNT1(W_H_CNT[1]), +.I_BD(W_BDI), +.I_PITCHn(W_PITCHn), +.I_VOL1(W_VOL1), +.I_VOL2(W_VOL2), + +.O_SDAT(W_SDAT_A), +.O_DO() + +); + +wire [7:0]W_SDAT_B; + +mc_sound_b MC_SOUND_B( + +.I_CLK1(I_CLK_18432M), +.I_CLK2(W_CLK_6M), +.I_RSTn(rst_count[3]), +.I_SW({&on_game[1:0],W_HIT,W_FIRE}), + +.O_WAV_A0(W_WAV_A0), +.O_WAV_A1(W_WAV_A1), +.O_WAV_A2(W_WAV_A2), +.I_WAV_D0(W_WAV_D0), +.I_WAV_D1(W_WAV_D1), +.I_WAV_D2(W_WAV_D2), + +.O_SDAT(W_SDAT_B) + +); + +wire W_DAC_A; +wire W_DAC_B; + +assign O_SOUND_OUT_L = W_DAC_A; +assign O_SOUND_OUT_R = W_DAC_B; + +dac wav_dac_a( + +.Clk(I_CLK_18432M), +.Reset(~W_RESETn), +.DACin(W_SDAT_A), +.DACout(W_DAC_A) + +); + +dac wav_dac_b( + +.Clk(I_CLK_18432M), +.Reset(~W_RESETn), +.DACin(W_SDAT_B), +.DACout(W_DAC_B) + +); + + +endmodule + diff --git a/galaxian/src/mc_vedio_mix.v b/galaxian/src/mc_vedio_mix.v new file mode 100644 index 0000000..106ea5c --- /dev/null +++ b/galaxian/src/mc_vedio_mix.v @@ -0,0 +1,64 @@ +//=============================================================================== +// FPGA MOONCRESTA VIDO-MIX +// +// Version : 1.00 +// +// Copyright(c) 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +//================================================================================ + + +module mc_vedio_mix( + +I_VID_R, +I_VID_G, +I_VID_B, +I_STR_R, +I_STR_G, +I_STR_B, + +I_C_BLnXX, +I_C_BLX, +I_MISSILEn, +I_SHELLn, + +O_R, +O_G, +O_B + +); + +input [2:0]I_VID_R; +input [2:0]I_VID_G; +input [1:0]I_VID_B; +input [2:0]I_STR_R; +input [2:0]I_STR_G; +input [1:0]I_STR_B; + +input I_C_BLnXX; +input I_C_BLX; +input I_MISSILEn; +input I_SHELLn; + +output [2:0]O_R; +output [2:0]O_G; +output [1:0]O_B; + +// MISSILE => Yellow ; +// SHELL => White ; +wire W_MS_D = ~(I_MISSILEn & I_SHELLn); +wire W_MS_R = ~I_C_BLX & W_MS_D; +wire W_MS_G = ~I_C_BLX & W_MS_D; +wire W_MS_B = ~I_C_BLX & W_MS_D & ~I_SHELLn ; + +assign O_R = I_C_BLnXX ? I_VID_R | I_STR_R | {1'b0,W_MS_R,W_MS_R}: 3'b000 ; +assign O_G = I_C_BLnXX ? I_VID_G | I_STR_G | {1'b0,W_MS_G,W_MS_G}: 3'b000 ; +assign O_B = I_C_BLnXX ? I_VID_B | I_STR_B | { W_MS_B,W_MS_B}: 2'b00 ; + +endmodule \ No newline at end of file diff --git a/galaxian/src/mc_vga_if.v b/galaxian/src/mc_vga_if.v new file mode 100644 index 0000000..707e8a1 --- /dev/null +++ b/galaxian/src/mc_vga_if.v @@ -0,0 +1,268 @@ +//=============================================================================== +// FPGA VGA INTERFACE FOR ALTERA CYCLONE & XILINX SPARTAN2E +// +// Version : 2.00 +// +// Copyright(c) 2003 - 2004 Katsumi Degawa , All rights reserved +// +// based on a design by Tatsuyuki Satoh +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +// 2004- 9-18 added SPARTAN2E DEVIDE . K.DEGAWA +//================================================================================ +`include "src/mc_conf.v" + +module mc_vga_if( + +I_CLK_1, +I_CLK_2, +I_R, +I_G, +I_B, +I_H_SYNC, +I_V_SYNC, + +O_R, +O_G, +O_B, +O_H_SYNCn, +O_V_SYNCn + +); + +// input signals +input I_CLK_1; // 6.144MHz input pixel clock +input I_CLK_2; // 12.288Mhz output pixel clock +input [2:0]I_R; // R in +input [2:0]I_G; // G in +input [1:0]I_B; // B in +input I_H_SYNC; // HSYNC input (16KHz) +input I_V_SYNC; // VSYNC input (60Hz) + +// output signals +output [4:0]O_R; // R out +output [4:0]O_G; // G out +output [4:0]O_B; // B out +output O_H_SYNCn; // HSYNC output +output O_V_SYNCn; // VSYNC output + +//--------------------------------------------------------------------------- +// setup parameter +//--------------------------------------------------------------------------- + +parameter H_COUNT = 384; // number of pixels in H-SCAN +parameter HS_POS = 16; // HSYNC position +parameter HS_WIDTH = HS_POS+8; // HSYNC width / pixel +parameter VS_WIDTH = 8; // VSYNC width / HSYNC_OUT + +//--------------------------------------------------------------------------- +// input timming +//--------------------------------------------------------------------------- +reg [8:0]Hpos_in; // input capture postion +reg L_Hsync_i; +wire HP_in = ~L_Hsync_i & I_H_SYNC; +always@(posedge I_CLK_1) +begin + Hpos_in <= HP_in ? 0: Hpos_in + 1; + L_Hsync_i <= I_H_SYNC; +end + +//--------------------------------------------------------------------------- +//output timming +//--------------------------------------------------------------------------- +reg [8:0]Hpos_out; +reg L_Hsync_o; +wire HP_out = ~L_Hsync_o & I_H_SYNC; +wire HP_ret = HP_out | (Hpos_out == H_COUNT-1); + +always@(posedge I_CLK_2) +begin + Hpos_out <= HP_ret ? 0:Hpos_out + 1; + L_Hsync_o <= I_H_SYNC; +end + +reg O_Hsync; +always@(posedge I_CLK_2) +begin + case(Hpos_out) + HS_POS :O_Hsync <= 1'b1; + HS_WIDTH:O_Hsync <= 1'b0; + default :; + endcase +end + +//--------------------------------------------------------------------------- +// RGB capture(portA) & output(portB) +//--------------------------------------------------------------------------- +wire [7:0]rgb_in = {I_R,I_G,I_B}; // RGB input +wire [7:0]rgb_out; // RGB output + +`ifdef DEVICE_CYCLONE +alt_ram_512_8_d double_scan_ram( + +.clock_a(I_CLK_1), +.address_a(Hpos_in), +.q_a(), +.data_a(rgb_in), +.wren_a(1'b1), +.enable_a(1'b1), +.aclr_a(1'b0), + +.clock_b(I_CLK_2), +.address_b(Hpos_out), +.q_b(rgb_out), +.data_b(4'h0), +.wren_b(1'b0), +.enable_b(1'b1), +.aclr_b(1'b0) + +); +`endif +`ifdef DEVICE_SPARTAN2E +RAMB4_S8_S8 double_scan_ram ( + +.CLKA(I_CLK_1), +.ADDRA(Hpos_in), +.DOA(), +.DIA(rgb_in), +.WEA(1'b1), +.ENA(1'b1), +.RSTA(1'b0), + +.CLKB(I_CLK_2), +.ADDRB(Hpos_out), +.DOB(rgb_out), +.DIB(4'h0), +.WEB(1'b0), +.ENB(1'b1), +.RSTB(1'b0) + +); +`endif +//--------------------------------------------------------------------------- +// vsync remake +// +// 1 HSYNC_IN delay & HSYNC pulse width = 4xHSYNC(in) +//--------------------------------------------------------------------------- + +reg [2:0]vs_cnt; +reg O_Vsync; + +always @(posedge O_Hsync) +begin + if(~I_V_SYNC)begin + vs_cnt <= VS_WIDTH-1; + end + else begin + if(vs_cnt==0) vs_cnt <= vs_cnt; + else vs_cnt <= vs_cnt-1; + end +end +always @(posedge O_Hsync) +begin + case(vs_cnt) + VS_WIDTH-2 :O_Vsync <= 1; + 0 :O_Vsync <= 0; + endcase +end +//--------------------------------------------------------------------------- +// output +//--------------------------------------------------------------------------- + +assign O_R = {2'b00,rgb_out[7:5]}; +assign O_G = {2'b00,rgb_out[4:2]}; +assign O_B = {3'b000,rgb_out[1:0]}; + +// converted H V SYNC +assign O_H_SYNCn = ~O_Hsync; +assign O_V_SYNCn = ~O_Vsync; + +endmodule + +`ifdef DEVICE_CYCLONE +module alt_ram_512_8_d ( + data_a, + wren_a, + address_a, + data_b, + address_b, + wren_b, + clock_a, + enable_a, + clock_b, + enable_b, + aclr_a, + aclr_b, + q_a, + q_b); + + input [7:0] data_a; + input wren_a; + input [8:0] address_a; + input [7:0] data_b; + input [8:0] address_b; + input wren_b; + input clock_a; + input enable_a; + input clock_b; + input enable_b; + input aclr_a; + input aclr_b; + output [7:0] q_a; + output [7:0] q_b; + + wire [7:0] sub_wire0; + wire [7:0] sub_wire1; + wire [7:0] q_a = sub_wire0[7:0]; + wire [7:0] q_b = sub_wire1[7:0]; + + altsyncram altsyncram_component ( + .clocken0 (enable_a), + .clocken1 (enable_b), + .wren_a (wren_a), + .aclr0 (aclr_a), + .clock0 (clock_a), + .wren_b (wren_b), + .aclr1 (aclr_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)); + defparam + altsyncram_component.operation_mode = "BIDIR_DUAL_PORT", + altsyncram_component.width_a = 8, + altsyncram_component.widthad_a = 9, + altsyncram_component.numwords_a = 512, + altsyncram_component.width_b = 8, + altsyncram_component.widthad_b = 9, + altsyncram_component.numwords_b = 512, + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.width_byteena_a = 1, + altsyncram_component.width_byteena_b = 1, + altsyncram_component.outdata_reg_a = "UNREGISTERED", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_reg_b = "UNREGISTERED", + altsyncram_component.indata_aclr_a = "CLEAR0", + altsyncram_component.wrcontrol_aclr_a = "CLEAR0", + altsyncram_component.address_aclr_a = "CLEAR0", + altsyncram_component.indata_reg_b = "CLOCK1", + altsyncram_component.address_reg_b = "CLOCK1", + altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1", + altsyncram_component.indata_aclr_b = "CLEAR1", + altsyncram_component.wrcontrol_aclr_b = "CLEAR1", + altsyncram_component.address_aclr_b = "CLEAR1", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.ram_block_type = "M4K", + altsyncram_component.intended_device_family = "Stratix"; + + +endmodule +`endif diff --git a/galaxian/src/mc_video.v b/galaxian/src/mc_video.v new file mode 100644 index 0000000..c93b557 --- /dev/null +++ b/galaxian/src/mc_video.v @@ -0,0 +1,395 @@ +//=============================================================================== +// FPGA GALAXIAN VIDEO +// +// Version : 2.50 +// +// Copyright(c) 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +// 2004- 4-30 galaxian modify by K.DEGAWA +// 2004- 5- 6 first release. +// 2004- 8-23 Improvement with T80-IP. +// 2004- 9-22 The problem which missile didn't sometimes come out from was improved. +//================================================================================ +//----------------------------------------------------------------------------------------- +// H_CNT[0],H_CNT[1],H_CNT[2],H_CNT[3],H_CNT[4],H_CNT[5],H_CNT[6],H_CNT[7],H_CNT[8], +// 1 H 2 H 4H 8H 16 H 32H 64 H 128 H 256 H +//----------------------------------------------------------------------------------------- +// V_CNT[0], V_CNT[1], V_CNT[2], V_CNT[3], V_CNT[4], V_CNT[5], V_CNT[6], V_CNT[7] +// 1 V 2 V 4 V 8 V 16 V 32 V 64 V 128 V +//----------------------------------------------------------------------------------------- + +module mc_video( + +I_CLK_18M, +I_CLK_12M, +I_CLK_6M, +I_H_CNT, +I_V_CNT, +I_H_FLIP, +I_V_FLIP, +I_V_BLn, +I_C_BLn, + +I_A, +I_OBJ_SUB_A, +I_BD, +I_OBJ_RAM_RQn, +I_OBJ_RAM_RDn, +I_OBJ_RAM_WRn, +I_VID_RAM_RDn, +I_VID_RAM_WRn, + +O_OBJ_ROM_A, +I_OBJ_ROM_A_D, +I_OBJ_ROM_B_D, + +O_C_BLnX, +O_8HF, +O_256HnX, +O_1VF, +O_MISSILEn, +O_SHELLn, +O_BD, +O_VID, +O_COL + +); + +input I_CLK_18M; +input I_CLK_12M; +input I_CLK_6M; +input [8:0]I_H_CNT; +input [7:0]I_V_CNT; +input I_H_FLIP; +input I_V_FLIP; +input I_V_BLn; +input I_C_BLn; + +input [9:0]I_A; +input [7:0]I_BD; +input [2:0]I_OBJ_SUB_A; +input I_OBJ_RAM_RQn; +input I_OBJ_RAM_RDn; +input I_OBJ_RAM_WRn; +input I_VID_RAM_RDn; +input I_VID_RAM_WRn; + +output [10:0]O_OBJ_ROM_A; +input [7:0]I_OBJ_ROM_A_D; +input [7:0]I_OBJ_ROM_B_D; + +output O_C_BLnX; +output O_8HF; +output O_256HnX; +output O_1VF; +output O_MISSILEn; +output O_SHELLn; + +output [7:0]O_BD; +output [1:0]O_VID; +output [2:0]O_COL; + +wire WB_LDn; +wire WB_CNTRLDn; +wire WB_CNTRCLRn; +wire WB_COLLn; +wire WB_VPLn; +wire WB_OBJDATALn; +wire WB_MLDn; +wire WB_SLDn; +wire W_3D; +reg W_LDn; +reg W_CNTRLDn; +reg W_CNTRCLRn; +reg W_COLLn; +reg W_VPLn; +reg W_OBJDATALn; +reg W_MLDn; +reg W_SLDn; + +always@(negedge I_CLK_12M) +begin + W_LDn <= WB_LDn; + W_CNTRLDn <= WB_CNTRLDn; + W_CNTRCLRn <= WB_CNTRCLRn; + W_COLLn <= WB_COLLn; + W_VPLn <= WB_VPLn; + W_OBJDATALn <= WB_OBJDATALn; + W_MLDn <= WB_MLDn; + W_SLDn <= WB_SLDn; +end + +mc_ld_pls LD_PLS( + +.I_CLK_6M(~I_CLK_6M), +.I_H_CNT(I_H_CNT), +.I_3D_DI(W_3D), + +.O_LDn(WB_LDn), +.O_CNTRLDn(WB_CNTRLDn), +.O_CNTRCLRn(WB_CNTRCLRn), +.O_COLLn(WB_COLLn), +.O_VPLn(WB_VPLn), +.O_OBJDATALn(WB_OBJDATALn), +.O_MLDn(WB_MLDn), +.O_SLDn(WB_SLDn) + +); + +wire W_H_FLIP1 = ~I_H_CNT[8]&I_H_FLIP; + +wire [7:3]W_HF_CNT = I_H_CNT[7:3]^{5{W_H_FLIP1}}; +wire [7:0]W_VF_CNT = I_V_CNT[7:0]^{8{I_V_FLIP}}; + +assign O_8HF = W_HF_CNT[3]; +assign O_1VF = W_VF_CNT[0]; + +reg [7:0]W_OBJ_D; +wire [3:0]W_6J_DA = {I_H_FLIP , W_HF_CNT[7],W_HF_CNT[3],I_H_CNT[2]}; +wire [3:0]W_6J_DB = {W_OBJ_D[6],W_HF_CNT[3]&I_H_CNT[1], I_H_CNT[2],I_H_CNT[1]}; +wire [3:0]W_6J_Q = I_H_CNT[8] ? W_6J_DB:W_6J_DA; + +wire W_H_FLIP2 = W_6J_Q[3]; +// Prats 4F,5F +wire [7:0]W_OBJ_RAM_AB = {1'b0,I_H_CNT[8],W_6J_Q[2],W_HF_CNT[6:4],W_6J_Q[1:0]}; +wire [7:0]W_OBJ_RAM_A = I_OBJ_RAM_RQn ? W_OBJ_RAM_AB: I_A[7:0] ; + +wire [7:0]W_OBJ_RAM_DOA,W_OBJ_RAM_DOB; + +reg [7:0]W_H_POSI; +always@(posedge I_CLK_12M) W_H_POSI <= W_OBJ_RAM_DOB; + +mc_obj_ram OBJ_RAM( + +.I_CLKA(I_CLK_12M), +.I_ADDRA(I_A[7:0]), +.I_WEA(~I_OBJ_RAM_WRn), +.I_CEA(~I_OBJ_RAM_RQn), +.I_DA(I_BD), +.O_DA(W_OBJ_RAM_DOA), + +.I_CLKB(I_CLK_12M), +.I_ADDRB(W_OBJ_RAM_AB), +.I_WEB(1'b0), +.I_CEB(1'b1), +.I_DB(8'h00), +.O_DB(W_OBJ_RAM_DOB) + +); + +wire [7:0]W_OBJ_RAM_D = I_OBJ_RAM_RDn ? 8'h00: W_OBJ_RAM_DOA; +// Prats 4L +always@(posedge W_OBJDATALn) W_OBJ_D <= W_H_POSI; +// Prats 4,5N + +wire [8:0]W_45N_Q = W_VF_CNT[7:0] + W_H_POSI ; +assign W_3D = ~(&W_45N_Q[7:0]); + +reg [7:0]W_2M_Q; +always@(posedge W_VPLn or negedge I_V_BLn) +begin + if(I_V_BLn==1'b0) + W_2M_Q <= 0; + else + W_2M_Q <= W_45N_Q[7:0]; +end + +wire W_2N = I_H_CNT[8]&W_OBJ_D[7]; +wire [3:0]W_1M = W_2M_Q[3:0]^{W_2N,W_2N,W_2N,W_2N}; + +wire W_VID_RAM_CSn = I_VID_RAM_RDn & I_VID_RAM_WRn; + +wire [7:0]W_VID_RAM_DI = I_VID_RAM_WRn ? 8'h00 : I_BD ; +wire [7:0]W_VID_RAM_DOA; + +wire [11:0]W_VID_RAM_AA = {~(&W_2M_Q[7:4]),W_VID_RAM_CSn, 10'h00 /*I_A[9:0]*/}; +wire [11:0]W_VID_RAM_AB = { 1'b0, 1'b0,W_2M_Q[7:4],W_1M[3],W_HF_CNT[7:3]}; + +wire [11:0]W_VID_RAM_A = I_C_BLn ? W_VID_RAM_AB:W_VID_RAM_AA; + +wire [7:0]W_VID_RAM_D = I_VID_RAM_RDn ? 8'h00 :W_VID_RAM_DOA; + +wire [7:0]W_VID_RAM_DOB; + +mc_vid_ram VID_RAM( + +.I_CLKA(I_CLK_12M), +.I_ADDRA(I_A[9:0]), +.I_DA(W_VID_RAM_DI), +.I_WEA(~I_VID_RAM_WRn), +.I_CEA(~W_VID_RAM_CSn), +.O_DA(W_VID_RAM_DOA), + +.I_CLKB(I_CLK_12M), +.I_ADDRB(W_VID_RAM_A[9:0]), +.I_DB(8'h00), +.I_WEB(1'b0), +.I_CEB(1'b1), +.O_DB(W_VID_RAM_DOB) + +); +//-- VIDEO DATA OUTPUT -------------- +assign O_BD = W_OBJ_RAM_D | W_VID_RAM_D; + +wire W_SRLD = ~(W_LDn | W_VID_RAM_A[11]); + +wire [7:0]W_OBJ_ROM_AB = {W_OBJ_D[5:0],W_1M[3],W_OBJ_D[6]^I_H_CNT[3]}; + +wire [7:0]W_OBJ_ROM_A = I_H_CNT[8] ? W_OBJ_ROM_AB: W_VID_RAM_DOB; + +assign O_OBJ_ROM_A = {W_OBJ_ROM_A,W_1M[2:0]}; + +wire [7:0]W_1K_D = I_OBJ_ROM_A_D; +wire [7:0]W_1H_D = I_OBJ_ROM_B_D; + +//--------------------------------------------------------------------------------- +wire W_2L_Qa,W_2K_Qd; +wire W_2J_Qa,W_2H_Qd; +wire W_H_FLIP2X; + +wire [3:0]W_3L_A = {W_2J_Qa,W_2L_Qa, 1'b1,W_SRLD}; +wire [3:0]W_3L_B = {W_2H_Qd,W_2K_Qd,W_SRLD, 1'b1}; +wire [3:0]W_3L_Y = W_H_FLIP2X ? W_3L_B: W_3L_A; // [3]=RAW1,[2]=RAW0 + +wire W_RAW0 = W_3L_Y[2]; +wire W_RAW1 = W_3L_Y[3]; + +wire W_SRCLK = I_CLK_6M; +//------ PARTS 2KL ---------------------------------------------- +wire [1:0]C_2KL = W_3L_Y[1:0]; +wire [7:0]I_2KL = W_1K_D; +reg [7:0]reg_2KL; + +assign W_2L_Qa = reg_2KL[7]; +assign W_2K_Qd = reg_2KL[0]; +always@(posedge W_SRCLK) +begin + case(C_2KL) + 2'b00: reg_2KL <= reg_2KL; + 2'b10: reg_2KL <= {reg_2KL[6:0],1'b0}; + 2'b01: reg_2KL <= {1'b0,reg_2KL[7:1]}; + 2'b11: reg_2KL <= I_2KL; + endcase +end +//------ PARTS 2HJ ---------------------------------------------- +wire [1:0]C_2HJ = W_3L_Y[1:0]; +wire [7:0]I_2HJ = W_1H_D; +reg [7:0]reg_2HJ; + +assign W_2J_Qa = reg_2HJ[7]; +assign W_2H_Qd = reg_2HJ[0]; +always@(posedge W_SRCLK) +begin + case(C_2HJ) + 2'b00: reg_2HJ <= reg_2HJ; + 2'b10: reg_2HJ <= {reg_2HJ[6:0],1'b0}; + 2'b01: reg_2HJ <= {1'b0,reg_2HJ[7:1]}; + 2'b11: reg_2HJ <= I_2HJ; + endcase +end + +//----- SHT2 ----------------------------------------------------- +// Prats 6K +reg [2:0]W_6K_Q; +always@(posedge W_COLLn) W_6K_Q <= W_H_POSI[2:0]; + +// Prats 6P +reg [6:0]W_6P_Q; +always@(posedge I_CLK_6M) +begin + if(W_LDn==1'b0) W_6P_Q <= {W_H_FLIP2,W_H_FLIP1,I_C_BLn,~I_H_CNT[8],W_6K_Q[2:0]}; + else W_6P_Q <= W_6P_Q; +end + +assign W_H_FLIP2X = W_6P_Q[6]; +wire W_H_FLIP1X = W_6P_Q[5]; +wire W_C_BLnX = W_6P_Q[4]; +wire W_256HnX = W_6P_Q[3]; +wire [2:0]W_CD = W_6P_Q[2:0]; + +assign O_256HnX = W_256HnX; +assign O_C_BLnX = W_C_BLnX; + +wire W_45T_CLR = W_CNTRCLRn | W_256HnX ; +reg [7:0]W_45T_Q; + +always@(posedge I_CLK_6M) +begin + if(W_45T_CLR==1'b0) + W_45T_Q <= 0; + else if(W_CNTRLDn==1'b0) + W_45T_Q <= W_H_POSI; + else + W_45T_Q <= W_45T_Q + 1; +end + +wire [7:0]W_LRAM_A = W_45T_Q^{8{W_H_FLIP1X}}; +wire W_LRAM_WE = ~I_CLK_6M; + +wire [4:0]W_LRAM_DI; +wire [4:0]W_LRAM_DO; + +reg [1:0]W_RV; +reg [2:0]W_RC; +wire W_1U_CLK = ~I_CLK_6M; + +always@(posedge W_1U_CLK) +begin + W_RV <= W_LRAM_DO[1:0]; + W_RC <= W_LRAM_DO[4:2]; +end + +wire W_LRAM_AND = ~(~((W_LRAM_A[4]|W_LRAM_A[5])|(W_LRAM_A[6]|W_LRAM_A[7]))|W_256HnX ); +wire W_RAW_OR = W_RAW0 | W_RAW1 ; + +wire [1:0]W_VID; +wire [2:0]W_COL; + +assign W_VID[0] = ~(~(W_RAW0&W_RV[1])&W_RV[0]); +assign W_VID[1] = ~(~(W_RAW1&W_RV[0])&W_RV[1]); +assign W_COL[0] = ~(~(W_RAW_OR&W_CD[0]&W_RC[1]&W_RC[2])&W_RC[0]); +assign W_COL[1] = ~(~(W_RAW_OR&W_CD[1]&W_RC[2]&W_RC[0])&W_RC[1]); +assign W_COL[2] = ~(~(W_RAW_OR&W_CD[2]&W_RC[0]&W_RC[1])&W_RC[2]); + +assign O_VID = W_VID; +assign O_COL = W_COL; + +assign W_LRAM_DI[0] = W_LRAM_AND&W_VID[0]; +assign W_LRAM_DI[1] = W_LRAM_AND&W_VID[1]; +assign W_LRAM_DI[2] = W_LRAM_AND&W_COL[0]; +assign W_LRAM_DI[3] = W_LRAM_AND&W_COL[1]; +assign W_LRAM_DI[4] = W_LRAM_AND&W_COL[2]; + +mc_lram LRAM( + +.I_CLK(I_CLK_18M), +.I_ADDR(W_LRAM_A), +.I_WE(W_LRAM_WE), +.I_D(W_LRAM_DI), +.O_Dn(W_LRAM_DO) + +); + +mc_missile MISSILE( + +.I_CLK_18M(I_CLK_18M), +.I_CLK_6M(I_CLK_6M), +.I_C_BLn_X(W_C_BLnX), +.I_MLDn(W_MLDn), +.I_SLDn(W_SLDn), +.I_HPOS(W_H_POSI), + +.O_MISSILEn(O_MISSILEn), +.O_SHELLn(O_SHELLn) + +); + +endmodule + + diff --git a/galaxian/src/psPAD_top.v b/galaxian/src/psPAD_top.v new file mode 100644 index 0000000..51e127e --- /dev/null +++ b/galaxian/src/psPAD_top.v @@ -0,0 +1,685 @@ +//------------------------------------------------------------------- +// +// PLAYSTATION CONTROLLER(DUALSHOCK TYPE) INTERFACE TOP +// +// Version : 2.00 +// +// Copyright(c) 2003 - 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +// 2003.10.30 It is optimized for the FPGA game. +// It was made an analog mode fixation.(Dualshock) +// by K Degawa +// +//------------------------------------------------------------------- +//--------- SIMULATION ---------------------------------------------- +//`define SIMULATION_1 + +`ifdef SIMULATION_1 +`define Timer_siz 18 +`else +`define Timer_siz 12 +`endif +//------------------------------------------------------------------- + +`timescale 100ps/10ps +`include "src/mc_conf.v" + +module psPAD_top( + +I_CLK250K, // MAIN CLK 250KHz +I_RSTn, // MAIN RESET +O_psCLK, // psCLK CLK OUT +O_psSEL, // psSEL OUT +O_psTXD, // psTXD OUT +I_psRXD, // psRXD IN +O_RXD_1, // RX DATA 1 (8bit) +O_RXD_2, // RX DATA 2 (8bit) +O_RXD_3, // RX DATA 3 (8bit) +O_RXD_4, // RX DATA 4 (8bit) +O_RXD_5, // RX DATA 5 (8bit) +O_RXD_6, // RX DATA 6 (8bit) +I_CONF_SW, // +I_MODE_SW, // +I_MODE_EN, // +I_VIB_SW, // Vibration SW VIB_SW[0] Small Moter OFF 0:ON 1: + // VIB_SW[1] Bic Moter OFF 0:ON 1(Dualshook Only) +I_VIB_DAT // Vibration(Bic Moter)Data 8'H00-8'HFF (Dualshook Only) + +); + +input I_CLK250K,I_RSTn; +input I_CONF_SW; +input I_MODE_SW,I_MODE_EN; +input [1:0]I_VIB_SW; +input [7:0]I_VIB_DAT; +input I_psRXD; +output O_psCLK; +output O_psSEL; +output O_psTXD; +output [7:0]O_RXD_1; +output [7:0]O_RXD_2; +output [7:0]O_RXD_3; +output [7:0]O_RXD_4; +output [7:0]O_RXD_5; +output [7:0]O_RXD_6; + +wire W_scan_seq_pls; +wire W_type; +wire [3:0]W_byte_cnt; +wire W_RXWT; +wire W_TXWT; +wire W_TXSET; +wire W_TXEN; +wire [7:0]W_TXD_DAT; +wire [7:0]W_RXD_DAT; +wire W_conf_ent; + +ps_pls_gan pls( + +.I_CLK(I_CLK250K), +.I_RSTn(I_RSTn), +.I_TYPE(W_type), // DEGITAL PAD 0: ANALOG PAD 1: + +.O_SCAN_SEQ_PLS(W_scan_seq_pls), +.O_RXWT(W_RXWT), +.O_TXWT(W_TXWT), +.O_TXSET(W_TXSET), +.O_TXEN(W_TXEN), +.O_psCLK(O_psCLK), +.O_psSEL(O_psSEL), +.O_byte_cnt(W_byte_cnt), + +//.Timer(O_Timer) +.Timer() + +); + +`ifdef Dualshock +txd_commnd cmd( + +.I_CLK(W_TXSET), +.I_RSTn(I_RSTn), +.I_BYTE_CNT(W_byte_cnt), +.I_MODE({I_CONF_SW,~I_MODE_EN,I_MODE_SW}), +.I_VIB_SW(I_VIB_SW), +.I_VIB_DAT(I_VIB_DAT), +.I_RXD_DAT(W_RXD_DAT), +.O_TXD_DAT(W_TXD_DAT), +.O_TYPE(W_type), +.O_CONF_ENT(W_conf_ent) + +); + +`else +txd_commnd_EZ cmd( + +.I_CLK(W_TXSET), +.I_RSTn(I_RSTn), +.I_BYTE_CNT(W_byte_cnt), +.I_MODE(), +.I_VIB_SW(I_VIB_SW), +.I_VIB_DAT(), +.I_RXD_DAT(), +.O_TXD_DAT(W_TXD_DAT), +.O_TYPE(W_type), +.O_CONF_ENT(W_conf_ent) + +); + +`endif + +ps_txd txd( + +.I_CLK(I_CLK250K), +.I_RSTn(I_RSTn), +.I_WT(W_TXWT), +.I_EN(W_TXEN), +.I_TXD_DAT(W_TXD_DAT), +.O_psTXD(O_psTXD) + +); + +ps_rxd rxd( + +.I_CLK(O_psCLK), +.I_RSTn(I_RSTn), +.I_WT(W_RXWT), +.I_psRXD(I_psRXD), +.O_RXD_DAT(W_RXD_DAT) + +); + +//---------- RXD DATA DEC ---------------------------------------- +reg [7:0]O_RXD_1; +reg [7:0]O_RXD_2; +reg [7:0]O_RXD_3; +reg [7:0]O_RXD_4; +reg [7:0]O_RXD_5; +reg [7:0]O_RXD_6; + +reg W_rxd_mask; +always@(posedge W_scan_seq_pls) + W_rxd_mask <= ~W_conf_ent; + +always@(negedge W_RXWT) +begin + if(W_rxd_mask)begin + case(W_byte_cnt) + 3: O_RXD_1 <= W_RXD_DAT; + 4: O_RXD_2 <= W_RXD_DAT; + 5: O_RXD_3 <= W_RXD_DAT; + 6: O_RXD_4 <= W_RXD_DAT; + 7: O_RXD_5 <= W_RXD_DAT; + 8: O_RXD_6 <= W_RXD_DAT; + default:; + endcase + end +end + +endmodule + +module txd_commnd_EZ( + +I_CLK, +I_RSTn, +I_BYTE_CNT, +I_MODE, +I_VIB_SW, +I_VIB_DAT, +I_RXD_DAT, +O_TXD_DAT, +O_TYPE, +O_CONF_ENT + +); + +input I_CLK,I_RSTn; +input [3:0]I_BYTE_CNT; +input [2:0]I_MODE; +input [1:0]I_VIB_SW; +input [7:0]I_VIB_DAT; +input [7:0]I_RXD_DAT; +output [7:0]O_TXD_DAT; +output O_TYPE; +output O_CONF_ENT; + +reg [7:0]O_TXD_DAT; + +assign O_TYPE = 1'b1; +assign O_CONF_ENT = 1'b0; +always@(posedge I_CLK or negedge I_RSTn) +begin + if(! I_RSTn)begin + O_TXD_DAT <= 8'h00; + end + else begin + case(I_BYTE_CNT) + 0:O_TXD_DAT <= 8'h01; + 1:O_TXD_DAT <= 8'h42; + 3:begin + if(I_VIB_SW) O_TXD_DAT <= 8'h40; + else O_TXD_DAT <= 8'h00; + end + 4:begin + if(I_VIB_SW) O_TXD_DAT <= 8'h01; + else O_TXD_DAT <= 8'h00; + end + default: O_TXD_DAT <= 8'h00; + endcase + end +end + +endmodule + +module txd_commnd( + + +I_CLK, +I_RSTn, +I_BYTE_CNT, +I_MODE, +I_VIB_SW, +I_VIB_DAT, +I_RXD_DAT, +O_TXD_DAT, +O_TYPE, +O_CONF_ENT + +); + +input I_CLK,I_RSTn; +input [3:0]I_BYTE_CNT; +input [2:0]I_MODE; +input [1:0]I_VIB_SW; +input [7:0]I_VIB_DAT; +input [7:0]I_RXD_DAT; +output [7:0]O_TXD_DAT; +output O_TYPE; +output O_CONF_ENT; + +reg [7:0]O_TXD_DAT; +reg [2:0]conf_state; +reg conf_entry; +reg conf_done; +reg pad_status; +reg pad_id; + +assign O_TYPE = pad_id; +assign O_CONF_ENT = conf_entry; + +always@(posedge I_CLK or negedge I_RSTn) +begin + if(! I_RSTn) pad_id <= 1'b0; + else begin + if(I_BYTE_CNT==2)begin + case(I_RXD_DAT) //------ GET TYPE(Byte_SEQ) + 8'h23: pad_id <= 1'b1; + 8'h41: pad_id <= 1'b0; + 8'h53: pad_id <= 1'b1; + 8'h73: pad_id <= 1'b1; + 8'hE3: pad_id <= 1'b1; + 8'hF3: pad_id <= 1'b1; + default: pad_id <= 1'b0; + endcase + end + end +end + +always@(posedge I_CLK or negedge I_RSTn) +begin + if(! I_RSTn)begin + O_TXD_DAT <= 8'h00; + conf_entry <= 1'b0; + conf_done <= 1'b1; + conf_state <= 0; + pad_status <= 0; + end + else begin +//---------- nomal mode -------------------------------------------------------- +//----------------- read_data_and_vibrate_ex 01,42,00,WW,PP(,00,00,00,00) +// --,ID,SS,XX,XX(,XX,XX,XX,XX) + if(~conf_entry)begin + case(I_BYTE_CNT) + 0:O_TXD_DAT <= 8'h01; + 1:O_TXD_DAT <= 8'h42; + 3:begin + if(pad_status)begin + if(I_VIB_SW[0]) O_TXD_DAT <= 8'h01; + else O_TXD_DAT <= 8'h00; + end + else begin + if(I_VIB_SW[0]|I_VIB_SW[1]) O_TXD_DAT <= 8'h40; + else O_TXD_DAT <= 8'h00; + end + end + 4:begin + if(pad_status)begin + if(I_VIB_SW[1]) O_TXD_DAT <= I_VIB_DAT; + else O_TXD_DAT <= 8'h00; + end + else begin + if(I_VIB_SW[0]|I_VIB_SW[1]) O_TXD_DAT <= 8'h01; + else O_TXD_DAT <= 8'h00; + end + if(pad_id==0)begin + if(conf_state == 0) + conf_entry <= 1'b1; + end + end + 8:begin + O_TXD_DAT <= 8'h00; + if(pad_id==1)begin + if(conf_state == 0) + conf_entry <= 1'b1; + end + end + default: O_TXD_DAT <= 8'h00; + endcase + end +//---------- confg mode -------------------------------------------------------- + else begin + case(conf_state) + //-------- config_mode_enter (43): 01,43,00,01,00(,00 x 4 or XX x 16) + // --,ID,SS,XX,XX(,XX x 4 or XX x 16) + 0:begin + case(I_BYTE_CNT) + 0:begin + O_TXD_DAT <= 8'h01; + conf_done <= 1'b0; + end + 1:O_TXD_DAT <= 8'h43; + 3:O_TXD_DAT <= 8'h01; + 4:begin + O_TXD_DAT <= 8'h00; + if(pad_id==0)begin + conf_state <= 1; + end + end + 8:begin + O_TXD_DAT <= 8'h00; + if(pad_id==1)begin + conf_state <= 1; + end + end + default:O_TXD_DAT <= 8'h00; + endcase + end + //-------- set_mode_and_lock (44): 01,44,00,XX,YY,00,00,00,00 + // + 1:begin + case(I_BYTE_CNT) + 0:O_TXD_DAT <= 8'h01; + 1:O_TXD_DAT <= 8'h44; + 2:begin + O_TXD_DAT <= 8'h00; + if(I_RXD_DAT == 8'hF3)begin + conf_done <= 1'b0; + pad_status <= 1'b1; + end + else begin + conf_done <= 1'b1; + pad_status <= 1'b0; + end + end + 3:O_TXD_DAT <= 8'h01; + 4:begin + O_TXD_DAT <= 8'h03; + if(pad_id==0 && conf_done==1'b1)begin + conf_state <= 7; + conf_entry <= 1'b0; + end + end + 8:begin + O_TXD_DAT <= 8'h00; + conf_state <= 3; + if(pad_id==1 && conf_done==1'b1)begin + conf_state <= 7; + conf_entry <= 1'b0; + end + end + default:O_TXD_DAT <= 8'h00; + endcase + end + //-------- query_model_and_mode (45): 01,45,00,5A,5A,5A,5A,5A,5A + // FF,F3,5A,TT,02,MM,VV,01,00 +/* + 1:begin + case(I_BYTE_CNT) + 0:O_TXD_DAT <= 8'h01; + 1:O_TXD_DAT <= 8'h45; + 2:begin + O_TXD_DAT <= 8'h00; + conf_done <= (I_RXD_DAT == 8'hF3)? 1'b0:1'b1; + end + 4:begin + O_TXD_DAT <= 8'h00; + if(I_RXD_DAT==8'h01 || I_RXD_DAT==8'h03) pad_status <= 1; + if(pad_id==0 && conf_done==1'b1)begin + conf_state <= 7; + conf_entry <= 1'b0; + end + end + 8:begin + O_TXD_DAT <= 8'h00; + conf_state <= 2; + if(pad_id==1 && conf_done==1'b1)begin + conf_state <= 7; + conf_entry <= 1'b0; + end + end + default:O_TXD_DAT <= 8'h00; + endcase + end + //-------- set_mode_and_lock (44): 01,44,00,XX,YY,00,00,00,00 + // --,F3,5A,00,00,00,00,00,00 + 2:begin + case(I_BYTE_CNT) + 0:O_TXD_DAT <= 8'h01; + 1:O_TXD_DAT <= 8'h44; + 3:O_TXD_DAT <= 8'h01; + 4:O_TXD_DAT <= 8'h03; + 8:begin + O_TXD_DAT <= 8'h00; + conf_state<= 3; + end + default:O_TXD_DAT <= 8'h00; + endcase + end +*/ + //-------- vibration_enable (4D): 01,4D,00,00,01,FF,FF,FF,FF + // --,F3,5A,XX,YY,FF,FF,FF,FF + 3:begin + case(I_BYTE_CNT) + 0:O_TXD_DAT <= 8'h01; + 1:O_TXD_DAT <= 8'h4D; + 2,3:O_TXD_DAT <= 8'h00; + 4:O_TXD_DAT <= 8'h01; + 8:begin + O_TXD_DAT <= 8'hFF; + conf_state<= 6; + end + default:O_TXD_DAT <= 8'hFF; + endcase + end + //-------- config_mode_exit (43): 01,43,00,00,00,00,00,00,00 + // --,F3,5A,00,00,00,00,00,00 + 6:begin + case(I_BYTE_CNT) + 0:O_TXD_DAT <= 8'h01; + 1:O_TXD_DAT <= 8'h43; + 2,3:O_TXD_DAT <= 8'h00; + 8:begin + O_TXD_DAT <= 8'h00; + conf_state<= 7; + conf_entry<= 1'b0; + conf_done <= 1'b1; + end + default:O_TXD_DAT <= 8'h00; + endcase + end + default:; + endcase + end + end +end + +endmodule + +module ps_pls_gan( + +I_CLK, +I_RSTn, +I_TYPE, + +O_SCAN_SEQ_PLS, +O_RXWT, +O_TXWT, +O_TXSET, +O_TXEN, +O_psCLK, +O_psSEL, +O_byte_cnt, + +Timer + +); + +parameter Timer_size = `Timer_siz; + +input I_CLK,I_RSTn; +input I_TYPE; +output O_SCAN_SEQ_PLS; +output O_RXWT; +output O_TXWT; +output O_TXSET; +output O_TXEN; +output O_psCLK; +output O_psSEL; +output [3:0]O_byte_cnt; + +output [Timer_size-1:0]Timer; +reg [Timer_size-1:0]Timer; + +reg O_SCAN_SEQ_PLS; +reg RXWT; +reg TXWT; +reg TXSET; +reg psCLK_gate; +reg psSEL; +reg [3:0]O_byte_cnt; + +always@(posedge I_CLK or negedge I_RSTn) +begin + if(! I_RSTn) Timer <= 0; + else Timer <= Timer+1; +end + +always@(posedge I_CLK or negedge I_RSTn) +begin + if(! I_RSTn) + O_SCAN_SEQ_PLS <= 0; + else begin + if(Timer == 0) O_SCAN_SEQ_PLS <= 1; + else O_SCAN_SEQ_PLS <= 0; + end +end + +always@(posedge I_CLK or negedge I_RSTn) +begin + if(! I_RSTn) + begin + psCLK_gate <= 1; + RXWT <= 0; + TXWT <= 0; + TXSET <= 0; + end + else begin + case(Timer[4:0]) + 6: TXSET <= 1; + 8: TXSET <= 0; + 9: TXWT <= 1; + 11: TXWT <= 0; + 12: psCLK_gate <= 0; + 20: psCLK_gate <= 1; + 21: RXWT <= 1; + 23: RXWT <= 0; + default:; + endcase + end +end + +always@(posedge I_CLK or negedge I_RSTn) +begin + if(! I_RSTn) + psSEL <= 1; + else begin + if(O_SCAN_SEQ_PLS == 1) + psSEL <= 0; + else if((I_TYPE == 0)&&(Timer == 158)) + psSEL <= 1; + else if((I_TYPE == 1)&&(Timer == 286)) + psSEL <= 1; + end +end + +always@(posedge I_CLK or negedge I_RSTn) +begin + if(! I_RSTn) + O_byte_cnt <= 0; + else begin + if( O_SCAN_SEQ_PLS == 1) + O_byte_cnt <= 0; + else begin + if( Timer[4:0] == 5'b11111)begin + if(I_TYPE == 0 && O_byte_cnt == 5) + O_byte_cnt <= O_byte_cnt; + else if(I_TYPE == 1 && O_byte_cnt == 9) + O_byte_cnt <= O_byte_cnt; + else + O_byte_cnt <= O_byte_cnt+1; + end + end + end +end + +assign O_psCLK = psCLK_gate | I_CLK | psSEL; +assign O_psSEL = psSEL; +assign O_RXWT = ~psSEL&RXWT; +assign O_TXSET = ~psSEL&TXSET; +assign O_TXWT = ~psSEL&TXWT; +assign O_TXEN = ~psSEL&(~psCLK_gate); + +endmodule + +module ps_rxd( + +I_CLK, +I_RSTn, +I_WT, +I_psRXD, +O_RXD_DAT + +); + +input I_CLK,I_RSTn,I_WT; +input I_psRXD; +output [7:0]O_RXD_DAT; +reg [7:0]O_RXD_DAT; +reg [7:0]sp; + +always@(posedge I_CLK or negedge I_RSTn) + if(! I_RSTn) sp <= 1; + else sp <= { I_psRXD, sp[7:1]}; +always@(posedge I_WT or negedge I_RSTn) + if(! I_RSTn) O_RXD_DAT <= 1; + else O_RXD_DAT <= sp; + +endmodule + +module ps_txd( + +I_CLK, +I_RSTn, +I_WT, +I_EN, +I_TXD_DAT, +O_psTXD + +); + +input I_CLK,I_RSTn; +input I_WT,I_EN; +input [7:0]I_TXD_DAT; +output O_psTXD; +reg O_psTXD; +reg [7:0]ps; + +always@(negedge I_CLK or negedge I_RSTn) +begin + if(! I_RSTn)begin + O_psTXD <= 1; + ps <= 0; + end + else begin + if(I_WT) + ps <= I_TXD_DAT; + else begin + if(I_EN)begin + O_psTXD <= ps[0]; + ps <= {1'b1, ps[7:1]}; + end + else begin + O_psTXD <= 1'd1; + ps <= ps; + end + end + end +end + +endmodule \ No newline at end of file diff --git a/galaxian/src/roms.v b/galaxian/src/roms.v new file mode 100644 index 0000000..403302d --- /dev/null +++ b/galaxian/src/roms.v @@ -0,0 +1,140 @@ +module galaxian_roms( +I_CLK_18432M, +I_CLK_12M, +I_ADDR, +O_DATA +); + +input I_CLK_12M; +input I_CLK_18432M; +input [18:0]I_ADDR; +output [7:0]O_DATA; + +//CPU-Roms +wire [7:0]U_ROM_D; +reg [10:0]U_ROM_A; + +GALAXIAN_U U_ROM( +.CLK(I_CLK_12M), +.ADDR(U_ROM_A), +.DATA(U_ROM_D), +.ENA(1'b1) +); + +wire [7:0]V_ROM_D; +reg [10:0]V_ROM_A; + +GALAXIAN_V V_ROM( +.CLK(I_CLK_12M), +.ADDR(V_ROM_A), +.DATA(V_ROM_D), +.ENA(1'b1) +); + +wire [7:0]W_ROM_D; +reg [10:0]W_ROM_A; + +GALAXIAN_W W_ROM( +.CLK(I_CLK_12M), +.ADDR(W_ROM_A), +.DATA(W_ROM_D), +.ENA(1'b1) +); + +wire [7:0]Y_ROM_D; +reg [10:0]Y_ROM_A; + +GALAXIAN_Y Y_ROM( +.CLK(YB_CLK_12M), +.ADDR(Y_ROM_A), +.DATA(Y_ROM_D), +.ENA(1'b1) +); + +//7L CPU-Rom +wire [7:0]L_ROM_D; +reg [10:0]L_ROM_A; + +GALAXIAN_7L L_ROM( +.CLK(LB_CLK_12M), +.ADDR(L_ROM_A), +.DATA(L_ROM_D), +.ENA(1'b1) +); + +//1K VID-Rom +wire [7:0]K_ROM_D; +reg [10:0]K_ROM_A; + +GALAXIAN_1K K_ROM( +.CLK(KB_CLK_12M), +.ADDR(K_ROM_A), +.DATA(K_ROM_D), +.ENA(1'b1) +); + +//1H VID-Rom +wire [7:0]H_ROM_D; +reg [10:0]H_ROM_A; + +GALAXIAN_1H H_ROM( +.CLK(HB_CLK_12M), +.ADDR(H_ROM_A), +.DATA(H_ROM_D), +.ENA(1'b1) +); + +reg [7:0]DATA_OUT; + +// address map +//-------------------------------------------------- +// 0x00000 - 0x007FF galmidw.u CPU-ROM +// 0x00800 - 0x00FFF galmidw.v CPU-ROM +// 0x01000 - 0x017FF galmidw.w CPU-ROM +// 0x01800 - 0x01FFF galmidw.y CPU-ROM +// 0x02000 - 0x027FF 7l CPU-ROM +// 0x04000 - 0x047FF 1k.bin VID-ROM +// 0x05000 - 0x057FF 1h.bin VID-ROM +// 0x10000 - 0x3FFFF mc_wav_2.bin Sound(Wav)Data +always @(posedge I_CLK_18432M) +begin + if (I_ADDR <= 18'h7ff) begin + //u + U_ROM_A <= I_ADDR[10:0]; + DATA_OUT <= U_ROM_D; + end + else if (I_ADDR >= 18'h800 && I_ADDR <= 18'hfff) begin + //v + V_ROM_A <= I_ADDR[10:0]; + DATA_OUT <= V_ROM_D; + end + else if (I_ADDR >= 18'h1000 && I_ADDR <= 18'h17ff) begin + //w + W_ROM_A <= I_ADDR[10:0]; + DATA_OUT <= W_ROM_D; + end + else if (I_ADDR >= 18'h1800 && I_ADDR <= 18'h1fff) begin + //y + Y_ROM_A <= I_ADDR[10:0]; + DATA_OUT <= Y_ROM_D; + end + else if (I_ADDR >= 18'h2000 && I_ADDR <= 18'h27ff) begin + //7l + L_ROM_A <= I_ADDR[10:0]; + DATA_OUT <= L_ROM_D; + end + else if (I_ADDR >= 18'h4000 && I_ADDR <= 18'h47ff) begin + //1k + K_ROM_A <= I_ADDR[10:0]; + DATA_OUT <= K_ROM_D; + end + else if (I_ADDR >= 18'h5000 && I_ADDR <= 18'h57ff) begin + //1h + H_ROM_A <= I_ADDR[10:0]; + DATA_OUT <= H_ROM_D; + end +end + +assign O_DATA = DATA_OUT; + +endmodule diff --git a/galaxian/src/t80as.v b/galaxian/src/t80as.v new file mode 100644 index 0000000..e2882e7 --- /dev/null +++ b/galaxian/src/t80as.v @@ -0,0 +1,25 @@ +// +// Daniel Wallner's T80 header file for verilog +// +// Copyright(c) 2002,2003 Tatsuyuki Satoh , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +// +module T80as( + RESET_n,CLK_n,WAIT_n,INT_n,NMI_n,BUSRQ_n, + M1_n,MREQ_n,IORQ_n,RD_n,WR_n,RFSH_n,HALT_n,BUSAK_n, + A,DI,DO,DOE); + +input RESET_n,CLK_n,WAIT_n,INT_n,NMI_n,BUSRQ_n; +output M1_n,MREQ_n,IORQ_n,RD_n,WR_n,RFSH_n,HALT_n,BUSAK_n; +output [15:0] A; +input [7:0] DI; +output [7:0] DO; +output DOE; + +endmodule diff --git a/galaxian/src/z80ip.v b/galaxian/src/z80ip.v new file mode 100644 index 0000000..a860dd8 --- /dev/null +++ b/galaxian/src/z80ip.v @@ -0,0 +1,69 @@ +//=============================================================================== +// FPGA MOONCRESTA T80_IP I/F +// +// Version : 1.00 +// +// Copyright(c) 2004 Katsumi Degawa , All rights reserved +// +// Important ! +// +// This program is freeware for non-commercial use. +// An author does no guarantee about this program. +// You can use this under your own risk. +// +//================================================================================ + +module Z80IP( + +ADRS, +DINP, +DOUT, +BUSWO, +RESET_N, +INT_N, +NMI_N, +WAIT_N, +M1_N, +MREQ_N, +IORQ_N, +RD_N, +WR_N, +RFSH_N, +HALT_N, +CLK + +); + +// I/O assign +output [15:0]ADRS; +input [7:0] DINP; +output [7:0] DOUT; +input RESET_N,INT_N,NMI_N,WAIT_N,CLK; +output M1_N,MREQ_N,IORQ_N,RD_N,WR_N,RFSH_N,HALT_N,BUSWO; + +// Z80IP interface +T80as z80core ( + +.RESET_n(RESET_N), +.CLK_n(CLK), +.WAIT_n(WAIT_N), +.INT_n(INT_N), +.NMI_n(NMI_N), +.BUSRQ_n(1'b1), +.M1_n(M1_N), +.MREQ_n(MREQ_N), +.IORQ_n(IORQ_N), +.RD_n(RD_N), +.WR_n(WR_N), +.RFSH_n(RFSH_N), +.HALT_n(HALT_N), +.BUSAK_n(), +.A(ADRS), +.DI(DINP), +.DO(DOUT), +.DOE(BUSWO) + +); + +endmodule + diff --git a/galaxian/t80_ip/T80.vhd b/galaxian/t80_ip/T80.vhd new file mode 100644 index 0000000..398fa0d --- /dev/null +++ b/galaxian/t80_ip/T80.vhd @@ -0,0 +1,1073 @@ +-- +-- Z80 compatible microprocessor core +-- +-- Version : 0247 +-- +-- Copyright (c) 2001-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/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0208 : First complete release +-- +-- 0210 : Fixed wait and halt +-- +-- 0211 : Fixed Refresh addition and IM 1 +-- +-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test +-- +-- 0232 : Removed refresh address output for Mode > 1 and added DJNZ M1_n fix by Mike Johnson +-- +-- 0235 : Added clock enable and IM 2 fix by Mike Johnson +-- +-- 0237 : Changed 8080 I/O address output, added IntE output +-- +-- 0238 : Fixed (IX/IY+d) timing and 16 bit ADC and SBC zero flag +-- +-- 0240 : Added interrupt ack fix by Mike Johnson, changed (IX/IY+d) timing and changed flags in GB mode +-- +-- 0242 : Added I/O wait, fixed refresh address, moved some registers to RAM +-- +-- 0247 : Fixed bus req/ack cycle +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T80_Pack.all; + +entity T80 is + generic( + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + IOWait : integer := 0; -- 1 => Single cycle I/O, 1 => Std I/O cycle + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + CEN : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + IORQ : out std_logic; + NoRead : out std_logic; + Write : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + DInst : in std_logic_vector(7 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0); + MC : out std_logic_vector(2 downto 0); + TS : out std_logic_vector(2 downto 0); + IntCycle_n : out std_logic; + IntE : out std_logic; + Stop : out std_logic + ); +end T80; + +architecture rtl of T80 is + + constant aNone : std_logic_vector(2 downto 0) := "111"; + constant aBC : std_logic_vector(2 downto 0) := "000"; + constant aDE : std_logic_vector(2 downto 0) := "001"; + constant aXY : std_logic_vector(2 downto 0) := "010"; + constant aIOA : std_logic_vector(2 downto 0) := "100"; + constant aSP : std_logic_vector(2 downto 0) := "101"; + constant aZI : std_logic_vector(2 downto 0) := "110"; + + -- Registers + signal ACC, F : std_logic_vector(7 downto 0); + signal Ap, Fp : std_logic_vector(7 downto 0); + signal I : std_logic_vector(7 downto 0); + signal R : unsigned(7 downto 0); + signal SP, PC : unsigned(15 downto 0); + signal RegDIH : std_logic_vector(7 downto 0); + signal RegDIL : std_logic_vector(7 downto 0); + signal RegBusA : std_logic_vector(15 downto 0); + signal RegBusB : std_logic_vector(15 downto 0); + signal RegBusC : std_logic_vector(15 downto 0); + signal RegAddrA_r : std_logic_vector(2 downto 0); + signal RegAddrA : std_logic_vector(2 downto 0); + signal RegAddrB_r : std_logic_vector(2 downto 0); + signal RegAddrB : std_logic_vector(2 downto 0); + signal RegAddrC : std_logic_vector(2 downto 0); + signal RegWEH : std_logic; + signal RegWEL : std_logic; + signal Alternate : std_logic; + + -- Help Registers + signal TmpAddr : std_logic_vector(15 downto 0); -- Temporary address register + signal IR : std_logic_vector(7 downto 0); -- Instruction register + signal ISet : std_logic_vector(1 downto 0); -- Instruction set selector + signal RegBusA_r : std_logic_vector(15 downto 0); + + signal ID16 : signed(15 downto 0); + signal Save_Mux : std_logic_vector(7 downto 0); + + signal TState : unsigned(2 downto 0); + signal MCycle : std_logic_vector(2 downto 0); + signal IntE_FF1 : std_logic; + signal IntE_FF2 : std_logic; + signal Halt_FF : std_logic; + signal BusReq_s : std_logic; + signal BusAck : std_logic; + signal ClkEn : std_logic; + signal NMI_s : std_logic; + signal INT_s : std_logic; + signal IStatus : std_logic_vector(1 downto 0); + + signal DI_Reg : std_logic_vector(7 downto 0); + signal T_Res : std_logic; + signal XY_State : std_logic_vector(1 downto 0); + signal Pre_XY_F_M : std_logic_vector(2 downto 0); + signal NextIs_XY_Fetch : std_logic; + signal XY_Ind : std_logic; + signal No_BTR : std_logic; + signal BTR_r : std_logic; + signal Auto_Wait : std_logic; + signal Auto_Wait_t1 : std_logic; + signal Auto_Wait_t2 : std_logic; + signal IncDecZ : std_logic; + + -- ALU signals + signal BusB : std_logic_vector(7 downto 0); + signal BusA : std_logic_vector(7 downto 0); + signal ALU_Q : std_logic_vector(7 downto 0); + signal F_Out : std_logic_vector(7 downto 0); + + -- Registered micro code outputs + signal Read_To_Reg_r : std_logic_vector(4 downto 0); + signal Arith16_r : std_logic; + signal Z16_r : std_logic; + signal ALU_Op_r : std_logic_vector(3 downto 0); + signal Save_ALU_r : std_logic; + signal PreserveC_r : std_logic; + signal MCycles : std_logic_vector(2 downto 0); + + -- Micro code outputs + signal MCycles_d : std_logic_vector(2 downto 0); + signal TStates : std_logic_vector(2 downto 0); + signal IntCycle : std_logic; + signal NMICycle : std_logic; + signal Inc_PC : std_logic; + signal Inc_WZ : std_logic; + signal IncDec_16 : std_logic_vector(3 downto 0); + signal Prefix : std_logic_vector(1 downto 0); + signal Read_To_Acc : std_logic; + signal Read_To_Reg : std_logic; + signal Set_BusB_To : std_logic_vector(3 downto 0); + signal Set_BusA_To : std_logic_vector(3 downto 0); + signal ALU_Op : std_logic_vector(3 downto 0); + signal Save_ALU : std_logic; + signal PreserveC : std_logic; + signal Arith16 : std_logic; + signal Set_Addr_To : std_logic_vector(2 downto 0); + signal Jump : std_logic; + signal JumpE : std_logic; + signal JumpXY : std_logic; + signal Call : std_logic; + signal RstP : std_logic; + signal LDZ : std_logic; + signal LDW : std_logic; + signal LDSPHL : std_logic; + signal IORQ_i : std_logic; + signal Special_LD : std_logic_vector(2 downto 0); + signal ExchangeDH : std_logic; + signal ExchangeRp : std_logic; + signal ExchangeAF : std_logic; + signal ExchangeRS : std_logic; + signal I_DJNZ : std_logic; + signal I_CPL : std_logic; + signal I_CCF : std_logic; + signal I_SCF : std_logic; + signal I_RETN : std_logic; + signal I_BT : std_logic; + signal I_BC : std_logic; + signal I_BTR : std_logic; + signal I_RLD : std_logic; + signal I_RRD : std_logic; + signal I_INRC : std_logic; + signal SetDI : std_logic; + signal SetEI : std_logic; + signal IMode : std_logic_vector(1 downto 0); + signal Halt : std_logic; + +begin + + mcode : T80_MCode + generic map( + Mode => Mode, + Flag_C => Flag_C, + Flag_N => Flag_N, + Flag_P => Flag_P, + Flag_X => Flag_X, + Flag_H => Flag_H, + Flag_Y => Flag_Y, + Flag_Z => Flag_Z, + Flag_S => Flag_S) + port map( + IR => IR, + ISet => ISet, + MCycle => MCycle, + F => F, + NMICycle => NMICycle, + IntCycle => IntCycle, + MCycles => MCycles_d, + TStates => TStates, + Prefix => Prefix, + Inc_PC => Inc_PC, + Inc_WZ => Inc_WZ, + IncDec_16 => IncDec_16, + Read_To_Acc => Read_To_Acc, + Read_To_Reg => Read_To_Reg, + Set_BusB_To => Set_BusB_To, + Set_BusA_To => Set_BusA_To, + ALU_Op => ALU_Op, + Save_ALU => Save_ALU, + PreserveC => PreserveC, + Arith16 => Arith16, + Set_Addr_To => Set_Addr_To, + IORQ => IORQ_i, + Jump => Jump, + JumpE => JumpE, + JumpXY => JumpXY, + Call => Call, + RstP => RstP, + LDZ => LDZ, + LDW => LDW, + LDSPHL => LDSPHL, + Special_LD => Special_LD, + ExchangeDH => ExchangeDH, + ExchangeRp => ExchangeRp, + ExchangeAF => ExchangeAF, + ExchangeRS => ExchangeRS, + I_DJNZ => I_DJNZ, + I_CPL => I_CPL, + I_CCF => I_CCF, + I_SCF => I_SCF, + I_RETN => I_RETN, + I_BT => I_BT, + I_BC => I_BC, + I_BTR => I_BTR, + I_RLD => I_RLD, + I_RRD => I_RRD, + I_INRC => I_INRC, + SetDI => SetDI, + SetEI => SetEI, + IMode => IMode, + Halt => Halt, + NoRead => NoRead, + Write => Write); + + alu : T80_ALU + generic map( + Mode => Mode, + Flag_C => Flag_C, + Flag_N => Flag_N, + Flag_P => Flag_P, + Flag_X => Flag_X, + Flag_H => Flag_H, + Flag_Y => Flag_Y, + Flag_Z => Flag_Z, + Flag_S => Flag_S) + port map( + Arith16 => Arith16_r, + Z16 => Z16_r, + ALU_Op => ALU_Op_r, + IR => IR(5 downto 0), + ISet => ISet, + BusA => BusA, + BusB => BusB, + F_In => F, + Q => ALU_Q, + F_Out => F_Out); + + ClkEn <= CEN and not BusAck; + + T_Res <= '1' when TState = unsigned(TStates) else '0'; + + NextIs_XY_Fetch <= '1' when XY_State /= "00" and XY_Ind = '0' and + ((Set_Addr_To = aXY) or + (MCycle = "001" and IR = "11001011") or + (MCycle = "001" and IR = "00110110")) else '0'; + + Save_Mux <= BusB when ExchangeRp = '1' else + DI_Reg when Save_ALU_r = '0' else + ALU_Q; + + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + PC <= (others => '0'); -- Program Counter + A <= (others => '0'); + TmpAddr <= (others => '0'); + IR <= "00000000"; + ISet <= "00"; + XY_State <= "00"; + IStatus <= "00"; + MCycles <= "000"; + DO <= "00000000"; + + ACC <= (others => '1'); + F <= (others => '1'); + Ap <= (others => '1'); + Fp <= (others => '1'); + I <= (others => '0'); + R <= (others => '0'); + SP <= (others => '1'); + Alternate <= '0'; + + Read_To_Reg_r <= "00000"; + F <= (others => '1'); + Arith16_r <= '0'; + BTR_r <= '0'; + Z16_r <= '0'; + ALU_Op_r <= "0000"; + Save_ALU_r <= '0'; + PreserveC_r <= '0'; + XY_Ind <= '0'; + + elsif CLK_n'event and CLK_n = '1' then + + if ClkEn = '1' then + + ALU_Op_r <= "0000"; + Save_ALU_r <= '0'; + Read_To_Reg_r <= "00000"; + + MCycles <= MCycles_d; + + if IMode /= "11" then + IStatus <= IMode; + end if; + + Arith16_r <= Arith16; + PreserveC_r <= PreserveC; + if ISet = "10" and ALU_OP(2) = '0' and ALU_OP(0) = '1' and MCycle = "011" then + Z16_r <= '1'; + else + Z16_r <= '0'; + end if; + + if MCycle = "001" and TState(2) = '0' then + -- MCycle = 1 and TState = 1, 2, or 3 + + if TState = 2 and Wait_n = '1' then + if Mode < 2 then + A(7 downto 0) <= std_logic_vector(R); + A(15 downto 8) <= I; + R(6 downto 0) <= R(6 downto 0) + 1; + end if; + + if Jump = '0' and Call = '0' and NMICycle = '0' and IntCycle = '0' and not (Halt_FF = '1' or Halt = '1') then + PC <= PC + 1; + end if; + + if IntCycle = '1' and IStatus = "01" then + IR <= "11111111"; + elsif Halt_FF = '1' or (IntCycle = '1' and IStatus = "10") or NMICycle = '1' then + IR <= "00000000"; + else + IR <= DInst; + end if; + + ISet <= "00"; + if Prefix /= "00" then + if Prefix = "11" then + if IR(5) = '1' then + XY_State <= "10"; + else + XY_State <= "01"; + end if; + else + if Prefix = "10" then + XY_State <= "00"; + XY_Ind <= '0'; + end if; + ISet <= Prefix; + end if; + else + XY_State <= "00"; + XY_Ind <= '0'; + end if; + end if; + + else + -- either (MCycle > 1) OR (MCycle = 1 AND TState > 3) + + if MCycle = "110" then + XY_Ind <= '1'; + if Prefix = "01" then + ISet <= "01"; + end if; + end if; + + if T_Res = '1' then + BTR_r <= (I_BT or I_BC or I_BTR) and not No_BTR; + if Jump = '1' then + A(15 downto 8) <= DI_Reg; + A(7 downto 0) <= TmpAddr(7 downto 0); + PC(15 downto 8) <= unsigned(DI_Reg); + PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0)); + elsif JumpXY = '1' then + A <= RegBusC; + PC <= unsigned(RegBusC); + elsif Call = '1' or RstP = '1' then + A <= TmpAddr; + PC <= unsigned(TmpAddr); + elsif MCycle = MCycles and NMICycle = '1' then + A <= "0000000001100110"; + PC <= "0000000001100110"; + elsif MCycle = "011" and IntCycle = '1' and IStatus = "10" then + A(15 downto 8) <= I; + A(7 downto 0) <= TmpAddr(7 downto 0); + PC(15 downto 8) <= unsigned(I); + PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0)); + else + case Set_Addr_To is + when aXY => + if XY_State = "00" then + A <= RegBusC; + else + if NextIs_XY_Fetch = '1' then + A <= std_logic_vector(PC); + else + A <= TmpAddr; + end if; + end if; + when aIOA => + if Mode = 3 then + -- Memory map I/O on GBZ80 + A(15 downto 8) <= (others => '1'); + elsif Mode = 2 then + -- Duplicate I/O address on 8080 + A(15 downto 8) <= DI_Reg; + else + A(15 downto 8) <= ACC; + end if; + A(7 downto 0) <= DI_Reg; + when aSP => + A <= std_logic_vector(SP); + when aBC => + if Mode = 3 and IORQ_i = '1' then + -- Memory map I/O on GBZ80 + A(15 downto 8) <= (others => '1'); + A(7 downto 0) <= RegBusC(7 downto 0); + else + A <= RegBusC; + end if; + when aDE => + A <= RegBusC; + when aZI => + if Inc_WZ = '1' then + A <= std_logic_vector(unsigned(TmpAddr) + 1); + else + A(15 downto 8) <= DI_Reg; + A(7 downto 0) <= TmpAddr(7 downto 0); + end if; + when others => + A <= std_logic_vector(PC); + end case; + end if; + + Save_ALU_r <= Save_ALU; + ALU_Op_r <= ALU_Op; + + if I_CPL = '1' then + -- CPL + ACC <= not ACC; + F(Flag_Y) <= not ACC(5); + F(Flag_H) <= '1'; + F(Flag_X) <= not ACC(3); + F(Flag_N) <= '1'; + end if; + if I_CCF = '1' then + -- CCF + F(Flag_C) <= not F(Flag_C); + F(Flag_Y) <= ACC(5); + F(Flag_H) <= F(Flag_C); + F(Flag_X) <= ACC(3); + F(Flag_N) <= '0'; + end if; + if I_SCF = '1' then + -- SCF + F(Flag_C) <= '1'; + F(Flag_Y) <= ACC(5); + F(Flag_H) <= '0'; + F(Flag_X) <= ACC(3); + F(Flag_N) <= '0'; + end if; + end if; + + if TState = 2 and Wait_n = '1' then + if ISet = "01" and MCycle = "111" then + IR <= DInst; + end if; + if JumpE = '1' then + PC <= unsigned(signed(PC) + signed(DI_Reg)); + elsif Inc_PC = '1' then + PC <= PC + 1; + end if; + if BTR_r = '1' then + PC <= PC - 2; + end if; + if RstP = '1' then + TmpAddr <= (others =>'0'); + TmpAddr(5 downto 3) <= IR(5 downto 3); + end if; + end if; + if TState = 3 and MCycle = "110" then + TmpAddr <= std_logic_vector(signed(RegBusC) + signed(DI_Reg)); + end if; + + if (TState = 2 and Wait_n = '1') or (TState = 4 and MCycle = "001") then + if IncDec_16(2 downto 0) = "111" then + if IncDec_16(3) = '1' then + SP <= SP - 1; + else + SP <= SP + 1; + end if; + end if; + end if; + + if LDSPHL = '1' then + SP <= unsigned(RegBusC); + end if; + if ExchangeAF = '1' then + Ap <= ACC; + ACC <= Ap; + Fp <= F; + F <= Fp; + end if; + if ExchangeRS = '1' then + Alternate <= not Alternate; + end if; + end if; + + if TState = 3 then + if LDZ = '1' then + TmpAddr(7 downto 0) <= DI_Reg; + end if; + if LDW = '1' then + TmpAddr(15 downto 8) <= DI_Reg; + end if; + + if Special_LD(2) = '1' then + case Special_LD(1 downto 0) is + when "00" => + ACC <= I; + F(Flag_P) <= IntE_FF2; + when "01" => + ACC <= std_logic_vector(R); + F(Flag_P) <= IntE_FF2; + when "10" => + I <= ACC; + when others => + R <= unsigned(ACC); + end case; + end if; + end if; + + if (I_DJNZ = '0' and Save_ALU_r = '1') or ALU_Op_r = "1001" then + if Mode = 3 then + F(6) <= F_Out(6); + F(5) <= F_Out(5); + F(7) <= F_Out(7); + if PreserveC_r = '0' then + F(4) <= F_Out(4); + end if; + else + F(7 downto 1) <= F_Out(7 downto 1); + if PreserveC_r = '0' then + F(Flag_C) <= F_Out(0); + end if; + end if; + end if; + if T_Res = '1' and I_INRC = '1' then + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; + if DI_Reg(7 downto 0) = "00000000" then + F(Flag_Z) <= '1'; + else + F(Flag_Z) <= '0'; + end if; + F(Flag_S) <= DI_Reg(7); + F(Flag_P) <= not (DI_Reg(0) xor DI_Reg(1) xor DI_Reg(2) xor DI_Reg(3) xor + DI_Reg(4) xor DI_Reg(5) xor DI_Reg(6) xor DI_Reg(7)); + end if; + + if TState = 1 and Auto_Wait_t1 = '0' then + DO <= BusB; + if I_RLD = '1' then + DO(3 downto 0) <= BusA(3 downto 0); + DO(7 downto 4) <= BusB(3 downto 0); + end if; + if I_RRD = '1' then + DO(3 downto 0) <= BusB(7 downto 4); + DO(7 downto 4) <= BusA(3 downto 0); + end if; + end if; + + if T_Res = '1' then + Read_To_Reg_r(3 downto 0) <= Set_BusA_To; + Read_To_Reg_r(4) <= Read_To_Reg; + if Read_To_Acc = '1' then + Read_To_Reg_r(3 downto 0) <= "0111"; + Read_To_Reg_r(4) <= '1'; + end if; + end if; + + if TState = 1 and I_BT = '1' then + F(Flag_X) <= ALU_Q(3); + F(Flag_Y) <= ALU_Q(1); + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; + end if; + if I_BC = '1' or I_BT = '1' then + F(Flag_P) <= IncDecZ; + end if; + + if (TState = 1 and Save_ALU_r = '0' and Auto_Wait_t1 = '0') or + (Save_ALU_r = '1' and ALU_OP_r /= "0111") then + case Read_To_Reg_r is + when "10111" => + ACC <= Save_Mux; + when "10110" => + DO <= Save_Mux; + when "11000" => + SP(7 downto 0) <= unsigned(Save_Mux); + when "11001" => + SP(15 downto 8) <= unsigned(Save_Mux); + when "11011" => + F <= Save_Mux; + when others => + end case; + end if; + + end if; + + end if; + + end process; + +--------------------------------------------------------------------------- +-- +-- BC('), DE('), HL('), IX and IY +-- +--------------------------------------------------------------------------- + process (CLK_n) + begin + if CLK_n'event and CLK_n = '1' then + if ClkEn = '1' then + -- Bus A / Write + RegAddrA_r <= Alternate & Set_BusA_To(2 downto 1); + if XY_Ind = '0' and XY_State /= "00" and Set_BusA_To(2 downto 1) = "10" then + RegAddrA_r <= XY_State(1) & "11"; + end if; + + -- Bus B + RegAddrB_r <= Alternate & Set_BusB_To(2 downto 1); + if XY_Ind = '0' and XY_State /= "00" and Set_BusB_To(2 downto 1) = "10" then + RegAddrB_r <= XY_State(1) & "11"; + end if; + + -- Address from register + RegAddrC <= Alternate & Set_Addr_To(1 downto 0); + -- Jump (HL), LD SP,HL + if (JumpXY = '1' or LDSPHL = '1') then + RegAddrC <= Alternate & "10"; + end if; + if ((JumpXY = '1' or LDSPHL = '1') and XY_State /= "00") or (MCycle = "110") then + RegAddrC <= XY_State(1) & "11"; + end if; + + if I_DJNZ = '1' and Save_ALU_r = '1' and Mode < 2 then + IncDecZ <= F_Out(Flag_Z); + end if; + if (TState = 2 or (TState = 3 and MCycle = "001")) and IncDec_16(2 downto 0) = "100" then + if ID16 = 0 then + IncDecZ <= '0'; + else + IncDecZ <= '1'; + end if; + end if; + + RegBusA_r <= RegBusA; + end if; + end if; + end process; + + RegAddrA <= + -- 16 bit increment/decrement + Alternate & IncDec_16(1 downto 0) when (TState = 2 or + (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and XY_State = "00" else + XY_State(1) & "11" when (TState = 2 or + (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and IncDec_16(1 downto 0) = "10" else + -- EX HL,DL + Alternate & "10" when ExchangeDH = '1' and TState = 3 else + Alternate & "01" when ExchangeDH = '1' and TState = 4 else + -- Bus A / Write + RegAddrA_r; + + RegAddrB <= + -- EX HL,DL + Alternate & "01" when ExchangeDH = '1' and TState = 3 else + -- Bus B + RegAddrB_r; + + ID16 <= signed(RegBusA) - 1 when IncDec_16(3) = '1' else + signed(RegBusA) + 1; + + process (Save_ALU_r, Auto_Wait_t1, ALU_OP_r, Read_To_Reg_r, + ExchangeDH, IncDec_16, MCycle, TState, Wait_n) + begin + RegWEH <= '0'; + RegWEL <= '0'; + if (TState = 1 and Save_ALU_r = '0' and Auto_Wait_t1 = '0') or + (Save_ALU_r = '1' and ALU_OP_r /= "0111") then + case Read_To_Reg_r is + when "10000" | "10001" | "10010" | "10011" | "10100" | "10101" => + RegWEH <= not Read_To_Reg_r(0); + RegWEL <= Read_To_Reg_r(0); + when others => + end case; + end if; + + if ExchangeDH = '1' and (TState = 3 or TState = 4) then + RegWEH <= '1'; + RegWEL <= '1'; + end if; + + if IncDec_16(2) = '1' and ((TState = 2 and Wait_n = '1' and MCycle /= "001") or (TState = 3 and MCycle = "001")) then + case IncDec_16(1 downto 0) is + when "00" | "01" | "10" => + RegWEH <= '1'; + RegWEL <= '1'; + when others => + end case; + end if; + end process; + + process (Save_Mux, RegBusB, RegBusA_r, ID16, + ExchangeDH, IncDec_16, MCycle, TState, Wait_n) + begin + RegDIH <= Save_Mux; + RegDIL <= Save_Mux; + + if ExchangeDH = '1' and TState = 3 then + RegDIH <= RegBusB(15 downto 8); + RegDIL <= RegBusB(7 downto 0); + end if; + if ExchangeDH = '1' and TState = 4 then + RegDIH <= RegBusA_r(15 downto 8); + RegDIL <= RegBusA_r(7 downto 0); + end if; + + if IncDec_16(2) = '1' and ((TState = 2 and MCycle /= "001") or (TState = 3 and MCycle = "001")) then + RegDIH <= std_logic_vector(ID16(15 downto 8)); + RegDIL <= std_logic_vector(ID16(7 downto 0)); + end if; + end process; + + Regs : T80_Reg + port map( + Clk => CLK_n, + CEN => ClkEn, + WEH => RegWEH, + WEL => RegWEL, + AddrA => RegAddrA, + AddrB => RegAddrB, + AddrC => RegAddrC, + DIH => RegDIH, + DIL => RegDIL, + DOAH => RegBusA(15 downto 8), + DOAL => RegBusA(7 downto 0), + DOBH => RegBusB(15 downto 8), + DOBL => RegBusB(7 downto 0), + DOCH => RegBusC(15 downto 8), + DOCL => RegBusC(7 downto 0)); + +--------------------------------------------------------------------------- +-- +-- Buses +-- +--------------------------------------------------------------------------- + process (CLK_n) + begin + if CLK_n'event and CLK_n = '1' then + if ClkEn = '1' then + case Set_BusB_To is + when "0111" => + BusB <= ACC; + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => + if Set_BusB_To(0) = '1' then + BusB <= RegBusB(7 downto 0); + else + BusB <= RegBusB(15 downto 8); + end if; + when "0110" => + BusB <= DI_Reg; + when "1000" => + BusB <= std_logic_vector(SP(7 downto 0)); + when "1001" => + BusB <= std_logic_vector(SP(15 downto 8)); + when "1010" => + BusB <= "00000001"; + when "1011" => + BusB <= F; + when "1100" => + BusB <= std_logic_vector(PC(7 downto 0)); + when "1101" => + BusB <= std_logic_vector(PC(15 downto 8)); + when "1110" => + BusB <= "00000000"; + when others => + BusB <= "--------"; + end case; + + case Set_BusA_To is + when "0111" => + BusA <= ACC; + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => + if Set_BusA_To(0) = '1' then + BusA <= RegBusA(7 downto 0); + else + BusA <= RegBusA(15 downto 8); + end if; + when "0110" => + BusA <= DI_Reg; + when "1000" => + BusA <= std_logic_vector(SP(7 downto 0)); + when "1001" => + BusA <= std_logic_vector(SP(15 downto 8)); + when "1010" => + BusA <= "00000000"; + when others => + BusB <= "--------"; + end case; + end if; + end if; + end process; + +--------------------------------------------------------------------------- +-- +-- Generate external control signals +-- +--------------------------------------------------------------------------- + process (RESET_n,CLK_n) + begin + if RESET_n = '0' then + RFSH_n <= '1'; + elsif CLK_n'event and CLK_n = '1' then + if CEN = '1' then + if MCycle = "001" and ((TState = 2 and Wait_n = '1') or TState = 3) then + RFSH_n <= '0'; + else + RFSH_n <= '1'; + end if; + end if; + end if; + end process; + + MC <= std_logic_vector(MCycle); + TS <= std_logic_vector(TState); + DI_Reg <= DI; + HALT_n <= not Halt_FF; + BUSAK_n <= not BusAck; + IntCycle_n <= not IntCycle; + IntE <= IntE_FF1; + IORQ <= IORQ_i; + Stop <= I_DJNZ; + +------------------------------------------------------------------------- +-- +-- Syncronise inputs +-- +------------------------------------------------------------------------- + process (RESET_n, CLK_n) + variable OldNMI_n : std_logic; + begin + if RESET_n = '0' then + BusReq_s <= '0'; + INT_s <= '0'; + NMI_s <= '0'; + OldNMI_n := '0'; + elsif CLK_n'event and CLK_n = '1' then + if CEN = '1' then + BusReq_s <= not BUSRQ_n; + INT_s <= not INT_n; + if NMICycle = '1' then + NMI_s <= '0'; + elsif NMI_n = '0' and OldNMI_n = '1' then + NMI_s <= '1'; + end if; + OldNMI_n := NMI_n; + end if; + end if; + end process; + +------------------------------------------------------------------------- +-- +-- Main state machine +-- +------------------------------------------------------------------------- + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + MCycle <= "001"; + TState <= "000"; + Pre_XY_F_M <= "000"; + Halt_FF <= '0'; + BusAck <= '0'; + NMICycle <= '0'; + IntCycle <= '0'; + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + No_BTR <= '0'; + Auto_Wait_t1 <= '0'; + Auto_Wait_t2 <= '0'; + M1_n <= '1'; + elsif CLK_n'event and CLK_n = '1' then + if CEN = '1' then + if T_Res = '1' then + Auto_Wait_t1 <= '0'; + else + Auto_Wait_t1 <= Auto_Wait or IORQ_i; + end if; + Auto_Wait_t2 <= Auto_Wait_t1; + No_BTR <= (I_BT and (not IR(4) or not F(Flag_P))) or + (I_BC and (not IR(4) or F(Flag_Z) or not F(Flag_P))) or + (I_BTR and (not IR(4) or F(Flag_Z))); + if TState = 2 then + if SetEI = '1' then + IntE_FF1 <= '1'; + IntE_FF2 <= '1'; + end if; + if I_RETN = '1' then + IntE_FF1 <= IntE_FF2; + end if; + end if; + if TState = 3 then + if SetDI = '1' then + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + end if; + end if; + if IntCycle = '1' or NMICycle = '1' then + Halt_FF <= '0'; + end if; + if MCycle = "001" and TState = 2 and Wait_n = '1' then + M1_n <= '1'; + end if; + if BusReq_s = '1' and BusAck = '1' then + else + BusAck <= '0'; + if TState = 2 and Wait_n = '0' then + elsif T_Res = '1' then + if Halt = '1' then + Halt_FF <= '1'; + end if; + if BusReq_s = '1' then + BusAck <= '1'; + else + TState <= "001"; + if NextIs_XY_Fetch = '1' then + MCycle <= "110"; + Pre_XY_F_M <= MCycle; + if IR = "00110110" and Mode = 0 then + Pre_XY_F_M <= "010"; + end if; + elsif (MCycle = "111") or + (MCycle = "110" and Mode = 1 and ISet /= "01") then + MCycle <= std_logic_vector(unsigned(Pre_XY_F_M) + 1); + elsif (MCycle = MCycles) or + No_BTR = '1' or + (MCycle = "010" and I_DJNZ = '1' and IncDecZ = '1') then + M1_n <= '0'; + MCycle <= "001"; + IntCycle <= '0'; + NMICycle <= '0'; + if NMI_s = '1' and Prefix = "00" then + NMICycle <= '1'; + IntE_FF1 <= '0'; + elsif (IntE_FF1 = '1' and INT_s = '1') and Prefix = "00" and SetEI = '0' then + IntCycle <= '1'; + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + end if; + else + MCycle <= std_logic_vector(unsigned(MCycle) + 1); + end if; + end if; + else + if (Auto_Wait = '1' and Auto_Wait_t2 = '0') nor + (IOWait = 1 and IORQ_i = '1' and Auto_Wait_t1 = '0') then + TState <= TState + 1; + end if; + end if; + end if; + if TState = 0 then + M1_n <= '0'; + end if; + end if; + end if; + end process; + + process (IntCycle, NMICycle, MCycle) + begin + Auto_Wait <= '0'; + if IntCycle = '1' or NMICycle = '1' then + if MCycle = "001" then + Auto_Wait <= '1'; + end if; + end if; + end process; + +end; diff --git a/galaxian/t80_ip/T80_ALU.vhd b/galaxian/t80_ip/T80_ALU.vhd new file mode 100644 index 0000000..86fddce --- /dev/null +++ b/galaxian/t80_ip/T80_ALU.vhd @@ -0,0 +1,351 @@ +-- +-- Z80 compatible microprocessor core +-- +-- Version : 0247 +-- +-- Copyright (c) 2001-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/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test +-- +-- 0238 : Fixed zero flag for 16 bit SBC and ADC +-- +-- 0240 : Added GB operations +-- +-- 0242 : Cleanup +-- +-- 0247 : Cleanup +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity T80_ALU is + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + Arith16 : in std_logic; + Z16 : in std_logic; + ALU_Op : in std_logic_vector(3 downto 0); + IR : in std_logic_vector(5 downto 0); + ISet : in std_logic_vector(1 downto 0); + BusA : in std_logic_vector(7 downto 0); + BusB : in std_logic_vector(7 downto 0); + F_In : in std_logic_vector(7 downto 0); + Q : out std_logic_vector(7 downto 0); + F_Out : out std_logic_vector(7 downto 0) + ); +end T80_ALU; + +architecture rtl of T80_ALU is + + procedure AddSub(A : std_logic_vector; + B : std_logic_vector; + Sub : std_logic; + Carry_In : std_logic; + signal Res : out std_logic_vector; + signal Carry : out std_logic) is + variable B_i : unsigned(A'length - 1 downto 0); + variable Res_i : unsigned(A'length + 1 downto 0); + begin + if Sub = '1' then + B_i := not unsigned(B); + else + B_i := unsigned(B); + end if; + Res_i := unsigned("0" & A & Carry_In) + unsigned("0" & B_i & "1"); + Carry <= Res_i(A'length + 1); + Res <= std_logic_vector(Res_i(A'length downto 1)); + end; + + -- AddSub variables (temporary signals) + signal UseCarry : std_logic; + signal Carry7_v : std_logic; + signal Overflow_v : std_logic; + signal HalfCarry_v : std_logic; + signal Carry_v : std_logic; + signal Q_v : std_logic_vector(7 downto 0); + + signal BitMask : std_logic_vector(7 downto 0); + +begin + + with IR(5 downto 3) select BitMask <= "00000001" when "000", + "00000010" when "001", + "00000100" when "010", + "00001000" when "011", + "00010000" when "100", + "00100000" when "101", + "01000000" when "110", + "10000000" when others; + + UseCarry <= not ALU_Op(2) and ALU_Op(0); + AddSub(BusA(3 downto 0), BusB(3 downto 0), ALU_Op(1), ALU_Op(1) xor (UseCarry and F_In(Flag_C)), Q_v(3 downto 0), HalfCarry_v); + AddSub(BusA(6 downto 4), BusB(6 downto 4), ALU_Op(1), HalfCarry_v, Q_v(6 downto 4), Carry7_v); + AddSub(BusA(7 downto 7), BusB(7 downto 7), ALU_Op(1), Carry7_v, Q_v(7 downto 7), Carry_v); + OverFlow_v <= Carry_v xor Carry7_v; + + process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16) + variable Q_t : std_logic_vector(7 downto 0); + variable DAA_Q : unsigned(8 downto 0); + begin + Q_t := "--------"; + F_Out <= F_In; + DAA_Q := "---------"; + case ALU_Op is + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" | "0110" | "0111" => + F_Out(Flag_N) <= '0'; + F_Out(Flag_C) <= '0'; + case ALU_OP(2 downto 0) is + when "000" | "001" => -- ADD, ADC + Q_t := Q_v; + F_Out(Flag_C) <= Carry_v; + F_Out(Flag_H) <= HalfCarry_v; + F_Out(Flag_P) <= OverFlow_v; + when "010" | "011" | "111" => -- SUB, SBC, CP + Q_t := Q_v; + F_Out(Flag_N) <= '1'; + F_Out(Flag_C) <= not Carry_v; + F_Out(Flag_H) <= not HalfCarry_v; + F_Out(Flag_P) <= OverFlow_v; + when "100" => -- AND + Q_t(7 downto 0) := BusA and BusB; + F_Out(Flag_H) <= '1'; + when "101" => -- XOR + Q_t(7 downto 0) := BusA xor BusB; + F_Out(Flag_H) <= '0'; + when others => -- OR "110" + Q_t(7 downto 0) := BusA or BusB; + F_Out(Flag_H) <= '0'; + end case; + if ALU_Op(2 downto 0) = "111" then -- CP + F_Out(Flag_X) <= BusB(3); + F_Out(Flag_Y) <= BusB(5); + else + F_Out(Flag_X) <= Q_t(3); + F_Out(Flag_Y) <= Q_t(5); + end if; + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + if Z16 = '1' then + F_Out(Flag_Z) <= F_In(Flag_Z); -- 16 bit ADC,SBC + end if; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_S) <= Q_t(7); + case ALU_Op(2 downto 0) is + when "000" | "001" | "010" | "011" | "111" => -- ADD, ADC, SUB, SBC, CP + when others => + F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor + Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7)); + end case; + if Arith16 = '1' then + F_Out(Flag_S) <= F_In(Flag_S); + F_Out(Flag_Z) <= F_In(Flag_Z); + F_Out(Flag_P) <= F_In(Flag_P); + end if; + when "1100" => + -- DAA + F_Out(Flag_H) <= F_In(Flag_H); + F_Out(Flag_C) <= F_In(Flag_C); + DAA_Q(7 downto 0) := unsigned(BusA); + DAA_Q(8) := '0'; + if F_In(Flag_N) = '0' then + -- After addition + -- Alow > 9 or H = 1 + if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then + if (DAA_Q(3 downto 0) > 9) then + F_Out(Flag_H) <= '1'; + else + F_Out(Flag_H) <= '0'; + end if; + DAA_Q := DAA_Q + 6; + end if; + -- new Ahigh > 9 or C = 1 + if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then + DAA_Q := DAA_Q + 96; -- 0x60 + end if; + else + -- After subtraction + if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then + if DAA_Q(3 downto 0) > 5 then + F_Out(Flag_H) <= '0'; + end if; + DAA_Q(7 downto 0) := DAA_Q(7 downto 0) - 6; + end if; + if unsigned(BusA) > 153 or F_In(Flag_C) = '1' then + DAA_Q := DAA_Q - 352; -- 0x160 + end if; + end if; + F_Out(Flag_X) <= DAA_Q(3); + F_Out(Flag_Y) <= DAA_Q(5); + F_Out(Flag_C) <= F_In(Flag_C) or DAA_Q(8); + Q_t := std_logic_vector(DAA_Q(7 downto 0)); + if DAA_Q(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_S) <= DAA_Q(7); + F_Out(Flag_P) <= not (DAA_Q(0) xor DAA_Q(1) xor DAA_Q(2) xor DAA_Q(3) xor + DAA_Q(4) xor DAA_Q(5) xor DAA_Q(6) xor DAA_Q(7)); + when "1101" | "1110" => + -- RLD, RRD + Q_t(7 downto 4) := BusA(7 downto 4); + if ALU_Op(0) = '1' then + Q_t(3 downto 0) := BusB(7 downto 4); + else + Q_t(3 downto 0) := BusB(3 downto 0); + end if; + F_Out(Flag_H) <= '0'; + F_Out(Flag_N) <= '0'; + F_Out(Flag_X) <= Q_t(3); + F_Out(Flag_Y) <= Q_t(5); + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_S) <= Q_t(7); + F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor + Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7)); + when "1001" => + -- BIT + Q_t(7 downto 0) := BusB and BitMask; + F_Out(Flag_S) <= Q_t(7); + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + F_Out(Flag_P) <= '1'; + else + F_Out(Flag_Z) <= '0'; + F_Out(Flag_P) <= '0'; + end if; + F_Out(Flag_H) <= '1'; + F_Out(Flag_N) <= '0'; + F_Out(Flag_X) <= '0'; + F_Out(Flag_Y) <= '0'; + if IR(2 downto 0) /= "110" then + F_Out(Flag_X) <= BusB(3); + F_Out(Flag_Y) <= BusB(5); + end if; + when "1010" => + -- SET + Q_t(7 downto 0) := BusB or BitMask; + when "1011" => + -- RES + Q_t(7 downto 0) := BusB and not BitMask; + when "1000" => + -- ROT + case IR(5 downto 3) is + when "000" => -- RLC + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := BusA(7); + F_Out(Flag_C) <= BusA(7); + when "010" => -- RL + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := F_In(Flag_C); + F_Out(Flag_C) <= BusA(7); + when "001" => -- RRC + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := BusA(0); + F_Out(Flag_C) <= BusA(0); + when "011" => -- RR + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := F_In(Flag_C); + F_Out(Flag_C) <= BusA(0); + when "100" => -- SLA + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := '0'; + F_Out(Flag_C) <= BusA(7); + when "110" => -- SLL (Undocumented) / SWAP + if Mode = 3 then + Q_t(7 downto 4) := BusA(3 downto 0); + Q_t(3 downto 0) := BusA(7 downto 4); + F_Out(Flag_C) <= '0'; + else + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := '1'; + F_Out(Flag_C) <= BusA(7); + end if; + when "101" => -- SRA + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := BusA(7); + F_Out(Flag_C) <= BusA(0); + when others => -- SRL + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := '0'; + F_Out(Flag_C) <= BusA(0); + end case; + F_Out(Flag_H) <= '0'; + F_Out(Flag_N) <= '0'; + F_Out(Flag_X) <= Q_t(3); + F_Out(Flag_Y) <= Q_t(5); + F_Out(Flag_S) <= Q_t(7); + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor + Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7)); + if ISet = "00" then + F_Out(Flag_P) <= F_In(Flag_P); + F_Out(Flag_S) <= F_In(Flag_S); + F_Out(Flag_Z) <= F_In(Flag_Z); + end if; + when others => + null; + end case; + Q <= Q_t; + end process; + +end; diff --git a/galaxian/t80_ip/T80_MCode.vhd b/galaxian/t80_ip/T80_MCode.vhd new file mode 100644 index 0000000..4cc30f3 --- /dev/null +++ b/galaxian/t80_ip/T80_MCode.vhd @@ -0,0 +1,1934 @@ +-- +-- Z80 compatible microprocessor core +-- +-- Version : 0242 +-- +-- Copyright (c) 2001-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/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0208 : First complete release +-- +-- 0211 : Fixed IM 1 +-- +-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test +-- +-- 0235 : Added IM 2 fix by Mike Johnson +-- +-- 0238 : Added NoRead signal +-- +-- 0238b: Fixed instruction timing for POP and DJNZ +-- +-- 0240 : Added (IX/IY+d) states, removed op-codes from mode 2 and added all remaining mode 3 op-codes +-- +-- 0242 : Fixed I/O instruction timing, cleanup +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity T80_MCode is + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + IR : in std_logic_vector(7 downto 0); + ISet : in std_logic_vector(1 downto 0); + MCycle : in std_logic_vector(2 downto 0); + F : in std_logic_vector(7 downto 0); + NMICycle : in std_logic; + IntCycle : in std_logic; + MCycles : out std_logic_vector(2 downto 0); + TStates : out std_logic_vector(2 downto 0); + Prefix : out std_logic_vector(1 downto 0); -- None,BC,ED,DD/FD + Inc_PC : out std_logic; + Inc_WZ : out std_logic; + IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc + Read_To_Reg : out std_logic; + Read_To_Acc : out std_logic; + Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F + Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0 + ALU_Op : out std_logic_vector(3 downto 0); + -- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None + Save_ALU : out std_logic; + PreserveC : out std_logic; + Arith16 : out std_logic; + Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI + IORQ : out std_logic; + Jump : out std_logic; + JumpE : out std_logic; + JumpXY : out std_logic; + Call : out std_logic; + RstP : out std_logic; + LDZ : out std_logic; + LDW : out std_logic; + LDSPHL : out std_logic; + Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None + ExchangeDH : out std_logic; + ExchangeRp : out std_logic; + ExchangeAF : out std_logic; + ExchangeRS : out std_logic; + I_DJNZ : out std_logic; + I_CPL : out std_logic; + I_CCF : out std_logic; + I_SCF : out std_logic; + I_RETN : out std_logic; + I_BT : out std_logic; + I_BC : out std_logic; + I_BTR : out std_logic; + I_RLD : out std_logic; + I_RRD : out std_logic; + I_INRC : out std_logic; + SetDI : out std_logic; + SetEI : out std_logic; + IMode : out std_logic_vector(1 downto 0); + Halt : out std_logic; + NoRead : out std_logic; + Write : out std_logic + ); +end T80_MCode; + +architecture rtl of T80_MCode is + + constant aNone : std_logic_vector(2 downto 0) := "111"; + constant aBC : std_logic_vector(2 downto 0) := "000"; + constant aDE : std_logic_vector(2 downto 0) := "001"; + constant aXY : std_logic_vector(2 downto 0) := "010"; + constant aIOA : std_logic_vector(2 downto 0) := "100"; + constant aSP : std_logic_vector(2 downto 0) := "101"; + constant aZI : std_logic_vector(2 downto 0) := "110"; +-- constant aNone : std_logic_vector(2 downto 0) := "000"; +-- constant aXY : std_logic_vector(2 downto 0) := "001"; +-- constant aIOA : std_logic_vector(2 downto 0) := "010"; +-- constant aSP : std_logic_vector(2 downto 0) := "011"; +-- constant aBC : std_logic_vector(2 downto 0) := "100"; +-- constant aDE : std_logic_vector(2 downto 0) := "101"; +-- constant aZI : std_logic_vector(2 downto 0) := "110"; + + function is_cc_true( + F : std_logic_vector(7 downto 0); + cc : bit_vector(2 downto 0) + ) return boolean is + begin + if Mode = 3 then + case cc is + when "000" => return F(7) = '0'; -- NZ + when "001" => return F(7) = '1'; -- Z + when "010" => return F(4) = '0'; -- NC + when "011" => return F(4) = '1'; -- C + when "100" => return false; + when "101" => return false; + when "110" => return false; + when "111" => return false; + end case; + else + case cc is + when "000" => return F(6) = '0'; -- NZ + when "001" => return F(6) = '1'; -- Z + when "010" => return F(0) = '0'; -- NC + when "011" => return F(0) = '1'; -- C + when "100" => return F(2) = '0'; -- PO + when "101" => return F(2) = '1'; -- PE + when "110" => return F(7) = '0'; -- P + when "111" => return F(7) = '1'; -- M + end case; + end if; + end; + +begin + + process (IR, ISet, MCycle, F, NMICycle, IntCycle) + variable DDD : std_logic_vector(2 downto 0); + variable SSS : std_logic_vector(2 downto 0); + variable DPair : std_logic_vector(1 downto 0); + variable IRB : bit_vector(7 downto 0); + begin + DDD := IR(5 downto 3); + SSS := IR(2 downto 0); + DPair := IR(5 downto 4); + IRB := to_bitvector(IR); + + MCycles <= "001"; + if MCycle = "001" then + TStates <= "100"; + else + TStates <= "011"; + end if; + Prefix <= "00"; + Inc_PC <= '0'; + Inc_WZ <= '0'; + IncDec_16 <= "0000"; + Read_To_Acc <= '0'; + Read_To_Reg <= '0'; + Set_BusB_To <= "0000"; + Set_BusA_To <= "0000"; + ALU_Op <= "0" & IR(5 downto 3); + Save_ALU <= '0'; + PreserveC <= '0'; + Arith16 <= '0'; + IORQ <= '0'; + Set_Addr_To <= aNone; + Jump <= '0'; + JumpE <= '0'; + JumpXY <= '0'; + Call <= '0'; + RstP <= '0'; + LDZ <= '0'; + LDW <= '0'; + LDSPHL <= '0'; + Special_LD <= "000"; + ExchangeDH <= '0'; + ExchangeRp <= '0'; + ExchangeAF <= '0'; + ExchangeRS <= '0'; + I_DJNZ <= '0'; + I_CPL <= '0'; + I_CCF <= '0'; + I_SCF <= '0'; + I_RETN <= '0'; + I_BT <= '0'; + I_BC <= '0'; + I_BTR <= '0'; + I_RLD <= '0'; + I_RRD <= '0'; + I_INRC <= '0'; + SetDI <= '0'; + SetEI <= '0'; + IMode <= "11"; + Halt <= '0'; + NoRead <= '0'; + Write <= '0'; + + case ISet is + when "00" => + +------------------------------------------------------------------------------ +-- +-- Unprefixed instructions +-- +------------------------------------------------------------------------------ + + case IRB is +-- 8 BIT LOAD GROUP + when "01000000"|"01000001"|"01000010"|"01000011"|"01000100"|"01000101"|"01000111" + |"01001000"|"01001001"|"01001010"|"01001011"|"01001100"|"01001101"|"01001111" + |"01010000"|"01010001"|"01010010"|"01010011"|"01010100"|"01010101"|"01010111" + |"01011000"|"01011001"|"01011010"|"01011011"|"01011100"|"01011101"|"01011111" + |"01100000"|"01100001"|"01100010"|"01100011"|"01100100"|"01100101"|"01100111" + |"01101000"|"01101001"|"01101010"|"01101011"|"01101100"|"01101101"|"01101111" + |"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" => + -- LD r,r' + Set_BusB_To(2 downto 0) <= SSS; + ExchangeRp <= '1'; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + when "00000110"|"00001110"|"00010110"|"00011110"|"00100110"|"00101110"|"00111110" => + -- LD r,n + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + when others => null; + end case; + when "01000110"|"01001110"|"01010110"|"01011110"|"01100110"|"01101110"|"01111110" => + -- LD r,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + when others => null; + end case; + when "01110000"|"01110001"|"01110010"|"01110011"|"01110100"|"01110101"|"01110111" => + -- LD (HL),r + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + when 2 => + Write <= '1'; + when others => null; + end case; + when "00110110" => + -- LD (HL),n + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aXY; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + when 3 => + Write <= '1'; + when others => null; + end case; + when "00001010" => + -- LD A,(BC) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + when 2 => + Read_To_Acc <= '1'; + when others => null; + end case; + when "00011010" => + -- LD A,(DE) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aDE; + when 2 => + Read_To_Acc <= '1'; + when others => null; + end case; + when "00111010" => + if Mode = 3 then + -- LDD A,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Read_To_Acc <= '1'; + IncDec_16 <= "1110"; + when others => null; + end case; + else + -- LD A,(nn) + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + when 4 => + Read_To_Acc <= '1'; + when others => null; + end case; + end if; + when "00000010" => + -- LD (BC),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + when others => null; + end case; + when "00010010" => + -- LD (DE),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aDE; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + when others => null; + end case; + when "00110010" => + if Mode = 3 then + -- LDD (HL),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + IncDec_16 <= "1110"; + when others => null; + end case; + else + -- LD (nn),A + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + Set_BusB_To <= "0111"; + when 4 => + Write <= '1'; + when others => null; + end case; + end if; + +-- 16 BIT LOAD GROUP + when "00000001"|"00010001"|"00100001"|"00110001" => + -- LD dd,nn + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "1000"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '1'; + end if; + when 3 => + Inc_PC <= '1'; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "1001"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '0'; + end if; + when others => null; + end case; + when "00101010" => + if Mode = 3 then + -- LDI A,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Read_To_Acc <= '1'; + IncDec_16 <= "0110"; + when others => null; + end case; + else + -- LD HL,(nn) + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + when 4 => + Set_BusA_To(2 downto 0) <= "101"; -- L + Read_To_Reg <= '1'; + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + when 5 => + Set_BusA_To(2 downto 0) <= "100"; -- H + Read_To_Reg <= '1'; + when others => null; + end case; + end if; + when "00100010" => + if Mode = 3 then + -- LDI (HL),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + IncDec_16 <= "0110"; + when others => null; + end case; + else + -- LD (nn),HL + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + Set_BusB_To <= "0101"; -- L + when 4 => + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + Write <= '1'; + Set_BusB_To <= "0100"; -- H + when 5 => + Write <= '1'; + when others => null; + end case; + end if; + when "11111001" => + -- LD SP,HL + TStates <= "110"; + LDSPHL <= '1'; + when "11000101"|"11010101"|"11100101"|"11110101" => + -- PUSH qq + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_TO <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "0111"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '0'; + Set_BusB_To(3) <= '0'; + end if; + when 2 => + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "1011"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '1'; + Set_BusB_To(3) <= '0'; + end if; + Write <= '1'; + when 3 => + Write <= '1'; + when others => null; + end case; + when "11000001"|"11010001"|"11100001"|"11110001" => + -- POP qq + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "1011"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '1'; + end if; + when 3 => + IncDec_16 <= "0111"; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "0111"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '0'; + end if; + when others => null; + end case; + +-- EXCHANGE, BLOCK TRANSFER AND SEARCH GROUP + when "11101011" => + if Mode /= 3 then + -- EX DE,HL + ExchangeDH <= '1'; + end if; + when "00001000" => + if Mode = 3 then + -- LD (nn),SP + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + Set_BusB_To <= "1000"; + when 4 => + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + Write <= '1'; + Set_BusB_To <= "1001"; + when 5 => + Write <= '1'; + when others => null; + end case; + elsif Mode < 2 then + -- EX AF,AF' + ExchangeAF <= '1'; + end if; + when "11011001" => + if Mode = 3 then + -- RETI + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_TO <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + I_RETN <= '1'; + SetEI <= '1'; + when others => null; + end case; + elsif Mode < 2 then + -- EXX + ExchangeRS <= '1'; + end if; + when "11100011" => + if Mode /= 3 then + -- EX (SP),HL + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aSP; + when 2 => + Read_To_Reg <= '1'; + Set_BusA_To <= "0101"; + Set_BusB_To <= "0101"; + Set_Addr_To <= aSP; + when 3 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + TStates <= "100"; + Write <= '1'; + when 4 => + Read_To_Reg <= '1'; + Set_BusA_To <= "0100"; + Set_BusB_To <= "0100"; + Set_Addr_To <= aSP; + when 5 => + IncDec_16 <= "1111"; + TStates <= "101"; + Write <= '1'; + when others => null; + end case; + end if; + +-- 8 BIT ARITHMETIC AND LOGICAL GROUP + when "10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000111" + |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001111" + |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010111" + |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011111" + |"10100000"|"10100001"|"10100010"|"10100011"|"10100100"|"10100101"|"10100111" + |"10101000"|"10101001"|"10101010"|"10101011"|"10101100"|"10101101"|"10101111" + |"10110000"|"10110001"|"10110010"|"10110011"|"10110100"|"10110101"|"10110111" + |"10111000"|"10111001"|"10111010"|"10111011"|"10111100"|"10111101"|"10111111" => + -- ADD A,r + -- ADC A,r + -- SUB A,r + -- SBC A,r + -- AND A,r + -- OR A,r + -- XOR A,r + -- CP A,r + Set_BusB_To(2 downto 0) <= SSS; + Set_BusA_To(2 downto 0) <= "111"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + when "10000110"|"10001110"|"10010110"|"10011110"|"10100110"|"10101110"|"10110110"|"10111110" => + -- ADD A,(HL) + -- ADC A,(HL) + -- SUB A,(HL) + -- SBC A,(HL) + -- AND A,(HL) + -- OR A,(HL) + -- XOR A,(HL) + -- CP A,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusA_To(2 downto 0) <= "111"; + when others => null; + end case; + when "11000110"|"11001110"|"11010110"|"11011110"|"11100110"|"11101110"|"11110110"|"11111110" => + -- ADD A,n + -- ADC A,n + -- SUB A,n + -- SBC A,n + -- AND A,n + -- OR A,n + -- XOR A,n + -- CP A,n + MCycles <= "010"; + if MCycle = "010" then + Inc_PC <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusA_To(2 downto 0) <= "111"; + end if; + when "00000100"|"00001100"|"00010100"|"00011100"|"00100100"|"00101100"|"00111100" => + -- INC r + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + ALU_Op <= "0000"; + when "00110100" => + -- INC (HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + TStates <= "100"; + Set_Addr_To <= aXY; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + ALU_Op <= "0000"; + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + when 3 => + Write <= '1'; + when others => null; + end case; + when "00000101"|"00001101"|"00010101"|"00011101"|"00100101"|"00101101"|"00111101" => + -- DEC r + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + ALU_Op <= "0010"; + when "00110101" => + -- DEC (HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + TStates <= "100"; + Set_Addr_To <= aXY; + ALU_Op <= "0010"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + when 3 => + Write <= '1'; + when others => null; + end case; + +-- GENERAL PURPOSE ARITHMETIC AND CPU CONTROL GROUPS + when "00100111" => + -- DAA + Set_BusA_To(2 downto 0) <= "111"; + Read_To_Reg <= '1'; + ALU_Op <= "1100"; + Save_ALU <= '1'; + when "00101111" => + -- CPL + I_CPL <= '1'; + when "00111111" => + -- CCF + I_CCF <= '1'; + when "00110111" => + -- SCF + I_SCF <= '1'; + when "00000000" => + if NMICycle = '1' then + -- NMI + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + TStates <= "100"; + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + TStates <= "100"; + Write <= '1'; + when others => null; + end case; + elsif IntCycle = '1' then + -- INT (IM 2) + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + LDZ <= '1'; + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + TStates <= "100"; + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + TStates <= "100"; + Write <= '1'; + when 4 => + Inc_PC <= '1'; + LDZ <= '1'; + when 5 => + Jump <= '1'; + when others => null; + end case; + else + -- NOP + end if; + when "01110110" => + -- HALT + Halt <= '1'; + when "11110011" => + -- DI + SetDI <= '1'; + when "11111011" => + -- EI + SetEI <= '1'; + +-- 16 BIT ARITHMETIC GROUP + when "00001001"|"00011001"|"00101001"|"00111001" => + -- ADD HL,ss + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + ALU_Op <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + Arith16 <= '1'; + when 3 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + when others => + Set_BusB_To <= "1001"; + end case; + Arith16 <= '1'; + when others => + end case; + when "00000011"|"00010011"|"00100011"|"00110011" => + -- INC ss + TStates <= "110"; + IncDec_16(3 downto 2) <= "01"; + IncDec_16(1 downto 0) <= DPair; + when "00001011"|"00011011"|"00101011"|"00111011" => + -- DEC ss + TStates <= "110"; + IncDec_16(3 downto 2) <= "11"; + IncDec_16(1 downto 0) <= DPair; + +-- ROTATE AND SHIFT GROUP + when "00000111" + -- RLCA + |"00010111" + -- RLA + |"00001111" + -- RRCA + |"00011111" => + -- RRA + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "1000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + +-- JUMP GROUP + when "11000011" => + -- JP nn + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Inc_PC <= '1'; + Jump <= '1'; + when others => null; + end case; + when "11000010"|"11001010"|"11010010"|"11011010"|"11100010"|"11101010"|"11110010"|"11111010" => + if IR(5) = '1' and Mode = 3 then + case IRB(4 downto 3) is + when "00" => + -- LD ($FF00+C),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + IORQ <= '1'; + when others => + end case; + when "01" => + -- LD (nn),A + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + Set_BusB_To <= "0111"; + when 4 => + Write <= '1'; + when others => null; + end case; + when "10" => + -- LD A,($FF00+C) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + when 2 => + Read_To_Acc <= '1'; + IORQ <= '1'; + when others => + end case; + when "11" => + -- LD A,(nn) + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + when 4 => + Read_To_Acc <= '1'; + when others => null; + end case; + end case; + else + -- JP cc,nn + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Inc_PC <= '1'; + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + Jump <= '1'; + end if; + when others => null; + end case; + end if; + when "00011000" => + if Mode /= 2 then + -- JR e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00111000" => + if Mode /= 2 then + -- JR C,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_C) = '0' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00110000" => + if Mode /= 2 then + -- JR NC,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_C) = '1' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00101000" => + if Mode /= 2 then + -- JR Z,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_Z) = '0' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00100000" => + if Mode /= 2 then + -- JR NZ,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_Z) = '1' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "11101001" => + -- JP (HL) + JumpXY <= '1'; + when "00010000" => + if Mode = 3 then + I_DJNZ <= '1'; + elsif Mode < 2 then + -- DJNZ,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + I_DJNZ <= '1'; + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= "000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0010"; + when 2 => + I_DJNZ <= '1'; + Inc_PC <= '1'; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + +-- CALL AND RETURN GROUP + when "11001101" => + -- CALL nn + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + IncDec_16 <= "1111"; + Inc_PC <= '1'; + TStates <= "100"; + Set_Addr_To <= aSP; + LDW <= '1'; + Set_BusB_To <= "1101"; + when 4 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 5 => + Write <= '1'; + Call <= '1'; + when others => null; + end case; + when "11000100"|"11001100"|"11010100"|"11011100"|"11100100"|"11101100"|"11110100"|"11111100" => + if IR(5) = '0' or Mode /= 3 then + -- CALL cc,nn + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Inc_PC <= '1'; + LDW <= '1'; + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + IncDec_16 <= "1111"; + Set_Addr_TO <= aSP; + TStates <= "100"; + Set_BusB_To <= "1101"; + else + MCycles <= "011"; + end if; + when 4 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 5 => + Write <= '1'; + Call <= '1'; + when others => null; + end case; + end if; + when "11001001" => + -- RET + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + Set_Addr_TO <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + when "11000000"|"11001000"|"11010000"|"11011000"|"11100000"|"11101000"|"11110000"|"11111000" => + if IR(5) = '1' and Mode = 3 then + case IRB(4 downto 3) is + when "00" => + -- LD ($FF00+nn),A + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + Set_BusB_To <= "0111"; + when 3 => + Write <= '1'; + when others => null; + end case; + when "01" => + -- ADD SP,n + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + ALU_Op <= "0000"; + Inc_PC <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To <= "1000"; + Set_BusB_To <= "0110"; + when 3 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To <= "1001"; + Set_BusB_To <= "1110"; -- Incorrect unsigned !!!!!!!!!!!!!!!!!!!!! + when others => + end case; + when "10" => + -- LD A,($FF00+nn) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + when 3 => + Read_To_Acc <= '1'; + when others => null; + end case; + when "11" => + -- LD HL,SP+n -- Not correct !!!!!!!!!!!!!!!!!!! + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + when 4 => + Set_BusA_To(2 downto 0) <= "101"; -- L + Read_To_Reg <= '1'; + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + when 5 => + Set_BusA_To(2 downto 0) <= "100"; -- H + Read_To_Reg <= '1'; + when others => null; + end case; + end case; + else + -- RET cc + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + Set_Addr_TO <= aSP; + else + MCycles <= "001"; + end if; + TStates <= "101"; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + end if; + when "11000111"|"11001111"|"11010111"|"11011111"|"11100111"|"11101111"|"11110111"|"11111111" => + -- RST p + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + Write <= '1'; + RstP <= '1'; + when others => null; + end case; + +-- INPUT AND OUTPUT GROUP + when "11011011" => + if Mode /= 3 then + -- IN A,(n) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + when 3 => + Read_To_Acc <= '1'; + IORQ <= '1'; + when others => null; + end case; + end if; + when "11010011" => + if Mode /= 3 then + -- OUT (n),A + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + Set_BusB_To <= "0111"; + when 3 => + Write <= '1'; + IORQ <= '1'; + when others => null; + end case; + end if; + +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +-- MULTIBYTE INSTRUCTIONS +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ + + when "11001011" => + if Mode /= 2 then + Prefix <= "01"; + end if; + + when "11101101" => + if Mode < 2 then + Prefix <= "10"; + end if; + + when "11011101"|"11111101" => + if Mode < 2 then + Prefix <= "11"; + end if; + + end case; + + when "01" => + +------------------------------------------------------------------------------ +-- +-- CB prefixed instructions +-- +------------------------------------------------------------------------------ + + Set_BusA_To(2 downto 0) <= IR(2 downto 0); + Set_BusB_To(2 downto 0) <= IR(2 downto 0); + + case IRB is + when "00000000"|"00000001"|"00000010"|"00000011"|"00000100"|"00000101"|"00000111" + |"00010000"|"00010001"|"00010010"|"00010011"|"00010100"|"00010101"|"00010111" + |"00001000"|"00001001"|"00001010"|"00001011"|"00001100"|"00001101"|"00001111" + |"00011000"|"00011001"|"00011010"|"00011011"|"00011100"|"00011101"|"00011111" + |"00100000"|"00100001"|"00100010"|"00100011"|"00100100"|"00100101"|"00100111" + |"00101000"|"00101001"|"00101010"|"00101011"|"00101100"|"00101101"|"00101111" + |"00110000"|"00110001"|"00110010"|"00110011"|"00110100"|"00110101"|"00110111" + |"00111000"|"00111001"|"00111010"|"00111011"|"00111100"|"00111101"|"00111111" => + -- RLC r + -- RL r + -- RRC r + -- RR r + -- SLA r + -- SRA r + -- SRL r + -- SLL r (Undocumented) / SWAP r + if MCycle = "001" then + ALU_Op <= "1000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + end if; + when "00000110"|"00010110"|"00001110"|"00011110"|"00101110"|"00111110"|"00100110"|"00110110" => + -- RLC (HL) + -- RL (HL) + -- RRC (HL) + -- RR (HL) + -- SRA (HL) + -- SRL (HL) + -- SLA (HL) + -- SLL (HL) (Undocumented) / SWAP (HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 | 7 => + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => + end case; + when "01000000"|"01000001"|"01000010"|"01000011"|"01000100"|"01000101"|"01000111" + |"01001000"|"01001001"|"01001010"|"01001011"|"01001100"|"01001101"|"01001111" + |"01010000"|"01010001"|"01010010"|"01010011"|"01010100"|"01010101"|"01010111" + |"01011000"|"01011001"|"01011010"|"01011011"|"01011100"|"01011101"|"01011111" + |"01100000"|"01100001"|"01100010"|"01100011"|"01100100"|"01100101"|"01100111" + |"01101000"|"01101001"|"01101010"|"01101011"|"01101100"|"01101101"|"01101111" + |"01110000"|"01110001"|"01110010"|"01110011"|"01110100"|"01110101"|"01110111" + |"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" => + -- BIT b,r + if MCycle = "001" then + Set_BusB_To(2 downto 0) <= IR(2 downto 0); + ALU_Op <= "1001"; + end if; + when "01000110"|"01001110"|"01010110"|"01011110"|"01100110"|"01101110"|"01110110"|"01111110" => + -- BIT b,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 | 7 => + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1001"; + TStates <= "100"; + when others => + end case; + when "11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000111" + |"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001111" + |"11010000"|"11010001"|"11010010"|"11010011"|"11010100"|"11010101"|"11010111" + |"11011000"|"11011001"|"11011010"|"11011011"|"11011100"|"11011101"|"11011111" + |"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100111" + |"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101111" + |"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110111" + |"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111111" => + -- SET b,r + if MCycle = "001" then + ALU_Op <= "1010"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + end if; + when "11000110"|"11001110"|"11010110"|"11011110"|"11100110"|"11101110"|"11110110"|"11111110" => + -- SET b,(HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 | 7 => + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1010"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => + end case; + when "10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000111" + |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001111" + |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010111" + |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011111" + |"10100000"|"10100001"|"10100010"|"10100011"|"10100100"|"10100101"|"10100111" + |"10101000"|"10101001"|"10101010"|"10101011"|"10101100"|"10101101"|"10101111" + |"10110000"|"10110001"|"10110010"|"10110011"|"10110100"|"10110101"|"10110111" + |"10111000"|"10111001"|"10111010"|"10111011"|"10111100"|"10111101"|"10111111" => + -- RES b,r + if MCycle = "001" then + ALU_Op <= "1011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + end if; + when "10000110"|"10001110"|"10010110"|"10011110"|"10100110"|"10101110"|"10110110"|"10111110" => + -- RES b,(HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 | 7 => + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => + end case; + end case; + + when others => + +------------------------------------------------------------------------------ +-- +-- ED prefixed instructions +-- +------------------------------------------------------------------------------ + + case IRB is + when "00000000"|"00000001"|"00000010"|"00000011"|"00000100"|"00000101"|"00000110"|"00000111" + |"00001000"|"00001001"|"00001010"|"00001011"|"00001100"|"00001101"|"00001110"|"00001111" + |"00010000"|"00010001"|"00010010"|"00010011"|"00010100"|"00010101"|"00010110"|"00010111" + |"00011000"|"00011001"|"00011010"|"00011011"|"00011100"|"00011101"|"00011110"|"00011111" + |"00100000"|"00100001"|"00100010"|"00100011"|"00100100"|"00100101"|"00100110"|"00100111" + |"00101000"|"00101001"|"00101010"|"00101011"|"00101100"|"00101101"|"00101110"|"00101111" + |"00110000"|"00110001"|"00110010"|"00110011"|"00110100"|"00110101"|"00110110"|"00110111" + |"00111000"|"00111001"|"00111010"|"00111011"|"00111100"|"00111101"|"00111110"|"00111111" + + + |"10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000110"|"10000111" + |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001110"|"10001111" + |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010110"|"10010111" + |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011110"|"10011111" + | "10100100"|"10100101"|"10100110"|"10100111" + | "10101100"|"10101101"|"10101110"|"10101111" + | "10110100"|"10110101"|"10110110"|"10110111" + | "10111100"|"10111101"|"10111110"|"10111111" + |"11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000110"|"11000111" + |"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001110"|"11001111" + |"11010000"|"11010001"|"11010010"|"11010011"|"11010100"|"11010101"|"11010110"|"11010111" + |"11011000"|"11011001"|"11011010"|"11011011"|"11011100"|"11011101"|"11011110"|"11011111" + |"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100110"|"11100111" + |"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101110"|"11101111" + |"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110110"|"11110111" + |"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111110"|"11111111" => + null; -- NOP, undocumented + when "01111110"|"01111111" => + -- NOP, undocumented + null; +-- 8 BIT LOAD GROUP + when "01010111" => + -- LD A,I + Special_LD <= "100"; + TStates <= "101"; + when "01011111" => + -- LD A,R + Special_LD <= "101"; + TStates <= "101"; + when "01000111" => + -- LD I,A + Special_LD <= "110"; + TStates <= "101"; + when "01001111" => + -- LD R,A + Special_LD <= "111"; + TStates <= "101"; +-- 16 BIT LOAD GROUP + when "01001011"|"01011011"|"01101011"|"01111011" => + -- LD dd,(nn) + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + when 4 => + Read_To_Reg <= '1'; + if IR(5 downto 4) = "11" then + Set_BusA_To <= "1000"; + else + Set_BusA_To(2 downto 1) <= IR(5 downto 4); + Set_BusA_To(0) <= '1'; + end if; + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + when 5 => + Read_To_Reg <= '1'; + if IR(5 downto 4) = "11" then + Set_BusA_To <= "1001"; + else + Set_BusA_To(2 downto 1) <= IR(5 downto 4); + Set_BusA_To(0) <= '0'; + end if; + when others => null; + end case; + when "01000011"|"01010011"|"01100011"|"01110011" => + -- LD (nn),dd + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + if IR(5 downto 4) = "11" then + Set_BusB_To <= "1000"; + else + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + Set_BusB_To(3) <= '0'; + end if; + when 4 => + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + Write <= '1'; + if IR(5 downto 4) = "11" then + Set_BusB_To <= "1001"; + else + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '0'; + Set_BusB_To(3) <= '0'; + end if; + when 5 => + Write <= '1'; + when others => null; + end case; + when "10100000" | "10101000" | "10110000" | "10111000" => + -- LDI, LDD, LDIR, LDDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + IncDec_16 <= "1100"; -- BC + when 2 => + Set_BusB_To <= "0110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "0000"; + Set_Addr_To <= aDE; + if IR(3) = '0' then + IncDec_16 <= "0110"; -- IX + else + IncDec_16 <= "1110"; + end if; + when 3 => + I_BT <= '1'; + TStates <= "101"; + Write <= '1'; + if IR(3) = '0' then + IncDec_16 <= "0101"; -- DE + else + IncDec_16 <= "1101"; + end if; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + when "10100001" | "10101001" | "10110001" | "10111001" => + -- CPI, CPD, CPIR, CPDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + IncDec_16 <= "1100"; -- BC + when 2 => + Set_BusB_To <= "0110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "0111"; + Save_ALU <= '1'; + PreserveC <= '1'; + if IR(3) = '0' then + IncDec_16 <= "0110"; + else + IncDec_16 <= "1110"; + end if; + when 3 => + NoRead <= '1'; + I_BC <= '1'; + TStates <= "101"; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + when "01000100"|"01001100"|"01010100"|"01011100"|"01100100"|"01101100"|"01110100"|"01111100" => + -- NEG + Alu_OP <= "0010"; + Set_BusB_To <= "0111"; + Set_BusA_To <= "1010"; + Read_To_Acc <= '1'; + Save_ALU <= '1'; + when "01000110"|"01001110"|"01100110"|"01101110" => + -- IM 0 + IMode <= "00"; + when "01010110"|"01110110" => + -- IM 1 + IMode <= "01"; + when "01011110"|"01110111" => + -- IM 2 + IMode <= "10"; +-- 16 bit arithmetic + when "01001010"|"01011010"|"01101010"|"01111010" => + -- ADC HL,ss + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + ALU_Op <= "0001"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + when 3 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '0'; + when others => + Set_BusB_To <= "1001"; + end case; + when others => + end case; + when "01000010"|"01010010"|"01100010"|"01110010" => + -- SBC HL,ss + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + ALU_Op <= "0011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + when 3 => + NoRead <= '1'; + ALU_Op <= "0011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + when others => + Set_BusB_To <= "1001"; + end case; + when others => + end case; + when "01101111" => + -- RLD + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + Set_Addr_To <= aXY; + when 3 => + Read_To_Reg <= '1'; + Set_BusB_To(2 downto 0) <= "110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "1101"; + TStates <= "100"; + Set_Addr_To <= aXY; + Save_ALU <= '1'; + when 4 => + I_RLD <= '1'; + Write <= '1'; + when others => + end case; + when "01100111" => + -- RRD + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Set_Addr_To <= aXY; + when 3 => + Read_To_Reg <= '1'; + Set_BusB_To(2 downto 0) <= "110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "1110"; + TStates <= "100"; + Set_Addr_To <= aXY; + Save_ALU <= '1'; + when 4 => + I_RRD <= '1'; + Write <= '1'; + when others => + end case; + when "01000101"|"01001101"|"01010101"|"01011101"|"01100101"|"01101101"|"01110101"|"01111101" => + -- RETI, RETN + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_TO <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + I_RETN <= '1'; + when others => null; + end case; + when "01000000"|"01001000"|"01010000"|"01011000"|"01100000"|"01101000"|"01110000"|"01111000" => + -- IN r,(C) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + when 2 => + IORQ <= '1'; + if IR(5 downto 3) /= "110" then + Read_To_Reg <= '1'; + Set_BusA_To(2 downto 0) <= IR(5 downto 3); + end if; + I_INRC <= '1'; + when others => + end case; + when "01000001"|"01001001"|"01010001"|"01011001"|"01100001"|"01101001"|"01110001"|"01111001" => + -- OUT (C),r + -- OUT (C),0 + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To(2 downto 0) <= IR(5 downto 3); + if IR(5 downto 3) = "110" then + Set_BusB_To(3) <= '1'; + end if; + when 2 => + Write <= '1'; + IORQ <= '1'; + when others => + end case; + when "10100010" | "10101010" | "10110010" | "10111010" => + -- INI, IND, INIR, INDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To <= "1010"; + Set_BusA_To <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0010"; + when 2 => + IORQ <= '1'; + Set_BusB_To <= "0110"; + Set_Addr_To <= aXY; + when 3 => + if IR(3) = '0' then + IncDec_16 <= "0010"; + else + IncDec_16 <= "1010"; + end if; + TStates <= "100"; + Write <= '1'; + I_BTR <= '1'; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + when "10100011" | "10101011" | "10110011" | "10111011" => + -- OUTI, OUTD, OTIR, OTDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + Set_Addr_To <= aXY; + Set_BusB_To <= "1010"; + Set_BusA_To <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0010"; + when 2 => + Set_BusB_To <= "0110"; + Set_Addr_To <= aBC; + when 3 => + if IR(3) = '0' then + IncDec_16 <= "0010"; + else + IncDec_16 <= "1010"; + end if; + IORQ <= '1'; + Write <= '1'; + I_BTR <= '1'; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + end case; + + end case; + + if Mode = 1 then + if MCycle = "001" then +-- TStates <= "100"; + else + TStates <= "011"; + end if; + end if; + + if Mode = 3 then + if MCycle = "001" then +-- TStates <= "100"; + else + TStates <= "100"; + end if; + end if; + + if Mode < 2 then + if MCycle = "110" then + Inc_PC <= '1'; + if Mode = 1 then + Set_Addr_To <= aXY; + TStates <= "100"; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + end if; + if IRB = "00110110" or IRB = "11001011" then + Set_Addr_To <= aNone; + end if; + end if; + if MCycle = "111" then + if Mode = 0 then + TStates <= "101"; + end if; + if ISet /= "01" then + Set_Addr_To <= aXY; + end if; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + if IRB = "00110110" or ISet = "01" then + -- LD (HL),n + Inc_PC <= '1'; + else + NoRead <= '1'; + end if; + end if; + end if; + + end process; + +end; diff --git a/galaxian/t80_ip/T80_Pack.vhd b/galaxian/t80_ip/T80_Pack.vhd new file mode 100644 index 0000000..ac7d34d --- /dev/null +++ b/galaxian/t80_ip/T80_Pack.vhd @@ -0,0 +1,208 @@ +-- +-- Z80 compatible microprocessor core +-- +-- Version : 0242 +-- +-- Copyright (c) 2001-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/t80/ +-- +-- Limitations : +-- +-- File history : +-- + +library IEEE; +use IEEE.std_logic_1164.all; + +package T80_Pack is + + component T80 + generic( + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + IOWait : integer := 0; -- 1 => Single cycle I/O, 1 => Std I/O cycle + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + CEN : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + IORQ : out std_logic; + NoRead : out std_logic; + Write : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + DInst : in std_logic_vector(7 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0); + MC : out std_logic_vector(2 downto 0); + TS : out std_logic_vector(2 downto 0); + IntCycle_n : out std_logic; + IntE : out std_logic; + Stop : out std_logic + ); + end component; + + component T80_Reg + port( + Clk : in std_logic; + CEN : in std_logic; + WEH : in std_logic; + WEL : in std_logic; + AddrA : in std_logic_vector(2 downto 0); + AddrB : in std_logic_vector(2 downto 0); + AddrC : in std_logic_vector(2 downto 0); + DIH : in std_logic_vector(7 downto 0); + DIL : in std_logic_vector(7 downto 0); + DOAH : out std_logic_vector(7 downto 0); + DOAL : out std_logic_vector(7 downto 0); + DOBH : out std_logic_vector(7 downto 0); + DOBL : out std_logic_vector(7 downto 0); + DOCH : out std_logic_vector(7 downto 0); + DOCL : out std_logic_vector(7 downto 0) + ); + end component; + + component T80_MCode + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + IR : in std_logic_vector(7 downto 0); + ISet : in std_logic_vector(1 downto 0); + MCycle : in std_logic_vector(2 downto 0); + F : in std_logic_vector(7 downto 0); + NMICycle : in std_logic; + IntCycle : in std_logic; + MCycles : out std_logic_vector(2 downto 0); + TStates : out std_logic_vector(2 downto 0); + Prefix : out std_logic_vector(1 downto 0); -- None,BC,ED,DD/FD + Inc_PC : out std_logic; + Inc_WZ : out std_logic; + IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc + Read_To_Reg : out std_logic; + Read_To_Acc : out std_logic; + Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F + Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0 + ALU_Op : out std_logic_vector(3 downto 0); + -- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None + Save_ALU : out std_logic; + PreserveC : out std_logic; + Arith16 : out std_logic; + Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI + IORQ : out std_logic; + Jump : out std_logic; + JumpE : out std_logic; + JumpXY : out std_logic; + Call : out std_logic; + RstP : out std_logic; + LDZ : out std_logic; + LDW : out std_logic; + LDSPHL : out std_logic; + Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None + ExchangeDH : out std_logic; + ExchangeRp : out std_logic; + ExchangeAF : out std_logic; + ExchangeRS : out std_logic; + I_DJNZ : out std_logic; + I_CPL : out std_logic; + I_CCF : out std_logic; + I_SCF : out std_logic; + I_RETN : out std_logic; + I_BT : out std_logic; + I_BC : out std_logic; + I_BTR : out std_logic; + I_RLD : out std_logic; + I_RRD : out std_logic; + I_INRC : out std_logic; + SetDI : out std_logic; + SetEI : out std_logic; + IMode : out std_logic_vector(1 downto 0); + Halt : out std_logic; + NoRead : out std_logic; + Write : out std_logic + ); + end component; + + component T80_ALU + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + Arith16 : in std_logic; + Z16 : in std_logic; + ALU_Op : in std_logic_vector(3 downto 0); + IR : in std_logic_vector(5 downto 0); + ISet : in std_logic_vector(1 downto 0); + BusA : in std_logic_vector(7 downto 0); + BusB : in std_logic_vector(7 downto 0); + F_In : in std_logic_vector(7 downto 0); + Q : out std_logic_vector(7 downto 0); + F_Out : out std_logic_vector(7 downto 0) + ); + end component; + +end; diff --git a/galaxian/t80_ip/T80_Reg.vhd b/galaxian/t80_ip/T80_Reg.vhd new file mode 100644 index 0000000..828485f --- /dev/null +++ b/galaxian/t80_ip/T80_Reg.vhd @@ -0,0 +1,105 @@ +-- +-- T80 Registers, technology independent +-- +-- Version : 0244 +-- +-- 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/t51/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0242 : Initial release +-- +-- 0244 : Changed to single register file +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity T80_Reg is + port( + Clk : in std_logic; + CEN : in std_logic; + WEH : in std_logic; + WEL : in std_logic; + AddrA : in std_logic_vector(2 downto 0); + AddrB : in std_logic_vector(2 downto 0); + AddrC : in std_logic_vector(2 downto 0); + DIH : in std_logic_vector(7 downto 0); + DIL : in std_logic_vector(7 downto 0); + DOAH : out std_logic_vector(7 downto 0); + DOAL : out std_logic_vector(7 downto 0); + DOBH : out std_logic_vector(7 downto 0); + DOBL : out std_logic_vector(7 downto 0); + DOCH : out std_logic_vector(7 downto 0); + DOCL : out std_logic_vector(7 downto 0) + ); +end T80_Reg; + +architecture rtl of T80_Reg is + + type Register_Image is array (natural range <>) of std_logic_vector(7 downto 0); + signal RegsH : Register_Image(0 to 7); + signal RegsL : Register_Image(0 to 7); + +begin + + process (Clk) + begin + if Clk'event and Clk = '1' then + if CEN = '1' then + if WEH = '1' then + RegsH(to_integer(unsigned(AddrA))) <= DIH; + end if; + if WEL = '1' then + RegsL(to_integer(unsigned(AddrA))) <= DIL; + end if; + end if; + end if; + end process; + + DOAH <= RegsH(to_integer(unsigned(AddrA))); + DOAL <= RegsL(to_integer(unsigned(AddrA))); + DOBH <= RegsH(to_integer(unsigned(AddrB))); + DOBL <= RegsL(to_integer(unsigned(AddrB))); + DOCH <= RegsH(to_integer(unsigned(AddrC))); + DOCL <= RegsL(to_integer(unsigned(AddrC))); + +end; diff --git a/galaxian/t80_ip/T80as.vhd b/galaxian/t80_ip/T80as.vhd new file mode 100644 index 0000000..b2d0352 --- /dev/null +++ b/galaxian/t80_ip/T80as.vhd @@ -0,0 +1,283 @@ +------------------------------------------------------------------------------ +-- t80as.vhd : The non-tristate signal edition of t80a.vhd +-- +-- 2003.2.7 non-tristate modification by Tatsuyuki Satoh +-- +-- 1.separate 'D' to 'DO' and 'DI'. +-- 2.added 'DOE' to 'DO' enable signal.(data direction) +-- 3.MREQ_n,IORQ_n,RD_n,WR_n,RFSH_n,A doesn't become the condition of 'Z'. +-- +-- There is a mark of "--AS" in all the change points. +-- +------------------------------------------------------------------------------ + +-- +-- Z80 compatible microprocessor core, asynchronous top level +-- +-- Version : 0247 +-- +-- Copyright (c) 2001-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/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0208 : First complete release +-- +-- 0211 : Fixed interrupt cycle +-- +-- 0235 : Updated for T80 interface change +-- +-- 0238 : Updated for T80 interface change +-- +-- 0240 : Updated for T80 interface change +-- +-- 0242 : Updated for T80 interface change +-- +-- 0247 : Fixed bus req/ack cycle +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T80_Pack.all; + +entity T80as is + generic( + Mode : integer := 0 -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + ); + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + MREQ_n : out std_logic; + IORQ_n : out std_logic; + RD_n : out std_logic; + WR_n : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); +--AS-- D : inout std_logic_vector(7 downto 0) +--AS>> + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0); + DOE : out std_logic +--< 'Z'); +--AS-- D <= DO when Write = '1' and BUSAK_n_i = '1' else (others => 'Z'); +--AS>> + MREQ_n <= MREQ_n_i; + IORQ_n <= IORQ_n_i; + RD_n <= RD_n_i; + WR_n <= WR_n_i; + RFSH_n <= RFSH_n_i; + A <= A_i; + DOE <= Write when BUSAK_n_i = '1' else '0'; +--< Mode, + IOWait => 1) + port map( + CEN => CEN, + M1_n => M1_n, + IORQ => IORQ, + NoRead => NoRead, + Write => Write, + RFSH_n => RFSH_n_i, + HALT_n => HALT_n, + WAIT_n => Wait_s, + INT_n => INT_n, + NMI_n => NMI_n, + RESET_n => Reset_s, + BUSRQ_n => BUSRQ_n, + BUSAK_n => BUSAK_n_i, + CLK_n => CLK_n, + A => A_i, +-- DInst => D, + DInst => DI, + DI => DI_Reg, + DO => DO, + MC => MCycle, + TS => TState, + IntCycle_n => IntCycle_n); + + process (CLK_n) + begin + if CLK_n'event and CLK_n = '0' then + Wait_s <= WAIT_n; + if TState = "011" and BUSAK_n_i = '1' then +--AS-- DI_Reg <= to_x01(D); +--AS>> + DI_Reg <= to_x01(DI); +--<