From 320d8a7b546010f5a6b73b3db7e1cd89b981293e Mon Sep 17 00:00:00 2001 From: Gehstock Date: Mon, 22 Jan 2018 11:32:25 +0100 Subject: [PATCH] Initial commit --- .gitattributes | 2 + Sharp -MZ-80K_MiST/clean.bat | 37 + Sharp -MZ-80K_MiST/mz80k.qpf | 30 + Sharp -MZ-80K_MiST/mz80k.qsf | 123 +++ Sharp -MZ-80K_MiST/rtl/80KCG.hex | 129 +++ Sharp -MZ-80K_MiST/rtl/80ktc.hex | 257 +++++ Sharp -MZ-80K_MiST/rtl/build_id.tcl | 35 + Sharp -MZ-80K_MiST/rtl/build_id.v | 2 + Sharp -MZ-80K_MiST/rtl/cgrom.qip | 3 + Sharp -MZ-80K_MiST/rtl/cgrom.v | 169 +++ Sharp -MZ-80K_MiST/rtl/dac.vhd | 48 + Sharp -MZ-80K_MiST/rtl/fz80.v | 1456 +++++++++++++++++++++++++ Sharp -MZ-80K_MiST/rtl/hq2x.sv | 454 ++++++++ Sharp -MZ-80K_MiST/rtl/i8253.v | 158 +++ Sharp -MZ-80K_MiST/rtl/keyboard.v | 82 ++ Sharp -MZ-80K_MiST/rtl/mist_io.v | 491 +++++++++ Sharp -MZ-80K_MiST/rtl/monrom.qip | 3 + Sharp -MZ-80K_MiST/rtl/monrom.v | 184 ++++ Sharp -MZ-80K_MiST/rtl/mycom.v | 139 +++ Sharp -MZ-80K_MiST/rtl/mz80k.sv | 136 +++ Sharp -MZ-80K_MiST/rtl/osd.v | 179 +++ Sharp -MZ-80K_MiST/rtl/pll.qip | 4 + Sharp -MZ-80K_MiST/rtl/pll.vhd | 350 ++++++ Sharp -MZ-80K_MiST/rtl/ps2.v | 283 +++++ Sharp -MZ-80K_MiST/rtl/rom/80KCG.ROM | Bin 0 -> 2048 bytes Sharp -MZ-80K_MiST/rtl/rom/80ktc.rom | Bin 0 -> 4096 bytes Sharp -MZ-80K_MiST/rtl/scandoubler.v | 183 ++++ Sharp -MZ-80K_MiST/rtl/sound.v | 49 + Sharp -MZ-80K_MiST/rtl/vga.v | 72 ++ Sharp -MZ-80K_MiST/rtl/video_mixer.sv | 242 ++++ Sharp -MZ-80K_MiST/rtl/vram.qip | 3 + Sharp -MZ-80K_MiST/rtl/vram.v | 177 +++ Sharp -MZ-80K_MiST/snapshot/mz80k.rbf | Bin 0 -> 244232 bytes 33 files changed, 5480 insertions(+) create mode 100644 .gitattributes create mode 100644 Sharp -MZ-80K_MiST/clean.bat create mode 100644 Sharp -MZ-80K_MiST/mz80k.qpf create mode 100644 Sharp -MZ-80K_MiST/mz80k.qsf create mode 100644 Sharp -MZ-80K_MiST/rtl/80KCG.hex create mode 100644 Sharp -MZ-80K_MiST/rtl/80ktc.hex create mode 100644 Sharp -MZ-80K_MiST/rtl/build_id.tcl create mode 100644 Sharp -MZ-80K_MiST/rtl/build_id.v create mode 100644 Sharp -MZ-80K_MiST/rtl/cgrom.qip create mode 100644 Sharp -MZ-80K_MiST/rtl/cgrom.v create mode 100644 Sharp -MZ-80K_MiST/rtl/dac.vhd create mode 100644 Sharp -MZ-80K_MiST/rtl/fz80.v create mode 100644 Sharp -MZ-80K_MiST/rtl/hq2x.sv create mode 100644 Sharp -MZ-80K_MiST/rtl/i8253.v create mode 100644 Sharp -MZ-80K_MiST/rtl/keyboard.v create mode 100644 Sharp -MZ-80K_MiST/rtl/mist_io.v create mode 100644 Sharp -MZ-80K_MiST/rtl/monrom.qip create mode 100644 Sharp -MZ-80K_MiST/rtl/monrom.v create mode 100644 Sharp -MZ-80K_MiST/rtl/mycom.v create mode 100644 Sharp -MZ-80K_MiST/rtl/mz80k.sv create mode 100644 Sharp -MZ-80K_MiST/rtl/osd.v create mode 100644 Sharp -MZ-80K_MiST/rtl/pll.qip create mode 100644 Sharp -MZ-80K_MiST/rtl/pll.vhd create mode 100644 Sharp -MZ-80K_MiST/rtl/ps2.v create mode 100644 Sharp -MZ-80K_MiST/rtl/rom/80KCG.ROM create mode 100644 Sharp -MZ-80K_MiST/rtl/rom/80ktc.rom create mode 100644 Sharp -MZ-80K_MiST/rtl/scandoubler.v create mode 100644 Sharp -MZ-80K_MiST/rtl/sound.v create mode 100644 Sharp -MZ-80K_MiST/rtl/vga.v create mode 100644 Sharp -MZ-80K_MiST/rtl/video_mixer.sv create mode 100644 Sharp -MZ-80K_MiST/rtl/vram.qip create mode 100644 Sharp -MZ-80K_MiST/rtl/vram.v create mode 100644 Sharp -MZ-80K_MiST/snapshot/mz80k.rbf diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..dfe07704 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/Sharp -MZ-80K_MiST/clean.bat b/Sharp -MZ-80K_MiST/clean.bat new file mode 100644 index 00000000..b3b7c3b5 --- /dev/null +++ b/Sharp -MZ-80K_MiST/clean.bat @@ -0,0 +1,37 @@ +@echo off +del /s *.bak +del /s *.orig +del /s *.rej +del /s *~ +rmdir /s /q db +rmdir /s /q incremental_db +rmdir /s /q output_files +rmdir /s /q simulation +rmdir /s /q greybox_tmp +rmdir /s /q hc_output +rmdir /s /q .qsys_edit +rmdir /s /q hps_isw_handoff +rmdir /s /q sys\.qsys_edit +rmdir /s /q sys\vip +cd sys +for /d %%i in (*_sim) do rmdir /s /q "%%~nxi" +cd .. +for /d %%i in (*_sim) do rmdir /s /q "%%~nxi" +del build_id.v +del c5_pin_model_dump.txt +del PLLJ_PLLSPE_INFO.txt +del /s *.qws +del /s *.ppf +del /s *.ddb +del /s *.csv +del /s *.cmp +del /s *.sip +del /s *.spd +del /s *.bsf +del /s *.f +del /s *.sopcinfo +del /s *.xml +del /s new_rtl_netlist +del /s old_rtl_netlist + +pause diff --git a/Sharp -MZ-80K_MiST/mz80k.qpf b/Sharp -MZ-80K_MiST/mz80k.qpf new file mode 100644 index 00000000..609aba22 --- /dev/null +++ b/Sharp -MZ-80K_MiST/mz80k.qpf @@ -0,0 +1,30 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition +# Date created = 20:08:26 November 23, 2017 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "13.1" +DATE = "20:08:26 November 23, 2017" + +# Revisions + +PROJECT_REVISION = "mz80k" diff --git a/Sharp -MZ-80K_MiST/mz80k.qsf b/Sharp -MZ-80K_MiST/mz80k.qsf new file mode 100644 index 00000000..65cc6ac8 --- /dev/null +++ b/Sharp -MZ-80K_MiST/mz80k.qsf @@ -0,0 +1,123 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition +# Date created = 20:08:26 November 23, 2017 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# mz80k_assignment_defaults.qdf +# If this file doesn't exist, see file: +# assignment_defaults.qdf +# +# 2) Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus II software +# and any changes you make may be lost or overwritten. +# +# -------------------------------------------------------------------------- # +set_location_assignment PIN_7 -to LED +set_location_assignment PIN_54 -to CLOCK_27 +set_location_assignment PIN_144 -to VGA_R[5] +set_location_assignment PIN_143 -to VGA_R[4] +set_location_assignment PIN_142 -to VGA_R[3] +set_location_assignment PIN_141 -to VGA_R[2] +set_location_assignment PIN_137 -to VGA_R[1] +set_location_assignment PIN_135 -to VGA_R[0] +set_location_assignment PIN_133 -to VGA_B[5] +set_location_assignment PIN_132 -to VGA_B[4] +set_location_assignment PIN_125 -to VGA_B[3] +set_location_assignment PIN_121 -to VGA_B[2] +set_location_assignment PIN_120 -to VGA_B[1] +set_location_assignment PIN_115 -to VGA_B[0] +set_location_assignment PIN_114 -to VGA_G[5] +set_location_assignment PIN_113 -to VGA_G[4] +set_location_assignment PIN_112 -to VGA_G[3] +set_location_assignment PIN_111 -to VGA_G[2] +set_location_assignment PIN_110 -to VGA_G[1] +set_location_assignment PIN_106 -to VGA_G[0] +set_location_assignment PIN_136 -to VGA_VS +set_location_assignment PIN_119 -to VGA_HS +set_location_assignment PIN_65 -to AUDIO_L +set_location_assignment PIN_80 -to AUDIO_R +set_location_assignment PIN_105 -to SPI_DO +set_location_assignment PIN_88 -to SPI_DI +set_location_assignment PIN_126 -to SPI_SCK +set_location_assignment PIN_127 -to SPI_SS2 +set_location_assignment PIN_91 -to SPI_SS3 +set_location_assignment PIN_13 -to CONF_DATA0 +set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component" + +set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl" +set_global_assignment -name FAMILY "Cyclone III" +set_global_assignment -name DEVICE EP3C25E144C8 +set_global_assignment -name TOP_LEVEL_ENTITY mz80k +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1 +set_global_assignment -name PROJECT_CREATION_TIME_DATE "20:08:26 NOVEMBER 23, 2017" +set_global_assignment -name LAST_QUARTUS_VERSION 13.1 +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1 +set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (VHDL)" +set_global_assignment -name EDA_OUTPUT_DATA_FORMAT VHDL -section_id eda_simulation +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF +set_global_assignment -name ENABLE_NCE_PIN OFF +set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF +set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF +set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON +set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" +set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" +set_global_assignment -name SYSTEMVERILOG_FILE rtl/mz80k.sv +set_global_assignment -name VERILOG_FILE rtl/mycom.v +set_global_assignment -name QIP_FILE rtl/vram.qip +set_global_assignment -name SYSTEMVERILOG_FILE rtl/video_mixer.sv +set_global_assignment -name VERILOG_FILE rtl/vga.v +set_global_assignment -name VERILOG_FILE rtl/sound.v +set_global_assignment -name VERILOG_FILE rtl/scandoubler.v +set_global_assignment -name VERILOG_FILE rtl/ps2.v +set_global_assignment -name QIP_FILE rtl/pll.qip +set_global_assignment -name VERILOG_FILE rtl/osd.v +set_global_assignment -name QIP_FILE rtl/monrom.qip +set_global_assignment -name VERILOG_FILE rtl/mist_io.v +set_global_assignment -name VERILOG_FILE rtl/keyboard.v +set_global_assignment -name VERILOG_FILE rtl/i8253.v +set_global_assignment -name SYSTEMVERILOG_FILE rtl/hq2x.sv +set_global_assignment -name VERILOG_FILE rtl/fz80.v +set_global_assignment -name VHDL_FILE rtl/dac.vhd +set_global_assignment -name QIP_FILE rtl/cgrom.qip +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Sharp -MZ-80K_MiST/rtl/80KCG.hex b/Sharp -MZ-80K_MiST/rtl/80KCG.hex new file mode 100644 index 00000000..884b9f47 --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/80KCG.hex @@ -0,0 +1,129 @@ +:1000000000000000000000001824427E424242002E +:100010007C22223C22227C001C22404040221C00E8 +:1000200078242222222478007E40407840407E00BE +:100030007E404078404040001C22404E42221C003E +:100040004242427E424242001C08080808081C0046 +:100050000E040404044438004244487048444200FA +:100060004040404040407E0042665A5A4242420070 +:100070004262524A46424200182442424224180038 +:100080007C42427C40404000182442424A241A00EC +:100090007C42427C484442003C42403C02423C009C +:1000A0003E080808080808004242424242423C001A +:1000B00042424224241818004242425A5A664200E0 +:1000C00042422418244242002222221C080808002E +:1000D0007E02041820407E000C12103810103E00E2 +:1000E000080808080F00000008080808F8000000C9 +:1000F000080808080F08080808080808FF0000009A +:100100003C42465A62423C000818280808083E0053 +:100110003C42020C30407E003C42023C02423C0029 +:10012000040C14247E0404007E4078040244380049 +:100130001C20407C42423C007E420408101010000B +:100140003C42423C42423C003C42423E02043800B7 +:100150000000007E0000000000007E007E00000025 +:1001600000000800000808100002040810204000E9 +:10017000000000000018180000000000000808102F +:1001800000FF000000000000404040404040404070 +:1001900080808080808080FF01010101010101FFDA +:1001A000000000FF000000001010101010101010D0 +:1001B000FFFF000000000000C0C0C0C0C0C0C0C041 +:1001C0000000000000FF0000040404040404040410 +:1001D00000000000FFFFFFFF0F0F0F0F0F0F0F0FAB +:1001E00000000000000000FF010101010101010108 +:1001F000000000000000FFFF0303030303030303E9 +:100200000000000000000000081C3E7F7F1C3E0034 +:10021000FF7F3F1F0F070301FFFFFFFFFFFFFFFFF0 +:10022000081C3E7F3E1C0800000010207F201000AC +:10023000081C2A7F2A080800003C7E7E7E7E3C0047 +:10024000003C424242423C003C42020C1000100082 +:10025000FFC381818181C3FF0000000003040808FF +:1002600000000000C020101080C0E0F0F8FCFEFF8D +:100270000103070F1F3F7FFF000008000008000078 +:1002800000081C2A080808000E18306030180E00FC +:100290003C20202020203C00367F7F7F3E1C080031 +:1002A0003C04040404043C001C224A564C201E005A +:1002B000FFFEFCF8F0E0C08070180C060C1870000F +:1002C000000808082A1C080000402010080402004A +:1002D000000004027F020400F0F0F0F00F0F0F0F97 +:1002E000000000000F08080800000000F8080808D7 +:1002F00008080808F808080800000000FF080808B7 +:100300000000013E5414140008080808000008000A +:10031000242424000000000024247E247E242400C1 +:10032000081E281C0A1C08000062640810264600EB +:10033000304848304A443A000408100000000000E9 +:1003400004081010100804002010080808102000ED +:100350000008083E08080000082A1C3E1C2A080065 +:100360000F0F0F0FF0F0F0F0814224181824428193 +:10037000101020C000000000080804030000000066 +:10038000FF0000000000000080808080808080806E +:10039000FF80808080808080FF01010101010101D8 +:1003A0000000FF000000000020202020202020204E +:1003B000010204081020408080402010080402013F +:1003C00000000000FF0000000808080808080808EE +:1003D000FFFFFFFF00000000F0F0F0F0F0F0F0F0A1 +:1003E000000000000000FF000202020202020202FE +:1003F0000000000000FFFFFF0707070707070707C8 +:100400000000000000000000000038043C443A00F6 +:1004100040405C6242625C0000003C4240423C0062 +:1004200002023A4642463A0000003C427E403C000E +:100430000C12107C1010100000003A46463A023CA4 +:1004400040405C62424242000800180808081C0054 +:1004500004000C04040444384040444850684400FC +:100460001808080808081C00000076494949490096 +:1004700000005C624242420000003C4242423C00BA +:1004800000005C62625C404000003A46463A02026C +:1004900000005C624040400000003E403C027C00A6 +:1004A00010107C1010120C000000424242423C002E +:1004B00000004242422418000000414949493600E8 +:1004C000000044281028440000004242463A023C02 +:1004D00000007E0418207E00240038043C443A00CA +:1004E0000000000102040810031C608000000000EE +:1004F000C038060100000000000000804020100805 +:1005000000000000C0300C0300FF000000FF0000EE +:10051000444444444444444444FF444444FF444425 +:1005200022448811224488118844221188442211CF +:10053000AA44AA11AA44AA1100000000030C30C06A +:10054000030C30C000000000C0300C0300000000AD +:100550003844444A42524C000022002222221C000D +:100560000022001C22221C004200424242423C0067 +:10057000421824427E42420042182442422418007B +:1005800010202040404080800106182020404080FC +:10059000806018040402020108040402020201013E +:1005A00080804040402020108040402020180601DC +:1005B000010202040418608001010202020404081E +:1005C00010080402010000000000000080601C030D +:1005D00000000000010638C0081020408000000024 +:1005E00022143E083E08080008080808FF0808080A +:1005F00024242424C381423C003C7AA9A97A3C00EB +:100600001C1C3E1C08003E00FFF7F7F7D5E3F7FF80 +:10061000FFF7E3D5F7F7F7FFFFFFF7FB81FBF7FFE6 +:10062000FFFFEFDF81DFEFFFBDBDBD81BDBDBDFFC2 +:10063000E3DDBFBFBFDDE3FF18247EFF5A240000C7 +:10064000E047427E4247E000223E2A0808497F41B7 +:100650001C1C083E080814220011D2FCD211000014 +:1006600000884B3F4B880000221408083E081C1CE1 +:100670003C7EFFDBFF677E3C3C4281A58199423C8A +:10068000AA55AA55AA55AA550A050A050A050A0532 +:10069000A050A050A050A050AA55AA55000000009C +:1006A00000000000AA55AA55AA54A850A0408000F6 +:1006B000AA552A150A0502018040A050A854AA553F +:1006C000000102050A152A558080404020201010A4 +:1006D0000808040402020101382838000000000064 +:1006E00000542A542A542A00010102020404080872 +:1006F000101020204040808000C0C8545455220073 +:10070000000000000002FF020202020202020702D1 +:10071000020202020202FF020000205088050200CD +:10072000000E1122C404020100FF00814242810038 +:10073000007088442320408000C4A4948F94A4C4F3 +:1007400000232549F14925238890A0C0C0A898B866 +:10075000A8B0B8C0C0A09088804020101F20408062 +:1007600000002424E724240008083E00003E080876 +:10077000081020100804020455AA55AA55AA55AA23 +:100780000000000000000000007070700000000019 +:1007900000070707000000000077777700000000DF +:1007A0000000000000707070007070700070707059 +:1007B000000707070070707000777777007070701F +:1007C00000000000000707070070707000070707AF +:1007D0000007070700070707007777770007070775 +:1007E00000000000007777770070707000777777EF +:1007F00000070707007777770077777700777777B5 +:00000001FF diff --git a/Sharp -MZ-80K_MiST/rtl/80ktc.hex b/Sharp -MZ-80K_MiST/rtl/80ktc.hex new file mode 100644 index 00000000..3b58ff5d --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/80ktc.hex @@ -0,0 +1,257 @@ +:10000000C34D00C3E607184200C31809C32009C343 +:100010002609C33509C38109C39909C3BD08C33281 +:100020000AC33604C37504C3D804C3F804C38805DF +:10003000C3C701C308030000C33810C35803C3E596 +:1000400002C3FA02C3AB02C3BE02C30E0931F010F1 +:10005000ED56CDC90F063C217011CDD80F2192036A +:100060003EC33238102239103E04329E113C329F7A +:10007000113EEF329211119E01CD150031F010CFDB +:100080003E3ECD1200CD3E00CD2D0721410106118F +:10009000BE232806232310F818EECD120011740198 +:1000A000D55E2356EBE9CD2D07FE66C8CDF90338A2 +:1000B000F55FC3D303F5DBFE0F38FBF1D3FF3E80C2 +:1000C000D3FEDBFE0F30FB3E00D3FEC9CD3A08D88D +:1000D000CFCD2D07FE62280EFE63280AFE66C87784 +:1000E00023CD960118EBCDD90D18E6CD3A08D8E509 +:1000F000CD3A08D1C9CD2700D8CFDF11F1103E0D80 +:10010000320111DFCF2A0411CD1602ED5B02111965 +:100110002BCD16022A0611CD16023AF010CDC303DC +:10012000CF06682108117E23CD960110F9C9CF189A +:10013000CA46B7A5B09C200D4CB7A19CA6B097208D +:100140000D4CB20A56A80643540853F90C472D0E1D +:10015000482E0146A00645480859BF0A4D1C0D57B8 +:100160009E0A58E40C44540D4B930D54CC002324A8 +:100170000E167C0011B50138021EB9CFDFC37C001A +:10018000C5D5E51ABE200B052808FE0D280413234B +:1001900018F1E1D1C1C9CDB90BCD6D09AFC9162098 +:1001A00020202020202053BDA49692B3204DB7B02C +:1001B000A696B79D0D4EB796204FA90D56929DA6B7 +:1001C000AABDA6B097200DC5D5E53E0232A0110606 +:1001D000011AFE0D2802FEC82830FECF281FFED7C8 +:1001E0002824FE23217102200421890213CD1C0240 +:1001F00038DFCDC8023816CDAB024118D43E0332E9 +:10020000A01113C3D1013E0118F5CDC802F5CDBE32 +:1002100002F1E1D1C1C9CDBA03C3E306C506081A8C +:10022000BE280923232310F83713C1C923D55E2321 +:1002300056EB7CB728093AA0113D28032918FA2269 +:10024000A1113E0232A011D1131A47E6F0FE302868 +:10025000053A9F1118071378E60F329F114F0600D9 +:1002600021A102094E3A9E1147AF8110FDC14FAF47 +:10027000C943770744A70645ED0546980547FC04A2 +:1002800041710442F503520000430C074447064500 +:10029000980546480547B40441310442BB03520067 +:1002A000000102030406080C1018202AA1117CB7D3 +:1002B000280CD5EB2104E073723E01D118063E34C0 +:1002C0003207E0AF3208E0C92100E036F9237EE6CC +:1002D00008200237C93A08E00F38FA3A08E00F3030 +:1002E000FA10F2AFC9C5E5217104CDAE020632AFF6 +:1002F000CD5B0710FAE1C1C3BE02F5C5E60F473E6C +:100300000890329E11C1F1C9F3C5D5E5329B113E6B +:10031000F0329C1121C0A8AFED52E523EB3E7432C0 +:1003200007E03EB03207E02106E073722B360A3652 +:10033000003E803207E0234E7EBA20FB79BB20F7D7 +:100340002B0000003612367A23D14E7EBA20FB797C +:10035000BB20F7E1D1C1FBC9E53E803207E02106B1 +:10036000E0F35E56FB7BB2CA7903AF21C0A8ED5221 +:10037000DA8303EB3A9B11E1C911C0A83A9B11EE55 +:1003800001E1C9F32106E07E2F5F7E2F57FB13C3E7 +:100390007C03F5C5D5E53A9B11EE01329B113E80F9 +:1003A0003207E02106E05E5621C0A8192B2BEB2175 +:1003B00006E07372E1D1C1F1FBC97CCDC3037DCDF1 +:1003C000C303C9F5E6F00F0F0F0FCDDA03CD3D09DA +:1003D000F1E60FCDDA03CD3D09C9D5E521E903E604 +:1003E0000F5F1600197EE1D1C93031323334353612 +:1003F000373839414243444546C5E501001021E9FB +:1004000003BE2003791806230C0520F537E1C1C986 +:10041000D5CD1F04380767CD1F0438016FD1C9C57A +:100420001A13CDF903380D070707074F1A13CDF933 +:10043000033801B1C1C9F3D5C5E516031ECC21F0BF +:1004400010018000CD3307CDB206DA63057BFECC08 +:100450002011CD0900D5116C04CD150011F110CD7E +:100460001800D1CDB807CD8D04C36305579DA6965E +:10047000A6B097200DF3D5C5E516031E532A021129 +:10048000E5C12A041178B1CAD404C34404D5C5E532 +:1004900016013EF93200E07ECDA5073A01E0E608FC +:1004A000C2A70437C3D404230B78B1C297042A9798 +:1004B000117CCDA5077DCDA507CD800715C2C4044D +:1004C000B7C3D4040600CD670705C2C604E1C1C5A1 +:1004D000E5C39704E1C1D1C9F3D5C5E5160A1E28C5 +:1004E00001800021F010CDB206DA8205CD5E06DA79 +:1004F0008205CD1005C36305F3D5C5E5160A1E14A4 +:100500002A0211E5C12A041178B1CA6305C3E604C1 +:10051000D5C5E526020101E01102E0CD0106DA822F +:1005200005CD6007CD6007CD60071AE620CA1B0520 +:1005300054210000229711E1C1C5E5CD2406DA82DD +:100540000577230B78B1C23B052A9711CD2406DA33 +:1005500082055FCD2406DA8205BDC274057BBCC26C +:100560007405AFE1C1D1CD0007F53A9C11FEF02032 +:1005700001FBF1C915CA7C0562C315053E0137C3ED +:1005800063053E0237C36305F3D5C5E52A0211E5CD +:10059000C12A0411160A1E1478B1CA6305CD3307A7 +:1005A000CDB206DA8205CD5E06DA8205CDB205C38C +:1005B0006305D5C5E526010101E01102E0CD010684 +:1005C000DA8205CD6007CD6007CD60071AE620CA44 +:1005D000BD0554E1C1C5E5CD2406DA8205BEC27C65 +:1005E00005230B78B1C2D7052A9911CD2406BCC2C8 +:1005F0007C05CD2406BDC27C0515CA620562C3B761 +:10060000053EF93200E0000AE608C20F0637C91AB3 +:10061000E620C207060AE608C21D0637C91AE62008 +:10062000CA1506C9C5D5E52100080101E01102E09F +:10063000CD0106DA5A06CD6007CD6007CD60071AF6 +:10064000E620CA4F06E52A971123229711E1377D4C +:10065000176F25C23006CD01067DE1D1C1C9C5D5D0 +:10066000E5636B2295110101E01102E02A9511CD9D +:100670000106382ACD6007CD6007CD60071AE62055 +:1006800028EA2520EACD01063814CD6007CD6007A1 +:10069000CD60071AE62020D42D20EACD010618BA35 +:1006A0002100F07EB737C0E911BC01CDF500D8C3F9 +:1006B0002D00C5D5E50E0A3A02E0E61020E03E0620 +:1006C0003203E03C3203E00D20EDCF42111E07DF84 +:1006D00078835FDF3A02E0E61020C3CD440A20F4BD +:1006E0003718BBAFC36D09CD0C00D9CDA600280EBD +:1006F0004BCDA6003728077907070707831CD9C900 +:10070000F5C5D5060A3A02E0E6102004D1C1F1C9C8 +:100710003E063203E03C3203E00520E918EE7F207C +:100720000D52929FB79D9C2B50B8A1BD0DCDB30922 +:10073000C3CE0BC5D5E511000078B1200BEB229795 +:1007400011229911E1D1C1C97EE5260807300113B4 +:100750002520F9E1230BC339073E0E3DC25B07C9D3 +:100760003E0D3DC26207C9F53E033203E0CD590795 +:10077000CD59073E023203E0CD5907CD5907F1C9E3 +:10078000F53E033203E0CD5907CD5907CD5907CDCA +:1007900059073E023203E0CD5907CD5907CD59071D +:1007A000CD6007F1C9C50608CD800707DC8007D4F6 +:1007B000670705C2AB07C1C9C5D57B01F055112834 +:1007C00028FECCCACC0701F82A111414CD67070BF8 +:1007D00078B120F8CD80071520FACD67071D20FAE3 +:1007E000CD8007D1C1C9F5C5E5D5219311AF77CD2E +:1007F000B30947E6F0FEC0C2A60878FECD285CFE2D +:10080000C92819FECA2815FECBCAB308FEC8281489 +:10081000FEC728087EB7FA2708200678CDDC0D1819 +:10082000CE3518033418F478CDA60DCDB50DFE6283 +:1008300020BD7EE680EE807718B5CDE70637C86725 +:10084000CDEA0637C83F6FC92120E07EFE3E37C0A3 +:10085000E93E2EC9CD2100D8C324002A71115C16AF +:100860000021731119EB1AB70128002A7111C27AFD +:1008700008131AB7CA7D08C37B08250E502E00CD79 +:10088000B40FD1D5C5CDA60DEDB0C1E1E5417ECD0A +:10089000CE0B772310F8360D2B7EFE2028F8CD06E0 +:1008A00000D1E1C1F1C93A9311B7FA2708CA270864 +:1008B000C32108E1E5361B23360DC39E08CDCA08C7 +:1008C000FEF02002AFC9CDCE0BC9C5D5E5CD500A8B +:1008D000780738063EF0E1D1C1C907D2EC0806001E +:1008E0002108000911C90A197EC3D6083A7011B748 +:1008F000C2FD08060021C90A097EC3D60879E6F0C0 +:100900000F4779E60F80C6A06F2600C3E408AF3218 +:1009100094113ECDCDDC0DC93A9411B7C8C3060081 +:100920003E20CD3509C9CD0C003A9411B7C8D60A7E +:1009300038F420FAC9FE0DCA0E09CDA60DC54F47E1 +:10094000CD460978C1C979CDB90B4FE6F0FEF0C8A4 +:10095000FEC0792018FEC73014CDDC0DFEC328136D +:10096000FEC5CA6809FEC6C0AF329411C9CDE30FF7 +:10097000CDB50D3A94113CFE503802D65032941148 +:10098000C9F5C5D50605CDA60D1AFE0DCADF0F4F58 +:10099000CD46091310F3C38409F5C5D50605CDA6C8 +:1009A0000D1AFE0DCADF0FCDB90BCD6D091310F175 +:1009B000C39C09C5D5E5CDB10FCDA60D7E328E11F4 +:1009C000228F11AF3200E03291112F3200E021006E +:1009D00010CD1B00280E7E3D280B770630CDFF0979 +:1009E00010FB18ED77CDFF09CDCA08FEF028F6F50B +:1009F000CDA60D3A8E112A8F1177F1E1D1C1C9F53B +:100A0000E53A02E00707DA250A3A91110FDA220ADD +:100A10003A92112A8F11CDA60D773A9111EE01323B +:100A20009111E1F1C93A91110FD2220A3A8E11C304 +:100A3000130A3EF83200E0003A01E02FE621C244FA +:100A40000AC601C93EF93200E0003A01E0E608C9F1 +:100A5000D5E506FA160005783200E0FEEF200442E4 +:100A6000D1E1C9FEF828233A01E02FB728E85F7AE0 +:100A7000F6805778E60F070707074F7BC50607077D +:100A8000380210FB78C1814F18CC3A01E02F5FE6A5 +:100A90002128047AF640577BE6DE28BA18D0CD3AF2 +:100AA00008D8CFCD16020608CDE706C8772310F880 +:100AB00018F0CDBF0AD82A06117CFE123FD0E911EA +:100AC0003801CDF500D8C32A0021232527292A1D66 +:100AD0001F61636567696A5D5F22242628201C1EEA +:100AE000D162646668605C5ED0110514150F2B310D +:100AF00033514554554F6B71731712190910303229 +:100B0000D357525949507072D20104070A0C1B3551 +:100B1000374144474A4C5B75771306080B2C343633 +:100B2000D55346484B6C7476D41A03020D2EC9393E +:100B30003B5A43424D6ECA797B18160E2F2D383A18 +:100B4000D758564E6F6D787AD6F0C7F0C3CDF03DCA +:100B50003FF0C8F0C4CDF07D7FC500C1F0F03C3E51 +:100B6000DCC600C2CBF07C7ED8A1A3A5A7A9AA9D14 +:100B70009FA2A4A6A8A09C9EDD918594958FABB161 +:100B8000B39792998990B0B2DE8184878A8C9BB5A5 +:100B9000B79386888BACB4B6D99A83828DAEC9B927 +:100BA000BB98968EAFADB8BADAF0C7F0C3CDF0BD42 +:100BB000BFC500C1F0F0BCBEDBD610D2C10B3EF009 +:100BC000C9C5E521DD0B4F0600097EE1C1C9C5E5B8 +:100BD00021DD0B01F000EDB1792FB718EEF0C1C2A5 +:100BE000C3C4C5C6F0F0F0F0F0F0F0F0F0006162C0 +:100BF000636465666768696B6A2F2A2E2D2021223F +:100C0000232425262728294F2C512B5749550102EB +:100C1000030405060708090A0B0C0D0E0F1011122C +:100C2000131415161718191A5259545045C7C8C924 +:100C3000CACBCCCDCECFDFE7E8E9EAECEDD0D1D21C +:100C4000D3D4D5D6D7D8D9DADBDCDDDEC000BD9D64 +:100C5000B1B5B9B49EB2B6BABE9FB3B7BBBFA38598 +:100C6000A4A5A69487889C82988492908391819A67 +:100C700097939589A1AF8B8696A2ABAA8A8EB0ADC9 +:100C80008DA7A8A98F8CAEAC9BA099BCB8003B3AAD +:100C9000703C715A3D43563F1E4A1C5D3E5C1F5FCF +:100CA0005E377B7F367A7E334B4C1D6C5B784135EB +:100CB0003474303875394D6F6E3277767273477C85 +:100CC00053314E6D48467D441B587942600603CD32 +:100CD0003A08E5380810F8D1E1C1C5ED42DA7401EF +:100CE000E5C1E1C9CDCD0CE5ED52E1380403EDB02D +:100CF000C9EB09EB0903EDB8C9CF11F110CD030021 +:100D00003E0D320111CDCD0C03ED43021122041131 +:100D1000ED5306113E0132F010C35408CD3A08D805 +:100D2000CFCD1602E516083A9D11B72802161042DB +:100D30007ECDC30323CDE30610F6CDE306E1427E6C +:100D4000CDB90BFEF0CC5108CD6D092310F1CD11BA +:100D50000EC818CCCDEB00D8ED52D823EBCFD5067A +:100D6000FF11A31104CDEA06DADD0C121320F5CF32 +:100D7000CD830DCC160223D11B7AB3C8CD110EC87A +:100D8000D518ED11A311C5E51ABE2004132310F8E0 +:100D9000E1C1C9CDEB00D8EBCDE70637C87723E535 +:100DA000ED52E138F8C9F53A02E00730FA3A02E0CC +:100DB0000738FAF1C9F5C5D5E547CDB10F702A71ED +:100DC000117DFE2720105C1600217311197EB720BB +:100DD000052336012372C3900ECDB90BF5C5D5E5B9 +:100DE000EEC0FE0DCCF40FCA8B0FFE0BD2DE0F212E +:100DF000F90D4704232310FCC3A100320E740E84A6 +:100E00000E900EAE0EBF0EC50EF80E490FE10EEE9F +:100E10000ECD320AC8CD440AC0CDB309FE63CC243E +:100E20000E28F6C93A9D112F329D113FC9CD3A08BF +:100E3000D8E9CDA60DAF3203E001C0031100D021E7 +:100E400028D0EDB0EB0628CDD80F011A0011731190 +:100E500021731123EDB036003A7311B7C26A0ECD7B +:100E6000A60D3E013203E0C3DE0F2A711125227167 +:100E700011C3390E2A71117CFE18CA320E24227158 +:100E800011C3DE0F2A71117CB7CADE0F25C37E0E97 +:100E90002A71117DFE27D29D0E2CC37E0E2E0024BA +:100EA0007CFE19DA7E0E2618227111C3320E2A71C9 +:100EB000117DB728042DC37E0E2E2725F27E0E212C +:100EC0000000C37E0ECDA60D0E192100D00628CD40 +:100ED000D80F0DC2CD0E217311061BCDD80FC3BF85 +:100EE0000E3E053203E03E00327011C3DE0F3E04B9 +:100EF0003203E03E01C3E80E2A71117CB5CADE0F51 +:100F00007DB7C21D0F5C1600217311197EB7C21D7B +:100F10000FCDB10FCDA60D2B3600C3AE0E2A711129 +:100F20005C1C1600217311197E47B73E2828023E2B +:100F3000502A7111954F0600CDB10FE5D11BCDA6FA +:100F40000DEDB02B3600C3AE0E2A71115C1C1600DD +:100F5000217311197EB70E002A71112E2728022441 +:100F60000CCDB40F7EB7C2DE0FE52A71113E279576 +:100F70004779B728043E288047D1D5E12BCDA60D6F +:100F80007E1236002B1B10F8C3DE0F2A71115C1C79 +:100F90001600217311197EB72A7111CA9D0E2E00F9 +:100FA0007CFE1728052424C37E0E24227111C3322F +:100FB0000E2A7111C5D5E5C111280021D8CF190518 +:100FC000F2BE0F060009D1C1C92103E0368A3607F7 +:100FD00036053E013203E0C9AF772310FCC9E1D1E9 +:100FE000C1F1C9F53A9D11B72808F1F5CDCE0BCD69 +:100FF000B500F1C93A9D11B7C83E0DCDB500AFC9D6 +:00000001FF diff --git a/Sharp -MZ-80K_MiST/rtl/build_id.tcl b/Sharp -MZ-80K_MiST/rtl/build_id.tcl new file mode 100644 index 00000000..938515d8 --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/build_id.tcl @@ -0,0 +1,35 @@ +# ================================================================================ +# +# Build ID Verilog Module Script +# Jeff Wiencrot - 8/1/2011 +# +# Generates a Verilog module that contains a timestamp, +# from the current build. These values are available from the build_date, build_time, +# physical_address, and host_name output ports of the build_id module in the build_id.v +# Verilog source file. +# +# ================================================================================ + +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate [ clock format [ clock seconds ] -format %y%m%d ] + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + + # Create a Verilog file for output + set outputFileName "rtl/build_id.v" + set outputFile [open $outputFileName "w"] + + # Output the Verilog source + puts $outputFile "`define BUILD_DATE \"$buildDate\"" + puts $outputFile "`define BUILD_TIME \"$buildTime\"" + close $outputFile + + # Send confirmation message to the Messages window + post_message "Generated build identification Verilog module: [pwd]/$outputFileName" + post_message "Date: $buildDate" + post_message "Time: $buildTime" +} + +# Comment out this line to prevent the process from automatically executing when the file is sourced: +generateBuildID_Verilog \ No newline at end of file diff --git a/Sharp -MZ-80K_MiST/rtl/build_id.v b/Sharp -MZ-80K_MiST/rtl/build_id.v new file mode 100644 index 00000000..9d95a4f0 --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/build_id.v @@ -0,0 +1,2 @@ +`define BUILD_DATE "171123" +`define BUILD_TIME "223444" diff --git a/Sharp -MZ-80K_MiST/rtl/cgrom.qip b/Sharp -MZ-80K_MiST/rtl/cgrom.qip new file mode 100644 index 00000000..d16c4c00 --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/cgrom.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "ROM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "cgrom.v"] diff --git a/Sharp -MZ-80K_MiST/rtl/cgrom.v b/Sharp -MZ-80K_MiST/rtl/cgrom.v new file mode 100644 index 00000000..02de61de --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/cgrom.v @@ -0,0 +1,169 @@ +// megafunction wizard: %ROM: 1-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: cgrom.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.0 Build 162 10/23/2013 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2013 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module cgrom ( + address, + clock, + rden, + q); + + input [10:0] address; + input clock; + input rden; + output [7:0] q; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri1 clock; + tri1 rden; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [7:0] sub_wire0; + wire [7:0] q = sub_wire0[7:0]; + + altsyncram altsyncram_component ( + .address_a (address), + .clock0 (clock), + .rden_a (rden), + .q_a (sub_wire0), + .aclr0 (1'b0), + .aclr1 (1'b0), + .address_b (1'b1), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_a ({8{1'b1}}), + .data_b (1'b1), + .eccstatus (), + .q_b (), + .rden_b (1'b1), + .wren_a (1'b0), + .wren_b (1'b0)); + defparam + altsyncram_component.address_aclr_a = "NONE", + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", +`ifdef NO_PLI + altsyncram_component.init_file = "../rtl/80KCG.rif" +`else + altsyncram_component.init_file = "../rtl/80KCG.hex" +`endif +, + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 2048, + altsyncram_component.operation_mode = "ROM", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_reg_a = "CLOCK0", + altsyncram_component.widthad_a = 11, + altsyncram_component.width_a = 8, + altsyncram_component.width_byteena_a = 1; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +// Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +// Retrieval info: PRIVATE: AclrByte NUMERIC "0" +// Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +// Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: Clken NUMERIC "0" +// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +// Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +// Retrieval info: PRIVATE: MIFfilename STRING "../rtl/80KCG.hex" +// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "2048" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: RegAddr NUMERIC "1" +// Retrieval info: PRIVATE: RegOutput NUMERIC "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: SingleClock NUMERIC "1" +// Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" +// Retrieval info: PRIVATE: WidthAddr NUMERIC "11" +// Retrieval info: PRIVATE: WidthData NUMERIC "8" +// Retrieval info: PRIVATE: rden NUMERIC "1" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: INIT_FILE STRING "../rtl/80KCG.hex" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "2048" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" +// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "11" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: USED_PORT: address 0 0 11 0 INPUT NODEFVAL "address[10..0]" +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" +// Retrieval info: USED_PORT: rden 0 0 0 0 INPUT VCC "rden" +// Retrieval info: CONNECT: @address_a 0 0 11 0 address 0 0 11 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +// Retrieval info: CONNECT: @rden_a 0 0 0 0 rden 0 0 0 0 +// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL cgrom.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL cgrom.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL cgrom.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL cgrom.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL cgrom_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL cgrom_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf diff --git a/Sharp -MZ-80K_MiST/rtl/dac.vhd b/Sharp -MZ-80K_MiST/rtl/dac.vhd new file mode 100644 index 00000000..db58d70b --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/dac.vhd @@ -0,0 +1,48 @@ +------------------------------------------------------------------------------- +-- +-- Delta-Sigma DAC +-- +-- Refer to Xilinx Application Note XAPP154. +-- +-- This DAC requires an external RC low-pass filter: +-- +-- dac_o 0---XXXXX---+---0 analog audio +-- 3k3 | +-- === 4n7 +-- | +-- GND +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +entity dac is + generic ( + C_bits : integer := 8 + ); + port ( + clk_i : in std_logic; + res_n_i : in std_logic; + dac_i : in std_logic_vector(C_bits-1 downto 0); + dac_o : out std_logic + ); +end dac; + +architecture rtl of dac is + signal sig_in: unsigned(C_bits downto 0); +begin + seq: process(clk_i, res_n_i) + begin + if res_n_i = '0' then + sig_in <= to_unsigned(2**C_bits, sig_in'length); + dac_o <= '0'; + elsif rising_edge(clk_i) then + -- not dac_i(C_bits-1) effectively adds 0x8..0 to dac_i + --sig_in <= sig_in + unsigned(sig_in(C_bits) & (not dac_i(C_bits-1)) & dac_i(C_bits-2 downto 0)); + sig_in <= sig_in + unsigned(sig_in(C_bits) & dac_i); + dac_o <= sig_in(C_bits); + end if; + end process seq; +end rtl; diff --git a/Sharp -MZ-80K_MiST/rtl/fz80.v b/Sharp -MZ-80K_MiST/rtl/fz80.v new file mode 100644 index 00000000..96014f60 --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/fz80.v @@ -0,0 +1,1456 @@ +// Z80 CPU binary compatible soft core +// Copyright (C) 2004,2005 by Yasuo Kuwahara +// version 1.04 + +// This software is provided "AS IS", with NO WARRANTY. +// NON-COMMERCIAL USE ONLY + +//`define DEBUG +//`define ICE +//`define M1 + +module fz80(data_in, reset_in, clk, adr, intreq, nmireq, busreq, start, +mreq, iorq, rd, wr, data_out, busack_out, intack_out, mr, +`ifdef M1 + m1, radr, nmiack_out, +`endif +`ifdef ICE + ice_enable, sclk, sdata, +`endif + waitreq +); +`ifdef M1 + output m1, nmiack_out; + output [15:0] radr; +`endif +`ifdef ICE + input sclk, ice_enable; + output sdata; +`endif + input [7:0] data_in; + input reset_in, clk, intreq, nmireq, busreq, waitreq; + output start, mreq, iorq, rd, wr, busack_out, intack_out, mr; + output [7:0] data_out; + output [15:0] adr; + wire [7:0] q_f; + wire [7:0] q_a, q_b, q_c, q_d, q_e, q_h, q_l, q_sph, q_spl, q_pch, q_pcl, q_adrh, q_adrl, q_r, q_i, q_data; + reg sel_af, sel_exx; + wire g_if, g_imm2, g_mr1, g_mr2, g_disp, g_mw1, g_mw2, g_in, g_out; + wire sgate; + wire s_if, s_if2, s_imm1, s_imm2, s_mr1, s_mr2, s_disp, s_iack, s_mw1, s_mw2, s_in, s_out; + wire [1:0] intmode; + wire eschalt; + wire icb, idd, ied, ifd; + wire [7:0] inst_reg; + wire [7:0] q_f_out; + wire [7:0] d_f; + wire cond, cond2; +`ifdef M1 + wire [15:0] radr = { q_i, q_r }; +`endif +// + function [3:0] decode2; + input [1:0] a; + begin + case (a) + 2'h0: decode2 = 4'b0001; + 2'h1: decode2 = 4'b0010; + 2'h2: decode2 = 4'b0100; + 2'h3: decode2 = 4'b1000; + endcase + end + endfunction + function [7:0] decode3; + input [2:0] a; + begin + case (a) + 3'h0: decode3 = 8'b00000001; + 3'h1: decode3 = 8'b00000010; + 3'h2: decode3 = 8'b00000100; + 3'h3: decode3 = 8'b00001000; + 3'h4: decode3 = 8'b00010000; + 3'h5: decode3 = 8'b00100000; + 3'h6: decode3 = 8'b01000000; + 3'h7: decode3 = 8'b10000000; + endcase + end + endfunction + function [7:0] select0; + input [1:0] sel; + input [15:0] a; + begin + case (sel) + 3'h1: select0 = a[15:8]; + 3'h2: select0 = a[7:0]; + default: select0 = 8'b00000000; + endcase + end + endfunction + function [3:0] select1h; + input [3:0] sel; + input [59:0] a; + begin + case (sel) + default: select1h = a[59:56]; + 4'h1: select1h = a[55:52]; + 4'h2: select1h = a[51:48]; + 4'h3: select1h = a[47:44]; + 4'h4: select1h = a[43:40]; + 4'h5: select1h = a[39:36]; + 4'h6: select1h = a[35:32]; + 4'h7: select1h = a[31:28]; + 4'h8: select1h = a[27:24]; + 4'h9: select1h = a[23:20]; + 4'ha: select1h = a[19:16]; + 4'hb: select1h = a[15:12]; + 4'hc: select1h = a[11:8]; + 4'hd: select1h = a[7:4]; + 4'hf: select1h = a[3:0]; + endcase + end + endfunction + function [3:0] select1l; + input [3:0] sel; + input [63:0] a; + begin + case (sel) + 4'h0: select1l = a[63:60]; + 4'h1: select1l = a[59:56]; + 4'h2: select1l = a[55:52]; + 4'h3: select1l = a[51:48]; + 4'h4: select1l = a[47:44]; + 4'h5: select1l = a[43:40]; + 4'h6: select1l = a[39:36]; + 4'h7: select1l = a[35:32]; + 4'h8: select1l = a[31:28]; + 4'h9: select1l = a[27:24]; + 4'ha: select1l = a[23:20]; + 4'hb: select1l = a[19:16]; + 4'hc: select1l = a[15:12]; + 4'hd: select1l = a[11:8]; + 4'he: select1l = a[7:4]; + 4'hf: select1l = a[3:0]; + endcase + end + endfunction + function [15:0] select2; + input [2:0] sel; + input [95:0] a; + begin + case (sel) + 3'h0: select2 = a[95:80]; + 3'h1: select2 = a[79:64]; + 3'h2: select2 = a[63:48]; + 3'h4: select2 = a[47:32]; + 3'h5: select2 = a[31:16]; + default: select2 = a[15:0]; + endcase + end + endfunction + function [7:0] select3; + input [1:0] sel; + input [15:0] a; + begin + case (sel) + 2'h1: select3 = a[15:8]; + 2'h2: select3 = a[7:0]; + default: select3 = 8'b00000000; + endcase + end + endfunction + function [7:0] selectah; + input [2:0] sel; + input [63:0] a; + begin + case (sel) + 3'h1: selectah = a[63:56]; + 3'h2: selectah = a[55:48]; + 3'h3: selectah = a[47:40]; + 3'h4: selectah = a[39:32]; + 3'h5: selectah = a[31:24]; + 3'h6: selectah = a[23:16]; + 3'h7: selectah = a[15:8]; + default: selectah = a[7:0]; + endcase + end + endfunction + function [7:0] selectal; + input [2:0] sel; + input [47:0] a; + begin + case (sel) + 3'h1: selectal = a[47:40]; + 3'h4: selectal = a[39:32]; + 3'h5: selectal = a[31:24]; + 3'h6: selectal = a[23:16]; + 3'h7: selectal = a[15:8]; + default: selectal = a[7:0]; + endcase + end + endfunction + function [7:0] selectf; + input [1:0] sel; + input [31:0] a; + begin + case (sel) + 2'h0: selectf = a[31:24]; + 2'h1: selectf = a[23:16]; + 2'h2: selectf = a[15:8]; + 2'h3: selectf = a[7:0]; + endcase + end + endfunction +`ifdef ICE + parameter INST_COUNT_TARGET = 0; + reg [6:0] rs_count = 0; + reg [5:0] rs_timing = 0; + reg ice_wait = 0, sclk1 = 0, sclk2 = 0; + reg [7:0] inst_count = 0; + wire [7:0] ice_data_tmp; + assign ice_data_tmp = rd ? data_in : data_out; + wire [111:0] sdata_sel = { 2'b00, g_if, mr, mreq, iorq, rd, wr, ice_data_tmp, adr, q_f_out, q_a, q_h, q_l, q_d, q_e, q_b, q_c, q_pch, q_pcl }; + wire sdata = sdata_sel[rs_count]; + wire waitreq1 = waitreq | start | ice_wait & inst_count == INST_COUNT_TARGET; + always @(posedge clk) begin + sclk1 <= sclk; + sclk2 <= sclk1; + if (sclk1 ^ sclk2) begin + if (rs_count == 111) ice_wait <= 0; + rs_count <= rs_count + 1; + end + else if (sclk2) begin + rs_timing <= rs_timing + 1; + if (rs_timing == 31) rs_count <= 0; + end + else rs_timing <= 0; + if (start & ice_enable) ice_wait <= 1; + if (s_if & ~s_if2 & inst_count != INST_COUNT_TARGET) + inst_count <= inst_count + 1; + end +`else + wire waitreq1 = waitreq; +`endif +// instruction decoder + wire intack; + wire int1 = intmode == 2'b10 & intack; + wire [7:0] data = data_in | { 8 { int1 } }; + wire [7:0] i = g_if ? data : inst_reg; + wire i0 = ~icb & ~ied; + wire [3:0] ih = decode2(i[7:6]); + wire [7:0] im = decode3(i[5:3]); + wire [7:0] il = decode3(i[2:0]); + // 8-bit load group + wire i_ldrr = i0 & ih[1] & ~im[6] & ~il[6]; + wire i_ldrn = i0 & ih[0] & ~im[6] & il[6]; + wire i_ldrhl = i0 & ih[1] & ~im[6] & il[6]; + wire i_ldhlr = i0 & ih[1] & im[6] & ~il[6]; + wire i_ldhln = i0 & ih[0] & im[6] & il[6]; + wire i_ldabc = i0 & ih[0] & im[1] & il[2]; + wire i_ldade = i0 & ih[0] & im[3] & il[2]; + wire i_ldann = i0 & ih[0] & im[7] & il[2]; + wire i_ldbca = i0 & ih[0] & im[0] & il[2]; + wire i_lddea = i0 & ih[0] & im[2] & il[2]; + wire i_ldnna = i0 & ih[0] & im[6] & il[2]; + wire i_ldai = ied & ih[1] & im[2] & il[7]; + wire i_ldar = ied & ih[1] & im[3] & il[7]; + wire i_ldia = ied & ih[1] & im[0] & il[7]; + wire i_ldra = ied & ih[1] & im[1] & il[7]; + wire ldair = i_ldai | i_ldar; + // 16-bit load group + wire i_ldddnn = i0 & ih[0] & ~i[3] & il[1]; + wire i_ldhl_nn = i0 & ih[0] & im[5] & il[2]; + wire i_lddd_nn = ied & ih[1] & i[3] & il[3]; + wire i_ldnnhl = i0 & ih[0] & im[4] & il[2]; + wire i_ldnndd = ied & ih[1] & ~i[3] & il[3]; + wire i_ldsphl = i0 & ih[3] & im[7] & il[1]; + wire i_push = i0 & ih[3] & ~i[3] & il[5]; + wire i_pop = i0 & ih[3] & ~i[3] & il[1]; + // exchange, block + wire i_exdehl = i0 & ih[3] & im[5] & il[3]; + wire i_exafaf = i0 & ih[0] & im[1] & il[0]; + wire i_exx = i0 & ih[3] & im[3] & il[1]; + wire i_exsphl = i0 & ih[3] & im[4] & il[3]; + wire i_ldblock = ied & ih[2] & i[5] & il[0]; + wire i_cpblock = ied & ih[2] & i[5] & il[1]; + // 8-bit arithmetic & logical + wire al = i0 & (ih[2] | ih[3] & il[6]); + wire al_r = i0 & ih[2] & ~il[6]; + wire al_n = i0 & ih[3] & il[6]; + wire al_hl = i0 & ih[2] & il[6]; + wire al_r_notcp = al_r & ~im[7]; + wire al_n_notcp = al_n & ~im[7]; + wire al_hl_notcp = al_hl & ~im[7]; + wire arith8_notcp = al & ~i[5]; + wire i_cp = al & im[7]; + wire arith8 = arith8_notcp | i_cp; + wire logica = al & i[5] & (~i[4] | ~i[3]); + wire i_and = logica & im[4]; + wire i_xor = logica & im[5]; + wire i_or = logica & im[6]; + wire incdec8 = i0 & ih[0] & i[2] & ~i[1]; + wire dec8 = incdec8 & i[0]; + wire incdec_hl = incdec8 & im[6]; + // gen. arithmetic & CPU control + wire i_daa = i0 & ih[0] & im[4] & il[7]; + wire i_cpl = i0 & ih[0] & im[5] & il[7]; + wire i_neg = ied & ih[1] & im[0] & il[4]; + wire i_ccf = i0 & ih[0] & im[7] & il[7]; + wire i_scf = i0 & ih[0] & im[6] & il[7]; + wire i_halt = i0 & ih[1] & im[6] & il[6]; + wire i_eidi = i0 & ih[3] & i[5] & i[4] & il[3]; + wire i_im = ied & ih[1] & ~i[5] & il[6]; + // 16-bit arithmetic + wire add16 = i0 & ih[0] & i[3] & il[1]; + wire arith16 = ied & ih[1] & il[2]; + wire i_c16 = add16 | arith16; + wire i_incdec16 = i0 & ih[0] & il[3]; + // rotate & shift + wire i_rotate1 = i0 & ih[0] & ~i[5] & il[7]; + wire i_rs_r = icb & ih[0] & ~il[6]; + wire i_rs_hl = icb & ih[0] & il[6]; + wire i_rotate2 = icb & ih[0] & ~i[5]; + wire rotate = i_rotate1 | i_rotate2; + wire shift = icb & ih[0] & i[5]; + wire rs = rotate | shift; + wire i_rd = ied & ih[1] & i[5] & ~i[4] & il[7]; + wire i_rld = i_rd & i[3]; + wire i_rrd = i_rd & ~i[3]; + wire l = rs & ~i[3]; + wire r = rs & i[3]; + // bit/set/res + wire i_bit_r = icb & ih[1] & ~il[6]; + wire i_bit_hl = icb & ih[1] & il[6]; + wire i_setres_r = icb & i[7] & ~il[6]; + wire i_setres_hl = icb & i[7] & il[6]; + wire ibit = icb & ih[1]; + wire set = icb & ih[3]; + wire res = icb & ih[2]; + // jump + wire i_jpnn = i0 & ih[3] & im[0] & il[3]; + wire i_jpccnn = i0 & ih[3] & il[2]; + wire i_jr = i0 & ih[0] & im[3] & il[0]; + wire i_jrcc = i0 & ih[0] & i[5] & il[0]; + wire i_jphl = i0 & ih[3] & im[5] & il[1]; + wire i_djnz = i0 & ih[0] & im[2] & il[0]; + // call/return + wire i_call = i0 & ih[3] & im[1] & il[5]; + wire i_callcc = i0 & ih[3] & il[4]; + wire i_ret = i0 & ih[3] & im[1] & il[1]; + wire i_retcc = i0 & ih[3] & il[0]; + wire retin = ied & ih[1] & (im[1] | im[0]) & il[5]; + wire i_rst = i0 & ih[3] & il[7]; + // I/O + wire i_inan = i0 & ih[3] & im[3] & il[3]; + wire i_inrc = ied & ih[1] & il[0]; + wire i_outna = ih[3] & im[2] & il[3]; + wire i_outcr = ied & ih[1] & il[1]; + wire i_ioblock = ied & ih[2] & i[5] & ~i[2] & i[1]; + wire i_inblock = i_ioblock & ~i[0]; + wire i_outblock = i_ioblock & i[0]; + // bus cycle decoder + wire nmiack, g_iack; + wire imm1 = i_ldrn | i_ldhln | al_n | i_inan | i_outna | i_jr | i_jrcc | i_djnz; + wire imm2 = i_ldddnn | i_ldann | i_ldnna | i_ldhl_nn | i_ldnnhl | i_ldnndd | i_lddd_nn + | i_jpnn | i_jpccnn | i_call | i_callcc; + wire mr1 = i_ldrhl | i_ldabc | i_ldade | i_ldann | i_ldblock | i_cpblock | al_hl | incdec_hl + | i_rs_hl | i_rd | i_bit_hl | i_setres_hl | i_outblock; + wire mr2 = i_ldhl_nn | i_lddd_nn | i_pop | i_exsphl + | i_ret | i_retcc & cond | retin + | intmode == 2'b11 & intack; + wire mw1 = i_ldhlr | i_ldbca | i_lddea | i_ldnna | i_ldhln | i_ldblock | incdec_hl + | i_rs_hl | i_rd | i_setres_hl | i_inblock; + wire mw2 = i_ldnnhl | i_ldnndd | i_exsphl | i_push | i_call | i_callcc & cond | i_rst + | intmode == 2'b11 & intack | nmiack; + wire disp = (idd | ifd) & (mr1 | mw1); + wire i_in = i_inan | i_inrc | i_inblock; + wire i_out = i_outna | i_outcr | i_outblock; + // + wire mr = g_mr1 | g_mr2; // for debug + wire intack_out = (g_if | g_iack) & intack; + wire nmiack_out = g_iack & nmiack; + // load + wire tmp0 = s_if & (i_rs_r | i_setres_r); + wire tmp1 = s_if & (i_ldrr | incdec8) | s_imm1 & i_ldrn | s_mr1 & i_ldrhl | s_in & i_inrc; + wire load_a = tmp1 & im[7] + | tmp0 & il[7] + | s_mr1 & (i_ldabc | i_ldade | i_ldann | al_hl_notcp) + | s_mr2 & i_pop & im[6] + | s_if & (ldair | al_r_notcp | i_daa | i_cpl | i_neg | i_rotate1) + | s_imm1 & al_n_notcp + | s_mw1 & i_rd + | s_in & i_inan; + wire load_f = s_mr1 & i_pop & im[6]; + wire load_b = tmp1 & im[0] + | tmp0 & il[0] + | s_imm2 & i_ldddnn & im[0] + | s_mr2 & i_lddd_nn & im[1] + | s_mr2 & i_pop & im[0] + | s_imm1 & i_djnz; + wire load_c = tmp1 & im[1] + | tmp0 & il[1] + | s_imm1 & i_ldddnn & im[0] + | s_mr1 & i_lddd_nn & im[1] + | s_mr1 & i_pop & im[0]; + wire load_d = tmp1 & im[2] + | tmp0 & il[2] + | s_imm2 & i_ldddnn & im[2] + | s_mr2 & i_lddd_nn & im[3] + | s_mr2 & i_pop & im[2]; + wire load_e = tmp1 & im[3] + | tmp0 & il[3] + | s_imm1 & i_ldddnn & im[2] + | s_mr1 & i_lddd_nn & im[3] + | s_mr1 & i_pop & im[2]; + wire load_h = tmp1 & im[4] + | tmp0 & il[4] + | s_imm2 & i_ldddnn & im[4] + | s_mr2 & i_ldhl_nn + | s_mr2 & i_lddd_nn & im[5] + | s_mr2 & i_pop & im[4] + | s_if & i_c16; + wire load_l = tmp1 & im[5] + | tmp0 & il[5] + | s_imm1 & i_ldddnn & im[4] + | s_mr1 & i_ldhl_nn + | s_mr1 & i_lddd_nn & im[5] + | s_mr1 & i_pop & im[4]; + wire tmp_adr = i_ldann | i_ldnna | i_ldhl_nn | i_lddd_nn | i_ldnnhl | i_ldnndd | i_call | i_callcc | i_inan | i_outna; + wire load_adrh = s_mr2 & i_exsphl | s_imm2 & tmp_adr; + wire load_adrl = s_mr1 & i_exsphl | s_imm1 & tmp_adr | s_iack; + wire load_r = s_if & i_ldra; + wire load_i = s_if & i_ldia; + wire loadex = s_if & i_exdehl; + wire tmp2 = s_imm2 & (i_jpnn | i_jpccnn & cond); + wire load_pch = tmp2 + | s_mr2 & (i_ret | i_retcc | retin | intack); + wire load_pcl = tmp2 + | s_mr1 & (i_ret | i_retcc | retin | intack); + wire load_sph = s_imm2 & i_ldddnn & im[6] + | s_mr2 & i_lddd_nn & im[7]; + wire load_spl = s_imm1 & i_ldddnn & im[6] + | s_mr1 & i_lddd_nn & im[7]; + wire load_data = s_if & (i_rst | i_outcr) + | s_mr1 & (i_ldblock | incdec_hl | i_rd | i_rs_hl | i_setres_hl | i_outblock) + | s_imm1 & (i_ldhln | i_jpnn | i_jpccnn) + | s_in & i_inblock; + wire loada_bc = s_if & (i_ldblock | i_cpblock | i_incdec16 & ~i[5] & ~i[4]) + | s_in & i_inblock | s_mr1 & i_outblock; + wire loada_de = s_if & (i_exdehl | (i_incdec16 & ~i[5] & i[4])) + | s_mw1 & i_ldblock; + wire loada_l = s_if & i_c16; + wire loada_hl = s_if & i_incdec16 & i[5] & ~i[4] + | s_mr1 & (i_ldblock | i_cpblock) + | s_out & i_outblock + | s_mw1 & i_inblock + | s_mw2 & i_exsphl; + wire loada_sp = s_if & (i_push | i_ldsphl | i_incdec16 & i[5] & i[4] | i_call | i_callcc & cond | i_rst | intack | nmiack) + | s_mw1 & (i_push | i_exsphl | i_call | i_callcc | i_rst | intack | nmiack) + | s_mr1 & (i_pop | i_exsphl | i_ret | i_retcc | retin) + | s_mr2 & (i_pop | i_ret | i_retcc | retin) + | s_iack; + wire alu_zero; + wire loada_pc = s_if & i_jphl + | s_imm1 & (i_jr | i_jrcc & cond2 | i_djnz & ~alu_zero) + | s_mw2 & (i_call | i_callcc); + wire loada_adr = s_disp + | s_mr1 & (i_ldhl_nn | i_lddd_nn | intack) + | s_mw1 & (i_ldnnhl | i_ldnndd); + wire load3_pc = s_mw2 & i_rst; + wire load66_pc = s_mw2 & nmiack; + wire clr_pch = s_mw2 & (i_rst | nmiack); + wire count_pc = (s_if | s_imm1 | s_imm2) & ~(i_halt | intack | nmiack) & ~(s_if2 & (i_ldblock | i_cpblock | i_ioblock)) + | s_disp + | s_mr1 & (i_ldblock | i_cpblock) + | s_in & i_inblock + | s_out & i_outblock + | eschalt; + wire asu_zero; + reg q_asu_zero; + wire dec_pc = (i_ldblock | i_cpblock) & i[4] & ~q_asu_zero & ~(i_cpblock & alu_zero) + | i_inblock & i[4] & ~asu_zero + | i_outblock & i[4] & ~q_f[6]; + wire count_r = s_if; + // + // ALU block + // + // selector 0 (for alu-input a) + wire sel0_a = i_cpblock | al | i_daa; + wire sel0_h = i_c16; + wire [1:0] sel0 = { sel0_h, sel0_a }; + // selector 1 (for alu-input b) + wire sel1_tmp = i_ldrr | i_ldrhl | i_ldhlr | al_r | i_rs_r | i_bit_r | i_setres_r; + wire sel1_b = sel1_tmp & il[0] + | incdec8 & im[0] + | g_mw2 & i_ldnndd & im[0] + | g_mw1 & i_push & im[0] + | i_c16 & (im[0] | im[1]) + | i_djnz + | i_outcr & im[0]; + wire sel1_c = sel1_tmp & il[1] + | incdec8 & im[1] + | g_mw1 & i_ldnndd & im[0] + | g_mw2 & i_push & im[0] + | i_outcr & im[1]; + wire sel1_d = sel1_tmp & il[2] + | incdec8 & im[2] + | g_mw2 & i_ldnndd & im[2] + | g_mw1 & i_push & im[2] + | i_c16 & (im[2] | im[3]) + | i_outcr & im[2]; + wire sel1_e = sel1_tmp & il[3] + | incdec8 & im[3] + | g_mw1 & i_ldnndd & im[2] + | g_mw2 & i_push & im[2] + | i_outcr & im[3]; + wire sel1_h = sel1_tmp & il[4] + | incdec8 & im[4] + | g_mw2 & (i_ldnnhl | i_ldnndd & im[4]) + | g_mw1 & (i_push & im[4] | i_exsphl) + | i_c16 & (im[4] | im[5]) + | i_outcr & im[4]; + wire sel1_l = sel1_tmp & il[5] + | incdec8 & im[5] + | g_mw1 & (i_ldnnhl | i_ldnndd & im[4]) + | g_mw2 & (i_push & im[4] | i_exsphl) + | i_outcr & im[5]; + wire sel1_a = sel1_tmp & il[7] | i_ldbca | i_lddea + | incdec8 & im[7] + | i_cpl | i_neg + | g_mw1 & (i_ldnna | i_push & im[6]) + | i_rotate1 + | i_outna + | i_outcr & im[7]; + wire sel1_data = g_mw1 & (i_ldhln | i_ldblock | incdec_hl | i_rs_hl | i_setres_hl | i_inblock) + | g_imm2 & (i_jpnn | i_jpccnn) + | g_out & (i_outcr & im[6] | i_outblock); + wire sel1_sph = g_mw2 & i_ldnndd & im[6] + | i_c16 & (im[6] | im[7]); + wire sel1_spl = g_mw1 & i_ldnndd & im[6]; + wire sel1_pch = g_mw1 & (i_call | i_callcc | i_rst | intack | nmiack); + wire sel1_pcl = g_mw2 & (i_call | i_callcc | i_rst | intack | nmiack); + wire sel1_i = i_ldai; + wire sel1_r = i_ldar; + wire [3:0] sel1 = { + sel1_b | sel1_c | sel1_d | sel1_e | sel1_h | sel1_l | sel1_a, + sel1_h | sel1_l | sel1_a | sel1_pch | sel1_pcl | sel1_i | sel1_r, + sel1_sph | sel1_spl | sel1_d | sel1_e | sel1_a | sel1_pch | sel1_pcl, + sel1_data | sel1_spl | sel1_c | sel1_e | sel1_l | sel1_a | sel1_pcl | sel1_r + }; + wire sel_rld = g_mw1 & i_rld; + wire sel_rrd = g_mw1 & i_rrd; + wire [3:0] sel1h = { + sel1[3] | sel_rld | sel_rrd, + sel1[2] | sel_rld | sel_rrd, + sel1[1] | sel_rld | sel_rrd, + sel1[0] | sel_rld | sel_rrd + }; + wire [3:0] sel1l = { + sel1[3] | sel_rld, + sel1[2] | sel_rld, + sel1[1] | sel_rld, + sel1[0] | sel_rrd + }; + //initial $monitor($stime,, sel1_b, sel1_c, sel1_d, sel1_e, sel1_h, sel1_l, sel1_a, sel1_data, sel1_sph, sel1_spl, sel1_pch, sel1_pcl); + // + wire [7:0] alu_z, alu_c; + assign alu_zero = ~| alu_z; + wire inva = dec8 | i_djnz; + wire sub = i_cpblock | arith8 & i[4] | i_daa & q_f[1] | i_cpl | i_neg | arith16 & ~i[3]; + wire asu_co; + wire ci = q_f[0] & arith8 & ~i[5] & i[3] | (add16 | arith16) & asu_co | incdec8 & ~i[0]; + wire s_and = i_and; + wire s_xor = i_cpblock | i_cpl | arith8 | i_xor | incdec8 | i_c16 | i_daa | i_neg | i_djnz; + wire s_or = ~s_and & ~s_xor & ~rs & ~i_outcr; + wire ec = i_cpblock | arith8 & (~i[5] | i[3]) | incdec8 | i_c16 | i_daa | i_neg | i_djnz; + wire [7:0] alu_a = select0(sel0, { q_a, q_h }); + wire [3:0] alu_bh = select1h(sel1h, { data[7:4], q_data[7:4], q_sph[7:4], q_spl[7:4], q_i[7:4], q_r[7:4], q_pch[7:4], q_pcl[7:4], q_b[7:4], q_c[7:4], q_d[7:4], q_e[7:4], q_h[7:4], q_l[7:4], q_a[7:4] }); + wire [3:0] alu_bl = select1l(sel1l, { data[3:0], q_data[3:0], q_sph[3:0], q_spl[3:0], q_i[3:0], q_r[3:0], q_pch[3:0], q_pcl[3:0], q_b[3:0], q_c[3:0], q_d[3:0], q_e[3:0], q_h[3:0], q_l[3:0], q_data[7:4], q_a[3:0] }); + wire [7:0] alu_b = { alu_bh, alu_bl }; + alu alu(.c_in(ci), .im(im), .a(alu_a), .b(alu_b), .inva(inva), .invb(sub), + .reg_q_c(q_f[0]), .reg_q_h(q_f[4]), + .s_and(s_and), .s_or(s_or), .s_xor(s_xor), .ec(ec), + .i_daa(i_daa), .set(set), .res(res), .l(l), .r(r), + .z(alu_z), .co(alu_c)); + // + // ASU block + // + // selector 2 (for asu-input a) + wire sel2_bc = g_if & (i_ldblock | i_cpblock | (i_c16 | i_incdec16) & ~i[5] & ~i[4]) + | g_in & i_inblock + | g_mr1 & i_outblock; + wire sel2_de = g_mw1 & i_ldblock + | (i_c16 | i_incdec16) & ~i[5] & i[4]; + wire sel2_hl = g_disp + | i_ldsphl | i_exdehl | (i_c16 | i_incdec16) & i[5] & ~i[4] | i_jphl + | g_mr1 & (i_ldblock | i_cpblock) + | g_out & i_outblock + | g_mw1 & i_inblock; + wire sel2_pc = i_jr | i_jrcc | i_djnz; + wire sel2_adr = i_ldhl_nn | i_lddd_nn | i_ldnnhl | i_ldnndd + | g_mr1 & intack + | g_mw2 & (i_exsphl | i_call | i_callcc); + wire [2:0] sel2 = { + sel2_bc | sel2_de | sel2_hl, + sel2_adr | sel2_hl, + sel2_pc | sel2_de + }; + // selector 3 (for asu-input b) + wire sel3_l = i_c16; + wire sel3_data_in = g_disp | i_jr | i_jrcc | i_djnz; + wire [1:0] sel3 = { + sel3_data_in, + sel3_l + }; + // + wire [15:0] asu_z; + assign asu_zero = ~| asu_z[15:8] & (i_ioblock | ~| asu_z[7:0]); + wire asu_ci = i_ldhl_nn | i_lddd_nn | i_ldnnhl | i_ldnndd | i_pop + | s_mr1 & (i_exsphl | intack) + | (s_mr1 | s_mw1) & (i_ldblock | i_cpblock) & ~i[3] + | (s_out | s_mw1) & i_ioblock & ~i[3] + | q_f[0] & arith16 | i_incdec16 & ~i[3] | i_jr | i_jrcc | i_djnz | i_ret | i_retcc | retin; + wire [2:0] asu_i = { + s_in & i_inblock | s_mr1 & i_outblock, + s_in & i_inblock | s_mr1 & i_outblock + | s_if & (i_push | i_ldblock | i_cpblock | i_incdec16 & i[3] | i_call | i_callcc | i_rst | intack | nmiack) + | s_mw1 & (i_push | i_exsphl | (i_ldblock | i_inblock) & i[3] | i_call | i_callcc | i_rst | intack | nmiack) + | s_mr1 & (i_ldblock | i_cpblock) & i[3] + | s_out & i_outblock & i[3] + | s_iack, + s_if & i_c16 & ~i[3] + }; + wire [15:0] asu_a = select2(sel2, { q_sph, q_spl, q_pch, q_pcl, q_adrh, q_adrl, q_b, q_c, q_d, q_e, q_h, q_l }); + wire [7:0] asu_b = select3(sel3, { q_l, data_in }); + asu asu(.a(asu_a), .b(asu_b), .ci(asu_ci), .i(asu_i), .z(asu_z), .co(asu_co)); + always @(posedge clk) + if (s_if | s_in) q_asu_zero <= asu_zero; + // + // address selector + // + wire sela_tmp = g_mr1 | g_mr2 | g_mw1 | g_mw2 | g_in | g_out; + wire sela_tmp2 = i_ldann | i_ldnna | i_ldhl_nn | i_lddd_nn | i_ldnnhl | i_ldnndd; + wire sela_tmp3 = (idd | ifd) & (g_mr1 | g_mw1); + wire selah_a = sela_tmp & (i_inan | i_outna); + wire sela_bc = sela_tmp & (i_ldabc | i_ldbca | i_inrc | i_outcr) + | g_in & i_inblock | g_out & i_outblock; + wire sela_de = g_mr1 & i_ldade | g_mw1 & (i_lddea | i_ldblock); + wire sela_hl = ~sela_tmp3 & (sela_tmp & (i_ldrhl | i_ldhlr | i_ldhln | i_cpblock | al_hl | incdec_hl | i_rs_hl | i_rd | i_bit_hl | i_setres_hl) + | g_mw1 & i_inblock + | g_mr1 & (i_ldblock | i_outblock)); + wire selah_adr = sela_tmp3 | sela_tmp & sela_tmp2; + wire selal_adr = sela_tmp3 + | sela_tmp & (sela_tmp2 | i_inan | i_outna) + | (g_mr1 | g_mr2) & intack; + wire sela_sp = sela_tmp & (i_push | i_pop | i_exsphl | i_call | i_callcc | i_ret | i_retcc | retin | i_rst) + | (g_mw1 | g_mw2) & (intack | nmiack); + wire selah_i = (g_mr1 | g_mr2) & intack; + wire [2:0] selah = { + sela_bc | sela_de | sela_hl | sela_sp, + selah_a | selah_i | sela_hl | sela_sp, + selah_adr | selah_i | sela_de | sela_sp + }; + wire [2:0] selal = { + sela_bc | sela_de | sela_hl | sela_sp, + sela_hl | sela_sp, + selal_adr | sela_de | sela_sp + }; + //initial $monitor($stime,, selal,, selah); + // final selector + wire sel_fr = g_mw2 & i_push & im[6]; + wire [1:0] self = { + sel_rld | sel_rrd, + sel_fr | sel_rrd + }; + //initial $monitor($stime,, self); + // sequencer + seq seq(.data_in(data), .busreq(busreq), .waitreq(waitreq1), .intreq(intreq), .nmireq(nmireq), .reset_in(reset_in), .clk(clk), + .intack(intack), .nmiack(nmiack), .busack(busack_out), .iff2(iff2), .start(start), + .icb(icb), .idd(idd), .ied(ied), .ifd(ifd), .inst_reg(inst_reg), + .mreq(mreq), .iorq(iorq), .rd(rd), .wr(wr), + .imm1(imm1), .imm2(imm2), .mr1(mr1), .mr2(mr2), .mw1(mw1), .mw2(mw2), .disp(disp), .i_in(i_in), .i_out(i_out), .i_eidi(i_eidi), .i_im(i_im), .retin(retin), .i43(i[4:3]), + .g_if(g_if), .g_imm2(g_imm2), .g_mr1(g_mr1), .g_mr2(g_mr2), .g_mw1(g_mw1), .g_mw2(g_mw2), .g_disp(g_disp), .g_in(g_in), .g_out(g_out), .g_iack(g_iack), + .sgate(sgate), + .s_if(s_if), .s_if2(s_if2), .s_imm1(s_imm1), .s_imm2(s_imm2), + .s_mr1(s_mr1), .s_mr2(s_mr2), .s_mw1(s_mw1), .s_mw2(s_mw2), + .s_disp(s_disp), .s_in(s_in), .s_out(s_out), .s_iack(s_iack), +`ifdef M1 + .m1(m1), +`endif + .intmode(intmode), .i_halt(i_halt), .eschalt(eschalt)); +// exchange register + always @(posedge clk) begin + if (reset_in) begin + sel_af <= 1'b0; + sel_exx <= 1'b0; + end + else begin + if (s_if & i_exafaf) sel_af <= ~sel_af; + if (s_if & i_exx) sel_exx <= ~sel_exx; + end + end +//// F register + wire sel = alu_z[i[5:3]]; + wire subf = incdec8 ? i[0] : sub; + wire cv0 = arith8 | arith16 | i_daa | i_neg | add16; + wire cv1 = i_ccf; + wire cv2 = i_scf; + wire cv3 = l; + wire cv4 = r; + wire cv5 = logica; + assign d_f[0] = data_in[0] & load_f + | (alu_c[7] ^ sub) & cv0 + | ~q_f[0] & cv1 + | cv2 + | alu_b[7] & cv3 + | alu_b[0] & cv4 + | q_f[0] & ~(load_f | cv0 | cv1 | cv2 | cv3 | cv4 | cv5); + wire nv0 = i_ioblock; + wire nv1 = (arith8 | incdec8 | arith16) & subf | i_cpblock | i_cpl | i_neg; + wire nv2 = (arith8 | incdec8 | add16 | arith16) & ~subf | ldair | i_inrc | i_rd | i_ccf | i_scf | i_ldblock | logica | rs | ibit; + assign d_f[1] = data_in[1] & load_f + | alu_b[7] & nv0 + | nv1 + | q_f[1] & ~(load_f | nv0 | nv1 | nv2); + wire pv0 = ldair; + wire pv1 = i_ldblock | i_cpblock; + wire pv2 = arith8 | arith16 | i_neg | incdec8; + wire pv3 = logica | i_daa | i_rotate2 | shift | i_rd | i_inrc; + wire pv4 = ibit; + assign d_f[2] = data_in[2] & load_f + | iff2 & pv0 + | ~q_asu_zero & pv1 + | (alu_c[7] ^ alu_c[6]) & pv2 + | ~^alu_z[7:0] & pv3 + |~sel & pv4 + | q_f[2] & ~(load_f | pv0 | pv1 | pv2 | pv3 | pv4); + wire xy0 = arith8_notcp | incdec8 | i_daa | i_cpl | i_neg | i_ccf | i_scf | add16 | arith16 | rs | i_rd | i_inrc; + wire xy1 = i_cp; + wire xy2 = ibit; + wire xy3 = i_ioblock; + assign d_f[3] = data_in[3] & load_f + | alu_z[3] & (xy0 | i_ldblock) + | alu_b[3] & xy1 + | ~i[5] & i[4] & i[3] & sel & xy2 + | q_b[3] & xy3 + | q_f[3] & ~(load_f | xy0 | xy1 | xy2 | xy3); + wire hv0 = arith8 | arith16 | i_neg | i_cpblock | incdec8 | add16; + wire hv1 = i_and | i_cpl | ibit; + wire hv2 = i_ccf; + wire hv3 = ldair | i_inrc | i_rd | i_ldblock | i_or | i_xor | i_scf | rs; + assign d_f[4] = data_in[4] & load_f + | (alu_c[3] ^ subf) & hv0 + | hv1 + | q_f[0] & hv2 + | (q_f[1] ? ~alu_b[3] & (~alu_b[2] | ~alu_b[1]) : alu_b[3] & (alu_b[2] | alu_b[1])) & i_daa + | q_f[4] & ~(load_f | hv0 | hv1 | hv2 | hv3 | i_daa); + assign d_f[5] = data_in[5] & load_f + | alu_z[5] & xy0 + | alu_b[5] & xy1 + | i[5] & ~i[4] & i[3] & sel & xy2 + | q_b[5] & xy3 + | alu_z[1] & i_ldblock + | q_f[5] & ~(load_f | xy0 | xy1 | xy2 | xy3 | i_ldblock); + wire zs0 = arith8 | arith16 | i_daa | i_neg | i_cpblock | incdec8 | ldair | i_inrc | i_rd | i_rotate2 | shift | logica; + wire zs1 = ibit; + wire zl = ~| alu_z[7:0]; + wire zu = ~| asu_z[7:0]; + assign d_f[6] = data_in[6] & load_f + | zl & zs0 & (~arith16 | zu) + | ~sel & zs1 + | q_asu_zero & i_inblock + | asu_zero & i_outblock + | q_f[6] & ~(load_f | zs0 | zs1 | i_ioblock); + assign d_f[7] = data_in[7] & load_f + | alu_z[7] & zs0 + | i[5] & i[4] & i[3] & sel & zs1 + | q_b[7] & i_ioblock + | q_f[7] & ~(load_f | zs0 | zs1 | i_ioblock); +// assign q_f_out = q_f; + assign q_f_out = { q_f[7:6], 1'b0, q_f[4], 1'b0, q_f[2:0] }; + wire [7:0] cond3_sel = { q_f[7], ~q_f[7], q_f[2], ~q_f[2], q_f[0], ~q_f[0], q_f[6], ~q_f[6] }; + assign cond = cond3_sel[i[5:3]]; + wire [3:0] cond2_sel = { q_f[0], ~q_f[0], q_f[6], ~q_f[6] }; + assign cond2 = cond2_sel[i[4:3]]; +// + wire [15:0] adr = { + selectah(selah, { q_adrh, q_a, q_i, q_b, q_d, q_h, q_sph, q_pch }), + selectal(selal, { q_adrl, q_c, q_e, q_l, q_spl, q_pcl }) + }; + wire [7:0] data_out = selectf(self, { alu_b, q_f_out, q_data[3:0], q_a[3:0], q_a[3:0], q_data[7:4] }); + wire loadal = loada_hl | loada_l; + wire clr_pch1 = reset_in | clr_pch; + wire reg_load_f = sgate & ~((g_if | g_mw1) & (al_n | al_hl | incdec_hl | i_rs_hl)) & ~g_out & ~g_disp; + reg_a reg_a(.a(alu_z), + .load(load_a), + .set(reset_in), .regsel(sel_af), .clk(clk), .q(q_a)); + reg_f reg_f(.a(d_f), + .load(reg_load_f), + .set(reset_in), .regsel(sel_af), .clk(clk), .q(q_f)); + reg_dual2 reg_b(.a(alu_z), .a2(asu_z[15:8]), + .load(load_b), .load2(loada_bc), + .regsel(sel_exx), .clk(clk), .q(q_b)); + reg_dual2 reg_c(.a(alu_z), .a2(asu_z[7:0]), + .load(load_c), .load2(loada_bc), + .regsel(sel_exx), + .clk(clk), .q(q_c)); + reg_dual2 reg_d(.a(alu_z), .a2(asu_z[15:8]), + .load(load_d), .load2(loada_de), + .regsel(sel_exx), + .clk(clk), .q(q_d)); + reg_dual2 reg_e(.a(alu_z), .a2(asu_z[7:0]), + .load(load_e), .load2(loada_de), + .regsel(sel_exx), + .clk(clk), .q(q_e)); + wire indexvalid = ~(g_mr1 & i_ldrhl | g_mw1 & i_ldhlr); + reg_quad3 reg_h(.a(alu_z), .a2(asu_z[15:8]), .a3(q_d), + .load(load_h), .load2(loada_hl), .load3(loadex), + .regsel(sel_exx), + .i_dd(idd & indexvalid), .i_fd(ifd & indexvalid), + .clk(clk), .q(q_h)); + reg_quad3 reg_l(.a(alu_z), .a2(asu_z[7:0]), .a3(q_e), + .load(load_l), .load2(loadal), .load3(loadex), + .regsel(sel_exx), + .i_dd(idd & indexvalid), .i_fd(ifd & indexvalid), + .clk(clk), .q(q_l)); + reg_2s reg_sph(.a(data_in), .a2(asu_z[15:8]), + .load(load_sph), .load2(loada_sp), + .set(reset_in), + .clk(clk), .q(q_sph)); + reg_2s reg_spl(.a(data_in), .a2(asu_z[7:0]), + .load(load_spl), .load2(loada_sp), + .set(reset_in), + .clk(clk), + .q(q_spl)); + reg_pch reg_pch(.a(data_in), .a2(asu_z[15:8]), + .load(load_pch), .load2(loada_pc), .count(co_pc), .dec(dec_pc), + .clr(clr_pch1), + .clk(clk), + .q(q_pch)); + reg_pcl reg_pcl(.a(alu_z), .a2(asu_z[7:0]), .a3(q_data[5:3]), + .load(load_pcl), .load2(loada_pc), .load3(load3_pc), .load66(load66_pc), .count(count_pc), .dec(dec_pc), + .clr(reset_in), + .clk(clk), + .q(q_pcl), .co(co_pc)); + reg_2 reg_adrh(.a(data_in), .a2(asu_z[15:8]), + .load(load_adrh), .load2(loada_adr), + .clk(clk), + .q(q_adrh)); + reg_2 reg_adrl(.a(data_in), .a2(asu_z[7:0]), + .load(load_adrl), .load2(loada_adr), + .clk(clk), + .q(q_adrl)); + reg_r reg_r(.a(q_a), + .load(load_r), + .count(count_r), + .clr(reset_in), + .clk(clk), + .q(q_r)); + reg_simplec reg_i(.a(q_a), + .load(load_i), + .clr(reset_in), + .clk(clk), + .q(q_i)); + reg_simple reg_data(.a(alu_z), + .load(load_data), + .clk(clk), + .q(q_data)); +`ifdef DEBUG + wire [15:0] debug_pc, debug_sp, debug_bc, debug_de, debug_hl; + assign debug_pc = { q_pch, q_pcl }; + assign debug_sp = { q_sph, q_spl }; + assign debug_bc = { q_b, q_c }; + assign debug_de = { q_d, q_e }; + assign debug_hl = { q_h, q_l }; + initial $monitor($stime, " %x %x %x %x %x %x %x %x", seq.state, debug_pc, debug_sp, debug_bc, debug_de, debug_hl, q_a, q_f_out); +`endif +endmodule + +module seq(data_in, busreq, waitreq, intreq, nmireq, reset_in, clk, + intack, nmiack, busack, iff2, icb, idd, ied, ifd, inst_reg, start, + mreq, iorq, rd, wr, + imm1, imm2, mr1, mr2, mw1, mw2, disp, i_in, i_out, i_eidi, i_im, retin, i43, + g_if, g_imm2, g_mr1, g_mr2, g_mw1, g_mw2, g_disp, g_in, g_out, g_iack, + sgate, + s_if, s_if2, s_imm1, s_imm2, s_mr1, s_mr2, s_mw1, s_mw2, s_disp, s_in, s_out, s_iack, +`ifdef M1 + m1, +`endif + intmode, i_halt, eschalt); + input [7:0] data_in; + input [1:0] i43; + input busreq, waitreq, intreq, nmireq, reset_in, clk; + input imm1, imm2, mr1, mr2, mw1, mw2, disp, i_in, i_out, i_eidi, i_im, retin; + input i_halt; + output mreq, iorq, rd, wr; + output intack, nmiack, busack, iff2, icb, idd, ied, ifd, start; + output [7:0] inst_reg; + output g_if, g_imm2, g_mr1, g_mr2, g_mw1, g_mw2, g_disp, g_in, g_out, g_iack; + output sgate; + output s_if, s_if2, s_imm1, s_imm2, s_mr1, s_mr2, s_mw1, s_mw2, s_disp, s_in, s_out, s_iack; + output [1:0] intmode; + output eschalt; +`ifdef M1 + output m1; +`endif + parameter S_IF1 = 4'b0000; + parameter S_IF2 = 4'b0001; + parameter S_IMM1 = 4'b0010; + parameter S_IMM2 = 4'b0011; + parameter S_MR1 = 4'b0100; + parameter S_MR2 = 4'b0101; + parameter S_DISP = 4'b0110; + parameter S_IN = 4'b0111; + parameter S_IACK = 4'b1000; + parameter S_MW1 = 4'b1100; + parameter S_MW2 = 4'b1101; + parameter S_OUT = 4'b1111; + reg [3:0] state; + reg [7:0] inst_reg; + reg icb, ied, idd, ifd, iff1, iff2, intack, nmiack, busack, eschalt; + reg [1:0] intmode; + reg start; + wire g_if = state[3:1] == 3'b000; + wire g_if1 = state == S_IF1; + wire g_if2 = state == S_IF2; + wire g_imm1 = state == S_IMM1; + wire g_imm2 = state == S_IMM2; + wire g_mr1 = state == S_MR1; + wire g_mr2 = state == S_MR2; + wire g_disp = state == S_DISP; + wire g_in = state == S_IN; + wire g_iack = state == S_IACK; // IM2 | NMI only + wire g_mw1 = state == S_MW1; + wire g_mw2 = state == S_MW2; + wire g_out = state == S_OUT; + wire sgate = ~reset_in & ~busack & ~waitreq; + wire s_if = sgate & g_if; + wire s_if2 = sgate & g_if2; + wire s_imm1 = sgate & g_imm1; + wire s_imm2 = sgate & g_imm2; + wire s_mr1 = sgate & g_mr1; + wire s_mr2 = sgate & g_mr2; + wire s_disp = sgate & g_disp; + wire s_in = sgate & g_in; + wire s_iack = sgate & g_iack; + wire s_mw1 = sgate & g_mw1; + wire s_mw2 = sgate & g_mw2; + wire s_out = sgate & g_out; + wire nextcycle = g_if1 & data_in != 8'hcb & data_in != 8'hdd & data_in != 8'hed & data_in != 8'hfd & ~intack & ~disp & ~imm1 & ~imm2 & ~mr1 & ~mr2 & ~mw1 & ~mw2 & ~i_in + | g_if2 & ~imm1 & ~imm2 & ~mr1 & ~mr2 & ~i_in & ~i_out + | g_imm1 & ~imm2 & ~mw1 & ~i_in & ~i_out + | g_imm2 & ~mr1 & ~mr2 & ~mw1 & ~mw2 + | g_mr1 & ~mr2 & ~mw1 & ~mw2 & ~i_out + | g_mr2 & ~intack & ~mw1 & ~mw2 + | g_mw1 & ~mw2 + | g_mw2 & ~intack + | g_in & ~mw1 + | g_out; + wire next_if2 = (g_if1 & (data_in == 8'hcb & ~idd & ~ifd | data_in == 8'hed) + | g_disp & icb); + wire next_imm1 = (g_if1 & ~disp & (imm1 | imm2) + | g_disp & ~icb & imm1 + | g_if2 & (imm1 | imm2)); + wire next_imm2 = g_imm1 & imm2; + wire next_mr1 = (g_if1 & ~disp & ~imm1 & ~imm2 & (mr1 | mr2) + | g_disp & ~icb & ~imm1 & mr1 + | g_if2 & ~imm1 & ~imm2 & (mr1 | mr2) + | g_imm2 & (mr1 | mr2) + | g_mw2 & intack & intmode == 2'b11); + wire next_mr2 = g_mr1 & mr2; + wire next_disp = g_if1 & (data_in == 8'hcb & (idd | ifd) | disp); + wire next_in = i_in & (g_if1 & ~imm1 & ~mw1 + | g_if2 + | g_imm1); + wire next_iack = (nextcycle & (nmireq | intreq & iff1 & intmode == 2'b11)); + wire next_mw1 = (g_if1 & ~disp & ~imm1 & ~imm2 & ~mr1 & ~mr2 & (mw1 | mw2) + | g_disp & ~icb & ~imm1 & ~mr1 + | g_imm1 & ~imm2 & mw1 + | g_imm2 & ~mr1 & ~mr2 & (mw1 | mw2) + | g_mr1 & ~mr2 & (mw1 | mw2) + | g_mr2 & ~intack & (mw1 | mw2) + | g_in & mw1 + | g_iack); + wire next_mw2 = g_mw1 & mw2; + wire next_out = i_out & (g_if2 & ~imm1 & ~mr1 + | g_imm1 + | g_mr1); + always @(posedge clk) begin + if (reset_in) begin + state <= S_IF1; + start <= 1'b1; + icb <= 1'b0; + ied <= 1'b0; + idd <= 1'b0; + ifd <= 1'b0; + iff1 <= 1'b0; + iff2 <= 1'b0; + intmode <= 2'b00; + intack <= 1'b0; + nmiack <= 1'b0; + busack <= 1'b0; + eschalt <= 1'b0; + end + else if (busack) begin + if (~busreq) busack <= 1'b0; + end + else if (waitreq) start <= 1'b0; + else begin + state <= { + next_iack | next_mw1 | next_mw2 | next_out, + next_mr1 | next_mr2 | next_disp | next_in | next_mw1 | next_mw2 | next_out, + next_imm1 | next_imm2 | next_disp | next_in | next_out, + next_if2 | next_imm2 | next_mr2 | next_in | next_mw2 | next_out + }; + start <= 1'b1; + if (g_if1) begin + inst_reg <= data_in; + intack <= 1'b0; // when IM0 | IM1 + eschalt <= 1'b0; + if (data_in == 8'hcb) icb <= 1'b1; + if (data_in == 8'hed) ied <= 1'b1; + if (data_in == 8'hdd) begin + idd <= 1'b1; + ifd <= 1'b0; + end + if (data_in == 8'hfd) begin + ifd <= 1'b1; + idd <= 1'b0; + end + end + else if (g_if2) inst_reg <= data_in; + else if (g_mr2) intack <= 1'b0; // IM2 + else if (g_mw2) begin + if (intack & intmode != 2'b11) intack <= 1'b0; + nmiack <= 1'b0; + end + else if (g_iack) eschalt <= 1'b0; + if (i_eidi) begin + iff1 <= i43[0]; + iff2 <= i43[0]; + end + if (retin) iff1 <= iff2; + if (i_im) intmode <= i43[1:0]; + if (nextcycle) begin + icb <= 1'b0; + ied <= 1'b0; + idd <= 1'b0; + ifd <= 1'b0; + if (nmireq) begin + nmiack <= 1'b1; + iff1 <= 1'b0; + eschalt <= i_halt; + inst_reg <= 8'b00000000; + end + else if (intreq & iff1) begin + intack <= 1'b1; + iff1 <= 1'b0; + iff2 <= 1'b0; + eschalt <= i_halt; + inst_reg <= 8'b00000000; + end + end + if (busreq) busack <= 1'b1; + end + end + wire intack_r = (g_if | g_iack) & intack; + wire iorq_t = state[2:0] == 3'b111 | intack_r; + wire iorq = ~busack & iorq_t; + wire mreq = ~busack & ~iorq_t & ~intack_r; + wire rd = ~busack & (~state[3] | g_iack) & ~intack_r; + wire wr = ~busack & state[3] & ~g_iack; +`ifdef M1 + wire m1 = g_if | g_iack; +`endif +endmodule + +// ASU +// z,co = a + b + ci 8bit/16bit i = 3'b000 for lower 8bit of 16bit arithmetic / 16bit increment +// z,co = b - a - ci 8bit i = 3'b001 for lower 8bit of 16bit arithmetic +// z = a - ~ci 16bit i = 3'b010 16bit decrement +// z = a - 0x100 16bit i = 3'b110 upper 8bit decrement + +module asu(a, b, ci, i, z, co); + input [15:0] a; + input [7:0] b; + input ci; + input [2:0] i; + output [15:0] z; + output co; + wire [14:0] c; + wire [14:0] tand, tor; + wire [7:0] a1 = a ^ { 8 { i[0] } }; + wire [7:0] b1 = b | { 8 { i[1] } }; + wire c1 = ci ^ (i[2] | i[0]); + assign tand[7:0] = a1[7:0] & b1[7:0]; + assign tor[7:0] = a1[7:0] | b1[7:0]; + assign c[0] = tand[0] | tor[0] & c1; + assign c[1] = tand[1] | tor[1] & tand[0] + | &tor[1:0] & c1; + assign c[2] = tand[2] | tor[2] & tand[1] + | &tor[2:1] & tand[0] + | &tor[2:0] & c1; + assign c[3] = tand[3] | tor[3] & tand[2] + | &tor[3:2] & tand[1] + | &tor[3:1] & tand[0] + | &tor[3:0] & c1; + assign c[4] = tand[4] | tor[4] & tand[3] + | &tor[4:3] & tand[2] + | &tor[4:2] & tand[1] + | &tor[4:1] & tand[0] + | &tor[4:0] & c1; + assign c[5] = tand[5] | tor[5] & tand[4] + | &tor[5:4] & tand[3] + | &tor[5:3] & tand[2] + | &tor[5:2] & tand[1] + | &tor[5:1] & tand[0] + | &tor[5:0] & c1; + assign c[6] = tand[6] | tor[6] & tand[5] + | &tor[6:5] & tand[4] + | &tor[6:4] & tand[3] + | &tor[6:3] & tand[2] + | &tor[6:2] & tand[1] + | &tor[6:1] & tand[0] + | &tor[6:0] & c1; + assign c[7] = tand[7] | tor[7] & tand[6] + | &tor[7:6] & tand[5] + | &tor[7:5] & tand[4] + | &tor[7:4] & tand[3] + | &tor[7:3] & tand[2] + | &tor[7:2] & tand[1] + | &tor[7:1] & tand[0] + | &tor[7:0] & c1; + assign z[7:0] = a1[7:0] ^ b1[7:0] ^ { c[6:0], c1 }; + wire co = c[7] ^ (i[2] | i[0]); + assign tand[14:8] = a[14:8] & { 8 { b1[7] } }; + assign tor[14:8] = a[14:8] | { 8 { b1[7] } }; + assign c[8] = tand[8] | tor[8] & co; + assign c[9] = tand[9] | tor[9] & tand[8] + | &tor[9:8] & co; + assign c[10] = tand[10] | tor[10] & tand[9] + | &tor[10:9] & tand[8] + | &tor[10:8] & co; + assign c[11] = tand[11] | tor[11] & tand[10] + | &tor[11:10] & tand[9] + | &tor[11:9] & tand[8] + | &tor[11:8] & co; + assign c[12] = tand[12] | tor[12] & tand[11] + | &tor[12:11] & tand[10] + | &tor[12:10] & tand[9] + | &tor[12:9] & tand[8] + | &tor[12:8] & co; + assign c[13] = tand[13] | tor[13] & tand[12] + | &tor[13:12] & tand[11] + | &tor[13:11] & tand[10] + | &tor[13:10] & tand[9] + | &tor[13:9] & tand[8] + | &tor[13:8] & co; + assign c[14] = tand[14] | tor[14] & tand[13] + | &tor[14:13] & tand[12] + | &tor[14:12] & tand[11] + | &tor[14:11] & tand[10] + | &tor[14:10] & tand[9] + | &tor[14:9] & tand[8] + | &tor[14:8] & co; + assign z[15:8] = a[15:8] ^ { 8 { b1[7] } } ^ { c[14:8], co }; + //initial $monitor($stime,, a,, b,, ci,, i,, c,, z,, co); +endmodule + +// ALU for general 8-bit arithmetic/logical + +module alu(c_in, im, a, b, inva, invb, reg_q_c, reg_q_h, s_and, s_or, s_xor, ec, i_daa, set, res, l, r, z, co); + input [7:0] im, a, b; + input inva, invb, c_in, reg_q_c, reg_q_h, s_and, s_or, s_xor, ec; + input i_daa, set, res, l, r; + output [7:0] z, co; + wire [7:0] b1, c; + wire [7:0] a1 = a ^ { 8 { inva } }; + wire daah = a1[3] & (a1[2] | a1[1]); + wire daac = a1[7] & (a1[6] | a1[5]) | a1[7] & a1[4] & daah; + wire daa0 = i_daa & (reg_q_h | daah); + wire daa1 = i_daa & (reg_q_c | daac); + wire [7:0] b0 = b & { 8 { ~i_daa } }; + assign b1[0] = (b0[0] ^ invb | set & im[0]) & ~(res & im[0]); + assign b1[1] = ((b0[1] | daa0) ^ invb | set & im[1]) & ~(res & im[1]); + assign b1[2] = ((b0[2] | daa0) ^ invb | set & im[2]) & ~(res & im[2]); + assign b1[3] = (b0[3] ^ invb | set & im[3]) & ~(res & im[3]); + assign b1[4] = (b0[4] ^ invb | set & im[4]) & ~(res & im[4]); + assign b1[5] = ((b0[5] | daa1) ^ invb | set & im[5]) & ~(res & im[5]); + assign b1[6] = ((b0[6] | daa1) ^ invb | set & im[6]) & ~(res & im[6]); + assign b1[7] = (b0[7] ^ invb | set & im[7]) & ~(res & im[7]); + wire [7:0] tand = a1 & b1; + wire [7:0] tor = a1 | b1; + wire rlc = l & im[0]; + wire rrc = r & im[1]; + wire rl = l & im[2]; + wire rr = r & im[3]; + wire sra = r & im[5]; + wire ci = c_in ^ invb; + assign z[0] = s_and & tand[0] | s_or & tor[0] | s_xor & (a1[0] ^ b1[0] ^ ci & ec) + | rlc & b1[7] | rl & reg_q_c | r & b1[1]; + assign c[0] = tand[0] | tor[0] & ci; + assign z[1] = s_and & tand[1] | s_or & tor[1] | s_xor & (a1[1] ^ b1[1] ^ c[0] & ec) + | l & b1[0] | r & b1[2]; + assign c[1] = tand[1] | tor[1] & tand[0] + | &tor[1:0] & ci; + assign z[2] = s_and & tand[2] | s_or & tor[2] | s_xor & (a1[2] ^ b1[2] ^ c[1] & ec) + | l & b1[1] | r & b1[3]; + assign c[2] = tand[2] | tor[2] & tand[1] + | &tor[2:1] & tand[0] + | &tor[2:0] & ci; + assign z[3] = s_and & tand[3] | s_or & tor[3] | s_xor & (a1[3] ^ b1[3] ^ c[2] & ec) + | l & b1[2] | r & b1[4]; + assign c[3] = tand[3] | tor[3] & tand[2] + | &tor[3:2] & tand[1] + | &tor[3:1] & tand[0] + | &tor[3:0] & ci; + assign z[4] = s_and & tand[4] | s_or & tor[4] | s_xor & (a1[4] ^ b1[4] ^ c[3] & ec) + | l & b1[3] | r & b1[5]; + assign c[4] = tand[4] | tor[4] & tand[3] + | &tor[4:3] & tand[2] + | &tor[4:2] & tand[1] + | &tor[4:1] & tand[0] + | &tor[4:0] & ci; + assign z[5] = s_and & tand[5] | s_or & tor[5] | s_xor & (a1[5] ^ b1[5] ^ c[4] & ec) + | l & b1[4] | r & b1[6]; + assign c[5] = tand[5] | tor[5] & tand[4] + | &tor[5:4] & tand[3] + | &tor[5:3] & tand[2] + | &tor[5:2] & tand[1] + | &tor[5:1] & tand[0] + | &tor[5:0] & ci; + assign z[6] = s_and & tand[6] | s_or & tor[6] | s_xor & (a1[6] ^ b1[6] ^ c[5] & ec) + | l & b1[5] | r & b1[7]; + assign c[6] = tand[6] | tor[6] & tand[5] + | &tor[6:5] & tand[4] + | &tor[6:4] & tand[3] + | &tor[6:3] & tand[2] + | &tor[6:2] & tand[1] + | &tor[6:1] & tand[0] + | &tor[6:0] & ci; + assign z[7] = s_and & tand[7] | s_or & tor[7] | s_xor & (a1[7] ^ b1[7] ^ c[6] & ec) + | l & b1[6] | rrc & b1[0] | rr & reg_q_c | sra & b1[7]; + assign c[7] = tand[7] | tor[7] & tand[6] + | &tor[7:6] & tand[5] + | &tor[7:5] & tand[4] + | &tor[7:4] & tand[3] + | &tor[7:3] & tand[2] + | &tor[7:2] & tand[1] + | &tor[7:1] & tand[0] + | &tor[7:0] & ci; + assign co = { i_daa ? daa1 ^ invb : c[7], c[6:0] }; + //initial $monitor($stime,, c_in, a1,, b1,, inva, invb, reg_q_c, reg_q_h, s_and, s_or, s_xor, ec, i_daa, set, res, l, r, z, co); +endmodule + +// A register: dual register + +module reg_a(a, load, set, regsel, clk, q); + input [7:0] a; + input load, set, regsel, clk; + output [7:0] q; + reg [7:0] q0, q1; + always @(posedge clk) begin + if (set) begin + q0 <= 8'b11111111; + q1 <= 8'b11111111; + end + else if (load) + if (regsel) q1 <= a; + else q0 <= a; + end + assign q = regsel ? q1 : q0; +endmodule + +// F register: dual register + +module reg_f(a, load, set, regsel, clk, q); + input [7:0] a; + input load, set, regsel, clk; + output [7:0] q; + reg [7:0] q0, q1; + always @(posedge clk) begin + if (set) begin + q0 <= 8'b11111111; + q1 <= 8'b11111111; + end + else if (load) + if (regsel) q1 <= a; + else q0 <= a; + end + assign q = regsel ? q1 : q0; +endmodule + +// simple register + +module reg_simple(a, load, clk, q); + input [7:0] a; + input load, clk; + output [7:0] q; + reg [7:0] q; + always @(posedge clk) begin + if (load) q <= a; + end +endmodule + +// simple register w/clear + +module reg_simplec(a, load, clr, clk, q); + input [7:0] a; + input load, clr, clk; + output [7:0] q; + reg [7:0] q; + always @(posedge clk) begin + if (clr) q <= 8'b00000000; + else if (load) q <= a; + end +endmodule + +// 2 input dual register + +module reg_dual2(a, a2, load, load2, regsel, clk, q); + input [7:0] a, a2; + input load, load2, regsel, clk; + output [7:0] q; + reg [7:0] q0 = 8'b00000000, q1 = 8'b00000000; + always @(posedge clk) begin + if (load) + if (regsel) q1 <= a; + else q0 <= a; + else if (load2) + if (regsel) q1 <= a2; + else q0 <= a2; + end + assign q = regsel ? q1 : q0; +endmodule + +// 2 input register + +module reg_2(a, a2, load, load2, clk, q); + input [7:0] a, a2; + input load, load2, clk; + output [7:0] q; + reg [7:0] q; + always @(posedge clk) begin + if (load) q <= a; + else if (load2) q <= a2; + end +endmodule + +// 2 input register w/ set + +module reg_2s(a, a2, load, load2, set, clk, q); + input [7:0] a, a2; + input load, load2, set, clk; + output [7:0] q; + reg [7:0] q; + always @(posedge clk) begin + if (set) q <= 8'b11111111; + else if (load) q <= a; + else if (load2) q <= a2; + end +endmodule + +// 3 input quad register + +module reg_quad3(a, a2, a3, load, load2, load3, regsel, i_dd, i_fd, clk, q); + input [7:0] a, a2, a3; + input load, load2, load3, regsel, i_dd, i_fd, clk; + output [7:0] q; + reg [7:0] q0 = 8'b00000000, q1 = 8'b00000000, qx = 8'b00000000, qy = 8'b00000000; + function [7:0] select; + input [1:0] sel; + input [31:0] a; + begin + case (sel) + 2'h0: select = a[31:24]; + 2'h1: select = a[23:16]; + 2'h2: select = a[15:8]; + 2'h3: select = a[7:0]; + endcase + end + endfunction + always @(posedge clk) begin + if (load) + if (i_dd) qx <= a; + else if (i_fd) qy <= a; + else if (regsel) q1 <= a; + else q0 <= a; + else if (load2) + if (i_dd) qx <= a2; + else if (i_fd) qy <= a2; + else if (regsel) q1 <= a2; + else q0 <= a2; + else if (load3) + if (i_dd) qx <= a3; + else if (i_fd) qy <= a3; + else if (regsel) q1 <= a3; + else q0 <= a3; + end + assign q = select({ i_dd | i_fd, ~i_dd & regsel | i_fd }, { q0, q1, qx, qy }); +endmodule + +// PCH register: 2 input register w/ increment, decrement, clear + +module reg_pch(a, a2, load, load2, count, dec, clr, clk, q); + input [7:0] a, a2; + input load, load2, count, dec, clr, clk; + output [7:0] q; + wire [6:0] c, qa; + reg [7:0] q; + wire notload = ~load & ~load2 & ~clr; + assign qa = q[6:0] ^ { 7 { dec } }; + assign c[0] = qa[0] & count; + assign c[1] = &qa[1:0] & count; + assign c[2] = &qa[2:0] & count; + assign c[3] = &qa[3:0] & count; + assign c[4] = &qa[4:0] & count; + assign c[5] = &qa[5:0] & count; + assign c[6] = &qa[6:0] & count; + wire [7:0] d = { 8 { load } } & a | { 8 { load2 } } & a2 | { 8 { notload } } & (q ^ { c, count }); + always @(posedge clk) q <= d; +endmodule + +// PCL register: 3 input register w/ increment, decrement, clear, load 66 + +module reg_pcl(a, a2, a3, load, load2, load3, count, dec, clr, load66, clk, q, co); + input [7:0] a, a2; + input [2:0] a3; + input load, load2, load3, count, dec, clr, load66, clk; + output [7:0] q; + output co; + wire [6:0] c; + wire [7:0] d, qa; + reg [7:0] q; + wire notload = ~load & ~load2 & ~load3 & ~load66 & ~clr; + assign qa = q ^ { 8 { dec } }; + assign c[0] = qa[0] & count; + assign c[1] = &qa[1:0] & count; + assign c[2] = &qa[2:0] & count; + assign c[3] = &qa[3:0] & count; + assign c[4] = &qa[4:0] & count; + assign c[5] = &qa[5:0] & count; + assign c[6] = &qa[6:0] & count; + assign co = &qa[7:0] & count; + assign d[0] = load & a[0] | load2 & a2[0] | notload & (q[0] ^ count); + assign d[1] = load & a[1] | load2 & a2[1] | notload & (q[1] ^ c[0]) | load66; + assign d[2] = load & a[2] | load2 & a2[2] | notload & (q[2] ^ c[1]) | load66; + assign d[3] = load & a[3] | load2 & a2[3] | notload & (q[3] ^ c[2]) | load3 & a3[0]; + assign d[4] = load & a[4] | load2 & a2[4] | notload & (q[4] ^ c[3]) | load3 & a3[1]; + assign d[5] = load & a[5] | load2 & a2[5] | notload & (q[5] ^ c[4]) | load3 & a3[2] | load66; + assign d[6] = load & a[6] | load2 & a2[6] | notload & (q[6] ^ c[5]) | load66; + assign d[7] = load & a[7] | load2 & a2[7] | notload & (q[7] ^ c[6]); + always @(posedge clk) q <= d; +endmodule + +// R register: up counter + +module reg_r(a, load, count, clr, clk, q); + input [7:0] a; + input load, count, clr, clk; + output [7:0] q; + reg [7:0] q; + always @(posedge clk) + if (clr) q <= 8'b00000000; + else if (load) q <= a; + else if (count) q[6:0] <= q[6:0] + 1; +endmodule + diff --git a/Sharp -MZ-80K_MiST/rtl/hq2x.sv b/Sharp -MZ-80K_MiST/rtl/hq2x.sv new file mode 100644 index 00000000..f17732b6 --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/hq2x.sv @@ -0,0 +1,454 @@ +// +// +// Copyright (c) 2012-2013 Ludvig Strigeus +// Copyright (c) 2017 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on + +`define BITS_TO_FIT(N) ( \ + N <= 2 ? 0 : \ + N <= 4 ? 1 : \ + N <= 8 ? 2 : \ + N <= 16 ? 3 : \ + N <= 32 ? 4 : \ + N <= 64 ? 5 : \ + N <= 128 ? 6 : \ + N <= 256 ? 7 : \ + N <= 512 ? 8 : \ + N <=1024 ? 9 : 10 ) + +module hq2x_in #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input rdbuf, + output[DWIDTH:0] q, + + input [AWIDTH:0] wraddr, + input wrbuf, + input [DWIDTH:0] data, + input wren +); + + localparam AWIDTH = `BITS_TO_FIT(LENGTH); + wire [DWIDTH:0] out[2]; + assign q = out[rdbuf]; + + hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); + hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); +endmodule + + +module hq2x_out #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input [1:0] rdbuf, + output[DWIDTH:0] q, + + input [AWIDTH:0] wraddr, + input [1:0] wrbuf, + input [DWIDTH:0] data, + input wren +); + + localparam AWIDTH = `BITS_TO_FIT(LENGTH*2); + wire [DWIDTH:0] out[4]; + assign q = out[rdbuf]; + + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf2(clk,data,rdaddr,wraddr,wren && (wrbuf == 2),out[2]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf3(clk,data,rdaddr,wraddr,wren && (wrbuf == 3),out[3]); +endmodule + + +module hq2x_buf #(parameter NUMWORDS, parameter AWIDTH, parameter DWIDTH) +( + input clock, + input [DWIDTH:0] data, + input [AWIDTH:0] rdaddress, + input [AWIDTH:0] wraddress, + input wren, + output [DWIDTH:0] q +); + + altsyncram altsyncram_component ( + .address_a (wraddress), + .clock0 (clock), + .data_a (data), + .wren_a (wren), + .address_b (rdaddress), + .q_b(q), + .aclr0 (1'b0), + .aclr1 (1'b0), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_b ({(DWIDTH+1){1'b1}}), + .eccstatus (), + .q_a (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_b (1'b0)); + defparam + altsyncram_component.address_aclr_b = "NONE", + altsyncram_component.address_reg_b = "CLOCK0", + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_input_b = "BYPASS", + altsyncram_component.clock_enable_output_b = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = NUMWORDS, + altsyncram_component.numwords_b = NUMWORDS, + altsyncram_component.operation_mode = "DUAL_PORT", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.outdata_reg_b = "UNREGISTERED", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE", + altsyncram_component.widthad_a = AWIDTH+1, + altsyncram_component.widthad_b = AWIDTH+1, + altsyncram_component.width_a = DWIDTH+1, + altsyncram_component.width_b = DWIDTH+1, + altsyncram_component.width_byteena_a = 1; + +endmodule + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +module DiffCheck +( + input [17:0] rgb1, + input [17:0] rgb2, + output result +); + + wire [5:0] r = rgb1[5:1] - rgb2[5:1]; + wire [5:0] g = rgb1[11:7] - rgb2[11:7]; + wire [5:0] b = rgb1[17:13] - rgb2[17:13]; + wire [6:0] t = $signed(r) + $signed(b); + wire [6:0] gx = {g[5], g}; + wire [7:0] y = $signed(t) + $signed(gx); + wire [6:0] u = $signed(r) - $signed(b); + wire [7:0] v = $signed({g, 1'b0}) - $signed(t); + + // if y is inside (-24..24) + wire y_inside = (y < 8'h18 || y >= 8'he8); + + // if u is inside (-4, 4) + wire u_inside = (u < 7'h4 || u >= 7'h7c); + + // if v is inside (-6, 6) + wire v_inside = (v < 8'h6 || v >= 8'hfA); + assign result = !(y_inside && u_inside && v_inside); +endmodule + +module InnerBlend +( + input [8:0] Op, + input [5:0] A, + input [5:0] B, + input [5:0] C, + output [5:0] O +); + + function [8:0] mul6x3; + input [5:0] op1; + input [2:0] op2; + begin + mul6x3 = 9'd0; + if(op2[0]) mul6x3 = mul6x3 + op1; + if(op2[1]) mul6x3 = mul6x3 + {op1, 1'b0}; + if(op2[2]) mul6x3 = mul6x3 + {op1, 2'b00}; + end + endfunction + + wire OpOnes = Op[4]; + wire [8:0] Amul = mul6x3(A, Op[7:5]); + wire [8:0] Bmul = mul6x3(B, {Op[3:2], 1'b0}); + wire [8:0] Cmul = mul6x3(C, {Op[1:0], 1'b0}); + wire [8:0] At = Amul; + wire [8:0] Bt = (OpOnes == 0) ? Bmul : {3'b0, B}; + wire [8:0] Ct = (OpOnes == 0) ? Cmul : {3'b0, C}; + wire [9:0] Res = {At, 1'b0} + Bt + Ct; + assign O = Op[8] ? A : Res[9:4]; +endmodule + +module Blend +( + input [5:0] rule, + input disable_hq2x, + input [17:0] E, + input [17:0] A, + input [17:0] B, + input [17:0] D, + input [17:0] F, + input [17:0] H, + output [17:0] Result +); + + reg [1:0] input_ctrl; + reg [8:0] op; + localparam BLEND0 = 9'b1_xxx_x_xx_xx; // 0: A + localparam BLEND1 = 9'b0_110_0_10_00; // 1: (A * 12 + B * 4) >> 4 + localparam BLEND2 = 9'b0_100_0_10_10; // 2: (A * 8 + B * 4 + C * 4) >> 4 + localparam BLEND3 = 9'b0_101_0_10_01; // 3: (A * 10 + B * 4 + C * 2) >> 4 + localparam BLEND4 = 9'b0_110_0_01_01; // 4: (A * 12 + B * 2 + C * 2) >> 4 + localparam BLEND5 = 9'b0_010_0_11_11; // 5: (A * 4 + (B + C) * 6) >> 4 + localparam BLEND6 = 9'b0_111_1_xx_xx; // 6: (A * 14 + B + C) >> 4 + localparam AB = 2'b00; + localparam AD = 2'b01; + localparam DB = 2'b10; + localparam BD = 2'b11; + wire is_diff; + DiffCheck diff_checker(rule[1] ? B : H, rule[0] ? D : F, is_diff); + + always @* begin + case({!is_diff, rule[5:2]}) + 1,17: {op, input_ctrl} = {BLEND1, AB}; + 2,18: {op, input_ctrl} = {BLEND1, DB}; + 3,19: {op, input_ctrl} = {BLEND1, BD}; + 4,20: {op, input_ctrl} = {BLEND2, DB}; + 5,21: {op, input_ctrl} = {BLEND2, AB}; + 6,22: {op, input_ctrl} = {BLEND2, AD}; + + 8: {op, input_ctrl} = {BLEND0, 2'bxx}; + 9: {op, input_ctrl} = {BLEND0, 2'bxx}; + 10: {op, input_ctrl} = {BLEND0, 2'bxx}; + 11: {op, input_ctrl} = {BLEND1, AB}; + 12: {op, input_ctrl} = {BLEND1, AB}; + 13: {op, input_ctrl} = {BLEND1, AB}; + 14: {op, input_ctrl} = {BLEND1, DB}; + 15: {op, input_ctrl} = {BLEND1, BD}; + + 24: {op, input_ctrl} = {BLEND2, DB}; + 25: {op, input_ctrl} = {BLEND5, DB}; + 26: {op, input_ctrl} = {BLEND6, DB}; + 27: {op, input_ctrl} = {BLEND2, DB}; + 28: {op, input_ctrl} = {BLEND4, DB}; + 29: {op, input_ctrl} = {BLEND5, DB}; + 30: {op, input_ctrl} = {BLEND3, BD}; + 31: {op, input_ctrl} = {BLEND3, DB}; + default: {op, input_ctrl} = 11'bx; + endcase + + // Setting op[8] effectively disables HQ2X because blend will always return E. + if (disable_hq2x) op[8] = 1; + end + + // Generate inputs to the inner blender. Valid combinations. + // 00: E A B + // 01: E A D + // 10: E D B + // 11: E B D + wire [17:0] Input1 = E; + wire [17:0] Input2 = !input_ctrl[1] ? A : + !input_ctrl[0] ? D : B; + + wire [17:0] Input3 = !input_ctrl[0] ? B : D; + InnerBlend inner_blend1(op, Input1[5:0], Input2[5:0], Input3[5:0], Result[5:0]); + InnerBlend inner_blend2(op, Input1[11:6], Input2[11:6], Input3[11:6], Result[11:6]); + InnerBlend inner_blend3(op, Input1[17:12], Input2[17:12], Input3[17:12], Result[17:12]); +endmodule + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +module Hq2x #(parameter LENGTH, parameter HALF_DEPTH) +( + input clk, + input ce_x4, + input [DWIDTH:0] inputpixel, + input mono, + input disable_hq2x, + input reset_frame, + input reset_line, + input [1:0] read_y, + input [AWIDTH+1:0] read_x, + output [DWIDTH:0] outpixel +); + + +localparam AWIDTH = `BITS_TO_FIT(LENGTH); +localparam DWIDTH = HALF_DEPTH ? 8 : 17; + +wire [5:0] hqTable[256] = '{ + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 35, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 35, 35, 23, 61, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 7, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 58, 23, 15, 51, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 39, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 7, 35, 23, 15, 7, 43 +}; + +reg [17:0] Prev0, Prev1, Prev2, Curr0, Curr1, Next0, Next1, Next2; +reg [17:0] A, B, D, F, G, H; +reg [7:0] pattern, nextpatt; +reg [1:0] i; +reg [7:0] y; + +wire curbuf = y[0]; +reg prevbuf = 0; +wire iobuf = !curbuf; + +wire diff0, diff1; +DiffCheck diffcheck0(Curr1, (i == 0) ? Prev0 : (i == 1) ? Curr0 : (i == 2) ? Prev2 : Next1, diff0); +DiffCheck diffcheck1(Curr1, (i == 0) ? Prev1 : (i == 1) ? Next0 : (i == 2) ? Curr2 : Next2, diff1); + +wire [7:0] new_pattern = {diff1, diff0, pattern[7:2]}; + +wire [17:0] X = (i == 0) ? A : (i == 1) ? Prev1 : (i == 2) ? Next1 : G; +wire [17:0] blend_result; +Blend blender(hqTable[nextpatt], disable_hq2x, Curr0, X, B, D, F, H, blend_result); + +reg Curr2_addr1; +reg [AWIDTH:0] Curr2_addr2; +wire [17:0] Curr2 = HALF_DEPTH ? h2rgb(Curr2tmp) : Curr2tmp; +wire [DWIDTH:0] Curr2tmp; + +reg [AWIDTH:0] wrin_addr2; +reg [DWIDTH:0] wrpix; +reg wrin_en; + +function [17:0] h2rgb; + input [8:0] v; +begin + h2rgb = mono ? {v[5:3],v[2:0], v[5:3],v[2:0], v[5:3],v[2:0]} : {v[8:6],v[8:6],v[5:3],v[5:3],v[2:0],v[2:0]}; +end +endfunction + +function [8:0] rgb2h; + input [17:0] v; +begin + rgb2h = mono ? {3'b000, v[17:15], v[14:12]} : {v[17:15], v[11:9], v[5:3]}; +end +endfunction + +hq2x_in #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_in +( + .clk(clk), + + .rdaddr(Curr2_addr2), + .rdbuf(Curr2_addr1), + .q(Curr2tmp), + + .wraddr(wrin_addr2), + .wrbuf(iobuf), + .data(wrpix), + .wren(wrin_en) +); + +reg [1:0] wrout_addr1; +reg [AWIDTH+1:0] wrout_addr2; +reg wrout_en; +reg [DWIDTH:0] wrdata; + +hq2x_out #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_out +( + .clk(clk), + + .rdaddr(read_x), + .rdbuf(read_y), + .q(outpixel), + + .wraddr(wrout_addr2), + .wrbuf(wrout_addr1), + .data(wrdata), + .wren(wrout_en) +); + +always @(posedge clk) begin + reg [AWIDTH:0] offs; + reg old_reset_line; + reg old_reset_frame; + + wrout_en <= 0; + wrin_en <= 0; + + if(ce_x4) begin + + pattern <= new_pattern; + + if(~&offs) begin + if (i == 0) begin + Curr2_addr1 <= prevbuf; + Curr2_addr2 <= offs; + end + if (i == 1) begin + Prev2 <= Curr2; + Curr2_addr1 <= curbuf; + Curr2_addr2 <= offs; + end + if (i == 2) begin + Next2 <= HALF_DEPTH ? h2rgb(inputpixel) : inputpixel; + wrpix <= inputpixel; + wrin_addr2 <= offs; + wrin_en <= 1; + end + if (i == 3) begin + offs <= offs + 1'd1; + end + + if(HALF_DEPTH) wrdata <= rgb2h(blend_result); + else wrdata <= blend_result; + + wrout_addr1 <= {curbuf, i[1]}; + wrout_addr2 <= {offs, i[1]^i[0]}; + wrout_en <= 1; + end + + if(i==3) begin + nextpatt <= {new_pattern[7:6], new_pattern[3], new_pattern[5], new_pattern[2], new_pattern[4], new_pattern[1:0]}; + {A, G} <= {Prev0, Next0}; + {B, F, H, D} <= {Prev1, Curr2, Next1, Curr0}; + {Prev0, Prev1} <= {Prev1, Prev2}; + {Curr0, Curr1} <= {Curr1, Curr2}; + {Next0, Next1} <= {Next1, Next2}; + end else begin + nextpatt <= {nextpatt[5], nextpatt[3], nextpatt[0], nextpatt[6], nextpatt[1], nextpatt[7], nextpatt[4], nextpatt[2]}; + {B, F, H, D} <= {F, H, D, B}; + end + + i <= i + 1'b1; + if(old_reset_line && ~reset_line) begin + old_reset_frame <= reset_frame; + offs <= 0; + i <= 0; + y <= y + 1'd1; + prevbuf <= curbuf; + if(old_reset_frame & ~reset_frame) begin + y <= 0; + prevbuf <= 0; + end + end + + old_reset_line <= reset_line; + end +end + +endmodule // Hq2x diff --git a/Sharp -MZ-80K_MiST/rtl/i8253.v b/Sharp -MZ-80K_MiST/rtl/i8253.v new file mode 100644 index 00000000..72e2b77d --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/i8253.v @@ -0,0 +1,158 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 09:58:45 02/25/2008 +// Design Name: +// Module Name: i8253 +// Project Name: +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +module i8253(reset, clk, addr, data_out, data_in, cs, rd, wr, clk0, clk1, clk2, out0, out1, out2); + input reset; + input clk; + input [1:0] addr; + output[7:0] data_out; + input [7:0] data_in; + input cs, rd, wr; + input clk0, clk1, clk2; + output out0, out1, out2; + wire [1:0] addr; + wire [7:0] data_out, data_in; + wire cs, rd, wr; + wire clk0, clk1, clk2; + wire out0, out1, out2; + + reg [7:0] mode0, mode1, mode2; + reg [15:0] max0, max1, max2; + reg [15:0] count0 = 0, count1 = 0, count2 = 0; + reg signal0 = 0, signal1 = 0, signal2 = 0; + reg read_hl0, read_hl1, read_hl2; + reg write_hl0, write_hl1, write_hl2; + reg [7:0] data; + + always @(posedge clk or posedge reset) begin + if ( reset ) begin + mode0 <= 8'h00; + mode1 <= 8'h00; + mode2 <= 8'h00; + max0 <= 16'd1; + max1 <= 16'd1; + max2 <= 16'd1; + write_hl0 <= 1'b0; + write_hl1 <= 1'b0; + write_hl2 <= 1'b0; + read_hl0 <= 1'b0; + read_hl1 <= 1'b0; + read_hl2 <= 1'b0; + end else if ( cs ) begin + if ( addr == 2'd0 & wr ) begin + write_hl0 <= ( mode0[5:4] == 2'b00 | mode0[5:4] == 2'b11 ) ? ~write_hl0: write_hl0; + if ( ((mode0[5:4] == 2'b00 | mode0[5:4] == 2'b11) & write_hl0) | mode0[5:4] == 2'b10 ) + max0[15:8] <= data_in; + else + max0[7:0] <= data_in; + end else if ( addr == 2'd1 & wr ) begin + write_hl1 <= ( mode1[5:4] == 2'b00 | mode1[5:4] == 2'b11 ) ? ~write_hl1: write_hl1; + if ( ((mode1[5:4] == 2'b00 | mode1[5:4] == 2'b11) & write_hl1) | mode1[5:4] == 2'b10 ) + max1[15:8] <= data_in; + else + max1[7:0] <= data_in; + end else if ( addr == 2'd2 & wr ) begin + write_hl2 <= ( mode2[5:4] == 2'b00 | mode2[5:4] == 2'b11 ) ? ~write_hl2: write_hl2; + if ( ((mode2[5:4] == 2'b00 | mode2[5:4] == 2'b11) & write_hl2) | mode2[5:4] == 2'b10 ) + max2[15:8] <= data_in; + else + max2[7:0] <= data_in; + end else if ( addr == 2'd3 & wr ) begin + if ( data_in[7:6] == 2'd0 ) begin + mode0 <= data_in; + read_hl0 <= data_in[5:4] == 2'b10 ? 1 : 0; + write_hl0 <= data_in[5:4] == 2'b10 ? 1 : 0; + end else if ( data_in[7:6] == 2'd1 ) begin + mode1 <= data_in; + read_hl1 <= data_in[5:4] == 2'b10 ? 1 : 0; + write_hl1 <= data_in[5:4] == 2'b10 ? 1 : 0; + end else if ( data_in[7:6] == 2'd2 ) begin + mode2 <= data_in; + read_hl2 <= data_in[5:4] == 2'b10 ? 1 : 0; + write_hl2 <= data_in[5:4] == 2'b10 ? 1 : 0; + end + end else if ( addr == 2'd0 & rd ) begin + read_hl0 <= ( mode0[5:4] == 2'b00 | mode0[5:4] == 2'b11 ) ? ~read_hl0: read_hl0; + data <= ~( ((mode0[5:4] == 2'b00 | mode0[5:4] == 2'b11 ) & read_hl0) | mode0[5:4] == 2'b10 ) ? count0[15:8] : count0[7:0]; + end else if ( addr == 2'd1 & rd ) begin + read_hl1 <= ( mode1[5:4] == 2'b00 | mode1[5:4] == 2'b11 ) ? ~read_hl1: read_hl1; + data <= ~( ((mode1[5:4] == 2'b00 | mode1[5:4] == 2'b11 ) & read_hl1) | mode1[5:4] == 2'b10 ) ? count1[15:8] : count1[7:0]; + end else if ( addr == 2'd2 & rd ) begin + read_hl2 <= ( mode2[5:4] == 2'b00 | mode2[5:4] == 2'b11 ) ? ~read_hl2: read_hl2; + data <= ~( ((mode2[5:4] == 2'b00 | mode2[5:4] == 2'b11 ) & read_hl2) | mode2[5:4] == 2'b10 ) ? count2[15:8] : count2[7:0]; + end + end + end + + always @(posedge clk0) begin + if ( count0 != 0 ) begin + count0 <= ( count0 <= max0 ) ? count0 - 1: max0; + if ( mode0[3:1] == 3'b000 | mode0[3:1] == 3'b001 ) // MODE0 + signal0 <= 0; + end else begin + if ( mode0[3:1] == 3'b000 | mode0[3:1] == 3'b001 ) begin // MODE0 + count0 <= max0; + signal0 <= 1; + end else begin + count0 <= max0; + signal0 <= ~signal0; + end + end + end + + always @(posedge clk1) begin + if ( count1 != 0 ) begin + count1 <= ( count1 <= max1 ) ? count1 - 1: max1; + if ( mode1[3:1] == 3'b000 | mode1[3:1] == 3'b001 ) // MODE0/1 + signal1 <= 0; + end else begin + if ( mode1[3:1] == 3'b000 | mode1[3:1] == 3'b001 ) begin // MODE0/1 + count1 <= max1; + signal1 <= 1; + end else begin + count1 <= max1; + signal1 <= ~signal1; + end + end + end + + always @(posedge clk2) begin + if ( count2 != 0 ) begin + count2 <= ( count2 <= max2 ) ? count2 - 1: max2; + if ( mode2[3:1] == 3'b000 | mode2[3:1] == 3'b001 ) // MODE0/1 + signal2 <= 0; + end else begin + if ( mode2[3:1] == 3'b000 | mode2[3:1] == 3'b001 ) begin // MODE0/1 + count2 <= max2; + signal2 <= 1; + end else begin + count2 <= max2; + signal2 <= ~signal2; + end + end + end + + assign out0 = signal0; + assign out1 = signal1; + assign out2 = signal2; + + assign data_out = data; + +endmodule diff --git a/Sharp -MZ-80K_MiST/rtl/keyboard.v b/Sharp -MZ-80K_MiST/rtl/keyboard.v new file mode 100644 index 00000000..ba7038b6 --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/keyboard.v @@ -0,0 +1,82 @@ + + +module keyboard +( + input clk, + input reset, + input ps2_kbd_clk, + input ps2_kbd_data, + + output reg[7:0] joystick +); + +reg [11:0] shift_reg = 12'hFFF; +wire[11:0] kdata = {ps2_kbd_data,shift_reg[11:1]}; +wire [7:0] kcode = kdata[9:2]; +reg release_btn = 0; + +reg [7:0] code; +reg input_strobe = 0; + +always @(negedge clk) begin + reg old_reset = 0; + + old_reset <= reset; + + if(~old_reset & reset)begin + joystick <= 0; + end + + if(input_strobe) begin + case(code) + 'h16: joystick[1] <= ~release_btn; // 1 + 'h1E: joystick[2] <= ~release_btn; // 2 + + 'h75: joystick[4] <= ~release_btn; // arrow up + 'h72: joystick[5] <= ~release_btn; // arrow down + 'h6B: joystick[6] <= ~release_btn; // arrow left + 'h74: joystick[7] <= ~release_btn; // arrow right + + 'h29: joystick[0] <= ~release_btn; // Space +// 'h11: joystick[1] <= ~release_btn; // Left Alt +// 'h0d: joystick[2] <= ~release_btn; // Tab + 'h76: joystick[3] <= ~release_btn; // Escape + endcase + end +end + +always @(posedge clk) begin + reg [3:0] prev_clk = 0; + reg old_reset = 0; + reg action = 0; + + old_reset <= reset; + input_strobe <= 0; + + if(~old_reset & reset)begin + prev_clk <= 0; + shift_reg <= 12'hFFF; + end else begin + prev_clk <= {ps2_kbd_clk,prev_clk[3:1]}; + if(prev_clk == 1) begin + if (kdata[11] & ^kdata[10:2] & ~kdata[1] & kdata[0]) begin + shift_reg <= 12'hFFF; + if (kcode == 8'he0) ; + // Extended key code follows + else if (kcode == 8'hf0) + // Release code follows + action <= 1; + else begin + // Cancel extended/release flags for next time + action <= 0; + release_btn <= action; + code <= kcode; + input_strobe <= 1; + end + end else begin + shift_reg <= kdata; + end + end + end +end +endmodule diff --git a/Sharp -MZ-80K_MiST/rtl/mist_io.v b/Sharp -MZ-80K_MiST/rtl/mist_io.v new file mode 100644 index 00000000..ad233a3b --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/mist_io.v @@ -0,0 +1,491 @@ +// +// mist_io.v +// +// mist_io for the MiST board +// http://code.google.com/p/mist-board/ +// +// Copyright (c) 2014 Till Harbaum +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////// + +// +// Use buffer to access SD card. It's time-critical part. +// Made module synchroneous with 2 clock domains: clk_sys and SPI_SCK +// (Sorgelig) +// +// for synchronous projects default value for PS2DIV is fine for any frequency of system clock. +// clk_ps2 = clk_sys/(PS2DIV*2) +// + +module mist_io #(parameter STRLEN=0, parameter PS2DIV=100) +( + + // parameter STRLEN and the actual length of conf_str have to match + input [(8*STRLEN)-1:0] conf_str, + + // Global clock. It should be around 100MHz (higher is better). + input clk_sys, + + // Global SPI clock from ARM. 24MHz + input SPI_SCK, + + input CONF_DATA0, + input SPI_SS2, + output SPI_DO, + input SPI_DI, + + output reg [7:0] joystick_0, + output reg [7:0] joystick_1, + output reg [15:0] joystick_analog_0, + output reg [15:0] joystick_analog_1, + output [1:0] buttons, + output [1:0] switches, + output scandoubler_disable, + output ypbpr, + + output reg [31:0] status, + + // SD config + input sd_conf, + input sd_sdhc, + output img_mounted, // signaling that new image has been mounted + output reg [31:0] img_size, // size of image in bytes + + // SD block level access + input [31:0] sd_lba, + input sd_rd, + input sd_wr, + output reg sd_ack, + output reg sd_ack_conf, + + // SD byte level access. Signals for 2-PORT altsyncram. + output reg [8:0] sd_buff_addr, + output reg [7:0] sd_buff_dout, + input [7:0] sd_buff_din, + output reg sd_buff_wr, + + // ps2 keyboard emulation + output ps2_kbd_clk, + output reg ps2_kbd_data, + output ps2_mouse_clk, + output reg ps2_mouse_data, + input ps2_caps_led, + + // ARM -> FPGA download + output reg ioctl_download = 0, // signal indicating an active download + output reg [7:0] ioctl_index, // menu index used to upload the file + output ioctl_wr, + output reg [24:0] ioctl_addr, + output reg [7:0] ioctl_dout +); + +reg [7:0] b_data; +reg [6:0] sbuf; +reg [7:0] cmd; +reg [2:0] bit_cnt; // counts bits 0-7 0-7 ... +reg [9:0] byte_cnt; // counts bytes +reg [7:0] but_sw; +reg [2:0] stick_idx; + +reg mount_strobe = 0; +assign img_mounted = mount_strobe; + +assign buttons = but_sw[1:0]; +assign switches = but_sw[3:2]; +assign scandoubler_disable = but_sw[4]; +assign ypbpr = but_sw[5]; + +wire [7:0] spi_dout = { sbuf, SPI_DI}; + +// this variant of user_io is for 8 bit cores (type == a4) only +wire [7:0] core_type = 8'ha4; + +// command byte read by the io controller +wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd }; + +reg spi_do; +assign SPI_DO = CONF_DATA0 ? 1'bZ : spi_do; + +wire [7:0] kbd_led = { 2'b01, 4'b0000, ps2_caps_led, 1'b1}; + +// drive MISO only when transmitting core id +always@(negedge SPI_SCK) begin + if(!CONF_DATA0) begin + // first byte returned is always core type, further bytes are + // command dependent + if(byte_cnt == 0) begin + spi_do <= core_type[~bit_cnt]; + + end else begin + case(cmd) + // reading config string + 8'h14: begin + // returning a byte from string + if(byte_cnt < STRLEN + 1) spi_do <= conf_str[{STRLEN - byte_cnt,~bit_cnt}]; + else spi_do <= 0; + end + + // reading sd card status + 8'h16: begin + if(byte_cnt == 1) spi_do <= sd_cmd[~bit_cnt]; + else if((byte_cnt >= 2) && (byte_cnt < 6)) spi_do <= sd_lba[{5-byte_cnt, ~bit_cnt}]; + else spi_do <= 0; + end + + // reading sd card write data + 8'h18: + spi_do <= b_data[~bit_cnt]; + + // reading keyboard LED status + 8'h1f: + spi_do <= kbd_led[~bit_cnt]; + + default: + spi_do <= 0; + endcase + end + end +end + +reg b_wr2,b_wr3; +always @(negedge clk_sys) begin + b_wr3 <= b_wr2; + sd_buff_wr <= b_wr3; +end + +// SPI receiver +always@(posedge SPI_SCK or posedge CONF_DATA0) begin + + if(CONF_DATA0) begin + b_wr2 <= 0; + bit_cnt <= 0; + byte_cnt <= 0; + sd_ack <= 0; + sd_ack_conf <= 0; + end else begin + b_wr2 <= 0; + + sbuf <= spi_dout[6:0]; + bit_cnt <= bit_cnt + 1'd1; + if(bit_cnt == 5) begin + if (byte_cnt == 0) sd_buff_addr <= 0; + if((byte_cnt != 0) & (sd_buff_addr != 511)) sd_buff_addr <= sd_buff_addr + 1'b1; + if((byte_cnt == 1) & ((cmd == 8'h17) | (cmd == 8'h19))) sd_buff_addr <= 0; + end + + // finished reading command byte + if(bit_cnt == 7) begin + if(~&byte_cnt) byte_cnt <= byte_cnt + 8'd1; + if(byte_cnt == 0) begin + cmd <= spi_dout; + + if(spi_dout == 8'h19) begin + sd_ack_conf <= 1; + sd_buff_addr <= 0; + end + if((spi_dout == 8'h17) || (spi_dout == 8'h18)) begin + sd_ack <= 1; + sd_buff_addr <= 0; + end + if(spi_dout == 8'h18) b_data <= sd_buff_din; + + mount_strobe <= 0; + + end else begin + + case(cmd) + // buttons and switches + 8'h01: but_sw <= spi_dout; + 8'h02: joystick_0 <= spi_dout; + 8'h03: joystick_1 <= spi_dout; + + // store incoming ps2 mouse bytes + 8'h04: begin + ps2_mouse_fifo[ps2_mouse_wptr] <= spi_dout; + ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1; + end + + // store incoming ps2 keyboard bytes + 8'h05: begin + ps2_kbd_fifo[ps2_kbd_wptr] <= spi_dout; + ps2_kbd_wptr <= ps2_kbd_wptr + 1'd1; + end + + 8'h15: status[7:0] <= spi_dout; + + // send SD config IO -> FPGA + // flag that download begins + // sd card knows data is config if sd_dout_strobe is asserted + // with sd_ack still being inactive (low) + 8'h19, + // send sector IO -> FPGA + // flag that download begins + 8'h17: begin + sd_buff_dout <= spi_dout; + b_wr2 <= 1; + end + + 8'h18: b_data <= sd_buff_din; + + // joystick analog + 8'h1a: begin + // first byte is joystick index + if(byte_cnt == 1) stick_idx <= spi_dout[2:0]; + else if(byte_cnt == 2) begin + // second byte is x axis + if(stick_idx == 0) joystick_analog_0[15:8] <= spi_dout; + else if(stick_idx == 1) joystick_analog_1[15:8] <= spi_dout; + end else if(byte_cnt == 3) begin + // third byte is y axis + if(stick_idx == 0) joystick_analog_0[7:0] <= spi_dout; + else if(stick_idx == 1) joystick_analog_1[7:0] <= spi_dout; + end + end + + // notify image selection + 8'h1c: mount_strobe <= 1; + + // send image info + 8'h1d: if(byte_cnt<5) img_size[(byte_cnt-1)<<3 +:8] <= spi_dout; + + // status, 32bit version + 8'h1e: if(byte_cnt<5) status[(byte_cnt-1)<<3 +:8] <= spi_dout; + default: ; + endcase + end + end + end +end + + +/////////////////////////////// PS2 /////////////////////////////// +// 8 byte fifos to store ps2 bytes +localparam PS2_FIFO_BITS = 3; + +reg clk_ps2; +always @(negedge clk_sys) begin + integer cnt; + cnt <= cnt + 1'd1; + if(cnt == PS2DIV) begin + clk_ps2 <= ~clk_ps2; + cnt <= 0; + end +end + +// keyboard +reg [7:0] ps2_kbd_fifo[1<= 1)&&(ps2_kbd_tx_state < 9)) begin + ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits + ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down + if(ps2_kbd_tx_byte[0]) + ps2_kbd_parity <= !ps2_kbd_parity; + end + + // transmission of parity + if(ps2_kbd_tx_state == 9) ps2_kbd_data <= ps2_kbd_parity; + + // transmission of stop bit + if(ps2_kbd_tx_state == 10) ps2_kbd_data <= 1; // stop bit is 1 + + // advance state machine + if(ps2_kbd_tx_state < 11) ps2_kbd_tx_state <= ps2_kbd_tx_state + 1'd1; + else ps2_kbd_tx_state <= 0; + end + end +end + +// mouse +reg [7:0] ps2_mouse_fifo[1<= 1)&&(ps2_mouse_tx_state < 9)) begin + ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits + ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down + if(ps2_mouse_tx_byte[0]) + ps2_mouse_parity <= !ps2_mouse_parity; + end + + // transmission of parity + if(ps2_mouse_tx_state == 9) ps2_mouse_data <= ps2_mouse_parity; + + // transmission of stop bit + if(ps2_mouse_tx_state == 10) ps2_mouse_data <= 1; // stop bit is 1 + + // advance state machine + if(ps2_mouse_tx_state < 11) ps2_mouse_tx_state <= ps2_mouse_tx_state + 1'd1; + else ps2_mouse_tx_state <= 0; + end + end +end + + +/////////////////////////////// DOWNLOADING /////////////////////////////// + +reg [7:0] data_w; +reg [24:0] addr_w; +reg rclk = 0; + +localparam UIO_FILE_TX = 8'h53; +localparam UIO_FILE_TX_DAT = 8'h54; +localparam UIO_FILE_INDEX = 8'h55; + +// data_io has its own SPI interface to the io controller +always@(posedge SPI_SCK, posedge SPI_SS2) begin + reg [6:0] sbuf; + reg [7:0] cmd; + reg [4:0] cnt; + reg [24:0] addr; + + if(SPI_SS2) cnt <= 0; + else begin + rclk <= 0; + + // don't shift in last bit. It is evaluated directly + // when writing to ram + if(cnt != 15) sbuf <= { sbuf[5:0], SPI_DI}; + + // increase target address after write + if(rclk) addr <= addr + 1'd1; + + // count 0-7 8-15 8-15 ... + if(cnt < 15) cnt <= cnt + 1'd1; + else cnt <= 8; + + // finished command byte + if(cnt == 7) cmd <= {sbuf, SPI_DI}; + + // prepare/end transmission + if((cmd == UIO_FILE_TX) && (cnt == 15)) begin + // prepare + if(SPI_DI) begin + addr <= 0; + ioctl_download <= 1; + end else begin + addr_w <= addr; + ioctl_download <= 0; + end + end + + // command 0x54: UIO_FILE_TX + if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin + addr_w <= addr; + data_w <= {sbuf, SPI_DI}; + rclk <= 1; + end + + // expose file (menu) index + if((cmd == UIO_FILE_INDEX) && (cnt == 15)) ioctl_index <= {sbuf, SPI_DI}; + end +end + +assign ioctl_wr = |ioctl_wrd; +reg [1:0] ioctl_wrd; + +always@(negedge clk_sys) begin + reg rclkD, rclkD2; + + rclkD <= rclk; + rclkD2 <= rclkD; + ioctl_wrd<= {ioctl_wrd[0],1'b0}; + + if(rclkD & ~rclkD2) begin + ioctl_dout <= data_w; + ioctl_addr <= addr_w; + ioctl_wrd <= 2'b11; + end +end + +endmodule diff --git a/Sharp -MZ-80K_MiST/rtl/monrom.qip b/Sharp -MZ-80K_MiST/rtl/monrom.qip new file mode 100644 index 00000000..381bc68d --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/monrom.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "RAM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "monrom.v"] diff --git a/Sharp -MZ-80K_MiST/rtl/monrom.v b/Sharp -MZ-80K_MiST/rtl/monrom.v new file mode 100644 index 00000000..e1ff0617 --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/monrom.v @@ -0,0 +1,184 @@ +// megafunction wizard: %RAM: 1-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: monrom.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.0 Build 162 10/23/2013 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2013 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module monrom ( + address, + clock, + data, + rden, + wren, + q); + + input [14:0] address; + input clock; + input [7:0] data; + input rden; + input wren; + output [7:0] q; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri1 clock; + tri1 rden; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [7:0] sub_wire0; + wire [7:0] q = sub_wire0[7:0]; + + altsyncram altsyncram_component ( + .address_a (address), + .clock0 (clock), + .data_a (data), + .wren_a (wren), + .rden_a (rden), + .q_a (sub_wire0), + .aclr0 (1'b0), + .aclr1 (1'b0), + .address_b (1'b1), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_b (1'b1), + .eccstatus (), + .q_b (), + .rden_b (1'b1), + .wren_b (1'b0)); + defparam + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", +`ifdef NO_PLI + altsyncram_component.init_file = "80ktc.rif" +`else + altsyncram_component.init_file = "80ktc.hex" +`endif +, + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 32768, + altsyncram_component.operation_mode = "SINGLE_PORT", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_reg_a = "CLOCK0", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", + altsyncram_component.widthad_a = 15, + altsyncram_component.width_a = 8, + altsyncram_component.width_byteena_a = 1; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +// Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +// Retrieval info: PRIVATE: AclrByte NUMERIC "0" +// Retrieval info: PRIVATE: AclrData NUMERIC "0" +// Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +// Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: Clken NUMERIC "0" +// Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1" +// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +// Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +// Retrieval info: PRIVATE: MIFfilename STRING "80ktc.hex" +// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "32768" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" +// Retrieval info: PRIVATE: RegAddr NUMERIC "1" +// Retrieval info: PRIVATE: RegData NUMERIC "1" +// Retrieval info: PRIVATE: RegOutput NUMERIC "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: SingleClock NUMERIC "1" +// Retrieval info: PRIVATE: UseDQRAM NUMERIC "1" +// Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0" +// Retrieval info: PRIVATE: WidthAddr NUMERIC "15" +// Retrieval info: PRIVATE: WidthData NUMERIC "8" +// Retrieval info: PRIVATE: rden NUMERIC "1" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: INIT_FILE STRING "80ktc.hex" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "32768" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT" +// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "15" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: USED_PORT: address 0 0 15 0 INPUT NODEFVAL "address[14..0]" +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]" +// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" +// Retrieval info: USED_PORT: rden 0 0 0 0 INPUT VCC "rden" +// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL "wren" +// Retrieval info: CONNECT: @address_a 0 0 15 0 address 0 0 15 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: @rden_a 0 0 0 0 rden 0 0 0 0 +// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0 +// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL monrom.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL monrom.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL monrom.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL monrom.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL monrom_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL monrom_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf diff --git a/Sharp -MZ-80K_MiST/rtl/mycom.v b/Sharp -MZ-80K_MiST/rtl/mycom.v new file mode 100644 index 00000000..7aed02a4 --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/mycom.v @@ -0,0 +1,139 @@ + + +module mycom(CLK_50MHZ, BTN_NORTH,BTN_EAST,BTN_SOUTH, BTN_WEST, + VGA_RED, VGA_GREEN, VGA_BLUE, VGA_HSYNC, VGA_VSYNC, Pix_ce, + PS2_CLK, PS2_DATA, Turbo, + SW,LED,TP1); + input CLK_50MHZ; + input BTN_NORTH,BTN_EAST,BTN_SOUTH,BTN_WEST; + input PS2_CLK, PS2_DATA; + input Turbo; + output VGA_RED, VGA_GREEN, VGA_BLUE, VGA_HSYNC, VGA_VSYNC; + output Pix_ce; + input [3:0] SW; + output [7:0] LED; + output TP1; +// �N���b�N�̐��� + wire CLK_CPU; + reg CLK_2M = 0, CLK_31250 = 0; + reg [4:0] count_2M = 0; + reg [10:0] count_31250 = 0; + reg [32:0] clk_count = 0; + always @(posedge CLK_50MHZ) begin + clk_count <= clk_count + 1; + end + always @(posedge CLK_50MHZ) begin + count_2M <= count_2M >= 13 ? 0 : count_2M + 1; + count_31250 <= count_31250 >= 800 ? 0 : count_31250 + 1; + CLK_2M <= count_2M == 0 ? ~CLK_2M : CLK_2M; + CLK_31250 <= count_31250 == 0 ? ~CLK_31250 : CLK_31250; + end + assign CLK_CPU = Turbo ? clk_count[2] : clk_count[3]; +// assign CLK_CPU = clk_count[2]; // 6MHZ +// assign CLK_CPU = clk_count[3]; // 3MHZ + +// reset���H + wire reset; + reg reset1 = 1, reset2 = 1; + always @( posedge CLK_CPU ) begin + reset1 <= BTN_EAST; + reset2 <= reset1; + end + assign reset = reset1 | reset2; + +// Z80��WIRE���` + wire [15:0] cpu_addr; + wire [7:0] cpu_data_in, cpu_data_out; + wire mreq, iorq, rd, wr, busreq, busack, intack; + wire start, waitreq; + +// I/O�̎�� +wire [15:0]io_led,io_e000,io_e001,io_e002,io_8253,io_e008; + assign io_led = (cpu_addr[15:0] == 16'he300) & mreq; + assign io_e000 = (cpu_addr[15:0] == 16'he000) & mreq; + assign io_e001 = (cpu_addr[15:0] == 16'he001) & mreq; + assign io_e002 = (cpu_addr[15:0] == 16'he002) & mreq; + assign io_8253 = (cpu_addr[15:2] == 14'b11100000000001) & mreq; + assign io_e008 = (cpu_addr[15:0] == 16'he008) & mreq; + wire [7:0] io_switch = {BTN_NORTH,BTN_EAST,BTN_SOUTH, + BTN_WEST,SW[3:0]}; + reg [7:0] led_buf; + reg [7:0] sound_buf; + reg [3:0] key_no; + reg speaker_enable; + always @(posedge CLK_CPU or posedge reset) begin + if (reset) begin + led_buf <= 0; + sound_buf <= 0; + key_no <= 0; + speaker_enable <= 0; + end else begin + if ( io_led & wr ) begin + led_buf <= cpu_data_out; + end else if (io_e000 & wr ) begin + key_no <= cpu_data_out[3:0]; + end else if (io_e008 & wr ) begin + speaker_enable <= cpu_data_out[0]; + end + end + end + assign LED = led_buf; + +// Z80�̎�� + assign waitreq = start; + wire out0, out1, out2; + fz80 z80(.data_in(cpu_data_in), .data_out(cpu_data_out), + .reset_in(reset), .clk(CLK_CPU), + .mreq(mreq), .iorq(iorq), .rd(rd), .wr(wr), + .adr(cpu_addr), .waitreq(waitreq), + .nmireq(0), .intreq(out2 & 0), .busreq(busreq), .busack_out(busack), + .start(start)); +// 8253�̎�� (CLK0=2M CLK1=31.25K CLK2=OUT1) + wire [7:0] i8253_data_out; + i8253 i8253_1(.reset(reset), .clk(CLK_CPU), .addr(cpu_addr[1:0]), .data_out(i8253_data_out), .data_in(cpu_data_out), + .cs(io_8253 & ~start), .rd(rd), .wr(wr), + .clk0(CLK_2M), .clk1(CLK_31250), .clk2(out1), + .out0(out0), .out1(out1), .out2(out2) ); + +// KEYBOARD�̎�� + wire [7:0] ps2_data; + ps2 ps2_1(.clk(CLK_50MHZ), .reset(reset), .ps2_clk(PS2_CLK), .ps2_data(PS2_DATA), .cs(io_e001 & rd), .rd(rd), .addr(key_no), .data(ps2_data)); + +// MAIN RAM�̎�� + wire ram_select = (( cpu_addr[15:15] == 1'b0 || cpu_addr[15:12] == 4'b1000) & mreq) & ~busack; + wire ram_en, ram_we; + wire [7:0] ram_data_out, ram_data_in; + + monrom monrom(.address(cpu_addr),.clock(CLK_50MHZ),.data(ram_data_in), + .q(ram_data_out),.rden(ram_en),.wren(ram_we)); + assign ram_en = ram_select; + assign ram_we = wr; + assign ram_data_in = cpu_data_out; + +// VRAM�̎�� + wire vram_select = ((cpu_addr[15:11] == 5'b11010) & mreq) | busack; + wire [11:0] vram_addr; + wire vram_rd, vram_wr; + wire [7:0] vram_data, vram_data_in; + vram vram(.address(vram_addr),.clock(CLK_50MHZ), + .data(vram_data_in),.q(vram_data),.rden(vram_select),.wren(vram_wr)); + assign vram_data_in = (vram_select & wr) ? cpu_data_out : 8'hzz; + +// VGA�̎�� + wire [11:0] vga_addr; + vga vga1(.CLK_50MHZ(CLK_50MHZ), .VGA_RED(VGA_RED), .VGA_GREEN(VGA_GREEN), .VGA_BLUE(VGA_BLUE), + .VGA_HSYNC(VGA_HSYNC), .VGA_VSYNC(VGA_VSYNC), .Pix_ce(Pix_ce), + .VGA_ADDR(vga_addr), .VGA_DATA(vram_data), .BUS_REQ(busreq), .BUS_ACK(busack)); + assign vram_addr[11:0] = busack ? vga_addr[11:0] : cpu_addr[11:0]; + assign vram_rd = busack | rd; + assign vram_wr = busack ? 1'b0 : wr; +// Memory�A�N�Z�X + assign cpu_data_in = ( io_led & rd ) ? io_switch : + ( io_e001 & rd ) ? ps2_data : + ( io_e002 & rd ) ? {VGA_VSYNC, clk_count[24], 6'b0000000} : + ( io_8253 & rd ) ? i8253_data_out : + ( io_e008 & rd ) ? {7'b0000000, clk_count[19]} : // MUSIC���Ȃǂ�WAIT�ŏd�v + (vram_select & rd) ? vram_data : + (ram_select & rd) ? ram_data_out: 8'hzz; + assign TP1 = speaker_enable & out0; +endmodule diff --git a/Sharp -MZ-80K_MiST/rtl/mz80k.sv b/Sharp -MZ-80K_MiST/rtl/mz80k.sv new file mode 100644 index 00000000..d99dec2e --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/mz80k.sv @@ -0,0 +1,136 @@ +module mz80k +( + output LED, + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_HS, + output VGA_VS, + output AUDIO_L, + output AUDIO_R, + input SPI_SCK, + output SPI_DO, + input SPI_DI, + input SPI_SS2, + input SPI_SS3, + input CONF_DATA0, + input CLOCK_27 +); + +`include "rtl\build_id.v" + +localparam CONF_STR = { + "MZ80K;;", + "O2,CPU CLOCK ,6MHZ,3MHZ;", + "O34,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;", + "T6,Reset;", + "V,v1.00.",`BUILD_DATE +}; + + +wire clk_sys; +wire [31:0] status; +wire [1:0] buttons; +wire [1:0] switches; +wire [7:0] kbjoy; +wire [7:0] joystick_0; +wire [7:0] joystick_1; +wire scandoubler_disable; +wire ypbpr; +wire ps2_kbd_clk, ps2_kbd_data; +wire [7:0] audio; +//assign LED = 1; + +wire hblank, vblank; +wire ce_vid; +wire hs, vs; +wire r,g,b; + + +pll pll +( + .inclk0(CLOCK_27), + .c0(clk_sys) + ); + +video_mixer #(.LINE_LENGTH(640), .HALF_DEPTH(1)) video_mixer +( + .clk_sys(clk_sys), + .ce_pix(ce_vid), + .ce_pix_actual(ce_vid), + .SPI_SCK(SPI_SCK), + .SPI_SS3(SPI_SS3), + .SPI_DI(SPI_DI), + .R({r,r,r}), + .G({g,g,g}), + .B({b,b,b}), + .HSync(hs), + .VSync(vs), + .VGA_R(VGA_R), + .VGA_G(VGA_G), + .VGA_B(VGA_B), + .VGA_VS(VGA_VS), + .VGA_HS(VGA_HS), + .scandoubler_disable(1),//scandoubler_disable), + .scanlines(scandoubler_disable ? 2'b00 : {status[4:3] == 3, status[4:3] == 2}), + .hq2x(status[4:3]==1), + .ypbpr_full(1), + .line_start(0), + .mono(0) +); + + +mist_io #(.STRLEN(($size(CONF_STR)>>3))) mist_io +( + .clk_sys (clk_sys ), + .conf_str (CONF_STR ), + .SPI_SCK (SPI_SCK ), + .CONF_DATA0 (CONF_DATA0 ), + .SPI_SS2 (SPI_SS2 ), + .SPI_DO (SPI_DO ), + .SPI_DI (SPI_DI ), + .buttons (buttons ), + .switches (switches ), + .scandoubler_disable(scandoubler_disable), + .ypbpr (ypbpr ), + .ps2_kbd_clk (ps2_kbd_clk ), + .ps2_kbd_data (ps2_kbd_data ), + .joystick_0 (joystick_0 ), + .joystick_1 (joystick_1 ), + .status (status ) +); + +mycom mycom +( + .CLK_50MHZ(clk_sys), + .BTN_NORTH(), + .BTN_EAST((status[0] | status[6] | buttons[1])),//reset + .BTN_SOUTH(), + .BTN_WEST(), + .VGA_RED(r), + .VGA_GREEN(g), + .VGA_BLUE(b), + .VGA_HSYNC(hs), + .VGA_VSYNC(vs), + .Turbo(status[2]), + .Pix_ce(ce_vid), + .PS2_CLK(ps2_kbd_clk), + .PS2_DATA(ps2_kbd_data), + .SW(), + .LED(LED), + .TP1(audio) + ); + + + +dac dac +( + .clk_i(clk_sys), + .res_n_i(1), + .dac_i(audio), + .dac_o(AUDIO_L) + ); + +assign AUDIO_R = AUDIO_L; + +endmodule diff --git a/Sharp -MZ-80K_MiST/rtl/osd.v b/Sharp -MZ-80K_MiST/rtl/osd.v new file mode 100644 index 00000000..c62c10af --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/osd.v @@ -0,0 +1,179 @@ +// A simple OSD implementation. Can be hooked up between a cores +// VGA output and the physical VGA pins + +module osd ( + // OSDs pixel clock, should be synchronous to cores pixel clock to + // avoid jitter. + input clk_sys, + + // SPI interface + input SPI_SCK, + input SPI_SS3, + input SPI_DI, + + // VGA signals coming from core + input [5:0] R_in, + input [5:0] G_in, + input [5:0] B_in, + input HSync, + input VSync, + + // VGA signals going to video connector + output [5:0] R_out, + output [5:0] G_out, + output [5:0] B_out +); + +parameter OSD_X_OFFSET = 10'd0; +parameter OSD_Y_OFFSET = 10'd0; +parameter OSD_COLOR = 3'd0; + +localparam OSD_WIDTH = 10'd256; +localparam OSD_HEIGHT = 10'd128; + +// ********************************************************************************* +// spi client +// ********************************************************************************* + +// this core supports only the display related OSD commands +// of the minimig +reg osd_enable; +(* ramstyle = "no_rw_check" *) reg [7:0] osd_buffer[2047:0]; // the OSD buffer itself + +// the OSD has its own SPI interface to the io controller +always@(posedge SPI_SCK, posedge SPI_SS3) begin + reg [4:0] cnt; + reg [10:0] bcnt; + reg [7:0] sbuf; + reg [7:0] cmd; + + if(SPI_SS3) begin + cnt <= 0; + bcnt <= 0; + end else begin + sbuf <= {sbuf[6:0], SPI_DI}; + + // 0:7 is command, rest payload + if(cnt < 15) cnt <= cnt + 1'd1; + else cnt <= 8; + + if(cnt == 7) begin + cmd <= {sbuf[6:0], SPI_DI}; + + // lower three command bits are line address + bcnt <= {sbuf[1:0], SPI_DI, 8'h00}; + + // command 0x40: OSDCMDENABLE, OSDCMDDISABLE + if(sbuf[6:3] == 4'b0100) osd_enable <= SPI_DI; + end + + // command 0x20: OSDCMDWRITE + if((cmd[7:3] == 5'b00100) && (cnt == 15)) begin + osd_buffer[bcnt] <= {sbuf[6:0], SPI_DI}; + bcnt <= bcnt + 1'd1; + end + end +end + +// ********************************************************************************* +// video timing and sync polarity anaylsis +// ********************************************************************************* + +// horizontal counter +reg [9:0] h_cnt; +reg [9:0] hs_low, hs_high; +wire hs_pol = hs_high < hs_low; +wire [9:0] dsp_width = hs_pol ? hs_low : hs_high; + +// vertical counter +reg [9:0] v_cnt; +reg [9:0] vs_low, vs_high; +wire vs_pol = vs_high < vs_low; +wire [9:0] dsp_height = vs_pol ? vs_low : vs_high; + +wire doublescan = (dsp_height>350); + +reg ce_pix; +always @(negedge clk_sys) begin + integer cnt = 0; + integer pixsz, pixcnt; + reg hs; + + cnt <= cnt + 1; + hs <= HSync; + + pixcnt <= pixcnt + 1; + if(pixcnt == pixsz) pixcnt <= 0; + ce_pix <= !pixcnt; + + if(hs && ~HSync) begin + cnt <= 0; + pixsz <= (cnt >> 9) - 1; + pixcnt <= 0; + ce_pix <= 1; + end +end + +always @(posedge clk_sys) begin + reg hsD, hsD2; + reg vsD, vsD2; + + if(ce_pix) begin + // bring hsync into local clock domain + hsD <= HSync; + hsD2 <= hsD; + + // falling edge of HSync + if(!hsD && hsD2) begin + h_cnt <= 0; + hs_high <= h_cnt; + end + + // rising edge of HSync + else if(hsD && !hsD2) begin + h_cnt <= 0; + hs_low <= h_cnt; + v_cnt <= v_cnt + 1'd1; + end else begin + h_cnt <= h_cnt + 1'd1; + end + + vsD <= VSync; + vsD2 <= vsD; + + // falling edge of VSync + if(!vsD && vsD2) begin + v_cnt <= 0; + vs_high <= v_cnt; + end + + // rising edge of VSync + else if(vsD && !vsD2) begin + v_cnt <= 0; + vs_low <= v_cnt; + end + end +end + +// area in which OSD is being displayed +wire [9:0] h_osd_start = ((dsp_width - OSD_WIDTH)>> 1) + OSD_X_OFFSET; +wire [9:0] h_osd_end = h_osd_start + OSD_WIDTH; +wire [9:0] v_osd_start = ((dsp_height- (OSD_HEIGHT<> 1) + OSD_Y_OFFSET; +wire [9:0] v_osd_end = v_osd_start + (OSD_HEIGHT<= h_osd_start) && (h_cnt < h_osd_end) && + (VSync != vs_pol) && (v_cnt >= v_osd_start) && (v_cnt < v_osd_end); + +reg [7:0] osd_byte; +always @(posedge clk_sys) if(ce_pix) osd_byte <= osd_buffer[{doublescan ? osd_vcnt[7:5] : osd_vcnt[6:4], osd_hcnt[7:0]}]; + +wire osd_pixel = osd_byte[doublescan ? osd_vcnt[4:2] : osd_vcnt[3:1]]; + +assign R_out = !osd_de ? R_in : {osd_pixel, osd_pixel, OSD_COLOR[2], R_in[5:3]}; +assign G_out = !osd_de ? G_in : {osd_pixel, osd_pixel, OSD_COLOR[1], G_in[5:3]}; +assign B_out = !osd_de ? B_in : {osd_pixel, osd_pixel, OSD_COLOR[0], B_in[5:3]}; + +endmodule diff --git a/Sharp -MZ-80K_MiST/rtl/pll.qip b/Sharp -MZ-80K_MiST/rtl/pll.qip new file mode 100644 index 00000000..48665362 --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/pll.qip @@ -0,0 +1,4 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "pll.vhd"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"] diff --git a/Sharp -MZ-80K_MiST/rtl/pll.vhd b/Sharp -MZ-80K_MiST/rtl/pll.vhd new file mode 100644 index 00000000..73463402 --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/pll.vhd @@ -0,0 +1,350 @@ +-- megafunction wizard: %ALTPLL% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altpll + +-- ============================================================ +-- File Name: pll.vhd +-- Megafunction Name(s): +-- altpll +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.1.0 Build 162 10/23/2013 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2013 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files from any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY pll IS + PORT + ( + inclk0 : IN STD_LOGIC := '0'; + c0 : OUT STD_LOGIC + ); +END pll; + + +ARCHITECTURE SYN OF pll IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (4 DOWNTO 0); + SIGNAL sub_wire1 : STD_LOGIC ; + SIGNAL sub_wire2 : STD_LOGIC ; + SIGNAL sub_wire3 : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL sub_wire4_bv : BIT_VECTOR (0 DOWNTO 0); + SIGNAL sub_wire4 : STD_LOGIC_VECTOR (0 DOWNTO 0); + + + + COMPONENT altpll + GENERIC ( + bandwidth_type : STRING; + clk0_divide_by : NATURAL; + clk0_duty_cycle : NATURAL; + clk0_multiply_by : NATURAL; + clk0_phase_shift : STRING; + compensate_clock : STRING; + inclk0_input_frequency : NATURAL; + intended_device_family : STRING; + lpm_hint : STRING; + lpm_type : STRING; + operation_mode : STRING; + pll_type : STRING; + port_activeclock : STRING; + port_areset : STRING; + port_clkbad0 : STRING; + port_clkbad1 : STRING; + port_clkloss : STRING; + port_clkswitch : STRING; + port_configupdate : STRING; + port_fbin : STRING; + port_inclk0 : STRING; + port_inclk1 : STRING; + port_locked : STRING; + port_pfdena : STRING; + port_phasecounterselect : STRING; + port_phasedone : STRING; + port_phasestep : STRING; + port_phaseupdown : STRING; + port_pllena : STRING; + port_scanaclr : STRING; + port_scanclk : STRING; + port_scanclkena : STRING; + port_scandata : STRING; + port_scandataout : STRING; + port_scandone : STRING; + port_scanread : STRING; + port_scanwrite : STRING; + port_clk0 : STRING; + port_clk1 : STRING; + port_clk2 : STRING; + port_clk3 : STRING; + port_clk4 : STRING; + port_clk5 : STRING; + port_clkena0 : STRING; + port_clkena1 : STRING; + port_clkena2 : STRING; + port_clkena3 : STRING; + port_clkena4 : STRING; + port_clkena5 : STRING; + port_extclk0 : STRING; + port_extclk1 : STRING; + port_extclk2 : STRING; + port_extclk3 : STRING; + width_clock : NATURAL + ); + PORT ( + clk : OUT STD_LOGIC_VECTOR (4 DOWNTO 0); + inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + sub_wire4_bv(0 DOWNTO 0) <= "0"; + sub_wire4 <= To_stdlogicvector(sub_wire4_bv); + sub_wire1 <= sub_wire0(0); + c0 <= sub_wire1; + sub_wire2 <= inclk0; + sub_wire3 <= sub_wire4(0 DOWNTO 0) & sub_wire2; + + altpll_component : altpll + GENERIC MAP ( + bandwidth_type => "AUTO", + clk0_divide_by => 27, + clk0_duty_cycle => 50, + clk0_multiply_by => 50, + clk0_phase_shift => "0", + compensate_clock => "CLK0", + inclk0_input_frequency => 37037, + intended_device_family => "Cyclone III", + lpm_hint => "CBX_MODULE_PREFIX=pll", + lpm_type => "altpll", + operation_mode => "NORMAL", + pll_type => "AUTO", + port_activeclock => "PORT_UNUSED", + port_areset => "PORT_UNUSED", + port_clkbad0 => "PORT_UNUSED", + port_clkbad1 => "PORT_UNUSED", + port_clkloss => "PORT_UNUSED", + port_clkswitch => "PORT_UNUSED", + port_configupdate => "PORT_UNUSED", + port_fbin => "PORT_UNUSED", + port_inclk0 => "PORT_USED", + port_inclk1 => "PORT_UNUSED", + port_locked => "PORT_UNUSED", + port_pfdena => "PORT_UNUSED", + port_phasecounterselect => "PORT_UNUSED", + port_phasedone => "PORT_UNUSED", + port_phasestep => "PORT_UNUSED", + port_phaseupdown => "PORT_UNUSED", + port_pllena => "PORT_UNUSED", + port_scanaclr => "PORT_UNUSED", + port_scanclk => "PORT_UNUSED", + port_scanclkena => "PORT_UNUSED", + port_scandata => "PORT_UNUSED", + port_scandataout => "PORT_UNUSED", + port_scandone => "PORT_UNUSED", + port_scanread => "PORT_UNUSED", + port_scanwrite => "PORT_UNUSED", + port_clk0 => "PORT_USED", + port_clk1 => "PORT_UNUSED", + port_clk2 => "PORT_UNUSED", + port_clk3 => "PORT_UNUSED", + port_clk4 => "PORT_UNUSED", + port_clk5 => "PORT_UNUSED", + port_clkena0 => "PORT_UNUSED", + port_clkena1 => "PORT_UNUSED", + port_clkena2 => "PORT_UNUSED", + port_clkena3 => "PORT_UNUSED", + port_clkena4 => "PORT_UNUSED", + port_clkena5 => "PORT_UNUSED", + port_extclk0 => "PORT_UNUSED", + port_extclk1 => "PORT_UNUSED", + port_extclk2 => "PORT_UNUSED", + port_extclk3 => "PORT_UNUSED", + width_clock => 5 + ) + PORT MAP ( + inclk => sub_wire3, + clk => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +-- Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +-- Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +-- Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +-- Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +-- Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +-- Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +-- Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +-- Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +-- Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +-- Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +-- Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +-- Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +-- Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +-- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +-- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "27" +-- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "50.000000" +-- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +-- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +-- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +-- Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +-- Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +-- Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +-- Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +-- Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000" +-- Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +-- Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +-- Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "0" +-- Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +-- Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +-- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "50" +-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "50.00000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +-- Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +-- Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +-- Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +-- Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +-- Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +-- Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +-- Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +-- Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +-- Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +-- Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +-- Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +-- Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +-- Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +-- Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +-- Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +-- Retrieval info: PRIVATE: SPREAD_USE STRING "0" +-- Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +-- Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +-- Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +-- Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: USE_CLK0 STRING "1" +-- Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +-- Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +-- Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" +-- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "27" +-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "50" +-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +-- Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +-- Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +-- Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +-- Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +-- Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +-- Retrieval info: USED_PORT: @inclk 0 0 2 0 INPUT_CLK_EXT VCC "@inclk[1..0]" +-- Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +-- Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +-- Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +-- Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +-- Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf +-- Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Sharp -MZ-80K_MiST/rtl/ps2.v b/Sharp -MZ-80K_MiST/rtl/ps2.v new file mode 100644 index 00000000..a61eee0c --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/ps2.v @@ -0,0 +1,283 @@ +module ps2(clk, reset, + ps2_clk, ps2_data, + cs, rd, addr, data); + + input clk,reset; + input ps2_clk, ps2_data; + input cs, rd; + input [7:0] addr; + output [7:0] data; + + wire clk, reset; + wire ps2_clk, ps2_data; + wire cs, rd; + wire [7:0] addr; + reg [7:0] data; + + reg [7:0]key_tbl0 = 8'b11111111, + key_tbl1 = 8'b11111111, + key_tbl2 = 8'b11111111, + key_tbl3 = 8'b11111111, + key_tbl4 = 8'b11111111, + key_tbl5 = 8'b11111111, + key_tbl6 = 8'b11111111, + key_tbl7 = 8'b11111111, + key_tbl8 = 8'b11111111, + key_tbl9 = 8'b11111111, + key_tbla = 8'b11111111, + key_tblb = 8'b11111111, + key_tblc = 8'b11111111, + key_tbld = 8'b11111111, + key_tble = 8'b11111111; + reg key_f0 = 1'b0; + reg key_e0 = 1'b0; + + // + // I/O(0-9) read + // + always @(posedge clk ) begin + if ( cs & rd ) begin + begin + case (addr[3:0]) + 4'h0: data <= key_tbl0; + 4'h1: data <= key_tbl1; + 4'h2: data <= key_tbl2; + 4'h3: data <= key_tbl3; + 4'h4: data <= key_tbl4; + 4'h5: data <= key_tbl5; + 4'h6: data <= key_tbl6; + 4'h7: data <= key_tbl7; + 4'h8: data <= key_tbl8; + 4'h9: data <= key_tbl9; + 4'ha: data <= key_tbla; + 4'hb: data <= key_tblb; + 4'hc: data <= key_tblc; + 4'hd: data <= key_tbld; + 4'he: data <= key_tble; + default: data <= 8'hzz; + endcase + end + end + end + + // + // PS/2���͏������ + // + wire dten; + wire [7:0] kdata; + ps2_recieve ps2_recieve1(.clk(clk), .reset(reset), + .ps2_clk(ps2_clk), .ps2_data(ps2_data), + .dten(dten), .kdata(kdata)); + + + // + // + // + always @(posedge clk or posedge reset) begin + if( reset ) begin + key_e0 <= 1'b0; + key_f0 <= 1'b0; + key_tbl0 <= 8'b11111111; + key_tbl1 <= 8'b11111111; + key_tbl2 <= 8'b11111111; + key_tbl3 <= 8'b11111111; + key_tbl4 <= 8'b11111111; + key_tbl5 <= 8'b11111111; + key_tbl6 <= 8'b11111111; + key_tbl7 <= 8'b11111111; + key_tbl8 <= 8'b11111111; + key_tbl9 <= 8'b11111111; + end else if ( dten ) begin + case ( kdata ) + 8'h70: begin + if ( key_e0 ) begin + key_tbl8[1] <= key_f0; key_f0 <= 1'b0; key_e0 <= 1'b0; // INS (E0) + end else begin + key_tbl1[4] <= key_f0; key_f0 <= 1'b0; // 0 + end + end + 8'h69: begin + if ( key_e0 ) begin + key_f0 <= 1'b0; key_e0 <= 1'b0; // END (E0) + end else begin + key_tbl0[0] <= key_f0; key_f0 <= 1'b0; // 1 + end + end + 8'h72: begin + if ( key_e0 ) begin + key_tbl9[2] <= key_f0; key_f0 <= 1'b0; key_e0 <= 1'b0; // DOWN (E0) + end else begin + key_tbl1[0] <= key_f0; key_f0 <= 1'b0; // 2 + end + end + 8'h7A: begin + if ( key_e0 ) begin + key_tble[0] <= key_f0; key_f0 <= 1'b0; key_e0 <= 1'b0; // PGDN (E0) + end else begin + key_tbl0[1] <= key_f0; key_f0 <= 1'b0; // 3 + end + end + 8'h6B: begin + if ( key_e0 ) begin + key_tbl8[3] <= key_f0; key_f0 <= 1'b0; key_e0 <= 1'b0; // LEFT (E0) + end else begin + key_tbl1[1] <= key_f0; key_f0 <= 1'b0; // 4 + end + end + 8'h73: begin key_tbl0[2] <= key_f0; key_f0 <= 1'b0; end // 5 + 8'h74: begin + if ( key_e0 ) begin + key_tbl8[3] <= key_f0; key_f0 <= 1'b0; key_e0 <= 1'b0; // RIGHT (E0) + end else begin + key_tbl1[2] <= key_f0; key_f0 <= 1'b0; // 6 + end + end + 8'h6C: begin + if ( key_e0 ) begin + key_tbl8[0] <= key_f0; key_f0 <= 1'b0; key_e0 <= 1'b0; // HOME (E0) + end else begin + key_tbl0[3] <= key_f0; key_f0 <= 1'b0; // 7 + end + end + 8'h75: begin + if ( key_e0 ) begin + key_tbl9[2] <= key_f0; key_f0 <= 1'b0; key_e0 <= 1'b0; // UP (E0) + end else begin + key_tbl1[3] <= key_f0; key_f0 <= 1'b0; // 8 + end + end + 8'h7D: begin + if ( key_e0 ) begin + key_tble[0] <= key_f0; key_f0 <= 1'b0; key_e0 <= 1'b0; // PGUP (E0) + end else begin + key_tbl0[4] <= key_f0; key_f0 <= 1'b0; // 9 + end + end + 8'h7C: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // * + 8'h79: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // + + 8'h7B: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // = + 8'h7C: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // , + 8'h71: begin + if ( key_e0 ) begin + key_tbl8[1] <= key_f0; key_tblc[7] <= key_f0; key_f0 <= 1'b0; key_e0 <= 1'b0; // DEL (E0) + end else begin + key_tble[0] <= key_f0; key_f0 <= 1'b0; // . + end + end + 8'h71: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // . + 8'h5A: begin key_tbl8[4] <= key_f0; key_f0 <= 1'b0; end // RET E0 + 8'h54: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // @ + 8'h1C: begin key_tbl4[0] <= key_f0; key_f0 <= 1'b0; end // A + 8'h32: begin key_tbl6[2] <= key_f0; key_f0 <= 1'b0; end // B + 8'h21: begin key_tbl6[1] <= key_f0; key_f0 <= 1'b0; end // C + 8'h23: begin key_tbl4[1] <= key_f0; key_f0 <= 1'b0; end // D + 8'h24: begin key_tbl2[1] <= key_f0; key_f0 <= 1'b0; end // E + 8'h2B: begin key_tbl5[1] <= key_f0; key_f0 <= 1'b0; end // F + 8'h34: begin key_tbl4[2] <= key_f0; key_f0 <= 1'b0; end // G + 8'h33: begin key_tbl5[2] <= key_f0; key_f0 <= 1'b0; end // H + 8'h43: begin key_tbl3[3] <= key_f0; key_f0 <= 1'b0; end // I + 8'h3B: begin key_tbl4[3] <= key_f0; key_f0 <= 1'b0; end // J + 8'h42: begin key_tbl5[3] <= key_f0; key_f0 <= 1'b0; end // K + 8'h4B: begin key_tbl4[4] <= key_f0; key_f0 <= 1'b0; end // L + 8'h3A: begin key_tbl6[3] <= key_f0; key_f0 <= 1'b0; end // M + 8'h31: begin key_tbl7[2] <= key_f0; key_f0 <= 1'b0; end // N + 8'h44: begin key_tbl2[4] <= key_f0; key_f0 <= 1'b0; end // O + 8'h4D: begin key_tbl3[4] <= key_f0; key_f0 <= 1'b0; end // P + 8'h15: begin key_tbl2[0] <= key_f0; key_f0 <= 1'b0; end // Q + 8'h2D: begin key_tbl3[1] <= key_f0; key_f0 <= 1'b0; end // R + 8'h1B: begin key_tbl5[0] <= key_f0; key_f0 <= 1'b0; end // S + 8'h2C: begin key_tbl2[2] <= key_f0; key_f0 <= 1'b0; end // T + 8'h3C: begin key_tbl2[3] <= key_f0; key_f0 <= 1'b0; end // U + 8'h2A: begin key_tbl7[1] <= key_f0; key_f0 <= 1'b0; end // V + 8'h1D: begin key_tbl3[0] <= key_f0; key_f0 <= 1'b0; end // W + 8'h22: begin key_tbl7[0] <= key_f0; key_f0 <= 1'b0; end // X + 8'h35: begin key_tbl3[2] <= key_f0; key_f0 <= 1'b0; end // Y + 8'h1A: begin key_tbl6[0] <= key_f0; key_f0 <= 1'b0; end // Z + 8'h5B: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // [ + 8'h6A: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // \ + 8'h5D: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // ] + 8'h55: begin key_tbl5[5] <= key_f0; key_f0 <= 1'b0; end // ^ + 8'h4E: begin key_tbl2[5] <= key_f0; key_f0 <= 1'b0; end // = + 8'h45: begin key_tbl1[4] <= key_f0; key_f0 <= 1'b0; end // 0 + 8'h16: begin key_tbl0[0] <= key_f0; key_f0 <= 1'b0; end // 1 + 8'h1E: begin key_tbl1[0] <= key_f0; key_f0 <= 1'b0; end // 2 + 8'h26: begin key_tbl0[1] <= key_f0; key_f0 <= 1'b0; end // 3 + 8'h25: begin key_tbl1[1] <= key_f0; key_f0 <= 1'b0; end // 4 + 8'h2E: begin key_tbl0[2] <= key_f0; key_f0 <= 1'b0; end // 5 + 8'h36: begin key_tbl1[2] <= key_f0; key_f0 <= 1'b0; end // 6 + 8'h3D: begin key_tbl0[3] <= key_f0; key_f0 <= 1'b0; end // 7 + 8'h3E: begin key_tbl1[3] <= key_f0; key_f0 <= 1'b0; end // 8 + 8'h46: begin key_tbl0[4] <= key_f0; key_f0 <= 1'b0; end // 9 + 8'h52: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // : + 8'h4C: begin key_tbl5[4] <= key_f0; key_f0 <= 1'b0; end // ; + 8'h41: begin key_tbl7[3] <= key_f0; key_f0 <= 1'b0; end // < , + 8'h49: begin key_tbl6[4] <= key_f0; key_f0 <= 1'b0; end // > . + 8'h4A: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // ? + 8'h51: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // _ + 8'h11: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // GRPH + 8'h13: begin key_tbl6[5] <= key_f0; key_f0 <= 1'b0; end // �J�i + 8'h12: begin key_tbl8[0] <= ( key_f0 | key_e0 ) & (key_tbl8[0] | ~key_e0 ); key_f0 <= 1'b0; key_e0 <= 1'b0; end // SHIFT + 8'h59: begin key_tbl8[5] <= ( key_f0 | key_e0 ) & (key_tbl8[5] | ~key_e0 ); key_f0 <= 1'b0; key_e0 <= 1'b0; end // SHIFT + 8'h14: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // CTRL + 8'h77: begin key_tbl9[3] <= key_f0; key_f0 <= 1'b0; end // STOP (E1) + 8'h7E: begin key_tbl9[3] <= key_f0; key_f0 <= 1'b0; end // STOP (SCROLL KEY) + 8'h05: begin key_tble[0] <= key_f0; key_tblc[0] <= key_f0; key_f0 <= 1'b0; end // F1 + 8'h06: begin key_tble[0] <= key_f0; key_tblc[1] <= key_f0; key_f0 <= 1'b0; end // F2 + 8'h04: begin key_tble[0] <= key_f0; key_tblc[2] <= key_f0; key_f0 <= 1'b0; end // F3 + 8'h0C: begin key_tble[0] <= key_f0; key_tblc[3] <= key_f0; key_f0 <= 1'b0; end // F4 + 8'h03: begin key_tble[0] <= key_f0; key_tblc[4] <= key_f0; key_f0 <= 1'b0; end // F5 + 8'h29: begin key_tbl9[1] <= key_f0; key_tbld[7] <= key_f0; key_f0 <= 1'b0; end // SPACE + 8'h76: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // ESC + 8'h0d: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // TAB + 8'h58: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // CAPS + 8'h66: begin key_tbl8[1] <= key_f0; key_f0 <= 1'b0; end // BS + 8'h0b: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // F6 + 8'h83: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // F7 + 8'h0a: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // F8 + 8'h01: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // F9 + 8'h09: begin key_tble[0] <= key_f0; key_f0 <= 1'b0; end // F10 + 8'he0: key_e0 <= 1'b1; + 8'hf0: key_f0 <= 1'b1; + default: begin key_e0 <= 1'b0; key_f0 <= 1'b0; end + endcase + end + end + +endmodule + +module ps2_recieve(clk, reset, + ps2_clk, ps2_data, + dten, kdata); + + input clk,reset; + input ps2_clk, ps2_data; + output dten; + output [7:0] kdata; + + wire clk, reset; + wire ps2_clk, ps2_data; + reg dten; + reg [7:0] kdata; + + reg [10:0] key_data; + reg [3:0] clk_data; + + always @(posedge clk or posedge reset) begin + if( reset ) begin + key_data <= 11'b11111111111; + dten <= 1'b0; + end else begin + clk_data <= {clk_data[2:0], ps2_clk}; + if ( clk_data == 4'b0011 ) + key_data <= {ps2_data, key_data[10:1]}; + if ( !key_data[0] & key_data[10] ) begin + dten <= 1'b1; + kdata <= key_data[8:1]; + key_data <= 11'b11111111111; + end else + dten <= 1'b0; + end + + end + +endmodule diff --git a/Sharp -MZ-80K_MiST/rtl/rom/80KCG.ROM b/Sharp -MZ-80K_MiST/rtl/rom/80KCG.ROM new file mode 100644 index 0000000000000000000000000000000000000000..6598e2172e90c9e93afd63aa383670a744c1af54 GIT binary patch literal 2048 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 +// Copyright (c) 2017 Sorgelig +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// TODO: Delay vsync one line + +module scandoubler #(parameter LENGTH, parameter HALF_DEPTH) +( + // system interface + input clk_sys, + input ce_pix, + input ce_pix_actual, + + input hq2x, + + // shifter video interface + input hs_in, + input vs_in, + input line_start, + + input [DWIDTH:0] r_in, + input [DWIDTH:0] g_in, + input [DWIDTH:0] b_in, + input mono, + + // output interface + output reg hs_out, + output vs_out, + output [DWIDTH:0] r_out, + output [DWIDTH:0] g_out, + output [DWIDTH:0] b_out +); + + +localparam DWIDTH = HALF_DEPTH ? 2 : 5; + +assign vs_out = vs_in; + +reg [2:0] phase; +reg [2:0] ce_div; +reg [7:0] pix_len = 0; +wire [7:0] pl = pix_len + 1'b1; + +reg ce_x1, ce_x4; +reg req_line_reset; +wire ls_in = hs_in | line_start; +always @(negedge clk_sys) begin + reg old_ce; + reg [2:0] ce_cnt; + + reg [7:0] pixsz2, pixsz4 = 0; + + old_ce <= ce_pix; + if(~&pix_len) pix_len <= pix_len + 1'd1; + + ce_x4 <= 0; + ce_x1 <= 0; + + // use such odd comparison to place c_x4 evenly if master clock isn't multiple 4. + if((pl == pixsz4) || (pl == pixsz2) || (pl == (pixsz2+pixsz4))) begin + phase <= phase + 1'd1; + ce_x4 <= 1; + end + + if(~old_ce & ce_pix) begin + pixsz2 <= {1'b0, pl[7:1]}; + pixsz4 <= {2'b00, pl[7:2]}; + ce_x1 <= 1; + ce_x4 <= 1; + pix_len <= 0; + phase <= phase + 1'd1; + + ce_cnt <= ce_cnt + 1'd1; + if(ce_pix_actual) begin + phase <= 0; + ce_div <= ce_cnt + 1'd1; + ce_cnt <= 0; + req_line_reset <= 0; + end + + if(ls_in) req_line_reset <= 1; + end +end + +reg ce_sd; +always @(*) begin + case(ce_div) + 2: ce_sd = !phase[0]; + 4: ce_sd = !phase[1:0]; + default: ce_sd <= 1; + endcase +end + +localparam AWIDTH = `BITS_TO_FIT(LENGTH); +Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x +( + .clk(clk_sys), + .ce_x4(ce_x4 & ce_sd), + .inputpixel({b_in,g_in,r_in}), + .mono(mono), + .disable_hq2x(~hq2x), + .reset_frame(vs_in), + .reset_line(req_line_reset), + .read_y(sd_line), + .read_x(sd_h_actual), + .outpixel({b_out,g_out,r_out}) +); + +reg [10:0] sd_h_actual; +always @(*) begin + case(ce_div) + 2: sd_h_actual = sd_h[10:1]; + 4: sd_h_actual = sd_h[10:2]; + default: sd_h_actual = sd_h; + endcase +end + +reg [10:0] sd_h; +reg [1:0] sd_line; +always @(posedge clk_sys) begin + + reg [11:0] hs_max,hs_rise,hs_ls; + reg [10:0] hcnt; + reg [11:0] sd_hcnt; + + reg hs, hs2, vs, ls; + + if(ce_x1) begin + hs <= hs_in; + ls <= ls_in; + + if(ls && !ls_in) hs_ls <= {hcnt,1'b1}; + + // falling edge of hsync indicates start of line + if(hs && !hs_in) begin + hs_max <= {hcnt,1'b1}; + hcnt <= 0; + if(ls && !ls_in) hs_ls <= {10'd0,1'b1}; + end else begin + hcnt <= hcnt + 1'd1; + end + + // save position of rising edge + if(!hs && hs_in) hs_rise <= {hcnt,1'b1}; + + vs <= vs_in; + if(vs && ~vs_in) sd_line <= 0; + end + + if(ce_x4) begin + hs2 <= hs_in; + + // output counter synchronous to input and at twice the rate + sd_hcnt <= sd_hcnt + 1'd1; + sd_h <= sd_h + 1'd1; + if(hs2 && !hs_in) sd_hcnt <= hs_max; + if(sd_hcnt == hs_max) sd_hcnt <= 0; + + // replicate horizontal sync at twice the speed + if(sd_hcnt == hs_max) hs_out <= 0; + if(sd_hcnt == hs_rise) hs_out <= 1; + + if(sd_hcnt == hs_ls) sd_h <= 0; + if(sd_hcnt == hs_ls) sd_line <= sd_line + 1'd1; + end +end + +endmodule diff --git a/Sharp -MZ-80K_MiST/rtl/sound.v b/Sharp -MZ-80K_MiST/rtl/sound.v new file mode 100644 index 00000000..921ad339 --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/sound.v @@ -0,0 +1,49 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 08:54:34 02/19/2008 +// Design Name: +// Module Name: clock_gen +// Project Name: +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +module sound(CLK_50MHZ, SW, TP1); + input CLK_50MHZ; + input [7:0] SW; + output TP1; + reg [14:0] count = 0; + reg [14:0] count2 = 1; + reg CLK = 0; + wire TP1; + + always @(posedge CLK_50MHZ) + begin + count <= count + 1; + end + + always @(posedge count[12]) + begin + if ( count2 >= SW ) + begin + CLK <= SW != 0 ? ~CLK: CLK; + count2 <= 1; + end else + begin + count2 <= count2 + 1; + end + end + + assign TP1 = CLK; + +endmodule diff --git a/Sharp -MZ-80K_MiST/rtl/vga.v b/Sharp -MZ-80K_MiST/rtl/vga.v new file mode 100644 index 00000000..38e585a1 --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/vga.v @@ -0,0 +1,72 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 16:27:35 02/19/2008 +// Design Name: +// Module Name: vga +// Project Name: +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +module vga(CLK_50MHZ, VGA_RED, VGA_GREEN, VGA_BLUE, VGA_HSYNC, VGA_VSYNC, Pix_ce, + VGA_ADDR, VGA_DATA, BUS_REQ, BUS_ACK); + input CLK_50MHZ; + output VGA_RED, VGA_GREEN, VGA_BLUE, VGA_HSYNC, VGA_VSYNC; + output Pix_ce; + output [11:0] VGA_ADDR; + input [7:0] VGA_DATA; + output BUS_REQ; + input BUS_ACK; + reg [9:0] x = 0; + reg [9:0] y = 0; + reg [1:0] counter = 0; + wire display; + wire [9:0] gx, gy; // �O���t�B�b�N��W(0,0)-(639,399) + + always @(posedge CLK_50MHZ) begin + counter <= counter + 1; + end + assign Pix_ce = counter[0]; + assign gx = x - 144; // (96+48) + assign gy = y - 71; // (2+29+40) + always @(posedge counter[0]) begin + if ( x < 800 ) + begin + x <= x + 1; + end else begin + x <= 0; + if ( y < 521 ) + y <= y + 1; + else + y <= 0; + end + end +// CGROM�̎�� + wire [7:0] cgrom_data; + wire [11:0] cgrom_addr; +cgrom cgrom(.address(cgrom_addr), .clock(CLK_50MHZ), .q(cgrom_data), .rden(1'b1)); + wire [5:0] cx, cy; // �L�����N�^�[��W�֕ϊ�(0,0)-(79,24) + assign cx = gx >> 4; // �P�U�Ŋ��� + assign cy = gy >> 4; // �P�U�Ŋ��� + assign VGA_ADDR = (cy * 40) + cx; + assign cgrom_addr = {VGA_DATA, gy[3:1]}; + +// assign BUS_REQ = ( (96+48-8) <= x & x < (96+48+640) ) & ( ( 2+29+40) <= y & y < (2+29+40+400)); + assign BUS_REQ = ( (96+48-16) <= x & x < (96+48+640) ) & ( ( 2+29+40) <= y & y < (2+29+40+400)); + assign display =( (96+48) <= x & x < (96+48+640) ) & ( ( 2+29+40) <= y & y < (2+29+40+400)); + assign VGA_RED = 0; //display ? (cgrom_data[7-((gx>>1) & 7)]) : 0; + assign VGA_GREEN = display & (y[0] & 1) ? cgrom_data[7-(((gx+15)>>1) & 7)] : 0; + assign VGA_BLUE = 0; //display ? (cgrom_data[7-((gx>>1) & 7)]) : 0; + assign VGA_HSYNC = x < 96 ? 0 : 1; + assign VGA_VSYNC = y < 2 ? 0 : 1; +endmodule diff --git a/Sharp -MZ-80K_MiST/rtl/video_mixer.sv b/Sharp -MZ-80K_MiST/rtl/video_mixer.sv new file mode 100644 index 00000000..04cfd4ba --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/video_mixer.sv @@ -0,0 +1,242 @@ +// +// +// Copyright (c) 2017 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + +// +// LINE_LENGTH: Length of display line in pixels +// Usually it's length from HSync to HSync. +// May be less if line_start is used. +// +// HALF_DEPTH: If =1 then color dept is 3 bits per component +// For half depth 6 bits monochrome is available with +// mono signal enabled and color = {G, R} + +module video_mixer +#( + parameter LINE_LENGTH = 768, + parameter HALF_DEPTH = 0, + + parameter OSD_COLOR = 3'd4, + parameter OSD_X_OFFSET = 10'd0, + parameter OSD_Y_OFFSET = 10'd0 +) +( + // master clock + // it should be multiple by (ce_pix*4). + input clk_sys, + + // Pixel clock or clock_enable (both are accepted). + input ce_pix, + + // Some systems have multiple resolutions. + // ce_pix_actual should match ce_pix where every second or fourth pulse is enabled, + // thus half or qurter resolutions can be used without brake video sync while switching resolutions. + // For fixed single resolution (or when video sync stability isn't required) ce_pix_actual = ce_pix. + input ce_pix_actual, + + // OSD SPI interface + input SPI_SCK, + input SPI_SS3, + input SPI_DI, + + // scanlines (00-none 01-25% 10-50% 11-75%) + input [1:0] scanlines, + + // 0 = HVSync 31KHz, 1 = CSync 15KHz + input scandoubler_disable, + + // High quality 2x scaling + input hq2x, + + // YPbPr always uses composite sync + input ypbpr, + + // 0 = 16-240 range. 1 = 0-255 range. (only for YPbPr color space) + input ypbpr_full, + + // color + input [DWIDTH:0] R, + input [DWIDTH:0] G, + input [DWIDTH:0] B, + + // Monochrome mode (for HALF_DEPTH only) + input mono, + + // interlace sync. Positive pulses. + input HSync, + input VSync, + + // Falling of this signal means start of informative part of line. + // It can be horizontal blank signal. + // This signal can be used to reduce amount of required FPGA RAM for HQ2x scan doubler + // If FPGA RAM is not an issue, then simply set it to 0 for whole line processing. + // Keep in mind: due to algo first and last pixels of line should be black to avoid side artefacts. + // Thus, if blank signal is used to reduce the line, make sure to feed at least one black (or paper) pixel + // before first informative pixel. + input line_start, + + // MiST video output signals + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_VS, + output VGA_HS +); + +localparam DWIDTH = HALF_DEPTH ? 2 : 5; + +wire [DWIDTH:0] R_sd; +wire [DWIDTH:0] G_sd; +wire [DWIDTH:0] B_sd; +wire hs_sd, vs_sd; + +scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH)) scandoubler +( + .*, + .hs_in(HSync), + .vs_in(VSync), + .r_in(R), + .g_in(G), + .b_in(B), + + .hs_out(hs_sd), + .vs_out(vs_sd), + .r_out(R_sd), + .g_out(G_sd), + .b_out(B_sd) +); + +wire [DWIDTH:0] rt = (scandoubler_disable ? R : R_sd); +wire [DWIDTH:0] gt = (scandoubler_disable ? G : G_sd); +wire [DWIDTH:0] bt = (scandoubler_disable ? B : B_sd); + +generate + if(HALF_DEPTH) begin + wire [5:0] r = mono ? {gt,rt} : {rt,rt}; + wire [5:0] g = mono ? {gt,rt} : {gt,gt}; + wire [5:0] b = mono ? {gt,rt} : {bt,bt}; + end else begin + wire [5:0] r = rt; + wire [5:0] g = gt; + wire [5:0] b = bt; + end +endgenerate + +wire hs = (scandoubler_disable ? HSync : hs_sd); +wire vs = (scandoubler_disable ? VSync : vs_sd); + +reg scanline = 0; +always @(posedge clk_sys) begin + reg old_hs, old_vs; + + old_hs <= hs; + old_vs <= vs; + + if(old_hs && ~hs) scanline <= ~scanline; + if(old_vs && ~vs) scanline <= 0; +end + +wire [5:0] r_out, g_out, b_out; +always @(*) begin + case(scanlines & {scanline, scanline}) + 1: begin // reduce 25% = 1/2 + 1/4 + r_out = {1'b0, r[5:1]} + {2'b00, r[5:2]}; + g_out = {1'b0, g[5:1]} + {2'b00, g[5:2]}; + b_out = {1'b0, b[5:1]} + {2'b00, b[5:2]}; + end + + 2: begin // reduce 50% = 1/2 + r_out = {1'b0, r[5:1]}; + g_out = {1'b0, g[5:1]}; + b_out = {1'b0, b[5:1]}; + end + + 3: begin // reduce 75% = 1/4 + r_out = {2'b00, r[5:2]}; + g_out = {2'b00, g[5:2]}; + b_out = {2'b00, b[5:2]}; + end + + default: begin + r_out = r; + g_out = g; + b_out = b; + end + endcase +end + +wire [5:0] red, green, blue; +osd #(OSD_X_OFFSET, OSD_Y_OFFSET, OSD_COLOR) osd +( + .*, + + .R_in(r_out), + .G_in(g_out), + .B_in(b_out), + .HSync(hs), + .VSync(vs), + + .R_out(red), + .G_out(green), + .B_out(blue) +); + +wire [5:0] yuv_full[225] = '{ + 6'd0, 6'd0, 6'd0, 6'd0, 6'd1, 6'd1, 6'd1, 6'd1, + 6'd2, 6'd2, 6'd2, 6'd3, 6'd3, 6'd3, 6'd3, 6'd4, + 6'd4, 6'd4, 6'd5, 6'd5, 6'd5, 6'd5, 6'd6, 6'd6, + 6'd6, 6'd7, 6'd7, 6'd7, 6'd7, 6'd8, 6'd8, 6'd8, + 6'd9, 6'd9, 6'd9, 6'd9, 6'd10, 6'd10, 6'd10, 6'd11, + 6'd11, 6'd11, 6'd11, 6'd12, 6'd12, 6'd12, 6'd13, 6'd13, + 6'd13, 6'd13, 6'd14, 6'd14, 6'd14, 6'd15, 6'd15, 6'd15, + 6'd15, 6'd16, 6'd16, 6'd16, 6'd17, 6'd17, 6'd17, 6'd17, + 6'd18, 6'd18, 6'd18, 6'd19, 6'd19, 6'd19, 6'd19, 6'd20, + 6'd20, 6'd20, 6'd21, 6'd21, 6'd21, 6'd21, 6'd22, 6'd22, + 6'd22, 6'd23, 6'd23, 6'd23, 6'd23, 6'd24, 6'd24, 6'd24, + 6'd25, 6'd25, 6'd25, 6'd25, 6'd26, 6'd26, 6'd26, 6'd27, + 6'd27, 6'd27, 6'd27, 6'd28, 6'd28, 6'd28, 6'd29, 6'd29, + 6'd29, 6'd29, 6'd30, 6'd30, 6'd30, 6'd31, 6'd31, 6'd31, + 6'd31, 6'd32, 6'd32, 6'd32, 6'd33, 6'd33, 6'd33, 6'd33, + 6'd34, 6'd34, 6'd34, 6'd35, 6'd35, 6'd35, 6'd35, 6'd36, + 6'd36, 6'd36, 6'd36, 6'd37, 6'd37, 6'd37, 6'd38, 6'd38, + 6'd38, 6'd38, 6'd39, 6'd39, 6'd39, 6'd40, 6'd40, 6'd40, + 6'd40, 6'd41, 6'd41, 6'd41, 6'd42, 6'd42, 6'd42, 6'd42, + 6'd43, 6'd43, 6'd43, 6'd44, 6'd44, 6'd44, 6'd44, 6'd45, + 6'd45, 6'd45, 6'd46, 6'd46, 6'd46, 6'd46, 6'd47, 6'd47, + 6'd47, 6'd48, 6'd48, 6'd48, 6'd48, 6'd49, 6'd49, 6'd49, + 6'd50, 6'd50, 6'd50, 6'd50, 6'd51, 6'd51, 6'd51, 6'd52, + 6'd52, 6'd52, 6'd52, 6'd53, 6'd53, 6'd53, 6'd54, 6'd54, + 6'd54, 6'd54, 6'd55, 6'd55, 6'd55, 6'd56, 6'd56, 6'd56, + 6'd56, 6'd57, 6'd57, 6'd57, 6'd58, 6'd58, 6'd58, 6'd58, + 6'd59, 6'd59, 6'd59, 6'd60, 6'd60, 6'd60, 6'd60, 6'd61, + 6'd61, 6'd61, 6'd62, 6'd62, 6'd62, 6'd62, 6'd63, 6'd63, + 6'd63 +}; + +// http://marsee101.blog19.fc2.com/blog-entry-2311.html +// Y = 16 + 0.257*R + 0.504*G + 0.098*B (Y = 0.299*R + 0.587*G + 0.114*B) +// Pb = 128 - 0.148*R - 0.291*G + 0.439*B (Pb = -0.169*R - 0.331*G + 0.500*B) +// Pr = 128 + 0.439*R - 0.368*G - 0.071*B (Pr = 0.500*R - 0.419*G - 0.081*B) + +wire [18:0] y_8 = 19'd04096 + ({red, 8'd0} + {red, 3'd0}) + ({green, 9'd0} + {green, 2'd0}) + ({blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0}); +wire [18:0] pb_8 = 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0}) - ({green, 8'd0} + {green, 5'd0} + {green, 3'd0}) + ({blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0}); +wire [18:0] pr_8 = 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0}) - ({green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0}) - ({blue, 6'd0} + {blue , 3'd0}); + +wire [7:0] y = ( y_8[17:8] < 16) ? 8'd16 : ( y_8[17:8] > 235) ? 8'd235 : y_8[15:8]; +wire [7:0] pb = (pb_8[17:8] < 16) ? 8'd16 : (pb_8[17:8] > 240) ? 8'd240 : pb_8[15:8]; +wire [7:0] pr = (pr_8[17:8] < 16) ? 8'd16 : (pr_8[17:8] > 240) ? 8'd240 : pr_8[15:8]; + +assign VGA_R = ypbpr ? (ypbpr_full ? yuv_full[pr-8'd16] : pr[7:2]) : red; +assign VGA_G = ypbpr ? (ypbpr_full ? yuv_full[y -8'd16] : y[7:2]) : green; +assign VGA_B = ypbpr ? (ypbpr_full ? yuv_full[pb-8'd16] : pb[7:2]) : blue; +assign VGA_VS = (scandoubler_disable | ypbpr) ? 1'b1 : ~vs_sd; +assign VGA_HS = scandoubler_disable ? ~(HSync ^ VSync) : ypbpr ? ~(hs_sd ^ vs_sd) : ~hs_sd; + +endmodule diff --git a/Sharp -MZ-80K_MiST/rtl/vram.qip b/Sharp -MZ-80K_MiST/rtl/vram.qip new file mode 100644 index 00000000..c2a4bc54 --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/vram.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "RAM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "vram.v"] diff --git a/Sharp -MZ-80K_MiST/rtl/vram.v b/Sharp -MZ-80K_MiST/rtl/vram.v new file mode 100644 index 00000000..54555898 --- /dev/null +++ b/Sharp -MZ-80K_MiST/rtl/vram.v @@ -0,0 +1,177 @@ +// megafunction wizard: %RAM: 1-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: vram.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.0 Build 162 10/23/2013 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2013 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module vram ( + address, + clock, + data, + rden, + wren, + q); + + input [11:0] address; + input clock; + input [7:0] data; + input rden; + input wren; + output [7:0] q; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri1 clock; + tri1 rden; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [7:0] sub_wire0; + wire [7:0] q = sub_wire0[7:0]; + + altsyncram altsyncram_component ( + .address_a (address), + .clock0 (clock), + .data_a (data), + .wren_a (wren), + .rden_a (rden), + .q_a (sub_wire0), + .aclr0 (1'b0), + .aclr1 (1'b0), + .address_b (1'b1), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_b (1'b1), + .eccstatus (), + .q_b (), + .rden_b (1'b1), + .wren_b (1'b0)); + defparam + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 4096, + altsyncram_component.operation_mode = "SINGLE_PORT", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_reg_a = "CLOCK0", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", + altsyncram_component.widthad_a = 12, + altsyncram_component.width_a = 8, + altsyncram_component.width_byteena_a = 1; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +// Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +// Retrieval info: PRIVATE: AclrByte NUMERIC "0" +// Retrieval info: PRIVATE: AclrData NUMERIC "0" +// Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +// Retrieval info: PRIVATE: BlankMemory NUMERIC "1" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: Clken NUMERIC "0" +// Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1" +// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +// Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +// Retrieval info: PRIVATE: MIFfilename STRING "" +// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "4096" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" +// Retrieval info: PRIVATE: RegAddr NUMERIC "1" +// Retrieval info: PRIVATE: RegData NUMERIC "1" +// Retrieval info: PRIVATE: RegOutput NUMERIC "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: SingleClock NUMERIC "1" +// Retrieval info: PRIVATE: UseDQRAM NUMERIC "1" +// Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0" +// Retrieval info: PRIVATE: WidthAddr NUMERIC "12" +// Retrieval info: PRIVATE: WidthData NUMERIC "8" +// Retrieval info: PRIVATE: rden NUMERIC "1" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "4096" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT" +// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "12" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: USED_PORT: address 0 0 12 0 INPUT NODEFVAL "address[11..0]" +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]" +// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" +// Retrieval info: USED_PORT: rden 0 0 0 0 INPUT VCC "rden" +// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL "wren" +// Retrieval info: CONNECT: @address_a 0 0 12 0 address 0 0 12 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: @rden_a 0 0 0 0 rden 0 0 0 0 +// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0 +// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL vram.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL vram.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL vram.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL vram.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL vram_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL vram_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf diff --git a/Sharp -MZ-80K_MiST/snapshot/mz80k.rbf b/Sharp -MZ-80K_MiST/snapshot/mz80k.rbf new file mode 100644 index 0000000000000000000000000000000000000000..629f2f13bb73e1983ffe067663781a768c2260e0 GIT binary patch literal 244232 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 literal 0 HcmV?d00001