├── rtl ├── roms │ ├── boot.rom │ ├── boot.hex │ └── boot2.hex ├── sd_debug.qip ├── pll │ ├── pll_0002.qip │ ├── pll_0002_q13.qip │ └── pll_0002.v ├── T80 │ ├── T80.qip │ ├── README │ ├── T80_Reg.vhd │ ├── T80sed.vhd │ ├── T80s.vhd │ ├── T80se.vhd │ ├── GBse.vhd │ └── T8080se.vhd ├── dpram.sv ├── ce_generator.sv ├── bootrom.txt ├── bleeper.sv ├── edge_det.sv ├── pcw_starter.sv ├── mouse.sv ├── z80_regset.sv ├── amx_mouse.sv ├── kempston_mouse.sv ├── fake_daisy.sv └── z80_debugger.sv ├── docs ├── images │ ├── worm.jpg │ ├── gnome.jpg │ └── change_disk.jpg └── Keymatrix.md ├── palette ├── CGA_0_high.GBP ├── CGA_0_low.GBP ├── CGA_1_high.GBP ├── CGA_1_low.GBP ├── BlackRedBlueCyan.GBP ├── BlackGreenBlyeCyan.GBP ├── DBlueBlueOrangeWhite.GBP ├── DBlueBlueWhiteOrange.GBP ├── MagentaBlackBlueYellow.GBP └── MagentaBlueBlackYellow.GBP ├── releases ├── Amstrad-PCW_20200815.rbf ├── Amstrad-PCW_20200830.rbf └── Amstrad-PCW_20250621.rbf ├── PCW.sdc ├── sys ├── pll_hdmi │ ├── pll_hdmi_0002.qip │ └── pll_hdmi_0002.v ├── pll_q17.qip ├── pll_q13.qip ├── pll_audio │ ├── pll_audio_0002.qip │ └── pll_audio_0002.v ├── pll_cfg.qip ├── i2s.v ├── sigma_delta_dac.v ├── pll.13.qip ├── pll_hdmi.13.qip ├── pll_audio.13.qip ├── scanlines.v ├── vga_out.sv ├── mcp23009.sv ├── video_cleaner.sv ├── build_id.tcl ├── math.sv ├── sys_dual_sdram.tcl ├── i2c.v ├── ddr_svc.sv ├── sys.qip ├── sys_analog.tcl ├── video_freezer.sv ├── gamma_corr.sv ├── sys_top.sdc ├── shadowmask.sv ├── ltc2308.sv ├── alsa.sv ├── pll_cfg │ └── pll_cfg.v ├── scandoubler.v ├── video_mixer.sv ├── audio_out.v ├── iir_filter.v └── mt32pi.sv ├── .gitignore ├── clean.bat ├── files.qip ├── TODO.md ├── PCW.qpf ├── PCW.srf └── README.md /rtl/roms/boot.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiSTer-devel/Amstrad-PCW_MiSTer/HEAD/rtl/roms/boot.rom -------------------------------------------------------------------------------- /docs/images/worm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiSTer-devel/Amstrad-PCW_MiSTer/HEAD/docs/images/worm.jpg -------------------------------------------------------------------------------- /docs/images/gnome.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiSTer-devel/Amstrad-PCW_MiSTer/HEAD/docs/images/gnome.jpg -------------------------------------------------------------------------------- /palette/CGA_0_high.GBP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiSTer-devel/Amstrad-PCW_MiSTer/HEAD/palette/CGA_0_high.GBP -------------------------------------------------------------------------------- /palette/CGA_0_low.GBP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiSTer-devel/Amstrad-PCW_MiSTer/HEAD/palette/CGA_0_low.GBP -------------------------------------------------------------------------------- /palette/CGA_1_high.GBP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiSTer-devel/Amstrad-PCW_MiSTer/HEAD/palette/CGA_1_high.GBP -------------------------------------------------------------------------------- /palette/CGA_1_low.GBP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiSTer-devel/Amstrad-PCW_MiSTer/HEAD/palette/CGA_1_low.GBP -------------------------------------------------------------------------------- /docs/images/change_disk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiSTer-devel/Amstrad-PCW_MiSTer/HEAD/docs/images/change_disk.jpg -------------------------------------------------------------------------------- /palette/BlackRedBlueCyan.GBP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiSTer-devel/Amstrad-PCW_MiSTer/HEAD/palette/BlackRedBlueCyan.GBP -------------------------------------------------------------------------------- /palette/BlackGreenBlyeCyan.GBP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiSTer-devel/Amstrad-PCW_MiSTer/HEAD/palette/BlackGreenBlyeCyan.GBP -------------------------------------------------------------------------------- /palette/DBlueBlueOrangeWhite.GBP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiSTer-devel/Amstrad-PCW_MiSTer/HEAD/palette/DBlueBlueOrangeWhite.GBP -------------------------------------------------------------------------------- /palette/DBlueBlueWhiteOrange.GBP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiSTer-devel/Amstrad-PCW_MiSTer/HEAD/palette/DBlueBlueWhiteOrange.GBP -------------------------------------------------------------------------------- /releases/Amstrad-PCW_20200815.rbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiSTer-devel/Amstrad-PCW_MiSTer/HEAD/releases/Amstrad-PCW_20200815.rbf -------------------------------------------------------------------------------- /releases/Amstrad-PCW_20200830.rbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiSTer-devel/Amstrad-PCW_MiSTer/HEAD/releases/Amstrad-PCW_20200830.rbf -------------------------------------------------------------------------------- /releases/Amstrad-PCW_20250621.rbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiSTer-devel/Amstrad-PCW_MiSTer/HEAD/releases/Amstrad-PCW_20250621.rbf -------------------------------------------------------------------------------- /palette/MagentaBlackBlueYellow.GBP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiSTer-devel/Amstrad-PCW_MiSTer/HEAD/palette/MagentaBlackBlueYellow.GBP -------------------------------------------------------------------------------- /palette/MagentaBlueBlackYellow.GBP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiSTer-devel/Amstrad-PCW_MiSTer/HEAD/palette/MagentaBlueBlackYellow.GBP -------------------------------------------------------------------------------- /PCW.sdc: -------------------------------------------------------------------------------- 1 | create_clock -name "CLOCK_50" -period 20.000 [get_ports {CLOCK_50}] 2 | create_clock -name {SPI_SCK} -period 41.666 -waveform { 20.8 41.666 } [get_ports {SPI_SCK}] 3 | 4 | derive_pll_clocks 5 | derive_clock_uncertainty; 6 | 7 | -------------------------------------------------------------------------------- /sys/pll_hdmi/pll_hdmi_0002.qip: -------------------------------------------------------------------------------- 1 | set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" 2 | set_instance_assignment -name UNFORCE_MERGE_PLL_OUTPUT_COUNTER ON -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" 3 | -------------------------------------------------------------------------------- /rtl/sd_debug.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "RAM: 1-PORT" 2 | set_global_assignment -name IP_TOOL_VERSION "17.0" 3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" 4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "sd_debug.v"] 5 | -------------------------------------------------------------------------------- /sys/pll_q17.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name QIP_FILE rtl/pll.qip 2 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi.qip ] 3 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_audio.qip ] 4 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_cfg.qip ] 5 | -------------------------------------------------------------------------------- /sys/pll_q13.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll.13.qip ] 2 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi.13.qip ] 3 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_audio.13.qip ] 4 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_cfg.qip ] 5 | -------------------------------------------------------------------------------- /rtl/pll/pll_0002.qip: -------------------------------------------------------------------------------- 1 | set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_0002*|altera_pll:altera_pll_i*|*" 2 | set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_0002*|altera_pll:altera_pll_i*|*" 3 | set_instance_assignment -name PLL_AUTO_RESET OFF -to "*pll_0002*|altera_pll:altera_pll_i*|*" 4 | set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*" 5 | -------------------------------------------------------------------------------- /rtl/pll/pll_0002_q13.qip: -------------------------------------------------------------------------------- 1 | set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_0002*|altera_pll:altera_pll_i*|*" 2 | set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_0002*|altera_pll:altera_pll_i*|*" 3 | set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_0002*|altera_pll:altera_pll_i*|*" 4 | set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*" 5 | -------------------------------------------------------------------------------- /sys/pll_audio/pll_audio_0002.qip: -------------------------------------------------------------------------------- 1 | set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" 2 | set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" 3 | set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" 4 | set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" 5 | -------------------------------------------------------------------------------- /sys/pll_cfg.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name SYNTHESIS_ONLY_QIP ON 2 | set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/pll_cfg.v"] 3 | set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/pll_cfg_hdmi.v"] 4 | set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/altera_pll_reconfig_top.v"] 5 | set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/altera_pll_reconfig_core.v"] 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | db 2 | greybox_tmp 3 | incremental_db 4 | output_files 5 | simulation 6 | hc_output 7 | scaler 8 | hps_isw_handoff 9 | vip 10 | traces 11 | tests 12 | *_sim 13 | .qsys_edit 14 | PLLJ_PLLSPE_INFO.txt 15 | *.bak 16 | *.orig 17 | *.rej 18 | *.qdf 19 | *.rpt 20 | *.smsg 21 | *.summary 22 | *.done 23 | *.jdi 24 | *.pin 25 | *.sof 26 | *.qws 27 | *.ppf 28 | *.ddb 29 | build_id.v 30 | c5_pin_model_dump.txt 31 | *.sopcinfo 32 | *.csv 33 | *.f 34 | *.cmp 35 | *.sip 36 | *.spd 37 | *.bsf 38 | *~ 39 | *.xml 40 | *.cdf 41 | *.qarlog 42 | qar_info.json 43 | *.swp 44 | -------------------------------------------------------------------------------- /rtl/roms/boot.hex: -------------------------------------------------------------------------------- 1 | :20000000C30201F383ED410D78058720F831F0FF3E09D3F811320706C8DCB100CD84001D08 2 | :20002000F217003E80D3F70E090C79D3F80621CDB100CB5120F11520F021F5FF77CB7E28D4 3 | :20004000FC3CD3F81D1D3E06D3F8CDE40009660000000102012AFF2100F0DB008730FB87E2 4 | :20006000F26B00EDA220F37C1F38EF3E05D3F8CDC700E6CBC0472110F0248625862C10F9BA 5 | :200080003C20A0E90E80CDDB0005030FFF0700CDA50006C8381BCD4400CD44000E00CDDBBD 6 | :2000A00000030F0014CDBD0030FB1738F817D806143EB3E3E3E3E33D20F910F5C9DBF8E6BB 7 | :2000C00020C8CDE9000108210201DB008730FB3A0201F0EDA2E3E3E3E318EFDBF8E6402858 8 | :2000E000FA79D3F7CDBD0038FBE34623E30E01E3DB008730FBFAFB007EED7923E3E3E310A3 9 | :13010000EEC9AFD3F00100003ED302033EF802AFC3000002 10 | :00000001FF 11 | -------------------------------------------------------------------------------- /rtl/roms/boot2.hex: -------------------------------------------------------------------------------- 1 | :020000040000FA 2 | :20000000C30201F383ED410D78058720F831F0FF3E09D3F811320706C8DCB100CD84001D08 3 | :20002000F217003E80D3F70E090C79D3F80621CDB100CB5120F11520F021F5FF77CB7E28D4 4 | :20004000FC3CD3F81D1D3E06D3F8CDE40009660000000102012AFF2100F0DB008730FB87E2 5 | :20006000F26B00EDA220F37C1F38EF3E05D3F8CDC700E6CBC0472110F0248625862C10F9BA 6 | :200080003C20A0E90E80CDDB0005030FFF0700CDA50006C8381BCD4400CD44000E00CDDBBD 7 | :2000A00000030F0014CDBD0030FB1738F817D806143EB3E3E3E3E33D20F910F5C9DBF8E6BB 8 | :2000C00020C8CDE9000108210201DB008730FB3A0201F0EDA2E3E3E3E318EFDBF8E6402858 9 | :2000E000FA79D3F7CDBD0038FBE34623E30E01E3DB008730FBFAFB007EED7923E3E3E310A3 10 | :13010000EEC9AFD3F00100003ED302033EF802AFC3000002 11 | :00000001FF 12 | -------------------------------------------------------------------------------- /clean.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | del /s *.bak 3 | del /s *.orig 4 | del /s *.rej 5 | del /s *~ 6 | rmdir /s /q db 7 | rmdir /s /q incremental_db 8 | rmdir /s /q output_files 9 | rmdir /s /q simulation 10 | rmdir /s /q greybox_tmp 11 | rmdir /s /q hc_output 12 | rmdir /s /q .qsys_edit 13 | rmdir /s /q hps_isw_handoff 14 | rmdir /s /q sys\.qsys_edit 15 | rmdir /s /q sys\vip 16 | cd sys 17 | for /d %%i in (*_sim) do rmdir /s /q "%%~nxi" 18 | cd .. 19 | for /d %%i in (*_sim) do rmdir /s /q "%%~nxi" 20 | del build_id.v 21 | del c5_pin_model_dump.txt 22 | del PLLJ_PLLSPE_INFO.txt 23 | del /s *.qws 24 | del /s *.ppf 25 | del /s *.ddb 26 | del /s *.csv 27 | del /s *.cmp 28 | del /s *.sip 29 | del /s *.spd 30 | del /s *.bsf 31 | del /s *.f 32 | del /s *.sopcinfo 33 | del /s *.xml 34 | del *.cdf 35 | del /s new_rtl_netlist 36 | del /s old_rtl_netlist 37 | pause 38 | -------------------------------------------------------------------------------- /sys/i2s.v: -------------------------------------------------------------------------------- 1 | 2 | module i2s 3 | #( 4 | parameter AUDIO_DW = 16 5 | ) 6 | ( 7 | input reset, 8 | input clk, 9 | input ce, 10 | 11 | output reg sclk, 12 | output reg lrclk, 13 | output reg sdata, 14 | 15 | input [AUDIO_DW-1:0] left_chan, 16 | input [AUDIO_DW-1:0] right_chan 17 | ); 18 | 19 | always @(posedge clk) begin 20 | reg [7:0] bit_cnt; 21 | reg msclk; 22 | 23 | reg [AUDIO_DW-1:0] left; 24 | reg [AUDIO_DW-1:0] right; 25 | 26 | if (reset) begin 27 | bit_cnt <= 1; 28 | lrclk <= 1; 29 | sclk <= 1; 30 | msclk <= 1; 31 | end 32 | else begin 33 | sclk <= msclk; 34 | if(ce) begin 35 | msclk <= ~msclk; 36 | if(msclk) begin 37 | if(bit_cnt >= AUDIO_DW) begin 38 | bit_cnt <= 1; 39 | lrclk <= ~lrclk; 40 | if(lrclk) begin 41 | left <= left_chan; 42 | right <= right_chan; 43 | end 44 | end 45 | else begin 46 | bit_cnt <= bit_cnt + 1'd1; 47 | end 48 | sdata <= lrclk ? right[AUDIO_DW - bit_cnt] : left[AUDIO_DW - bit_cnt]; 49 | end 50 | end 51 | end 52 | end 53 | 54 | endmodule 55 | -------------------------------------------------------------------------------- /sys/sigma_delta_dac.v: -------------------------------------------------------------------------------- 1 | // 2 | // PWM DAC 3 | // 4 | // MSBI is the highest bit number. NOT amount of bits! 5 | // 6 | module sigma_delta_dac #(parameter MSBI=7, parameter INV=1'b1) 7 | ( 8 | output reg DACout, //Average Output feeding analog lowpass 9 | input [MSBI:0] DACin, //DAC input (excess 2**MSBI) 10 | input CLK, 11 | input RESET 12 | ); 13 | 14 | reg [MSBI+2:0] DeltaAdder; //Output of Delta Adder 15 | reg [MSBI+2:0] SigmaAdder; //Output of Sigma Adder 16 | reg [MSBI+2:0] SigmaLatch; //Latches output of Sigma Adder 17 | reg [MSBI+2:0] DeltaB; //B input of Delta Adder 18 | 19 | always @(*) DeltaB = {SigmaLatch[MSBI+2], SigmaLatch[MSBI+2]} << (MSBI+1); 20 | always @(*) DeltaAdder = DACin + DeltaB; 21 | always @(*) SigmaAdder = DeltaAdder + SigmaLatch; 22 | 23 | always @(posedge CLK or posedge RESET) begin 24 | if(RESET) begin 25 | SigmaLatch <= 1'b1 << (MSBI+1); 26 | DACout <= INV; 27 | end else begin 28 | SigmaLatch <= SigmaAdder; 29 | DACout <= SigmaLatch[MSBI+2] ^ INV; 30 | end 31 | end 32 | 33 | endmodule 34 | -------------------------------------------------------------------------------- /rtl/T80/T80.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) GBse.vhd ] 2 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80pa.vhd ] 3 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80s.vhd ] 4 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80se.vhd ] 5 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80a.vhd ] 6 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80as.vhd ] 7 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80sed.vhd ] 8 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T8080se.vhd ] 9 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80_Reg.vhd ] 10 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80_MCode.vhd ] 11 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80_ALU.vhd ] 12 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80.vhd ] 13 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80_Pack.vhd ] -------------------------------------------------------------------------------- /sys/pll.13.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_NAME "altera_pll" 2 | set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_VERSION "13.1" 3 | set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_ENV "mwpim" 4 | set_global_assignment -library "pll" -name MISC_FILE [file join $::quartus(qip_path) "pll.cmp"] 5 | set_global_assignment -name SYNTHESIS_ONLY_QIP ON 6 | 7 | set_global_assignment -library "pll" -name VERILOG_FILE rtl/pll.v 8 | set_global_assignment -library "pll" -name VERILOG_FILE rtl/pll/pll_0002.v 9 | 10 | set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_0002*|altera_pll:altera_pll_i*|*" 11 | set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_0002*|altera_pll:altera_pll_i*|*" 12 | set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_0002*|altera_pll:altera_pll_i*|*" 13 | set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*" 14 | 15 | set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_NAME "altera_pll" 16 | set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_VERSION "13.1" 17 | set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_ENV "mwpim" 18 | -------------------------------------------------------------------------------- /files.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name QIP_FILE rtl/T80/T80.qip 2 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/key_joystick.sv 3 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/mouse.sv 4 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/amx_mouse.sv 5 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/kempston_mouse.sv 6 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/dpram.sv 7 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/ym2149.sv 8 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/u765.sv 9 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/boot_loader.sv 10 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/fake_daisy.sv 11 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/z80_regset.sv 12 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/video_controller.sv 13 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/video_sync.sv 14 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/bleeper.sv 15 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/pcw_core.sv 16 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv 17 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/z80_debugger.sv 18 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/sd_debug.v 19 | set_global_assignment -name SYSTEMVERILOG_FILE rtl/edge_det.sv 20 | set_global_assignment -name SYSTEMVERILOG_FILE PCW.sv 21 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # PCW_MiSTer - To Do's: 2 | 3 | * Fixes and features to implement 4 | * Fix top line showing bottom line issue - Done 5 | * Check why resolution is now reporting 1440 x 256 - Fixed 6 | * Create boot from bios on startup - Done 7 | * Fix disk boot issue with fast CPU (ST0=40,ST1=04 in RW_DATA_EXEC3) - Done 8 | * Fix corruption writing at 16x and higher - Done 9 | * Fix Beeper sound - Done 10 | * Add DKTronics joystick and sound support - Done 11 | * Get Mouse support working - AMS Done, Kempston Done, Keymouse Done 12 | * Create fake daisywheel module to boot 3.5" disks - Done 13 | * RAMtest has corrupt screen at start - done 14 | * Find issue with intermittent disk corruption 15 | * Find screen corruption issue with HoE at boot 16 | * Fix Blagger stuck key 17 | 18 | 19 | 20 | * CF2DD support 21 | * Disk 40 - Drive 40 = 1 : 1 Track 22 | * Disk 40 - Drive 80 = 1 : 2 Track 23 | * Disk 80 - Drive 40 = 1 : 1 Track - will error 24 | * Disk 80 - Drive 80 = 1 : 1 Tract 25 | * SENSE_INT_STATE - returns modified cylinder number 26 | * SEEK needs cylinder halving 27 | 28 | * Future features 29 | * Add memory above 128K as SDRAM and options for different memory sizes 30 | * Get multiple drives working 31 | 32 | * Notes 33 | * System timing is 64Mhz clock 34 | * Video clock is 16 Mhz 35 | 36 | -------------------------------------------------------------------------------- /PCW.qpf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- # 2 | # 3 | # Copyright (C) 2017 Intel Corporation. All rights reserved. 4 | # Your use of Intel Corporation's design tools, logic functions 5 | # and other software and tools, and its AMPP partner logic 6 | # functions, and any output files from any of the foregoing 7 | # (including device programming or simulation files), and any 8 | # associated documentation or information are expressly subject 9 | # to the terms and conditions of the Intel Program License 10 | # Subscription Agreement, the Intel Quartus Prime License Agreement, 11 | # the Intel MegaCore Function License Agreement, or other 12 | # applicable license agreement, including, without limitation, 13 | # that your use is for the sole purpose of programming logic 14 | # devices manufactured by Intel and sold by Intel or its 15 | # authorized distributors. Please refer to the applicable 16 | # agreement for further details. 17 | # 18 | # -------------------------------------------------------------------------- # 19 | # 20 | # Quartus Prime 21 | # Version 17.0.2 Build 602 07/19/2017 SJ Lite Edition 22 | # Date created = 17:03:58 February 06, 2025 23 | # 24 | # -------------------------------------------------------------------------- # 25 | 26 | QUARTUS_VERSION = "17.0" 27 | DATE = "17:03:58 February 06, 2025" 28 | 29 | # Revisions 30 | 31 | PROJECT_REVISION = "PCW" 32 | -------------------------------------------------------------------------------- /sys/pll_hdmi.13.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_NAME "altera_pll" 2 | set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_VERSION "13.1" 3 | set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_ENV "mwpim" 4 | set_global_assignment -library "pll_hdmi" -name MISC_FILE [file join $::quartus(qip_path) "pll_hdmi.cmp"] 5 | set_global_assignment -name SYNTHESIS_ONLY_QIP ON 6 | 7 | set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi.v"] 8 | set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi/pll_hdmi_0002.v"] 9 | 10 | set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" 11 | set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" 12 | set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" 13 | set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" 14 | 15 | set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_NAME "altera_pll" 16 | set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_VERSION "13.1" 17 | set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_ENV "mwpim" 18 | -------------------------------------------------------------------------------- /sys/pll_audio.13.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_NAME "altera_pll" 2 | set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_VERSION "13.1" 3 | set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_ENV "mwpim" 4 | set_global_assignment -library "pll_audio" -name MISC_FILE [file join $::quartus(qip_path) "pll_audio.cmp"] 5 | set_global_assignment -name SYNTHESIS_ONLY_QIP ON 6 | 7 | set_global_assignment -library "pll_audio" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_audio.v"] 8 | set_global_assignment -library "pll_audio" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_audio/pll_audio_0002.v"] 9 | 10 | set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" 11 | set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" 12 | set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" 13 | set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" 14 | 15 | set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_NAME "altera_pll" 16 | set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_VERSION "13.1" 17 | set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_ENV "mwpim" 18 | -------------------------------------------------------------------------------- /sys/scanlines.v: -------------------------------------------------------------------------------- 1 | module scanlines #(parameter v2=0) 2 | ( 3 | input clk, 4 | 5 | input [1:0] scanlines, 6 | input [23:0] din, 7 | input hs_in,vs_in, 8 | input de_in,ce_in, 9 | 10 | output reg [23:0] dout, 11 | output reg hs_out,vs_out, 12 | output reg de_out,ce_out 13 | ); 14 | 15 | reg [1:0] scanline; 16 | always @(posedge clk) begin 17 | reg old_hs, old_vs; 18 | 19 | old_hs <= hs_in; 20 | old_vs <= vs_in; 21 | 22 | if(old_hs && ~hs_in) begin 23 | if(v2) begin 24 | scanline <= scanline + 1'd1; 25 | if (scanline == scanlines) scanline <= 0; 26 | end 27 | else scanline <= scanline ^ scanlines; 28 | end 29 | if(old_vs && ~vs_in) scanline <= 0; 30 | end 31 | 32 | wire [7:0] r,g,b; 33 | assign {r,g,b} = din; 34 | 35 | reg [23:0] d; 36 | always @(*) begin 37 | case(scanline) 38 | 1: // reduce 25% = 1/2 + 1/4 39 | d = {{1'b0, r[7:1]} + {2'b00, r[7:2]}, 40 | {1'b0, g[7:1]} + {2'b00, g[7:2]}, 41 | {1'b0, b[7:1]} + {2'b00, b[7:2]}}; 42 | 43 | 2: // reduce 50% = 1/2 44 | d = {{1'b0, r[7:1]}, 45 | {1'b0, g[7:1]}, 46 | {1'b0, b[7:1]}}; 47 | 48 | 3: // reduce 75% = 1/4 49 | d = {{2'b00, r[7:2]}, 50 | {2'b00, g[7:2]}, 51 | {2'b00, b[7:2]}}; 52 | 53 | default: d = {r,g,b}; 54 | endcase 55 | end 56 | 57 | always @(posedge clk) begin 58 | reg [23:0] dout1, dout2; 59 | reg de1,de2,vs1,vs2,hs1,hs2,ce1,ce2; 60 | 61 | dout <= dout2; dout2 <= dout1; dout1 <= d; 62 | vs_out <= vs2; vs2 <= vs1; vs1 <= vs_in; 63 | hs_out <= hs2; hs2 <= hs1; hs1 <= hs_in; 64 | de_out <= de2; de2 <= de1; de1 <= de_in; 65 | ce_out <= ce2; ce2 <= ce1; ce1 <= ce_in; 66 | end 67 | 68 | endmodule 69 | -------------------------------------------------------------------------------- /rtl/dpram.sv: -------------------------------------------------------------------------------- 1 | // 2 | // dpram.sv 3 | // 4 | // sdram controller implementation for the MiSTer board by 5 | // 6 | // Copyright (c) 2020 Frank Bruno 7 | // 8 | // This source file is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published 10 | // by the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // This source file is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with this program. If not, see . 20 | // 21 | 22 | module dpram #( 23 | parameter DATA = 72, 24 | parameter ADDR = 10 25 | ) ( 26 | // Port A 27 | input wire a_clk, 28 | input wire a_wr, 29 | input wire [ADDR-1:0] a_addr, 30 | input wire [DATA-1:0] a_din, 31 | output logic [DATA-1:0] a_dout, 32 | 33 | // Port B 34 | input wire b_clk, 35 | input wire b_wr, 36 | input wire [ADDR-1:0] b_addr, 37 | input wire [DATA-1:0] b_din, 38 | output logic [DATA-1:0] b_dout 39 | ); 40 | 41 | // Shared memory 42 | logic [DATA-1:0] mem [(2**ADDR)-1:0]; 43 | 44 | /* initial begin 45 | mem = '{default:'0}; 46 | end */ 47 | 48 | // Port A 49 | always @(posedge a_clk) begin 50 | a_dout <= mem[a_addr]; 51 | if(a_wr) begin 52 | a_dout <= a_din; 53 | mem[a_addr] <= a_din; 54 | end 55 | end 56 | 57 | // Port B 58 | always @(posedge b_clk) begin 59 | b_dout <= mem[b_addr]; 60 | if(b_wr) begin 61 | b_dout <= b_din; 62 | mem[b_addr] <= b_din; 63 | end 64 | end 65 | 66 | endmodule 67 | -------------------------------------------------------------------------------- /rtl/ce_generator.sv: -------------------------------------------------------------------------------- 1 | module ce_generator( 2 | input wire clk, 3 | input wire reset, 4 | input wire [1:0] overclock, 5 | output logic cpu_ce_p, 6 | output logic cpu_ce_n, 7 | output logic sdram_clk_ref, 8 | output logic ce_16mhz, 9 | output logic ce_4mhz, 10 | output logic ce_1mhz, 11 | output logic clk_2mhz 12 | ); 13 | reg [5:0] counter; 14 | reg [2:0] div_factor; 15 | 16 | always @(posedge clk or posedge reset) begin 17 | if (reset) counter <= 'b0; 18 | else counter <= counter + 1'b1; 19 | end 20 | 21 | always @(*) begin 22 | case (overclock) 23 | 2'b00: div_factor = 3'd3; // 4 MHz 24 | 2'b01: div_factor = 3'd2; // 8 MHz 25 | 2'b10: div_factor = 3'd1; // 16 MHz 26 | 2'b11: div_factor = 3'd0; // 32 MHz 27 | default: div_factor = 3'd3; // Default to 4 MHz 28 | endcase 29 | end 30 | reg cpu_4mhz_n; 31 | // Generar las señales de habilitación del reloj 32 | assign ce_4mhz = ~counter[3] & ~counter[2] & ~counter[1] & ~counter[0]; // 4MHz positive CE 33 | assign cpu_4mhz_n = counter[3] & ~counter[2] & ~counter[1] & ~counter[0]; // 4MHz negative CE 34 | assign cpu_ce_p = counter[div_factor] == 1'b0; // CE positivo 35 | assign cpu_ce_n = counter[div_factor] == 1'b1; // CE negativo 36 | assign ce_1mhz = ~|counter; // 1MHz 37 | assign ce_16mhz = ~counter[1] & ~counter[0]; // 16MHz 38 | 39 | 40 | assign sdram_clk_ref = cpu_ce_p; 41 | 42 | // Generate 2MHz clock - toggle on every other 4MHz enable pulse 43 | reg clk_2mhz_reg; // Renamed from clk_4mhz_reg 44 | reg toggle_control; // Divider control 45 | 46 | // Create 2 MHz signal (half of 4 MHz) 47 | always @(posedge clk or posedge reset) begin 48 | if (reset) begin 49 | toggle_control <= 1'b0; 50 | clk_2mhz_reg <= 1'b0; 51 | end 52 | else if (ce_4mhz || cpu_4mhz_n) begin 53 | toggle_control <= ~toggle_control; 54 | if (toggle_control) // Only toggle clk_2mhz on every other cpu_ce 55 | clk_2mhz_reg <= ~clk_2mhz_reg; 56 | end 57 | end 58 | 59 | assign clk_2mhz = clk_2mhz_reg; 60 | endmodule -------------------------------------------------------------------------------- /sys/vga_out.sv: -------------------------------------------------------------------------------- 1 | 2 | module vga_out 3 | ( 4 | input clk, 5 | input ypbpr_en, 6 | 7 | input hsync, 8 | input vsync, 9 | input csync, 10 | input de, 11 | 12 | input [23:0] din, 13 | output [23:0] dout, 14 | 15 | output reg hsync_o, 16 | output reg vsync_o, 17 | output reg csync_o, 18 | output reg de_o 19 | ); 20 | 21 | wire [7:0] red = din[23:16]; 22 | wire [7:0] green = din[15:8]; 23 | wire [7:0] blue = din[7:0]; 24 | 25 | // http://marsee101.blog19.fc2.com/blog-entry-2311.html 26 | 27 | 28 | // Y = 0.301*R + 0.586*G + 0.113*B (Y = 0.299*R + 0.587*G + 0.114*B) 29 | // Pb = 128 - 0.168*R - 0.332*G + 0.500*B (Pb = -0.169*R - 0.331*G + 0.500*B) 30 | // Pr = 128 + 0.500*R - 0.418*G - 0.082*B (Pr = 0.500*R - 0.419*G - 0.081*B) 31 | 32 | reg [7:0] y, pb, pr; 33 | reg [23:0] rgb; 34 | always @(posedge clk) begin 35 | reg [18:0] y_1r, pb_1r, pr_1r; 36 | reg [18:0] y_1g, pb_1g, pr_1g; 37 | reg [18:0] y_1b, pb_1b, pr_1b; 38 | reg [18:0] y_2, pb_2, pr_2; 39 | reg [23:0] din1, din2; 40 | reg hsync2, vsync2, csync2, de2; 41 | reg hsync1, vsync1, csync1, de1; 42 | 43 | y_1r <= {red, 6'd0} + {red, 3'd0} + {red, 2'd0} + red; 44 | pb_1r <= 19'd32768 - ({red, 5'd0} + {red, 3'd0} + {red, 1'd0}); 45 | pr_1r <= 19'd32768 + {red, 7'd0}; 46 | 47 | y_1g <= {green, 7'd0} + {green, 4'd0} + {green, 2'd0} + {green, 1'd0}; 48 | pb_1g <= {green, 6'd0} + {green, 4'd0} + {green, 2'd0} + green; 49 | pr_1g <= {green, 6'd0} + {green, 5'd0} + {green, 3'd0} + {green, 1'd0}; 50 | 51 | y_1b <= {blue, 4'd0} + {blue, 3'd0} + {blue, 2'd0} + blue; 52 | pb_1b <= {blue, 7'd0}; 53 | pr_1b <= {blue, 4'd0} + {blue, 2'd0} + blue; 54 | 55 | y_2 <= y_1r + y_1g + y_1b; 56 | pb_2 <= pb_1r - pb_1g + pb_1b; 57 | pr_2 <= pr_1r - pr_1g - pr_1b; 58 | 59 | y <= y_2[18] ? 8'd0 : y_2[16] ? 8'd255 : y_2[15:8]; 60 | pb <= pb_2[18] ? 8'd0 : pb_2[16] ? 8'd255 : pb_2[15:8]; 61 | pr <= pr_2[18] ? 8'd0 : pr_2[16] ? 8'd255 : pr_2[15:8]; 62 | 63 | hsync_o <= hsync2; hsync2 <= hsync1; hsync1 <= hsync; 64 | vsync_o <= vsync2; vsync2 <= vsync1; vsync1 <= vsync; 65 | csync_o <= csync2; csync2 <= csync1; csync1 <= csync; 66 | de_o <= de2; de2 <= de1; de1 <= de; 67 | 68 | rgb <= din2; din2 <= din1; din1 <= din; 69 | end 70 | 71 | assign dout = ypbpr_en ? {pr, y, pb} : rgb; 72 | 73 | endmodule 74 | -------------------------------------------------------------------------------- /docs/Keymatrix.md: -------------------------------------------------------------------------------- 1 | # Amstrad PCW Keyboard Matrix 2 | 3 | | **Row** | **0** | **1** | **2** | **3** | **4** | **5** | **6** | **7** | 4 | |---------|-------------|-------------|-------------|-------------|-------------|-------------|-------------|-------------| 5 | | **0** | Keypad 2 | Keypad 3 | Keypad 6 | Keypad 9 | Paste | F1/F2 | Keypad 0 | F3/F4 | 6 | | **1** | Keypad 1 | Keypad 5 | Keypad 4 | Keypad 8 | Copy | Cut | PTR | Exit | 7 | | **2** | [+] | ½ | Shift | Keypad 7 | > | Return | ] | Del-> | 8 | | **3** | . | ? | ; | < | P | [ | - | = | 9 | | **4** | , | M | K | L | I | O | 9 | 0 | 10 | | **5** | Space | N | J | H | Y | U | 7 | 8 | 11 | | **6** | V | B | F | G | T | R | S | 6 | 12 | | **7** | X | C | D | S | W | E | 3 | 4 | 13 | | **8** | Z | Shift Lock | A | Tab | Q | Stop | 2 | 1 | 14 | | **9** | <-Del | | J1 Fire 1 | J1 Fire 2 | J1 Right | J1 Left | J1 Down | J1 Up | 15 | | **A** | Alt | Keypad . | Keypad Enter| F7/F8 | [-] | Cancel | Extra | F5/F6 | 16 | | **B** | | | J2 Fire 1 | J2 Fire 2 | J2 Right | J2 Left | J2 Down | J2 Up | 17 | | **C** | | (KP Enter) | (Space) | (KP 0) | (Exit) | (F1/F2) | (F3/F4) | | 18 | | **C (LK2)** | | (Shift) | (S) | (D) | (A) | (X) | (W) | | 19 | | **D** | ~LK2 | Shift Lock LED | (Space) | (KP 2) | (KP 3) | (KP 1) | (KP .) | (KP 5) | 20 | | **E** | LK3 | LK1 (never set) | (Shift) | (Space) | (W R P ] ; > . ½) | (Q E O [ L < , /) | (Z X C V B N M) | (A S D F G H J) | 21 | | **F** | Update flag | Ticker | (Shift) | (Space) | (W R P ] S F X V) | (Q E O [ A D Z C) | (B N M , . / ½) | (H J K L ; < >) | 22 | -------------------------------------------------------------------------------- /sys/mcp23009.sv: -------------------------------------------------------------------------------- 1 | // 2 | // MCP23009 3 | // (C) 2019 Alexey Melnikov 4 | // 5 | module mcp23009 6 | ( 7 | input clk, 8 | 9 | output reg [2:0] btn, 10 | input [2:0] led, 11 | output reg flg_sd_cd, 12 | output reg flg_present, 13 | output reg flg_mode, 14 | 15 | output scl, 16 | inout sda 17 | ); 18 | 19 | 20 | reg start = 0; 21 | wire ready; 22 | wire error; 23 | reg rw; 24 | wire [7:0] dout; 25 | reg [15:0] din; 26 | 27 | i2c #(50_000_000, 500_000) i2c 28 | ( 29 | .CLK(clk), 30 | .START(start), 31 | .READ(rw), 32 | .I2C_ADDR('h20), 33 | .I2C_WLEN(1), 34 | .I2C_WDATA1(din[15:8]), 35 | .I2C_WDATA2(din[7:0]), 36 | .I2C_RDATA(dout), 37 | .END(ready), 38 | .ACK(error), 39 | .I2C_SCL(scl), 40 | .I2C_SDA(sda) 41 | ); 42 | 43 | always@(posedge clk) begin 44 | reg [3:0] idx = 0; 45 | reg [1:0] state = 0; 46 | reg [15:0] timeout = 0; 47 | 48 | if(~&timeout) begin 49 | timeout <= timeout + 1'd1; 50 | start <= 0; 51 | state <= 0; 52 | idx <= 0; 53 | btn <= 0; 54 | rw <= 0; 55 | flg_sd_cd <= 1; 56 | flg_present <= 0; 57 | flg_mode <= 1; 58 | end 59 | else begin 60 | if(~&init_data[idx]) begin 61 | case(state) 62 | 0: begin 63 | start <= 1; 64 | state <= 1; 65 | din <= init_data[idx]; 66 | end 67 | 1: if(~ready) state <= 2; 68 | 2: begin 69 | start <= 0; 70 | if(ready) begin 71 | state <= 0; 72 | if(!error) idx <= idx + 1'd1; 73 | end 74 | end 75 | endcase 76 | end 77 | else begin 78 | case(state) 79 | 0: begin 80 | start <= 1; 81 | state <= 1; 82 | din <= {8'h09,5'b00000,led}; 83 | end 84 | 1: if(~ready) state <= 2; 85 | 2: begin 86 | start <= 0; 87 | if(ready) begin 88 | state <= 0; 89 | rw <= 0; 90 | if(!error) begin 91 | if(rw) begin 92 | {flg_sd_cd, flg_mode, btn} <= {dout[7:3]}; 93 | flg_present <= 1; 94 | end 95 | rw <= ~rw; 96 | end 97 | end 98 | end 99 | endcase 100 | end 101 | end 102 | end 103 | 104 | wire [15:0] init_data[12] = 105 | '{ 106 | 16'h00F8, 107 | 16'h0138, 108 | 16'h0200, 109 | 16'h0300, 110 | 16'h0400, 111 | 16'h0524, 112 | 16'h06FF, 113 | 16'h0700, 114 | 16'h0800, 115 | 16'h0900, 116 | 16'h0A00, 117 | 16'hFFFF 118 | }; 119 | 120 | endmodule 121 | -------------------------------------------------------------------------------- /sys/video_cleaner.sv: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2018 Sorgelig 4 | // 5 | // This program is GPL Licensed. See COPYING for the full license. 6 | // 7 | // 8 | //////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | `timescale 1ns / 1ps 11 | 12 | module video_cleaner 13 | ( 14 | input clk_vid, 15 | input ce_pix, 16 | 17 | input [7:0] R, 18 | input [7:0] G, 19 | input [7:0] B, 20 | 21 | input HSync, 22 | input VSync, 23 | input HBlank, 24 | input VBlank, 25 | 26 | //optional de 27 | input DE_in, 28 | 29 | //optional interlace support 30 | input interlace, 31 | input f1, 32 | 33 | // video output signals 34 | output reg [7:0] VGA_R, 35 | output reg [7:0] VGA_G, 36 | output reg [7:0] VGA_B, 37 | output reg VGA_VS, 38 | output reg VGA_HS, 39 | output VGA_DE, 40 | 41 | // optional aligned blank 42 | output reg HBlank_out, 43 | output reg VBlank_out, 44 | 45 | // optional aligned de 46 | output reg DE_out 47 | ); 48 | 49 | wire hs, vs; 50 | s_fix sync_v(clk_vid, HSync, hs); 51 | s_fix sync_h(clk_vid, VSync, vs); 52 | 53 | wire hbl = hs | HBlank; 54 | wire vbl = vs | VBlank; 55 | 56 | assign VGA_DE = ~(HBlank_out | VBlank_out); 57 | 58 | always @(posedge clk_vid) begin 59 | if(ce_pix) begin 60 | HBlank_out <= hbl; 61 | 62 | VGA_HS <= hs; 63 | 64 | VGA_R <= R; 65 | VGA_G <= G; 66 | VGA_B <= B; 67 | DE_out <= DE_in; 68 | 69 | if (interlace & f1) begin 70 | VGA_VS <= vs; 71 | VBlank_out <= vbl; 72 | end else begin 73 | if(~VGA_HS & hs) VGA_VS <= vs; 74 | if(HBlank_out & ~hbl) VBlank_out <= vbl; 75 | end 76 | end 77 | end 78 | 79 | endmodule 80 | 81 | module s_fix 82 | ( 83 | input clk, 84 | 85 | input sync_in, 86 | output sync_out 87 | ); 88 | 89 | assign sync_out = sync_in ^ pol; 90 | 91 | reg pol; 92 | always @(posedge clk) begin 93 | integer pos = 0, neg = 0, cnt = 0; 94 | reg s1,s2; 95 | 96 | s1 <= sync_in; 97 | s2 <= s1; 98 | 99 | if(~s2 & s1) neg <= cnt; 100 | if(s2 & ~s1) pos <= cnt; 101 | 102 | cnt <= cnt + 1; 103 | if(s2 != s1) cnt <= 0; 104 | 105 | pol <= pos > neg; 106 | end 107 | 108 | endmodule 109 | -------------------------------------------------------------------------------- /sys/build_id.tcl: -------------------------------------------------------------------------------- 1 | 2 | # Build TimeStamp Verilog Module 3 | # Jeff Wiencrot - 8/1/2011 4 | # Sorgelig - 02/11/2019 5 | proc generateBuildID_Verilog {} { 6 | 7 | # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) 8 | set buildDate "`define BUILD_DATE \"[clock format [ clock seconds ] -format %y%m%d]\"" 9 | 10 | # Create a Verilog file for output 11 | set outputFileName "build_id.v" 12 | 13 | set fileData "" 14 | if { [file exists $outputFileName]} { 15 | set outputFile [open $outputFileName "r"] 16 | set fileData [read $outputFile] 17 | close $outputFile 18 | } 19 | 20 | if {$buildDate ne $fileData} { 21 | set outputFile [open $outputFileName "w"] 22 | puts -nonewline $outputFile $buildDate 23 | close $outputFile 24 | # Send confirmation message to the Messages window 25 | post_message "Generated: [pwd]/$outputFileName: $buildDate" 26 | } 27 | } 28 | 29 | # Build CDF file 30 | # Sorgelig - 17/2/2018 31 | proc generateCDF {revision device outpath} { 32 | 33 | set outputFileName "jtag.cdf" 34 | set outputFile [open $outputFileName "w"] 35 | 36 | puts $outputFile "JedecChain;" 37 | puts $outputFile " FileRevision(JESD32A);" 38 | puts $outputFile " DefaultMfr(6E);" 39 | puts $outputFile "" 40 | puts $outputFile " P ActionCode(Ign)" 41 | puts $outputFile " Device PartName(SOCVHPS) MfrSpec(OpMask(0));" 42 | puts $outputFile " P ActionCode(Cfg)" 43 | puts $outputFile " Device PartName($device) Path(\"$outpath/\") File(\"$revision.sof\") MfrSpec(OpMask(1));" 44 | puts $outputFile "ChainEnd;" 45 | puts $outputFile "" 46 | puts $outputFile "AlteraBegin;" 47 | puts $outputFile " ChainType(JTAG);" 48 | puts $outputFile "AlteraEnd;" 49 | } 50 | 51 | set project_name [lindex $quartus(args) 1] 52 | set revision [lindex $quartus(args) 2] 53 | 54 | if {[project_exists $project_name]} { 55 | if {[string equal "" $revision]} { 56 | project_open $project_name -revision [get_current_revision $project_name] 57 | } else { 58 | project_open $project_name -revision $revision 59 | } 60 | } else { 61 | post_message -type error "Project $project_name does not exist" 62 | exit 63 | } 64 | 65 | set device [get_global_assignment -name DEVICE] 66 | set outpath [get_global_assignment -name PROJECT_OUTPUT_DIRECTORY] 67 | 68 | if [is_project_open] { 69 | project_close 70 | } 71 | 72 | generateBuildID_Verilog 73 | generateCDF $revision $device $outpath 74 | -------------------------------------------------------------------------------- /rtl/bootrom.txt: -------------------------------------------------------------------------------- 1 | AF 2 | D3 3 | 01 4 | F3 5 | 83 6 | ED 7 | 41 8 | 0D 9 | 78 10 | 05 11 | 87 12 | 20 13 | F8 14 | 31 15 | F0 16 | FF 17 | 3E 18 | 09 19 | D3 20 | F8 21 | 11 22 | 32 23 | 07 24 | 06 25 | C8 26 | DC 27 | B1 28 | 00 29 | CD 30 | 84 31 | 00 32 | 1D 33 | F2 34 | 17 35 | 00 36 | 3E 37 | 80 38 | D3 39 | F7 40 | 0E 41 | 09 42 | 0C 43 | 79 44 | D3 45 | F8 46 | 06 47 | 21 48 | CD 49 | B1 50 | 00 51 | CB 52 | 51 53 | 20 54 | F1 55 | 15 56 | 20 57 | F0 58 | 21 59 | F5 60 | FF 61 | 77 62 | CB 63 | 7E 64 | 28 65 | FC 66 | 3C 67 | D3 68 | F8 69 | 1D 70 | 1D 71 | 3E 72 | 06 73 | D3 74 | F8 75 | CD 76 | E4 77 | 00 78 | 09 79 | 66 80 | 00 81 | 00 82 | 00 83 | 01 84 | 02 85 | 01 86 | 2A 87 | FF 88 | 21 89 | 00 90 | F0 91 | DB 92 | 00 93 | 87 94 | 30 95 | FB 96 | 87 97 | F2 98 | 6B 99 | 00 100 | ED 101 | A2 102 | 20 103 | F3 104 | 7C 105 | 1F 106 | 38 107 | EF 108 | 3E 109 | 05 110 | D3 111 | F8 112 | CD 113 | C7 114 | 00 115 | E6 116 | CB 117 | C0 118 | 47 119 | 21 120 | 10 121 | F0 122 | 24 123 | 86 124 | 25 125 | 86 126 | 2C 127 | 10 128 | F9 129 | 3C 130 | 20 131 | A0 132 | E9 133 | 0E 134 | 80 135 | CD 136 | DB 137 | 00 138 | 05 139 | 03 140 | 0F 141 | FF 142 | 07 143 | 00 144 | CD 145 | A5 146 | 00 147 | 06 148 | C8 149 | 38 150 | 1B 151 | CD 152 | 44 153 | 00 154 | CD 155 | 44 156 | 00 157 | 0E 158 | 00 159 | CD 160 | DB 161 | 00 162 | 03 163 | 0F 164 | 00 165 | 14 166 | CD 167 | BD 168 | 00 169 | 30 170 | FB 171 | 17 172 | 38 173 | F8 174 | 17 175 | D8 176 | 06 177 | 14 178 | 3E 179 | B3 180 | E3 181 | E3 182 | E3 183 | E3 184 | 3D 185 | 20 186 | F9 187 | 10 188 | F5 189 | C9 190 | DB 191 | F8 192 | E6 193 | 20 194 | C8 195 | CD 196 | E9 197 | 00 198 | 01 199 | 08 200 | 21 201 | 02 202 | 01 203 | DB 204 | 00 205 | 87 206 | 30 207 | FB 208 | 3A 209 | 02 210 | 01 211 | F0 212 | ED 213 | A2 214 | E3 215 | E3 216 | E3 217 | E3 218 | 18 219 | EF 220 | DB 221 | F8 222 | E6 223 | 40 224 | 28 225 | FA 226 | 79 227 | D3 228 | F7 229 | CD 230 | BD 231 | 00 232 | 38 233 | FB 234 | E3 235 | 46 236 | 23 237 | E3 238 | 0E 239 | 01 240 | E3 241 | DB 242 | 00 243 | 87 244 | 30 245 | FB 246 | FA 247 | FB 248 | 00 249 | 7E 250 | ED 251 | 79 252 | 23 253 | E3 254 | E3 255 | E3 256 | 10 257 | EE 258 | C9 -------------------------------------------------------------------------------- /rtl/pll/pll_0002.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/10ps 2 | module pll_0002( 3 | 4 | // interface 'refclk' 5 | input wire refclk, 6 | 7 | // interface 'reset' 8 | input wire rst, 9 | 10 | // interface 'outclk0' 11 | output wire outclk_0, 12 | 13 | // interface 'locked' 14 | output wire locked 15 | ); 16 | 17 | altera_pll #( 18 | .fractional_vco_multiplier("true"), 19 | .reference_clock_frequency("50.0 MHz"), 20 | .operation_mode("direct"), 21 | .number_of_clocks(1), 22 | .output_clock_frequency0("64.000000 MHz"), 23 | .phase_shift0("0 ps"), 24 | .duty_cycle0(50), 25 | .output_clock_frequency1("0 MHz"), 26 | .phase_shift1("0 ps"), 27 | .duty_cycle1(50), 28 | .output_clock_frequency2("0 MHz"), 29 | .phase_shift2("0 ps"), 30 | .duty_cycle2(50), 31 | .output_clock_frequency3("0 MHz"), 32 | .phase_shift3("0 ps"), 33 | .duty_cycle3(50), 34 | .output_clock_frequency4("0 MHz"), 35 | .phase_shift4("0 ps"), 36 | .duty_cycle4(50), 37 | .output_clock_frequency5("0 MHz"), 38 | .phase_shift5("0 ps"), 39 | .duty_cycle5(50), 40 | .output_clock_frequency6("0 MHz"), 41 | .phase_shift6("0 ps"), 42 | .duty_cycle6(50), 43 | .output_clock_frequency7("0 MHz"), 44 | .phase_shift7("0 ps"), 45 | .duty_cycle7(50), 46 | .output_clock_frequency8("0 MHz"), 47 | .phase_shift8("0 ps"), 48 | .duty_cycle8(50), 49 | .output_clock_frequency9("0 MHz"), 50 | .phase_shift9("0 ps"), 51 | .duty_cycle9(50), 52 | .output_clock_frequency10("0 MHz"), 53 | .phase_shift10("0 ps"), 54 | .duty_cycle10(50), 55 | .output_clock_frequency11("0 MHz"), 56 | .phase_shift11("0 ps"), 57 | .duty_cycle11(50), 58 | .output_clock_frequency12("0 MHz"), 59 | .phase_shift12("0 ps"), 60 | .duty_cycle12(50), 61 | .output_clock_frequency13("0 MHz"), 62 | .phase_shift13("0 ps"), 63 | .duty_cycle13(50), 64 | .output_clock_frequency14("0 MHz"), 65 | .phase_shift14("0 ps"), 66 | .duty_cycle14(50), 67 | .output_clock_frequency15("0 MHz"), 68 | .phase_shift15("0 ps"), 69 | .duty_cycle15(50), 70 | .output_clock_frequency16("0 MHz"), 71 | .phase_shift16("0 ps"), 72 | .duty_cycle16(50), 73 | .output_clock_frequency17("0 MHz"), 74 | .phase_shift17("0 ps"), 75 | .duty_cycle17(50), 76 | .pll_type("General"), 77 | .pll_subtype("General") 78 | ) altera_pll_i ( 79 | .rst (rst), 80 | .outclk ({outclk_0}), 81 | .locked (locked), 82 | .fboutclk ( ), 83 | .fbclk (1'b0), 84 | .refclk (refclk) 85 | ); 86 | endmodule 87 | 88 | -------------------------------------------------------------------------------- /sys/math.sv: -------------------------------------------------------------------------------- 1 | 2 | // result = num/div 3 | module sys_udiv 4 | #( 5 | parameter NB_NUM, 6 | parameter NB_DIV 7 | ) 8 | ( 9 | input clk, 10 | input start, 11 | output busy, 12 | 13 | input [NB_NUM-1:0] num, 14 | input [NB_DIV-1:0] div, 15 | output reg [NB_NUM-1:0] result, 16 | output reg [NB_DIV-1:0] remainder 17 | ); 18 | 19 | reg run; 20 | assign busy = run; 21 | 22 | always @(posedge clk) begin 23 | reg [5:0] cpt; 24 | reg [NB_NUM+NB_DIV+1:0] rem; 25 | 26 | if (start) begin 27 | cpt <= 0; 28 | run <= 1; 29 | rem <= num; 30 | end 31 | else if (run) begin 32 | cpt <= cpt + 1'd1; 33 | run <= (cpt != NB_NUM + 1'd1); 34 | remainder <= rem[NB_NUM+NB_DIV:NB_NUM+1]; 35 | if (!rem[NB_DIV + NB_NUM + 1'd1]) 36 | rem <= {rem[NB_DIV+NB_NUM:0] - (div << NB_NUM),1'b0}; 37 | else 38 | rem <= {rem[NB_DIV+NB_NUM:0] + (div << NB_NUM),1'b0}; 39 | result <= {result[NB_NUM-2:0], !rem[NB_DIV + NB_NUM + 1'd1]}; 40 | end 41 | end 42 | 43 | endmodule 44 | 45 | // result = mul1*mul2 46 | module sys_umul 47 | #( 48 | parameter NB_MUL1, 49 | parameter NB_MUL2 50 | ) 51 | ( 52 | input clk, 53 | input start, 54 | output busy, 55 | 56 | input [NB_MUL1-1:0] mul1, 57 | input [NB_MUL2-1:0] mul2, 58 | output reg [NB_MUL1+NB_MUL2-1:0] result 59 | ); 60 | 61 | reg run; 62 | assign busy = run; 63 | 64 | always @(posedge clk) begin 65 | reg [NB_MUL1+NB_MUL2-1:0] add; 66 | reg [NB_MUL2-1:0] map; 67 | 68 | if (start) begin 69 | run <= 1; 70 | result <= 0; 71 | add <= mul1; 72 | map <= mul2; 73 | end 74 | else if (run) begin 75 | if(!map) run <= 0; 76 | if(map[0]) result <= result + add; 77 | add <= add << 1; 78 | map <= map >> 1; 79 | end 80 | end 81 | 82 | endmodule 83 | 84 | // result = (mul1*mul2)/div 85 | module sys_umuldiv 86 | #( 87 | parameter NB_MUL1, 88 | parameter NB_MUL2, 89 | parameter NB_DIV 90 | ) 91 | ( 92 | input clk, 93 | input start, 94 | output busy, 95 | 96 | input [NB_MUL1-1:0] mul1, 97 | input [NB_MUL2-1:0] mul2, 98 | input [NB_DIV-1:0] div, 99 | output [NB_MUL1+NB_MUL2-1:0] result, 100 | output [NB_DIV-1:0] remainder 101 | ); 102 | 103 | wire mul_run; 104 | wire [NB_MUL1+NB_MUL2-1:0] mul_res; 105 | sys_umul #(NB_MUL1,NB_MUL2) umul(clk,start,mul_run,mul1,mul2,mul_res); 106 | 107 | sys_udiv #(NB_MUL1+NB_MUL2,NB_DIV) udiv(clk,start|mul_run,busy,mul_res,div,result,remainder); 108 | 109 | endmodule 110 | -------------------------------------------------------------------------------- /sys/pll_audio/pll_audio_0002.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/10ps 2 | module pll_audio_0002( 3 | 4 | // interface 'refclk' 5 | input wire refclk, 6 | 7 | // interface 'reset' 8 | input wire rst, 9 | 10 | // interface 'outclk0' 11 | output wire outclk_0, 12 | 13 | // interface 'locked' 14 | output wire locked 15 | ); 16 | 17 | altera_pll #( 18 | .fractional_vco_multiplier("true"), 19 | .reference_clock_frequency("50.0 MHz"), 20 | .operation_mode("direct"), 21 | .number_of_clocks(1), 22 | .output_clock_frequency0("24.576000 MHz"), 23 | .phase_shift0("0 ps"), 24 | .duty_cycle0(50), 25 | .output_clock_frequency1("0 MHz"), 26 | .phase_shift1("0 ps"), 27 | .duty_cycle1(50), 28 | .output_clock_frequency2("0 MHz"), 29 | .phase_shift2("0 ps"), 30 | .duty_cycle2(50), 31 | .output_clock_frequency3("0 MHz"), 32 | .phase_shift3("0 ps"), 33 | .duty_cycle3(50), 34 | .output_clock_frequency4("0 MHz"), 35 | .phase_shift4("0 ps"), 36 | .duty_cycle4(50), 37 | .output_clock_frequency5("0 MHz"), 38 | .phase_shift5("0 ps"), 39 | .duty_cycle5(50), 40 | .output_clock_frequency6("0 MHz"), 41 | .phase_shift6("0 ps"), 42 | .duty_cycle6(50), 43 | .output_clock_frequency7("0 MHz"), 44 | .phase_shift7("0 ps"), 45 | .duty_cycle7(50), 46 | .output_clock_frequency8("0 MHz"), 47 | .phase_shift8("0 ps"), 48 | .duty_cycle8(50), 49 | .output_clock_frequency9("0 MHz"), 50 | .phase_shift9("0 ps"), 51 | .duty_cycle9(50), 52 | .output_clock_frequency10("0 MHz"), 53 | .phase_shift10("0 ps"), 54 | .duty_cycle10(50), 55 | .output_clock_frequency11("0 MHz"), 56 | .phase_shift11("0 ps"), 57 | .duty_cycle11(50), 58 | .output_clock_frequency12("0 MHz"), 59 | .phase_shift12("0 ps"), 60 | .duty_cycle12(50), 61 | .output_clock_frequency13("0 MHz"), 62 | .phase_shift13("0 ps"), 63 | .duty_cycle13(50), 64 | .output_clock_frequency14("0 MHz"), 65 | .phase_shift14("0 ps"), 66 | .duty_cycle14(50), 67 | .output_clock_frequency15("0 MHz"), 68 | .phase_shift15("0 ps"), 69 | .duty_cycle15(50), 70 | .output_clock_frequency16("0 MHz"), 71 | .phase_shift16("0 ps"), 72 | .duty_cycle16(50), 73 | .output_clock_frequency17("0 MHz"), 74 | .phase_shift17("0 ps"), 75 | .duty_cycle17(50), 76 | .pll_type("General"), 77 | .pll_subtype("General") 78 | ) altera_pll_i ( 79 | .rst (rst), 80 | .outclk ({outclk_0}), 81 | .locked (locked), 82 | .fboutclk ( ), 83 | .fbclk (1'b0), 84 | .refclk (refclk) 85 | ); 86 | endmodule 87 | 88 | -------------------------------------------------------------------------------- /rtl/bleeper.sv: -------------------------------------------------------------------------------- 1 | // 2 | // Bleeper simulator 3 | // 4 | // Copyright (c) 2020 Stephen Eddy 5 | // 6 | // All rights reserved 7 | // 8 | // Redistribution and use in source and synthezised forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // 11 | // * Redistributions of source code must retain the above copyright notice, 12 | // this list of conditions and the following disclaimer. 13 | // 14 | // * Redistributions in synthesized form must reproduce the above copyright 15 | // notice, this list of conditions and the following disclaimer in the 16 | // documentation and/or other materials provided with the distribution. 17 | // 18 | // * Neither the name of the author nor the names of other contributors may 19 | // be used to endorse or promote products derived from this software without 20 | // specific prior written agreement from the author. 21 | // 22 | // * License is granted for non-commercial use only. A fee may not be charged 23 | // for redistributions as source code or in synthesized/hardware form without 24 | // specific prior written agreement from the author. 25 | // 26 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 27 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 28 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 30 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | // POSSIBILITY OF SUCH DAMAGE. 37 | 38 | module bleeper( 39 | input wire clk_sys, 40 | input wire ce, 41 | output logic speaker 42 | ); 43 | 44 | parameter bit[19:0] clkdivider = (64000000/4000)/2; 45 | 46 | logic [19:0] cnt = 'd0; 47 | reg sq_wave = 1'b0; 48 | 49 | assign speaker = sq_wave; 50 | 51 | always @(posedge clk_sys) 52 | begin 53 | if(ce) 54 | begin 55 | if(cnt == 'd0) begin 56 | sq_wave <= ~sq_wave; 57 | cnt = clkdivider; 58 | end 59 | else cnt <= cnt - 'd1; 60 | end 61 | end 62 | 63 | endmodule -------------------------------------------------------------------------------- /rtl/edge_det.sv: -------------------------------------------------------------------------------- 1 | // 2 | // Simple edge detector 3 | // 4 | // Copyright (c) 2020 Stephen Eddy 5 | // 6 | // All rights reserved 7 | // 8 | // Redistribution and use in source and synthezised forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // 11 | // * Redistributions of source code must retain the above copyright notice, 12 | // this list of conditions and the following disclaimer. 13 | // 14 | // * Redistributions in synthesized form must reproduce the above copyright 15 | // notice, this list of conditions and the following disclaimer in the 16 | // documentation and/or other materials provided with the distribution. 17 | // 18 | // * Neither the name of the author nor the names of other contributors may 19 | // be used to endorse or promote products derived from this software without 20 | // specific prior written agreement from the author. 21 | // 22 | // * License is granted for non-commercial use only. A fee may not be charged 23 | // for redistributions as source code or in synthesized/hardware form without 24 | // specific prior written agreement from the author. 25 | // 26 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 27 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 28 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 30 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | // POSSIBILITY OF SUCH DAMAGE. 37 | 38 | 39 | module edge_det(clk_sys, signal, pos_edge, neg_edge); 40 | input wire clk_sys; 41 | input wire signal; 42 | output logic pos_edge, neg_edge; 43 | 44 | logic old_edge; 45 | always @(posedge clk_sys) 46 | begin 47 | old_edge <= signal; 48 | if(~old_edge & signal) 49 | begin 50 | pos_edge <= 1'b1; 51 | neg_edge <= 1'b0; 52 | end 53 | else if(old_edge & ~signal) 54 | begin 55 | pos_edge <= 1'b0; 56 | neg_edge <= 1'b1; 57 | end 58 | else begin 59 | pos_edge <= 1'b0; 60 | neg_edge <= 1'b0; 61 | end 62 | end 63 | 64 | endmodule -------------------------------------------------------------------------------- /sys/sys_dual_sdram.tcl: -------------------------------------------------------------------------------- 1 | #============================================================ 2 | # Secondary SDRAM 3 | #============================================================ 4 | set_location_assignment PIN_Y15 -to SDRAM2_DQ[0] 5 | set_location_assignment PIN_AC24 -to SDRAM2_DQ[1] 6 | set_location_assignment PIN_AA15 -to SDRAM2_DQ[2] 7 | set_location_assignment PIN_AD26 -to SDRAM2_DQ[3] 8 | set_location_assignment PIN_AG28 -to SDRAM2_DQ[4] 9 | set_location_assignment PIN_AF28 -to SDRAM2_DQ[5] 10 | set_location_assignment PIN_AE25 -to SDRAM2_DQ[6] 11 | set_location_assignment PIN_AF27 -to SDRAM2_DQ[7] 12 | set_location_assignment PIN_AG26 -to SDRAM2_DQ[14] 13 | set_location_assignment PIN_AH27 -to SDRAM2_DQ[15] 14 | 15 | set_location_assignment PIN_AG25 -to SDRAM2_DQ[13] 16 | set_location_assignment PIN_AH26 -to SDRAM2_DQ[12] 17 | set_location_assignment PIN_AH24 -to SDRAM2_DQ[11] 18 | set_location_assignment PIN_AF25 -to SDRAM2_DQ[10] 19 | set_location_assignment PIN_AG23 -to SDRAM2_DQ[9] 20 | set_location_assignment PIN_AF23 -to SDRAM2_DQ[8] 21 | set_location_assignment PIN_AG24 -to SDRAM2_A[12] 22 | set_location_assignment PIN_AH22 -to SDRAM2_CLK 23 | set_location_assignment PIN_AH21 -to SDRAM2_A[9] 24 | set_location_assignment PIN_AG21 -to SDRAM2_A[11] 25 | set_location_assignment PIN_AH23 -to SDRAM2_A[7] 26 | set_location_assignment PIN_AA20 -to SDRAM2_A[8] 27 | set_location_assignment PIN_AF22 -to SDRAM2_A[5] 28 | set_location_assignment PIN_AE22 -to SDRAM2_A[6] 29 | set_location_assignment PIN_AG20 -to SDRAM2_nWE 30 | set_location_assignment PIN_AF21 -to SDRAM2_A[4] 31 | 32 | set_location_assignment PIN_AG19 -to SDRAM2_nCAS 33 | set_location_assignment PIN_AH19 -to SDRAM2_nRAS 34 | set_location_assignment PIN_AG18 -to SDRAM2_nCS 35 | set_location_assignment PIN_AH18 -to SDRAM2_BA[0] 36 | set_location_assignment PIN_AF18 -to SDRAM2_BA[1] 37 | set_location_assignment PIN_AF20 -to SDRAM2_A[10] 38 | set_location_assignment PIN_AG15 -to SDRAM2_A[0] 39 | set_location_assignment PIN_AE20 -to SDRAM2_A[1] 40 | set_location_assignment PIN_AE19 -to SDRAM2_A[2] 41 | set_location_assignment PIN_AE17 -to SDRAM2_A[3] 42 | 43 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM2_* 44 | set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM2_* 45 | set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM2_* 46 | set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM2_DQ[*] 47 | set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM2_DQ[*] 48 | set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDRAM2_DQ[*] 49 | set_instance_assignment -name ALLOW_SYNCH_CTRL_USAGE OFF -to *|SDRAM2_* 50 | 51 | set_global_assignment -name VERILOG_MACRO "MISTER_DUAL_SDRAM=1" 52 | -------------------------------------------------------------------------------- /rtl/T80/README: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- **** 3 | -- T80(c) core. Attempt to finish all undocumented features and provide 4 | -- accurate timings. 5 | -- 6 | -- Version 351. 7 | -- Merged Gameboy fixes from Bruno Duarte Gouveia (brNX) 8 | -- Passes Blargg's test ROMs 9 | -- 10 | -- Version 350. 11 | -- Copyright (c) 2018 Sorgelig 12 | -- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr 13 | -- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as 14 | -- correct implementation is still unclear. 15 | -- 16 | -- **** 17 | -- T80(b) core. In an effort to merge and maintain bug fixes .... 18 | -- 19 | -- Ver 303 add undocumented DDCB and FDCB opcodes by TobiFlex 20.04.2010 20 | -- Ver 301 parity flag is just parity for 8080, also overflow for Z80, by Sean Riddle 21 | -- Ver 300 started tidyup. 22 | -- 23 | -- MikeJ March 2005 24 | -- Latest version from www.fpgaarcade.com (original www.opencores.org) 25 | -- 26 | -- **** 27 | -- Z80 compatible microprocessor core 28 | -- 29 | -- Version : 0250 30 | -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) 31 | -- All rights reserved 32 | -- 33 | -- Redistribution and use in source and synthezised forms, with or without 34 | -- modification, are permitted provided that the following conditions are met: 35 | -- 36 | -- Redistributions of source code must retain the above copyright notice, 37 | -- this list of conditions and the following disclaimer. 38 | -- 39 | -- Redistributions in synthesized form must reproduce the above copyright 40 | -- notice, this list of conditions and the following disclaimer in the 41 | -- documentation and/or other materials provided with the distribution. 42 | -- 43 | -- Neither the name of the author nor the names of other contributors may 44 | -- be used to endorse or promote products derived from this software without 45 | -- specific prior written permission. 46 | -- 47 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 48 | -- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 49 | -- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 50 | -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 51 | -- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 52 | -- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 53 | -- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 54 | -- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 55 | -- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 56 | -- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 57 | -- POSSIBILITY OF SUCH DAMAGE. 58 | -- 59 | -------------------------------------------------------------------------------- /rtl/pcw_starter.sv: -------------------------------------------------------------------------------- 1 | module pcw_starter( 2 | input wire clk, 3 | input wire reset, 4 | input wire sdram_clk_ref, 5 | input wire sdram_ready, 6 | input wire model, 7 | output logic wr, 8 | output logic rd, 9 | output logic [15:0] addr, 10 | output logic [7:0] data, 11 | output logic [15:0] exec_addr, 12 | output logic exec_enable, 13 | output logic active 14 | ); 15 | 16 | localparam BOOT_ROM_END = 16'd275; // Length of boot rom 17 | // Rom containing boot rom code to transfer to address 0 18 | boot_loader boot_loader( 19 | .address(loader_addr), 20 | .data(loader_data), 21 | .model(model) 22 | ); 23 | 24 | reg [15:0] loader_addr; 25 | reg [7:0] loader_data; 26 | logic enabled; 27 | logic reset_ne; 28 | 29 | assign active = enabled; 30 | 31 | edge_det reset_edge_det( 32 | .clk_sys(clk), 33 | .signal(reset), 34 | .neg_edge(reset_ne)); 35 | 36 | logic [15:0] read_addr; 37 | logic [7:0] read_data; 38 | logic [2:0] state; 39 | 40 | reg sdram_clk_ref_last; 41 | 42 | always @(posedge clk) begin 43 | if(reset_ne) begin 44 | loader_addr <= 'b0; 45 | addr <= 'b0; 46 | wr <= 1'b0; 47 | rd <= 1'b0; 48 | enabled <= 1'b1; 49 | state <= 2'b00; 50 | exec_addr <= 'b0; 51 | exec_enable <= 1'b0; 52 | end 53 | else begin 54 | sdram_clk_ref_last <= sdram_clk_ref; 55 | if (sdram_ready & ~sdram_clk_ref_last & sdram_clk_ref) begin 56 | if (enabled) begin 57 | case (state) 58 | 2'b00: begin 59 | data <= loader_data; 60 | wr <= 1'b1; 61 | state <= 2'b01; 62 | end 63 | 2'b01: begin 64 | addr <= addr + 1'd1; 65 | loader_addr <= loader_addr + 1'd1; 66 | wr <= 1'b0; 67 | state <= 2'b00; 68 | if (loader_addr >= BOOT_ROM_END) begin 69 | loader_addr <= 'b0; 70 | state <= 2'b10; 71 | exec_enable <= 1'b1; 72 | end 73 | end 74 | 2'b10: begin 75 | enabled <= 1'b0; 76 | exec_enable <= 1'b0; 77 | end 78 | endcase 79 | end 80 | end 81 | end 82 | end 83 | 84 | 85 | 86 | 87 | 88 | 89 | endmodule 90 | -------------------------------------------------------------------------------- /sys/i2c.v: -------------------------------------------------------------------------------- 1 | 2 | module i2c 3 | ( 4 | input CLK, 5 | 6 | input START, 7 | input READ, 8 | input [6:0] I2C_ADDR, 9 | input I2C_WLEN, // 0 - one byte, 1 - two bytes 10 | input [7:0] I2C_WDATA1, 11 | input [7:0] I2C_WDATA2, 12 | output [7:0] I2C_RDATA, 13 | output reg END = 1, 14 | output reg ACK = 0, 15 | 16 | //I2C bus 17 | output I2C_SCL, 18 | inout I2C_SDA 19 | ); 20 | 21 | 22 | // Clock Setting 23 | parameter CLK_Freq = 50_000_000; // 50 MHz 24 | parameter I2C_Freq = 400_000; // 400 KHz 25 | 26 | localparam I2C_FreqX2 = I2C_Freq*2; 27 | 28 | reg I2C_CLOCK; 29 | reg [31:0] cnt; 30 | wire [31:0] cnt_next = cnt + I2C_FreqX2; 31 | 32 | always @(posedge CLK) begin 33 | cnt <= cnt_next; 34 | if(cnt_next >= CLK_Freq) begin 35 | cnt <= cnt_next - CLK_Freq; 36 | I2C_CLOCK <= ~I2C_CLOCK; 37 | end 38 | end 39 | 40 | assign I2C_SCL = (SCLK | I2C_CLOCK) ? 1'bZ : 1'b0; 41 | assign I2C_SDA = SDO[3] ? 1'bz : 1'b0; 42 | 43 | reg SCLK; 44 | reg [3:0] SDO; 45 | reg [0:7] rdata; 46 | 47 | reg [5:0] SD_COUNTER; 48 | reg [0:31] SD; 49 | 50 | initial begin 51 | SD_COUNTER = 'b111111; 52 | SD = 'hFFFF; 53 | SCLK = 1; 54 | SDO = 4'b1111; 55 | end 56 | 57 | assign I2C_RDATA = rdata; 58 | 59 | always @(posedge CLK) begin 60 | reg old_clk; 61 | reg old_st; 62 | reg rd,len; 63 | 64 | old_clk <= I2C_CLOCK; 65 | old_st <= START; 66 | 67 | // delay to make sure SDA changed while SCL is stabilized at low 68 | if(old_clk && ~I2C_CLOCK && ~SD_COUNTER[5]) SDO[0] <= SD[SD_COUNTER[4:0]]; 69 | SDO[3:1] <= SDO[2:0]; 70 | 71 | if(~old_st && START) begin 72 | SCLK <= 1; 73 | SDO <= 4'b1111; 74 | ACK <= 0; 75 | END <= 0; 76 | rd <= READ; 77 | len <= I2C_WLEN; 78 | if(READ) SD <= {2'b10, I2C_ADDR, 1'b1, 1'b1, 8'b11111111, 1'b1, 3'b011, 9'b111111111}; 79 | else SD <= {2'b10, I2C_ADDR, 1'b0, 1'b1, I2C_WDATA1, 1'b1, I2C_WDATA2, 4'b1011}; 80 | SD_COUNTER <= 0; 81 | end else begin 82 | if(~old_clk && I2C_CLOCK && ~&SD_COUNTER) begin 83 | SD_COUNTER <= SD_COUNTER + 6'd1; 84 | case(SD_COUNTER) 85 | 01: SCLK <= 0; 86 | 10: ACK <= ACK | I2C_SDA; 87 | 19: if(~rd) begin 88 | ACK <= ACK | I2C_SDA; 89 | if(~len) SD_COUNTER <= 29; 90 | end 91 | 20: if(rd) SCLK <= 1; 92 | 23: if(rd) END <= 1; 93 | 28: if(~rd) ACK <= ACK | I2C_SDA; 94 | 29: if(~rd) SCLK <= 1; 95 | 32: if(~rd) END <= 1; 96 | endcase 97 | 98 | if(SD_COUNTER >= 11 && SD_COUNTER <= 18) rdata[SD_COUNTER[4:0]-11] <= I2C_SDA; 99 | end 100 | end 101 | end 102 | 103 | endmodule 104 | -------------------------------------------------------------------------------- /sys/ddr_svc.sv: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2020 Alexey Melnikov 3 | // 4 | // 5 | // This source file is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published 7 | // by the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This source file is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | // 18 | // ------------------------------------------ 19 | // 20 | 21 | // 16-bit version 22 | 23 | module ddr_svc 24 | ( 25 | input clk, 26 | 27 | input ram_waitrequest, 28 | output [7:0] ram_burstcnt, 29 | output [28:0] ram_addr, 30 | input [63:0] ram_readdata, 31 | input ram_read_ready, 32 | output reg ram_read, 33 | output [63:0] ram_writedata, 34 | output [7:0] ram_byteenable, 35 | output reg ram_write, 36 | 37 | output [7:0] ram_bcnt, 38 | 39 | input [31:3] ch0_addr, 40 | input [7:0] ch0_burst, 41 | output [63:0] ch0_data, 42 | input ch0_req, 43 | output ch0_ready, 44 | 45 | input [31:3] ch1_addr, 46 | input [7:0] ch1_burst, 47 | output [63:0] ch1_data, 48 | input ch1_req, 49 | output ch1_ready 50 | ); 51 | 52 | assign ram_burstcnt = ram_burst; 53 | assign ram_byteenable = 8'hFF; 54 | assign ram_addr = ram_address; 55 | assign ram_writedata = 0; 56 | 57 | assign ch0_data = ram_q[0]; 58 | assign ch1_data = ram_q[1]; 59 | assign ch0_ready = ready[0]; 60 | assign ch1_ready = ready[1]; 61 | 62 | reg [7:0] ram_burst; 63 | reg [63:0] ram_q[2]; 64 | reg [31:3] ram_address; 65 | reg [1:0] ack = 0; 66 | reg [1:0] ready; 67 | reg state = 0; 68 | reg ch = 0; 69 | 70 | always @(posedge clk) begin 71 | ready <= 0; 72 | 73 | if(!ram_waitrequest) begin 74 | ram_read <= 0; 75 | ram_write <= 0; 76 | 77 | case(state) 78 | 0: if(ch0_req != ack[0]) begin 79 | ack[0] <= ch0_req; 80 | ram_address <= ch0_addr; 81 | ram_burst <= ch0_burst; 82 | ram_read <= 1; 83 | ch <= 0; 84 | ram_bcnt <= 8'hFF; 85 | state <= 1; 86 | end 87 | else if(ch1_req != ack[1]) begin 88 | ack[1] <= ch1_req; 89 | ram_address <= ch1_addr; 90 | ram_burst <= ch1_burst; 91 | ram_read <= 1; 92 | ch <= 1; 93 | ram_bcnt <= 8'hFF; 94 | state <= 1; 95 | end 96 | 1: begin 97 | if(ram_read_ready) begin 98 | ram_bcnt <= ram_bcnt + 1'd1; 99 | ram_q[ch] <= ram_readdata; 100 | ready[ch] <= 1; 101 | if ((ram_bcnt+2'd2) == ram_burst) state <= 0; 102 | end 103 | end 104 | endcase 105 | end 106 | end 107 | 108 | endmodule 109 | -------------------------------------------------------------------------------- /sys/sys.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name QIP_FILE [join [list $::quartus(qip_path) pll_q [regexp -inline {[0-9]+} $quartus(version)] .qip] {}] 2 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sys_top.v ] 3 | set_global_assignment -name SDC_FILE [file join $::quartus(qip_path) sys_top.sdc ] 4 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) ascal.vhd ] 5 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) pll_hdmi_adj.vhd ] 6 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) math.sv ] 7 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hq2x.sv ] 8 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scandoubler.v ] 9 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scanlines.v ] 10 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) shadowmask.sv ] 11 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_cleaner.sv ] 12 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) gamma_corr.sv ] 13 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_mixer.sv ] 14 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_freak.sv ] 15 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_freezer.sv ] 16 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) arcade_video.v ] 17 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) osd.v ] 18 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) vga_out.sv ] 19 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) yc_out.sv ] 20 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i2c.v ] 21 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) alsa.sv ] 22 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i2s.v ] 23 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) spdif.v ] 24 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) audio_out.v ] 25 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) iir_filter.v ] 26 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ltc2308.sv ] 27 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sigma_delta_dac.v ] 28 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) mt32pi.sv ] 29 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) mcp23009.sv ] 30 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) f2sdram_safe_terminator.sv ] 31 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ddr_svc.sv ] 32 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) sysmem.sv ] 33 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) sd_card.sv ] 34 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hps_io.sv ] 35 | -------------------------------------------------------------------------------- /rtl/mouse.sv: -------------------------------------------------------------------------------- 1 | // 2 | // PCW for MiSTer Mouse emulation module 3 | // 4 | // Copyright (c) 2020 Stephen Eddy 5 | // 6 | // All rights reserved 7 | // 8 | // Redistribution and use in source and synthezised forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // 11 | // * Redistributions of source code must retain the above copyright notice, 12 | // this list of conditions and the following disclaimer. 13 | // 14 | // * Redistributions in synthesized form must reproduce the above copyright 15 | // notice, this list of conditions and the following disclaimer in the 16 | // documentation and/or other materials provided with the distribution. 17 | // 18 | // * Neither the name of the author nor the names of other contributors may 19 | // be used to endorse or promote products derived from this software without 20 | // specific prior written agreement from the author. 21 | // 22 | // * License is granted for non-commercial use only. A fee may not be charged 23 | // for redistributions as source code or in synthesized/hardware form without 24 | // specific prior written agreement from the author. 25 | // 26 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 27 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 28 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 30 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | // POSSIBILITY OF SUCH DAMAGE. 37 | 38 | // Keyboard and Joystick mapper for Amstrad PCW keyboard matrix 39 | 40 | module mouse 41 | ( 42 | input wire reset, // reset when driven high 43 | input wire clk_sys, // should be same clock as clk_sys from HPS_IO 44 | 45 | // [24] toggle, [23:16] buttons, [15:8] move X, [7:0] move Y 46 | input wire [24:0] ps2_mouse, 47 | 48 | // Buttons and axis output 49 | output logic mouse_left, 50 | output logic mouse_middle, 51 | output logic mouse_right, 52 | output logic signed [8:0] mouse_x, // Signed 9 bit value (twos complement) 53 | output logic signed [8:0] mouse_y 54 | ); 55 | 56 | logic [23:0] mouse_latch; 57 | logic old_strobe; 58 | 59 | assign mouse_left = mouse_latch[0]; 60 | assign mouse_middle = mouse_latch[2]; 61 | assign mouse_right = mouse_latch[1]; 62 | 63 | assign mouse_x = {mouse_latch[4],mouse_latch[15:8]}; 64 | assign mouse_y = {mouse_latch[5],mouse_latch[23:16]}; 65 | 66 | // Latch updates to mouse positon. Bit 24 is input latch 67 | always @(posedge clk_sys) 68 | begin 69 | old_strobe <= ps2_mouse[24]; 70 | if(reset) mouse_latch <= 24'b0; 71 | 72 | if(old_strobe != ps2_mouse[24]) 73 | begin 74 | mouse_latch <= ps2_mouse[23:0]; 75 | end 76 | end 77 | 78 | endmodule -------------------------------------------------------------------------------- /sys/sys_analog.tcl: -------------------------------------------------------------------------------- 1 | #============================================================ 2 | # SDIO 3 | #============================================================ 4 | set_location_assignment PIN_AF25 -to SDIO_DAT[0] 5 | set_location_assignment PIN_AF23 -to SDIO_DAT[1] 6 | set_location_assignment PIN_AD26 -to SDIO_DAT[2] 7 | set_location_assignment PIN_AF28 -to SDIO_DAT[3] 8 | set_location_assignment PIN_AF27 -to SDIO_CMD 9 | set_location_assignment PIN_AH26 -to SDIO_CLK 10 | set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDIO_* 11 | 12 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDIO_* 13 | set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDIO_DAT[*] 14 | set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDIO_CMD 15 | 16 | #============================================================ 17 | # VGA 18 | #============================================================ 19 | set_location_assignment PIN_AE17 -to VGA_R[0] 20 | set_location_assignment PIN_AE20 -to VGA_R[1] 21 | set_location_assignment PIN_AF20 -to VGA_R[2] 22 | set_location_assignment PIN_AH18 -to VGA_R[3] 23 | set_location_assignment PIN_AH19 -to VGA_R[4] 24 | set_location_assignment PIN_AF21 -to VGA_R[5] 25 | 26 | set_location_assignment PIN_AE19 -to VGA_G[0] 27 | set_location_assignment PIN_AG15 -to VGA_G[1] 28 | set_location_assignment PIN_AF18 -to VGA_G[2] 29 | set_location_assignment PIN_AG18 -to VGA_G[3] 30 | set_location_assignment PIN_AG19 -to VGA_G[4] 31 | set_location_assignment PIN_AG20 -to VGA_G[5] 32 | 33 | set_location_assignment PIN_AG21 -to VGA_B[0] 34 | set_location_assignment PIN_AA20 -to VGA_B[1] 35 | set_location_assignment PIN_AE22 -to VGA_B[2] 36 | set_location_assignment PIN_AF22 -to VGA_B[3] 37 | set_location_assignment PIN_AH23 -to VGA_B[4] 38 | set_location_assignment PIN_AH21 -to VGA_B[5] 39 | 40 | set_location_assignment PIN_AH22 -to VGA_HS 41 | set_location_assignment PIN_AG24 -to VGA_VS 42 | 43 | set_location_assignment PIN_AH27 -to VGA_EN 44 | set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to VGA_EN 45 | 46 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_* 47 | set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to VGA_* 48 | 49 | #============================================================ 50 | # AUDIO 51 | #============================================================ 52 | set_location_assignment PIN_AC24 -to AUDIO_L 53 | set_location_assignment PIN_AE25 -to AUDIO_R 54 | set_location_assignment PIN_AG26 -to AUDIO_SPDIF 55 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to AUDIO_* 56 | set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to AUDIO_* 57 | 58 | #============================================================ 59 | # I/O #1 60 | #============================================================ 61 | set_location_assignment PIN_Y15 -to LED_USER 62 | set_location_assignment PIN_AA15 -to LED_HDD 63 | set_location_assignment PIN_AG28 -to LED_POWER 64 | 65 | set_location_assignment PIN_AH24 -to BTN_USER 66 | set_location_assignment PIN_AG25 -to BTN_OSD 67 | set_location_assignment PIN_AG23 -to BTN_RESET 68 | 69 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED_* 70 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to BTN_* 71 | set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to BTN_* 72 | -------------------------------------------------------------------------------- /rtl/z80_regset.sv: -------------------------------------------------------------------------------- 1 | // 2 | // HT1080Z for MiSTer Z80 Register Loader - For Loading and Jumping to PC 3 | // 4 | // Copyright (c) 2020 Stephen Eddy 5 | // 6 | // All rights reserved 7 | // 8 | // Redistribution and use in source and synthezised forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // 11 | // * Redistributions of source code must retain the above copyright notice, 12 | // this list of conditions and the following disclaimer. 13 | // 14 | // * Redistributions in synthesized form must reproduce the above copyright 15 | // notice, this list of conditions and the following disclaimer in the 16 | // documentation and/or other materials provided with the distribution. 17 | // 18 | // * Neither the name of the author nor the names of other contributors may 19 | // be used to endorse or promote products derived from this software without 20 | // specific prior written agreement from the author. 21 | // 22 | // * License is granted for non-commercial use only. A fee may not be charged 23 | // for redistributions as source code or in synthesized/hardware form without 24 | // specific prior written agreement from the author. 25 | // 26 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 27 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 28 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 30 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | // POSSIBILITY OF SUCH DAMAGE. 37 | 38 | module z80_regset 39 | #( parameter 40 | SP_ADDR = 16'h4200 // Stack pointer address 41 | ) 42 | ( 43 | input wire [15:0] execute_addr, // Start address for program start 44 | input wire execute_enable, // Jump to start address (out_execute_addr) - Not implemented 45 | //input wire [211:0] dir_in, // Z80 Register set as defined in T80pa / T80 46 | 47 | output logic [211:0] dir_out, // Z80 Register set as defined in T80pa / T80 48 | output logic dir_set // Signal to set registers 49 | ); 50 | 51 | always_comb 52 | begin 53 | dir_out[211:0] <= { 54 | 2'b0, // 211-210 - IFF2, IFF1 55 | 2'b0, // 209-208 - IM 56 | 127'b0, // 207-080 - Regular and Alt registers 57 | //dir_in[211:80], 58 | execute_addr[15:8], // 079-071 - PCH 59 | execute_addr[7:0], // 071-064 - PCL 60 | SP_ADDR[15:8], // 063-056 - SPH 61 | SP_ADDR[7:0], // 055-048 - SPL 62 | //dir_in[47:0] 63 | 8'b0, // 047-040 - R 64 | 8'b0, // 039-032 - I 65 | 8'b1, // 031-024 - Fp 66 | 8'b1, // 023-016 - Ap 67 | 16'b1 // 015-000 - ACC 68 | }; 69 | end 70 | 71 | assign dir_set = execute_enable; 72 | 73 | endmodule -------------------------------------------------------------------------------- /sys/video_freezer.sv: -------------------------------------------------------------------------------- 1 | // 2 | // video freeze with sync 3 | // (C) Alexey Melnikov 4 | // 5 | // 6 | // This program is free software; you can redistribute it and/or modify it 7 | // under the terms of the GNU General Public License as published by the Free 8 | // Software Foundation; either version 2 of the License, or (at your option) 9 | // any later version. 10 | // 11 | // This program is distributed in the hope that it will be useful, but WITHOUT 12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 | // more details. 15 | // 16 | // You should have received a copy of the GNU General Public License along 17 | // with this program; if not, write to the Free Software Foundation, Inc., 18 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | 21 | module video_freezer 22 | ( 23 | input clk, 24 | 25 | output sync, 26 | input freeze, 27 | 28 | input hs_in, 29 | input vs_in, 30 | input hbl_in, 31 | input vbl_in, 32 | 33 | output hs_out, 34 | output vs_out, 35 | output hbl_out, 36 | output vbl_out 37 | ); 38 | 39 | sync_lock #(33) vs_lock 40 | ( 41 | .clk(clk), 42 | .sync_in(vs_in), 43 | .sync_out(vs_out), 44 | .de_in(vbl_in), 45 | .de_out(vbl_out), 46 | .freeze(freeze) 47 | ); 48 | 49 | wire sync_pt; 50 | sync_lock #(21) hs_lock 51 | ( 52 | .clk(clk), 53 | .sync_in(hs_in), 54 | .sync_out(hs_out), 55 | .de_in(hbl_in), 56 | .de_out(hbl_out), 57 | .freeze(freeze), 58 | .sync_pt(sync_pt) 59 | ); 60 | 61 | reg sync_o; 62 | always @(posedge clk) begin 63 | reg old_hs, old_vs; 64 | reg vs_sync; 65 | 66 | old_vs <= vs_out; 67 | 68 | if(~old_vs & vs_out) vs_sync <= 1; 69 | if(sync_pt & vs_sync) begin 70 | vs_sync <= 0; 71 | sync_o <= ~sync_o; 72 | end 73 | end 74 | 75 | assign sync = sync_o; 76 | 77 | endmodule 78 | 79 | 80 | module sync_lock #(parameter WIDTH) 81 | ( 82 | input clk, 83 | 84 | input sync_in, 85 | input de_in, 86 | 87 | output sync_out, 88 | output de_out, 89 | 90 | input freeze, 91 | output sync_pt, 92 | output valid 93 | ); 94 | 95 | reg [WIDTH-1:0] f_len, s_len, de_start, de_end; 96 | reg sync_valid; 97 | 98 | reg old_sync; 99 | always @(posedge clk) old_sync <= sync_in; 100 | 101 | always @(posedge clk) begin 102 | reg [WIDTH-1:0] cnti; 103 | reg f_valid; 104 | reg old_de; 105 | 106 | cnti <= cnti + 1'd1; 107 | if(~old_sync & sync_in) begin 108 | if(sync_valid) f_len <= cnti; 109 | f_valid <= 1; 110 | sync_valid <= f_valid; 111 | cnti <= 0; 112 | end 113 | 114 | if(old_sync & ~sync_in & sync_valid) s_len <= cnti; 115 | 116 | old_de <= de_in; 117 | if(~old_de & de_in & sync_valid) de_start <= cnti; 118 | if(old_de & ~de_in & sync_valid) de_end <= cnti; 119 | 120 | if(freeze) {f_valid, sync_valid} <= 0; 121 | end 122 | 123 | reg sync_o, de_o, sync_o_pre; 124 | always @(posedge clk) begin 125 | reg [WIDTH-1:0] cnto; 126 | 127 | cnto <= cnto + 1'd1; 128 | if(old_sync & ~sync_in & sync_valid) cnto <= s_len + 2'd2; 129 | if(cnto == f_len) cnto <= 0; 130 | 131 | sync_o_pre <= (cnto == (s_len>>1)); // middle in sync 132 | if(cnto == f_len) sync_o <= 1; 133 | if(cnto == s_len) sync_o <= 0; 134 | if(cnto == de_start) de_o <= 1; 135 | if(cnto == de_end) de_o <= 0; 136 | end 137 | 138 | assign sync_out = freeze ? sync_o : sync_in; 139 | assign valid = sync_valid; 140 | assign sync_pt = sync_o_pre; 141 | assign de_out = freeze ? de_o : de_in; 142 | 143 | endmodule 144 | -------------------------------------------------------------------------------- /rtl/amx_mouse.sv: -------------------------------------------------------------------------------- 1 | // 2 | // PCW for MiSTer AMX Mouse emulation module 3 | // 4 | // Copyright (c) 2020 Stephen Eddy 5 | // 6 | // All rights reserved 7 | // 8 | // Redistribution and use in source and synthezised forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // 11 | // * Redistributions of source code must retain the above copyright notice, 12 | // this list of conditions and the following disclaimer. 13 | // 14 | // * Redistributions in synthesized form must reproduce the above copyright 15 | // notice, this list of conditions and the following disclaimer in the 16 | // documentation and/or other materials provided with the distribution. 17 | // 18 | // * Neither the name of the author nor the names of other contributors may 19 | // be used to endorse or promote products derived from this software without 20 | // specific prior written agreement from the author. 21 | // 22 | // * License is granted for non-commercial use only. A fee may not be charged 23 | // for redistributions as source code or in synthesized/hardware form without 24 | // specific prior written agreement from the author. 25 | // 26 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 27 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 28 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 30 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | // POSSIBILITY OF SUCH DAMAGE. 37 | 38 | // Keyboard and Joystick mapper for Amstrad PCW keyboard matrix 39 | 40 | module amx_mouse 41 | ( 42 | input wire reset, // reset when driven high 43 | input wire clk_sys, // should be same clock as clk_sys from HPS_IO 44 | 45 | // Inputs from generic mouse module 46 | input wire signed [8:0] mouse_x, // Signed 9 bit value (twos complement) 47 | input wire signed [8:0] mouse_y, 48 | input wire mouse_left, 49 | input wire mouse_middle, 50 | input wire mouse_right, 51 | 52 | input wire sel, // Select enable line 53 | input wire [1:0] addr, // Address line 54 | 55 | output logic [7:0] dout // Data output for address 56 | ); 57 | 58 | reg [7:0] data; 59 | assign dout = sel ? data : 8'hff; 60 | 61 | wire signed [8:0] dxt = mouse_x / 9'sd8; 62 | wire signed [8:0] dyt = mouse_y / 9'sd8; 63 | 64 | wire signed [3:0] dx = (dxt > 9'sd7) ? 4'sd7 : dxt < 9'(-8) ? 4'(-8) : 4'(dxt[3:0]); 65 | wire signed [3:0] dy = (dyt > 9'sd7) ? 4'sd7 : dyt < 9'(-8) ? 4'(-8) : 4'(dyt[3:0]); 66 | 67 | always @(posedge clk_sys) 68 | begin 69 | logic old_sel; 70 | 71 | old_sel <= sel; 72 | if(~old_sel & sel) 73 | begin 74 | case(addr) 75 | 2'b00: data <= (dy < 0) ? {(~dy + 1'd1),4'b0} : {4'b0,dy}; 76 | 2'b01: data <= (dx >= 0) ? {4'b0,dx} : {(~dx + 1'd1),4'b0}; 77 | 2'b10: data <= {5'b1,~mouse_right,~mouse_middle,~mouse_left}; 78 | 2'b11: data <= 8'h00; 79 | endcase 80 | end 81 | end 82 | 83 | endmodule 84 | -------------------------------------------------------------------------------- /sys/gamma_corr.sv: -------------------------------------------------------------------------------- 1 | module gamma_corr 2 | ( 3 | input clk_sys, 4 | input clk_vid, 5 | input ce_pix, 6 | input gamma_en, 7 | input gamma_wr, 8 | input [9:0] gamma_wr_addr, 9 | input [7:0] gamma_value, 10 | input HSync, 11 | input VSync, 12 | input HBlank, 13 | input VBlank, 14 | input [23:0] RGB_in, 15 | output reg HSync_out, 16 | output reg VSync_out, 17 | output reg HBlank_out, 18 | output reg VBlank_out, 19 | output reg [23:0] RGB_out 20 | ); 21 | 22 | (* ramstyle="no_rw_check" *) reg [7:0] gamma_curve[768]; 23 | 24 | always @(posedge clk_sys) if (gamma_wr) gamma_curve[gamma_wr_addr] <= gamma_value; 25 | always @(posedge clk_vid) gamma <= gamma_curve[gamma_index]; 26 | 27 | reg [9:0] gamma_index; 28 | reg [7:0] gamma; 29 | 30 | always @(posedge clk_vid) begin 31 | reg [7:0] R_in, G_in, B_in; 32 | reg [7:0] R_gamma, G_gamma; 33 | reg hs,vs,hb,vb; 34 | reg [1:0] ctr = 0; 35 | reg old_ce; 36 | 37 | old_ce <= ce_pix; 38 | if(~old_ce & ce_pix) begin 39 | {R_in,G_in,B_in} <= RGB_in; 40 | hs <= HSync; vs <= VSync; 41 | hb <= HBlank; vb <= VBlank; 42 | 43 | RGB_out <= gamma_en ? {R_gamma,G_gamma,gamma} : {R_in,G_in,B_in}; 44 | HSync_out <= hs; VSync_out <= vs; 45 | HBlank_out <= hb; VBlank_out <= vb; 46 | 47 | ctr <= 1; 48 | gamma_index <= {2'b00,RGB_in[23:16]}; 49 | end 50 | 51 | if (|ctr) ctr <= ctr + 1'd1; 52 | 53 | case(ctr) 54 | 1: begin gamma_index <= {2'b01,G_in}; end 55 | 2: begin R_gamma <= gamma; gamma_index <= {2'b10,B_in}; end 56 | 3: begin G_gamma <= gamma; end 57 | endcase 58 | end 59 | 60 | endmodule 61 | 62 | module gamma_fast 63 | ( 64 | input clk_vid, 65 | input ce_pix, 66 | 67 | inout [21:0] gamma_bus, 68 | 69 | input HSync, 70 | input VSync, 71 | input HBlank, 72 | input VBlank, 73 | input DE, 74 | input [23:0] RGB_in, 75 | 76 | output reg HSync_out, 77 | output reg VSync_out, 78 | output reg HBlank_out, 79 | output reg VBlank_out, 80 | output reg DE_out, 81 | output reg [23:0] RGB_out 82 | ); 83 | 84 | (* ramstyle="no_rw_check" *) reg [7:0] gamma_curve_r[256]; 85 | (* ramstyle="no_rw_check" *) reg [7:0] gamma_curve_g[256]; 86 | (* ramstyle="no_rw_check" *) reg [7:0] gamma_curve_b[256]; 87 | 88 | assign gamma_bus[21] = 1; 89 | wire clk_sys = gamma_bus[20]; 90 | wire gamma_en = gamma_bus[19]; 91 | wire gamma_wr = gamma_bus[18]; 92 | wire [9:0] gamma_wr_addr = gamma_bus[17:8]; 93 | wire [7:0] gamma_value = gamma_bus[7:0]; 94 | 95 | always @(posedge clk_sys) if (gamma_wr) begin 96 | case(gamma_wr_addr[9:8]) 97 | 0: gamma_curve_r[gamma_wr_addr[7:0]] <= gamma_value; 98 | 1: gamma_curve_g[gamma_wr_addr[7:0]] <= gamma_value; 99 | 2: gamma_curve_b[gamma_wr_addr[7:0]] <= gamma_value; 100 | endcase 101 | end 102 | 103 | reg [7:0] gamma_index_r,gamma_index_g,gamma_index_b; 104 | 105 | always @(posedge clk_vid) begin 106 | reg [7:0] R_in, G_in, B_in; 107 | reg [7:0] R_gamma, G_gamma; 108 | reg hs,vs,hb,vb,de; 109 | 110 | if(ce_pix) begin 111 | {gamma_index_r,gamma_index_g,gamma_index_b} <= RGB_in; 112 | hs <= HSync; vs <= VSync; 113 | hb <= HBlank; vb <= VBlank; 114 | de <= DE; 115 | 116 | RGB_out <= gamma_en ? {gamma_curve_r[gamma_index_r],gamma_curve_g[gamma_index_g],gamma_curve_b[gamma_index_b]} 117 | : {gamma_index_r,gamma_index_g,gamma_index_b}; 118 | HSync_out <= hs; VSync_out <= vs; 119 | HBlank_out <= hb; VBlank_out <= vb; 120 | DE_out <= de; 121 | end 122 | end 123 | 124 | endmodule 125 | -------------------------------------------------------------------------------- /sys/sys_top.sdc: -------------------------------------------------------------------------------- 1 | # Specify root clocks 2 | create_clock -period "50.0 MHz" [get_ports FPGA_CLK1_50] 3 | create_clock -period "50.0 MHz" [get_ports FPGA_CLK2_50] 4 | create_clock -period "50.0 MHz" [get_ports FPGA_CLK3_50] 5 | create_clock -period "100.0 MHz" [get_pins -compatibility_mode *|h2f_user0_clk] 6 | create_clock -period "100.0 MHz" [get_pins -compatibility_mode spi|sclk_out] -name spi_sck 7 | create_clock -period "10.0 MHz" [get_pins -compatibility_mode hdmi_i2c|out_clk] -name hdmi_sck 8 | 9 | derive_pll_clocks 10 | derive_clock_uncertainty 11 | 12 | # Decouple different clock groups (to simplify routing) 13 | set_clock_groups -exclusive \ 14 | -group [get_clocks { *|pll|pll_inst|altera_pll_i|*[*].*|divclk}] \ 15 | -group [get_clocks { pll_hdmi|pll_hdmi_inst|altera_pll_i|*[0].*|divclk}] \ 16 | -group [get_clocks { pll_audio|pll_audio_inst|altera_pll_i|*[0].*|divclk}] \ 17 | -group [get_clocks { spi_sck}] \ 18 | -group [get_clocks { hdmi_sck}] \ 19 | -group [get_clocks { *|h2f_user0_clk}] \ 20 | -group [get_clocks { FPGA_CLK1_50 }] \ 21 | -group [get_clocks { FPGA_CLK2_50 }] \ 22 | -group [get_clocks { FPGA_CLK3_50 }] 23 | 24 | set_false_path -from [get_ports {KEY*}] 25 | set_false_path -from [get_ports {BTN_*}] 26 | set_false_path -to [get_ports {LED_*}] 27 | set_false_path -to [get_ports {VGA_*}] 28 | set_false_path -from [get_ports {VGA_EN}] 29 | set_false_path -to [get_ports {AUDIO_SPDIF}] 30 | set_false_path -to [get_ports {AUDIO_L}] 31 | set_false_path -to [get_ports {AUDIO_R}] 32 | set_false_path -from {get_ports {SW[*]}} 33 | set_false_path -to {cfg[*]} 34 | set_false_path -from {cfg[*]} 35 | set_false_path -from {VSET[*]} 36 | set_false_path -to {wcalc[*] hcalc[*]} 37 | set_false_path -to {hdmi_width[*] hdmi_height[*]} 38 | set_false_path -to {deb_* btn_en btn_up} 39 | 40 | set_multicycle_path -to {*_osd|osd_vcnt*} -setup 2 41 | set_multicycle_path -to {*_osd|osd_vcnt*} -hold 1 42 | 43 | set_false_path -to {*_osd|v_cnt*} 44 | set_false_path -to {*_osd|v_osd_start*} 45 | set_false_path -to {*_osd|v_info_start*} 46 | set_false_path -to {*_osd|h_osd_start*} 47 | set_false_path -from {*_osd|v_osd_start*} 48 | set_false_path -from {*_osd|v_info_start*} 49 | set_false_path -from {*_osd|h_osd_start*} 50 | set_false_path -from {*_osd|rot*} 51 | set_false_path -from {*_osd|dsp_width*} 52 | set_false_path -to {*_osd|half} 53 | 54 | set_false_path -to {WIDTH[*] HFP[*] HS[*] HBP[*] HEIGHT[*] VFP[*] VS[*] VBP[*]} 55 | set_false_path -from {WIDTH[*] HFP[*] HS[*] HBP[*] HEIGHT[*] VFP[*] VS[*] VBP[*]} 56 | set_false_path -to {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*] LFB_HMAX[*] LFB_VMIN[*] LFB_VMAX[*]} 57 | set_false_path -from {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*] LFB_HMAX[*] LFB_VMIN[*] LFB_VMAX[*]} 58 | set_false_path -to {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]} 59 | set_false_path -from {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]} 60 | set_false_path -from {aflt_* acx* acy* areset* arc*} 61 | set_false_path -from {arx* ary*} 62 | set_false_path -from {vs_line*} 63 | set_false_path -from {ColorBurst_Range* PhaseInc* pal_en cvbs yc_en} 64 | 65 | set_false_path -from {ascal|o_ihsize*} 66 | set_false_path -from {ascal|o_ivsize*} 67 | set_false_path -from {ascal|o_format*} 68 | set_false_path -from {ascal|o_hdown} 69 | set_false_path -from {ascal|o_vdown} 70 | set_false_path -from {ascal|o_hmin* ascal|o_hmax* ascal|o_vmin* ascal|o_vmax* ascal|o_vrrmax* ascal|o_vrr} 71 | set_false_path -from {ascal|o_hdisp* ascal|o_vdisp*} 72 | set_false_path -from {ascal|o_htotal* ascal|o_vtotal*} 73 | set_false_path -from {ascal|o_hsstart* ascal|o_vsstart* ascal|o_hsend* ascal|o_vsend*} 74 | set_false_path -from {ascal|o_hsize* ascal|o_vsize*} 75 | 76 | set_false_path -from {mcp23009|flg_*} 77 | set_false_path -to {sysmem|fpga_interfaces|clocks_resets|f2h*} 78 | -------------------------------------------------------------------------------- /rtl/kempston_mouse.sv: -------------------------------------------------------------------------------- 1 | // 2 | // PCW for MiSTer AMX Mouse emulation module 3 | // 4 | // Copyright (c) 2020 Stephen Eddy 5 | // 6 | // All rights reserved 7 | // 8 | // Redistribution and use in source and synthezised forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // 11 | // * Redistributions of source code must retain the above copyright notice, 12 | // this list of conditions and the following disclaimer. 13 | // 14 | // * Redistributions in synthesized form must reproduce the above copyright 15 | // notice, this list of conditions and the following disclaimer in the 16 | // documentation and/or other materials provided with the distribution. 17 | // 18 | // * Neither the name of the author nor the names of other contributors may 19 | // be used to endorse or promote products derived from this software without 20 | // specific prior written agreement from the author. 21 | // 22 | // * License is granted for non-commercial use only. A fee may not be charged 23 | // for redistributions as source code or in synthesized/hardware form without 24 | // specific prior written agreement from the author. 25 | // 26 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 27 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 28 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 30 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | // POSSIBILITY OF SUCH DAMAGE. 37 | 38 | // Keyboard and Joystick mapper for Amstrad PCW keyboard matrix 39 | 40 | module kempston_mouse 41 | ( 42 | input wire reset, // reset when driven high 43 | input wire clk_sys, // should be same clock as clk_sys from HPS_IO 44 | 45 | // Inputs from generic mouse module 46 | input wire signed [8:0] mouse_x, // Signed 9 bit value (twos complement) 47 | input wire signed [8:0] mouse_y, 48 | input wire mouse_left, 49 | input wire mouse_right, 50 | input wire input_pulse, 51 | 52 | input sel, 53 | input [2:0] addr, 54 | output [7:0] dout 55 | ); 56 | 57 | logic [7:0] data; 58 | assign dout = sel ? data : 8'hff; 59 | 60 | // Clamped delta movement locked at 15 pixels max 61 | integer dxt, dyt; 62 | assign dxt = mouse_x / 4; 63 | assign dyt = mouse_y / 4; 64 | 65 | integer dx, dy; 66 | assign dx = (dxt > 15) ? 15 : dxt < -16 ? -16 : dxt; 67 | assign dy = (dyt > 15) ? 15 : dyt < -16 ? -16 : dyt; 68 | 69 | // Tracked position 70 | integer dxp, dyp; 71 | 72 | // Update absolute positions on mouse input strobe on a virtual screen 73 | always @(posedge clk_sys) 74 | begin 75 | reg old_pulse; 76 | old_pulse <= input_pulse; 77 | 78 | if(reset) begin 79 | dxp <= 0; // dx != dy for better mouse detection 80 | dyp <= 0; 81 | end 82 | // Update positions on new mouse data and wrap around 83 | else if(old_pulse != input_pulse) begin 84 | // Update X position 85 | if(dxp + dx < 0) dxp <= 0; 86 | else if(dxp + dx > 719) dxp <= 719; 87 | else dxp = dxp + dx; 88 | // Update Y position 89 | if(dyp + dy < 0) dyp <= 0; 90 | else if(dyp + dy > 255) dyp <= 255; 91 | else dyp = dyp + dy; 92 | end 93 | end 94 | 95 | // Data drivers 96 | always_comb 97 | begin 98 | casez(addr) 99 | 3'b0?0: data <= 8'(dxp); //(dxp * 3) / 2); //unsigned'(dxp) & 8'hff; // X pos 100 | 3'b0?1: data <= 8'(dyp); //unsigned'(dyp) & 8'hff; // Y pos 101 | 3'b100: data <= {6'b1,~mouse_left,~mouse_right}; // Buttons 102 | default: data <= 8'hff; 103 | endcase 104 | end 105 | 106 | endmodule 107 | -------------------------------------------------------------------------------- /sys/shadowmask.sv: -------------------------------------------------------------------------------- 1 | module shadowmask 2 | ( 3 | input clk, 4 | input clk_sys, 5 | 6 | input cmd_wr, 7 | input [15:0] cmd_in, 8 | 9 | input [23:0] din, 10 | input hs_in,vs_in, 11 | input de_in, 12 | input brd_in, 13 | input enable, 14 | 15 | output reg [23:0] dout, 16 | output reg hs_out,vs_out, 17 | output reg de_out 18 | ); 19 | 20 | 21 | reg [4:0] hmax; 22 | reg [4:0] vmax; 23 | reg [7:0] mask_idx; 24 | reg mask_2x; 25 | reg mask_rotate; 26 | reg mask_enable; 27 | reg [10:0] mask_lut[256]; 28 | 29 | always @(posedge clk) begin 30 | reg [4:0] hcount; 31 | reg [4:0] vcount; 32 | reg [3:0] hindex; 33 | reg [3:0] vindex; 34 | reg [4:0] hmax2; 35 | reg [4:0] vmax2; 36 | reg [11:0] pcnt,pde; 37 | reg old_hs, old_vs, old_brd; 38 | reg next_v; 39 | 40 | old_hs <= hs_in; 41 | old_vs <= vs_in; 42 | old_brd<= brd_in; 43 | 44 | // hcount and vcount counts pixel rows and columns 45 | // hindex and vindex half the value of the counters for double size patterns 46 | // hindex2, vindex2 swap the h and v counters for drawing rotated masks 47 | hindex <= mask_2x ? hcount[4:1] : hcount[3:0]; 48 | vindex <= mask_2x ? vcount[4:1] : vcount[3:0]; 49 | mask_idx <= mask_rotate ? {hindex,vindex} : {vindex,hindex}; 50 | 51 | // hmax and vmax store these sizes 52 | // hmax2 and vmax2 swap the values to handle rotation 53 | hmax2 <= ((mask_rotate ? vmax : hmax) << mask_2x) | mask_2x; 54 | vmax2 <= ((mask_rotate ? hmax : vmax) << mask_2x) | mask_2x; 55 | 56 | pcnt <= pcnt+1'd1; 57 | if(old_brd && ~brd_in) pde <= pcnt-4'd3; 58 | 59 | hcount <= hcount+1'b1; 60 | if(hcount == hmax2 || pde == pcnt) hcount <= 0; 61 | 62 | if(~old_brd && brd_in) next_v <= 1; 63 | if(old_vs && ~vs_in) vcount <= 0; 64 | if(old_hs && ~hs_in) begin 65 | vcount <= vcount + next_v; 66 | next_v <= 0; 67 | pcnt <= 0; 68 | if (vcount == vmax2) vcount <= 0; 69 | end 70 | end 71 | 72 | reg [4:0] r_mul, g_mul, b_mul; // 1.4 fixed point multipliers 73 | always @(posedge clk) begin 74 | reg [10:0] lut; 75 | 76 | lut <= mask_lut[mask_idx]; 77 | 78 | r_mul <= 5'b10000; g_mul <= 5'b10000; b_mul <= 5'b10000; // default 100% to all channels 79 | if (mask_enable) begin 80 | r_mul <= lut[10] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]}; 81 | g_mul <= lut[9] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]}; 82 | b_mul <= lut[8] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]}; 83 | end 84 | end 85 | 86 | always @(posedge clk) begin 87 | reg [11:0] vid; 88 | reg [7:0] r1, g1, b1; 89 | reg [7:0] r2, g2, b2; 90 | reg [7:0] r3_x, g3_x, b3_x; // 6.25% + 12.5% 91 | reg [8:0] r3_y, g3_y, b3_y; // 25% + 50% + 100% 92 | reg [8:0] r4, g4, b4; 93 | 94 | // C1 - data input 95 | {r1,g1,b1} <= din; 96 | vid <= {vid[8:0],vs_in, hs_in, de_in}; 97 | 98 | // C2 - relax timings 99 | {r2,g2,b2} <= {r1,g1,b1}; 100 | 101 | // C3 - perform multiplications 102 | r3_x <= ({4{r_mul[0]}} & r2[7:4]) + ({8{r_mul[1]}} & r2[7:3]); 103 | r3_y <= ({6{r_mul[2]}} & r2[7:2]) + ({7{r_mul[3]}} & r2[7:1]) + ({9{r_mul[4]}} & r2[7:0]); 104 | g3_x <= ({4{g_mul[0]}} & g2[7:4]) + ({8{g_mul[1]}} & g2[7:3]); 105 | g3_y <= ({6{g_mul[2]}} & g2[7:2]) + ({7{g_mul[3]}} & g2[7:1]) + ({9{g_mul[4]}} & g2[7:0]); 106 | b3_x <= ({4{b_mul[0]}} & b2[7:4]) + ({8{b_mul[1]}} & b2[7:3]); 107 | b3_y <= ({6{b_mul[2]}} & b2[7:2]) + ({7{b_mul[3]}} & b2[7:1]) + ({9{b_mul[4]}} & b2[7:0]); 108 | 109 | // C4 - combine results 110 | r4 <= r3_x + r3_y; 111 | g4 <= g3_x + g3_y; 112 | b4 <= b3_x + b3_y; 113 | 114 | // C5 - clamp and output 115 | dout <= {{8{r4[8]}} | r4[7:0], {8{g4[8]}} | g4[7:0], {8{b4[8]}} | b4[7:0]}; 116 | {vs_out,hs_out,de_out} <= vid[11:9]; 117 | end 118 | 119 | // clock in mask commands 120 | always @(posedge clk_sys) begin 121 | reg m_enable; 122 | reg [7:0] idx; 123 | 124 | if (cmd_wr) begin 125 | case(cmd_in[15:13]) 126 | 3'b000: begin {m_enable, mask_rotate, mask_2x} <= cmd_in[3:1]; idx <= 0; end 127 | 3'b001: vmax <= cmd_in[3:0]; 128 | 3'b010: hmax <= cmd_in[3:0]; 129 | 3'b011: begin mask_lut[idx] <= cmd_in[10:0]; idx <= idx + 1'd1; end 130 | endcase 131 | end 132 | 133 | mask_enable <= m_enable & enable; 134 | end 135 | 136 | endmodule 137 | -------------------------------------------------------------------------------- /sys/ltc2308.sv: -------------------------------------------------------------------------------- 1 | //============================================================================ 2 | // 3 | // LTC2308 controller 4 | // Copyright (C) 2019 Sorgelig 5 | // 6 | // 7 | // This program is free software; you can redistribute it and/or modify it 8 | // under the terms of the GNU General Public License as published by the Free 9 | // Software Foundation; either version 2 of the License, or (at your option) 10 | // any later version. 11 | // 12 | // This program is distributed in the hope that it will be useful, but WITHOUT 13 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 | // more details. 16 | // 17 | // You should have received a copy of the GNU General Public License along 18 | // with this program; if not, write to the Free Software Foundation, Inc., 19 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 | // 21 | //============================================================================ 22 | 23 | 24 | // NUM_CH 1..8 25 | // Sampling rate = ADC_RATE/NUM_CH 26 | // ADC_RATE max is ~500KHz 27 | // CLK_RATE max is ~80MHz 28 | module ltc2308 #(parameter NUM_CH = 2, ADC_RATE = 96000, CLK_RATE = 50000000) 29 | ( 30 | input reset, 31 | input clk, 32 | 33 | inout [3:0] ADC_BUS, 34 | 35 | output reg dout_sync, // toggle with every ADC round 36 | output reg [(NUM_CH*12)-1:0] dout // 12 bits per channel (unsigned) 37 | ); 38 | 39 | localparam TCONV = CLK_RATE/625000; 40 | 41 | reg sck; 42 | wire sdo = cfg[5]; 43 | 44 | assign ADC_BUS[3] = sck; 45 | wire sdi = ADC_BUS[2]; 46 | assign ADC_BUS[1] = sdo; 47 | assign ADC_BUS[0] = convst; 48 | 49 | reg convst; 50 | reg [5:0] cfg; 51 | 52 | reg [31:0] sum; 53 | wire [31:0] next_sum = sum + ADC_RATE; 54 | 55 | reg [2:0] pin; 56 | wire [2:0] next_pin = (pin == (NUM_CH-1)) ? 3'd0 : (pin + 1'd1); 57 | 58 | always @(posedge clk) begin 59 | reg [7:0] tconv; 60 | reg [3:0] bitcnt; 61 | reg [10:0] adcin; 62 | 63 | convst <= 0; 64 | 65 | if(reset) begin 66 | sum <= 0; 67 | tconv <= 0; 68 | bitcnt <= 0; 69 | sck <= 0; 70 | cfg <= 0; 71 | dout <= 0; 72 | pin <= NUM_CH[2:0]-1'd1; 73 | end 74 | else begin 75 | sum <= next_sum; 76 | if(next_sum >= CLK_RATE) begin 77 | sum <= next_sum - CLK_RATE; 78 | tconv <= TCONV[7:0]; 79 | convst <= 1; 80 | bitcnt <= 12; 81 | cfg <= {1'b1, next_pin[0], next_pin[2:1], 1'b1, 1'b0}; 82 | if(!next_pin) dout_sync <= ~dout_sync; 83 | end 84 | 85 | if(tconv) tconv <= tconv - 1'd1; 86 | else if(bitcnt) begin 87 | sck <= ~sck; 88 | 89 | if(sck) cfg <= cfg<<1; 90 | else begin 91 | adcin <= {adcin[9:0],sdi}; 92 | bitcnt <= bitcnt - 1'd1; 93 | if(bitcnt == 1) begin 94 | dout[pin*12 +:12] <= {adcin,sdi}; 95 | pin <= next_pin; 96 | end 97 | end 98 | end 99 | else sck <= 0; 100 | end 101 | end 102 | 103 | endmodule 104 | 105 | module ltc2308_tape #(parameter HIST_LOW = 16, HIST_HIGH = 64, ADC_RATE = 48000, CLK_RATE = 50000000, NUM_CH = 1) 106 | ( 107 | input reset, 108 | input clk, 109 | 110 | inout [3:0] ADC_BUS, 111 | output reg dout, 112 | output active, 113 | output adc_sync, 114 | output [(NUM_CH*12)-1:0] adc_data 115 | ); 116 | 117 | ltc2308 #(NUM_CH, ADC_RATE, CLK_RATE) adc 118 | ( 119 | .reset(reset), 120 | .clk(clk), 121 | 122 | .ADC_BUS(ADC_BUS), 123 | .dout(adc_data), 124 | .dout_sync(adc_sync) 125 | ); 126 | 127 | always @(posedge clk) begin 128 | reg [13:0] data1,data2,data3,data4, sum; 129 | reg adc_sync_d; 130 | 131 | adc_sync_d<=adc_sync; 132 | if(adc_sync_d ^ adc_sync) begin 133 | data1 <= data2; 134 | data2 <= data3; 135 | data3 <= data4; 136 | data4 <= adc_data[11:0]; 137 | 138 | sum <= data1+data2+data3+data4; 139 | 140 | if(sum[13:2]HIST_HIGH) dout <= 1; 142 | end 143 | end 144 | 145 | assign active = |act; 146 | 147 | reg [1:0] act; 148 | always @(posedge clk) begin 149 | reg [31:0] onesec; 150 | reg old_dout; 151 | 152 | onesec <= onesec + 1; 153 | if(onesec>CLK_RATE) begin 154 | onesec <= 0; 155 | if(act) act <= act - 1'd1; 156 | end 157 | 158 | old_dout <= dout; 159 | if(old_dout ^ dout) act <= 2; 160 | end 161 | 162 | endmodule 163 | -------------------------------------------------------------------------------- /sys/alsa.sv: -------------------------------------------------------------------------------- 1 | //============================================================================ 2 | // 3 | // ALSA sound support for MiSTer 4 | // (c)2019,2020 Alexey Melnikov 5 | // 6 | // This program is free software; you can redistribute it and/or modify it 7 | // under the terms of the GNU General Public License as published by the Free 8 | // Software Foundation; either version 2 of the License, or (at your option) 9 | // any later version. 10 | // 11 | // This program is distributed in the hope that it will be useful, but WITHOUT 12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 | // more details. 15 | // 16 | // You should have received a copy of the GNU General Public License along 17 | // with this program; if not, write to the Free Software Foundation, Inc., 18 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | // 20 | //============================================================================ 21 | 22 | module alsa 23 | #( 24 | parameter CLK_RATE = 24576000 25 | ) 26 | ( 27 | input reset, 28 | input clk, 29 | 30 | output reg [31:3] ram_address, 31 | input [63:0] ram_data, 32 | output reg ram_req = 0, 33 | input ram_ready, 34 | 35 | input spi_ss, 36 | input spi_sck, 37 | input spi_mosi, 38 | output spi_miso, 39 | 40 | output reg [15:0] pcm_l, 41 | output reg [15:0] pcm_r 42 | ); 43 | 44 | reg [60:0] buf_info; 45 | reg [6:0] spicnt = 0; 46 | always @(posedge spi_sck, posedge spi_ss) begin 47 | reg [95:0] spi_data; 48 | 49 | if(spi_ss) spicnt <= 0; 50 | else begin 51 | spi_data[{spicnt[6:3],~spicnt[2:0]}] <= spi_mosi; 52 | if(&spicnt) buf_info <= {spi_data[82:67],spi_data[50:35],spi_data[31:3]}; 53 | spicnt <= spicnt + 1'd1; 54 | end 55 | end 56 | 57 | assign spi_miso = spi_out[{spicnt[4:3],~spicnt[2:0]}]; 58 | 59 | reg [31:0] spi_out = 0; 60 | always @(posedge clk) if(spi_ss) spi_out <= {buf_rptr, hurryup, 8'h00}; 61 | 62 | 63 | reg [31:3] buf_addr; 64 | reg [18:3] buf_len; 65 | reg [18:3] buf_wptr = 0; 66 | 67 | always @(posedge clk) begin 68 | reg [60:0] data1,data2; 69 | 70 | data1 <= buf_info; 71 | data2 <= data1; 72 | if(data2 == data1) {buf_wptr,buf_len,buf_addr} <= data2; 73 | end 74 | 75 | reg [2:0] hurryup = 0; 76 | reg [18:3] buf_rptr = 0; 77 | 78 | always @(posedge clk) begin 79 | reg [18:3] len = 0; 80 | reg [1:0] ready = 0; 81 | reg [63:0] readdata; 82 | reg got_first = 0; 83 | reg [7:0] ce_cnt = 0; 84 | reg [1:0] state = 0; 85 | 86 | if(reset) begin 87 | ready <= 0; 88 | ce_cnt <= 0; 89 | state <= 0; 90 | got_first <= 0; 91 | len <= 0; 92 | end 93 | else begin 94 | 95 | //ramp up 96 | if(len[18:14] && (hurryup < 1)) hurryup <= 1; 97 | if(len[18:16] && (hurryup < 2)) hurryup <= 2; 98 | if(len[18:17] && (hurryup < 4)) hurryup <= 4; 99 | 100 | //ramp down 101 | if(!len[18:15] && (hurryup > 2)) hurryup <= 2; 102 | if(!len[18:13] && (hurryup > 1)) hurryup <= 1; 103 | if(!len[18:10]) hurryup <= 0; 104 | 105 | if(ce_sample && ~&ce_cnt) ce_cnt <= ce_cnt + 1'd1; 106 | 107 | case(state) 108 | 0: if(!ce_sample) begin 109 | if(ready) begin 110 | if(ce_cnt) begin 111 | {readdata[31:0],pcm_r,pcm_l} <= readdata; 112 | ready <= ready - 1'd1; 113 | ce_cnt <= ce_cnt - 1'd1; 114 | end 115 | end 116 | else if(buf_rptr != buf_wptr) begin 117 | if(~got_first) begin 118 | buf_rptr <= buf_wptr; 119 | got_first <= 1; 120 | end 121 | else begin 122 | ram_address <= buf_addr + buf_rptr; 123 | ram_req <= ~ram_req; 124 | buf_rptr <= buf_rptr + 1'd1; 125 | len <= (buf_wptr < buf_rptr) ? (buf_len + buf_wptr - buf_rptr) : (buf_wptr - buf_rptr); 126 | state <= 1; 127 | end 128 | end 129 | else begin 130 | len <= 0; 131 | ce_cnt <= 0; 132 | hurryup <= 0; 133 | end 134 | end 135 | 1: if(ram_ready) begin 136 | ready <= 2; 137 | readdata <= ram_data; 138 | if(buf_rptr >= buf_len) buf_rptr <= buf_rptr - buf_len; 139 | state <= 0; 140 | end 141 | endcase 142 | end 143 | end 144 | 145 | reg ce_sample; 146 | always @(posedge clk) begin 147 | reg [31:0] acc = 0; 148 | 149 | ce_sample <= 0; 150 | acc <= acc + 48000 + {hurryup,6'd0}; 151 | if(acc >= CLK_RATE) begin 152 | acc <= acc - CLK_RATE; 153 | ce_sample <= 1; 154 | end 155 | end 156 | 157 | endmodule 158 | -------------------------------------------------------------------------------- /sys/pll_cfg/pll_cfg.v: -------------------------------------------------------------------------------- 1 | // megafunction wizard: %Altera PLL Reconfig v17.0% 2 | // GENERATION: XML 3 | // pll_cfg.v 4 | 5 | // Generated using ACDS version 17.0 598 6 | 7 | `timescale 1 ps / 1 ps 8 | module pll_cfg #( 9 | parameter ENABLE_BYTEENABLE = 0, 10 | parameter BYTEENABLE_WIDTH = 4, 11 | parameter RECONFIG_ADDR_WIDTH = 6, 12 | parameter RECONFIG_DATA_WIDTH = 32, 13 | parameter reconf_width = 64, 14 | parameter WAIT_FOR_LOCK = 1 15 | ) ( 16 | input wire mgmt_clk, // mgmt_clk.clk 17 | input wire mgmt_reset, // mgmt_reset.reset 18 | output wire mgmt_waitrequest, // mgmt_avalon_slave.waitrequest 19 | input wire mgmt_read, // .read 20 | input wire mgmt_write, // .write 21 | output wire [31:0] mgmt_readdata, // .readdata 22 | input wire [5:0] mgmt_address, // .address 23 | input wire [31:0] mgmt_writedata, // .writedata 24 | output wire [63:0] reconfig_to_pll, // reconfig_to_pll.reconfig_to_pll 25 | input wire [63:0] reconfig_from_pll // reconfig_from_pll.reconfig_from_pll 26 | ); 27 | 28 | altera_pll_reconfig_top #( 29 | .device_family ("Cyclone V"), 30 | .ENABLE_MIF (0), 31 | .MIF_FILE_NAME ("sys/pll_cfg.mif"), 32 | .ENABLE_BYTEENABLE (ENABLE_BYTEENABLE), 33 | .BYTEENABLE_WIDTH (BYTEENABLE_WIDTH), 34 | .RECONFIG_ADDR_WIDTH (RECONFIG_ADDR_WIDTH), 35 | .RECONFIG_DATA_WIDTH (RECONFIG_DATA_WIDTH), 36 | .reconf_width (reconf_width), 37 | .WAIT_FOR_LOCK (WAIT_FOR_LOCK) 38 | ) pll_cfg_inst ( 39 | .mgmt_clk (mgmt_clk), // mgmt_clk.clk 40 | .mgmt_reset (mgmt_reset), // mgmt_reset.reset 41 | .mgmt_waitrequest (mgmt_waitrequest), // mgmt_avalon_slave.waitrequest 42 | .mgmt_read (mgmt_read), // .read 43 | .mgmt_write (mgmt_write), // .write 44 | .mgmt_readdata (mgmt_readdata), // .readdata 45 | .mgmt_address (mgmt_address), // .address 46 | .mgmt_writedata (mgmt_writedata), // .writedata 47 | .reconfig_to_pll (reconfig_to_pll), // reconfig_to_pll.reconfig_to_pll 48 | .reconfig_from_pll (reconfig_from_pll), // reconfig_from_pll.reconfig_from_pll 49 | .mgmt_byteenable (4'b0000) // (terminated) 50 | ); 51 | 52 | endmodule 53 | // Retrieval info: 54 | // 79 | // Retrieval info: 80 | // Retrieval info: 81 | // Retrieval info: 82 | // Retrieval info: 83 | // Retrieval info: 84 | // Retrieval info: 85 | // IPFS_FILES : pll_cfg.vo 86 | // RELATED_FILES: pll_cfg.v, altera_pll_reconfig_top.v, altera_pll_reconfig_core.v, altera_std_synchronizer.v 87 | -------------------------------------------------------------------------------- /rtl/fake_daisy.sv: -------------------------------------------------------------------------------- 1 | // 2 | // PCW for MiSTer Fake Daisywheel module 3 | // required to boot 9512+ 3.5" disks 4 | // 5 | // Copyright (c) 2020 Stephen Eddy 6 | // 7 | // All rights reserved 8 | // 9 | // Redistribution and use in source and synthezised forms, with or without 10 | // modification, are permitted provided that the following conditions are met: 11 | // 12 | // * Redistributions of source code must retain the above copyright notice, 13 | // this list of conditions and the following disclaimer. 14 | // 15 | // * Redistributions in synthesized form must reproduce the above copyright 16 | // notice, this list of conditions and the following disclaimer in the 17 | // documentation and/or other materials provided with the distribution. 18 | // 19 | // * Neither the name of the author nor the names of other contributors may 20 | // be used to endorse or promote products derived from this software without 21 | // specific prior written agreement from the author. 22 | // 23 | // * License is granted for non-commercial use only. A fee may not be charged 24 | // for redistributions as source code or in synthesized/hardware form without 25 | // specific prior written agreement from the author. 26 | // 27 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 29 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 31 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 | // POSSIBILITY OF SUCH DAMAGE. 38 | 39 | // Keyboard and Joystick mapper for Amstrad PCW keyboard matrix 40 | 41 | module fake_daisy 42 | ( 43 | input wire reset, // reset when driven high 44 | input wire clk_sys, // should be same clock as clk_sys from HPS_IO 45 | input wire ce, // Clock enable line from CPU 46 | input wire sel, // Select signal 47 | 48 | // Responds to following PCW address: 00 - FC, 01 - FD, 10 - 01FC 49 | input wire [1:0] address, // Address 50 | input wire wr, // 1 = Write, 0 = Read 51 | input wire [7:0] din, 52 | output logic [7:0] dout 53 | 54 | ); 55 | 56 | localparam HOST_RECV = 8'b11001010; 57 | localparam HOST_SEND = 8'b11101001; 58 | logic [7:0] status; // Current status 59 | logic [7:0] command; // First byte of any command received 60 | logic [7:0] data; // Second byte of any command received 61 | logic [7:0] out; // Output from command 62 | 63 | 64 | // State machine for processing commands written to controller via FC 65 | always @(posedge clk_sys) 66 | begin 67 | logic old_sel; 68 | 69 | if(reset) 70 | begin 71 | status <= HOST_SEND; 72 | command <= 8'h00; 73 | data <= 8'h00; 74 | out <= 8'h00; 75 | old_sel <= 1'b0; 76 | end 77 | else begin 78 | if(ce) begin 79 | old_sel <= sel; 80 | if(~old_sel && sel && wr && address==2'b10) begin // New command received 81 | command <= din; 82 | status <= HOST_SEND; 83 | end 84 | if(~old_sel && sel && wr && address==2'b00) begin // Data for command recieved, update output 85 | data <= din; 86 | // Set output based on command 87 | if(command==8'h12 || command==8'h02 || command==8'h06 || command==8'h0a || command==8'h0b) 88 | begin 89 | status <= HOST_RECV; 90 | out <= 8'h00; 91 | end 92 | else begin 93 | status <= HOST_SEND; 94 | out <= 8'hff; 95 | end 96 | end 97 | // A read of FD will also reset the mode back to HOST_SEND 98 | if(~old_sel && sel && ~wr && address==2'b01) status <= HOST_SEND; 99 | end 100 | end 101 | end 102 | 103 | always_comb 104 | begin 105 | if(sel) begin 106 | if(~wr && address==2'b00) dout = out; // Data output from command (0xFC) 107 | else if(~wr && address==2'b10) dout = 8'h40; // Printer status (0x1FC) - No printer 108 | else dout = status; // Status (0xFD) 109 | end else dout = 8'hff; 110 | end 111 | 112 | endmodule -------------------------------------------------------------------------------- /PCW.srf: -------------------------------------------------------------------------------- 1 | { "" "" "" "Inferred RAM node \"emu:emu\|mister_io:mister_io\|ps2_kbd_fifo_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} 2 | { "" "" "" "Inferred RAM node \"emu:emu\|mister_io:mister_io\|ps2_mouse_fifo_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} 3 | { "" "" "" "Synthesized away node \"emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|outclk_wire\[2\]\"" { } { } 0 14320 "" 0 0 "Design Software" 0 -1 0 ""} 4 | { "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[1\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Design Software" 0 -1 0 ""} 5 | { "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[0\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Design Software" 0 -1 0 ""} 6 | { "" "" "" "Ignored locations or region assignments to the following nodes" { } { } 0 15705 "" 0 0 "Design Software" 0 -1 0 ""} 7 | { "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[2\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Design Software" 0 -1 0 ""} 8 | { "" "" "" "Verilog HDL or VHDL warning at de10_top.v(129): object \"io_win\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} 9 | { "" "" "" "Verilog HDL or VHDL warning at de10_top.v(134): object \"io_sdd\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} 10 | { "" "" "" "Verilog HDL or VHDL warning at de10_top.v(97): object \"io_win\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} 11 | { "" "" "" "Verilog HDL or VHDL warning at de10_top.v(102): object \"io_sdd\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} 12 | { "" "" "" "Some pins have incomplete I/O assignments. Refer to the I/O Assignment Warnings report for details" { } { } 0 15714 "" 0 0 "Design Software" 0 -1 0 ""} 13 | { "" "" "" "LOCKED port on the PLL is not properly connected on instance \"pll_hdmi:pll_hdmi\|pll_hdmi_0002:pll_hdmi_inst\|altera_pll:altera_pll_i\|general\[0\].gpll\". The LOCKED port on the PLL should be connected when the FBOUTCLK port is connected. Although it is unnecessary to connect the LOCKED signal, any logic driven off of an output clock of the PLL will not know when the PLL is locked and ready." { } { } 0 21300 "" 0 0 "Design Software" 0 -1 0 ""} 14 | { "" "" "" "Found combinational loop of 47 nodes" { } { } 0 332125 "" 0 0 "Design Software" 0 -1 0 ""} 15 | { "" "" "" "LOCKED port on the PLL is not properly connected on instance \"emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[0\].gpll\". The LOCKED port on the PLL should be connected when the FBOUTCLK port is connected. Although it is unnecessary to connect the LOCKED signal, any logic driven off of an output clock of the PLL will not know when the PLL is locked and ready." { } { } 0 21300 "" 0 0 "Design Software" 0 -1 0 ""} 16 | { "" "" "" "Verilog HDL or VHDL warning at sys_top.v(209): object \"vip_newcfg\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} 17 | { "" "" "" "Verilog HDL or VHDL warning at sys_top.v(594): object \"VSET\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} 18 | { "" "" "" "Ignored filter at sys_top.sdc(17): vip\|output_inst\|vid_clk could not be matched with a net" { } { } 0 332174 "" 0 0 "Design Software" 0 -1 0 ""} 19 | { "" "" "" "Ignored create_generated_clock at sys_top.sdc(16): Argument is an empty collection" { } { } 0 332049 "" 0 0 "Design Software" 0 -1 0 ""} 20 | { "" "" "" "Ignored filter at sys_top.sdc(37): VID_CLK could not be matched with a clock" { } { } 0 332174 "" 0 0 "Design Software" 0 -1 0 ""} 21 | { "" "" "" "*" { } { } 0 21074 "" 0 0 "Design Software" 0 -1 0 ""} 22 | { "" "" "" "*" { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} 23 | { "" "" "" "*" { } { } 0 276027 "" 0 0 "Design Software" 0 -1 0 ""} 24 | { "" "" "" "RST" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 25 | { "" "" "" "altera_pll.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 26 | { "" "" "" "altera_cyclonev_pll.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 27 | { "" "" "" "altera_pll_reconfig_core.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 28 | { "" "" "" "cyclonev_pll" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 29 | -------------------------------------------------------------------------------- /sys/scandoubler.v: -------------------------------------------------------------------------------- 1 | // 2 | // scandoubler.v 3 | // 4 | // Copyright (c) 2015 Till Harbaum 5 | // Copyright (c) 2017-2021 Alexey Melnikov 6 | // 7 | // This source file is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published 9 | // by the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | // 12 | // This source file is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | // 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program. If not, see . 19 | 20 | // TODO: Delay vsync one line 21 | 22 | module scandoubler #(parameter LENGTH, parameter HALF_DEPTH) 23 | ( 24 | // system interface 25 | input clk_vid, 26 | input hq2x, 27 | 28 | // shifter video interface 29 | input ce_pix, 30 | input hs_in, 31 | input vs_in, 32 | input hb_in, 33 | input vb_in, 34 | input [DWIDTH:0] r_in, 35 | input [DWIDTH:0] g_in, 36 | input [DWIDTH:0] b_in, 37 | 38 | // output interface 39 | output ce_pix_out, 40 | output reg hs_out, 41 | output vs_out, 42 | output hb_out, 43 | output vb_out, 44 | output [DWIDTH:0] r_out, 45 | output [DWIDTH:0] g_out, 46 | output [DWIDTH:0] b_out 47 | ); 48 | 49 | localparam DWIDTH = HALF_DEPTH ? 3 : 7; 50 | 51 | reg [7:0] pix_len = 0; 52 | wire [7:0] pl = pix_len + 1'b1; 53 | 54 | reg [7:0] pix_in_cnt = 0; 55 | wire [7:0] pc_in = pix_in_cnt + 1'b1; 56 | reg [7:0] pixsz, pixsz2, pixsz4 = 0; 57 | 58 | reg ce_x4i, ce_x1i; 59 | always @(posedge clk_vid) begin 60 | reg old_ce, valid, hs; 61 | 62 | if(~&pix_len) pix_len <= pl; 63 | if(~&pix_in_cnt) pix_in_cnt <= pc_in; 64 | 65 | ce_x4i <= 0; 66 | ce_x1i <= 0; 67 | 68 | // use such odd comparison to place ce_x4 evenly if master clock isn't multiple of 4. 69 | if((pc_in == pixsz4) || (pc_in == pixsz2) || (pc_in == (pixsz2+pixsz4))) ce_x4i <= 1; 70 | 71 | old_ce <= ce_pix; 72 | if(~old_ce & ce_pix) begin 73 | if(valid & ~hb_in & ~vb_in) begin 74 | pixsz <= pl; 75 | pixsz2 <= {1'b0, pl[7:1]}; 76 | pixsz4 <= {2'b00, pl[7:2]}; 77 | end 78 | pix_len <= 0; 79 | valid <= 1; 80 | end 81 | 82 | hs <= hs_in; 83 | if((~hs & hs_in) || (pc_in >= pixsz)) begin 84 | ce_x4i <= 1; 85 | ce_x1i <= 1; 86 | pix_in_cnt <= 0; 87 | end 88 | 89 | if(hb_in | vb_in) valid <= 0; 90 | end 91 | 92 | reg req_line_reset; 93 | reg [DWIDTH:0] r_d, g_d, b_d; 94 | always @(posedge clk_vid) begin 95 | if(ce_x1i) begin 96 | req_line_reset <= hb_in; 97 | r_d <= r_in; 98 | g_d <= g_in; 99 | b_d <= b_in; 100 | end 101 | end 102 | 103 | Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x 104 | ( 105 | .clk(clk_vid), 106 | 107 | .ce_in(ce_x4i), 108 | .inputpixel({b_d,g_d,r_d}), 109 | .disable_hq2x(~hq2x), 110 | .reset_frame(vb_in), 111 | .reset_line(req_line_reset), 112 | 113 | .ce_out(ce_x4o), 114 | .read_y(sd_line), 115 | .hblank(hbo[0]&hbo[8]), 116 | .outpixel({b_out,g_out,r_out}) 117 | ); 118 | 119 | reg [7:0] pix_out_cnt = 0; 120 | wire [7:0] pc_out = pix_out_cnt + 1'b1; 121 | 122 | reg ce_x4o, ce_x2o; 123 | always @(posedge clk_vid) begin 124 | reg hs; 125 | 126 | if(~&pix_out_cnt) pix_out_cnt <= pc_out; 127 | 128 | ce_x4o <= 0; 129 | ce_x2o <= 0; 130 | 131 | // use such odd comparison to place ce_x4 evenly if master clock isn't multiple of 4. 132 | if((pc_out == pixsz4) || (pc_out == pixsz2) || (pc_out == (pixsz2+pixsz4))) ce_x4o <= 1; 133 | if( pc_out == pixsz2) ce_x2o <= 1; 134 | 135 | hs <= hs_out; 136 | if((~hs & hs_out) || (pc_out >= pixsz)) begin 137 | ce_x2o <= 1; 138 | ce_x4o <= 1; 139 | pix_out_cnt <= 0; 140 | end 141 | end 142 | 143 | reg [1:0] sd_line; 144 | reg [3:0] vbo; 145 | reg [3:0] vso; 146 | reg [8:0] hbo; 147 | always @(posedge clk_vid) begin 148 | 149 | reg [31:0] hcnt; 150 | reg [30:0] sd_hcnt; 151 | reg [30:0] hs_start, hs_end; 152 | reg [30:0] hde_start, hde_end; 153 | 154 | reg hs, hb; 155 | 156 | if(ce_x4o) begin 157 | hbo[8:1] <= hbo[7:0]; 158 | end 159 | 160 | // output counter synchronous to input and at twice the rate 161 | sd_hcnt <= sd_hcnt + 1'd1; 162 | if(sd_hcnt == hde_start) begin 163 | sd_hcnt <= 0; 164 | vbo[3:1] <= vbo[2:0]; 165 | end 166 | 167 | if(sd_hcnt == hs_end) begin 168 | sd_line <= sd_line + 1'd1; 169 | if(&vbo[3:2]) sd_line <= 1; 170 | vso[3:1] <= vso[2:0]; 171 | end 172 | 173 | if(sd_hcnt == hde_start)hbo[0] <= 0; 174 | if(sd_hcnt == hde_end) hbo[0] <= 1; 175 | 176 | // replicate horizontal sync at twice the speed 177 | if(sd_hcnt == hs_end) hs_out <= 0; 178 | if(sd_hcnt == hs_start) hs_out <= 1; 179 | 180 | hs <= hs_in; 181 | hb <= hb_in; 182 | 183 | hcnt <= hcnt + 1'd1; 184 | if(hb && !hb_in) begin 185 | hde_start <= hcnt[31:1]; 186 | hbo[0] <= 0; 187 | hcnt <= 0; 188 | sd_hcnt <= 0; 189 | vbo <= {vbo[2:0],vb_in}; 190 | end 191 | 192 | if(!hb && hb_in) hde_end <= hcnt[31:1]; 193 | 194 | // falling edge of hsync indicates start of line 195 | if(hs && !hs_in) begin 196 | hs_end <= hcnt[31:1]; 197 | vso[0] <= vs_in; 198 | end 199 | 200 | // save position of rising edge 201 | if(!hs && hs_in) hs_start <= hcnt[31:1]; 202 | end 203 | 204 | assign vs_out = vso[3]; 205 | assign ce_pix_out = hq2x ? ce_x4o : ce_x2o; 206 | 207 | //Compensate picture shift after HQ2x 208 | assign vb_out = vbo[3]; 209 | assign hb_out = hbo[6]; 210 | 211 | endmodule 212 | -------------------------------------------------------------------------------- /rtl/T80/T80_Reg.vhd: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- **** 3 | -- T80(c) core. Attempt to finish all undocumented features and provide 4 | -- accurate timings. 5 | -- Version 350. 6 | -- Copyright (c) 2018 Sorgelig 7 | -- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr 8 | -- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as 9 | -- correct implementation is still unclear. 10 | -- 11 | -- **** 12 | -- T80(b) core. In an effort to merge and maintain bug fixes .... 13 | -- 14 | -- 15 | -- Ver 300 started tidyup 16 | -- MikeJ March 2005 17 | -- Latest version from www.fpgaarcade.com (original www.opencores.org) 18 | -- 19 | -- **** 20 | -- 21 | -- T80 Registers, technology independent 22 | -- 23 | -- Version : 0244 24 | -- 25 | -- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) 26 | -- 27 | -- All rights reserved 28 | -- 29 | -- Redistribution and use in source and synthezised forms, with or without 30 | -- modification, are permitted provided that the following conditions are met: 31 | -- 32 | -- Redistributions of source code must retain the above copyright notice, 33 | -- this list of conditions and the following disclaimer. 34 | -- 35 | -- Redistributions in synthesized form must reproduce the above copyright 36 | -- notice, this list of conditions and the following disclaimer in the 37 | -- documentation and/or other materials provided with the distribution. 38 | -- 39 | -- Neither the name of the author nor the names of other contributors may 40 | -- be used to endorse or promote products derived from this software without 41 | -- specific prior written permission. 42 | -- 43 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 44 | -- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 45 | -- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 46 | -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 47 | -- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 48 | -- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 49 | -- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 50 | -- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 51 | -- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 52 | -- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 53 | -- POSSIBILITY OF SUCH DAMAGE. 54 | -- 55 | -- Please report bugs to the author, but before you do so, please 56 | -- make sure that this is not a derivative work and that 57 | -- you have the latest version of this file. 58 | -- 59 | -- The latest version of this file can be found at: 60 | -- http://www.opencores.org/cvsweb.shtml/t51/ 61 | -- 62 | -- Limitations : 63 | -- 64 | -- File history : 65 | -- 66 | -- 0242 : Initial release 67 | -- 68 | -- 0244 : Changed to single register file 69 | -- 70 | 71 | library IEEE; 72 | use IEEE.std_logic_1164.all; 73 | use IEEE.numeric_std.all; 74 | 75 | entity T80_Reg is 76 | port( 77 | Clk : in std_logic; 78 | CEN : in std_logic; 79 | WEH : in std_logic; 80 | WEL : in std_logic; 81 | AddrA : in std_logic_vector(2 downto 0); 82 | AddrB : in std_logic_vector(2 downto 0); 83 | AddrC : in std_logic_vector(2 downto 0); 84 | DIH : in std_logic_vector(7 downto 0); 85 | DIL : in std_logic_vector(7 downto 0); 86 | DOAH : out std_logic_vector(7 downto 0); 87 | DOAL : out std_logic_vector(7 downto 0); 88 | DOBH : out std_logic_vector(7 downto 0); 89 | DOBL : out std_logic_vector(7 downto 0); 90 | DOCH : out std_logic_vector(7 downto 0); 91 | DOCL : out std_logic_vector(7 downto 0); 92 | DOR : out std_logic_vector(127 downto 0); 93 | DIRSet : in std_logic; 94 | DIR : in std_logic_vector(127 downto 0) 95 | ); 96 | end T80_Reg; 97 | 98 | architecture rtl of T80_Reg is 99 | 100 | type Register_Image is array (natural range <>) of std_logic_vector(7 downto 0); 101 | signal RegsH : Register_Image(0 to 7); 102 | signal RegsL : Register_Image(0 to 7); 103 | 104 | begin 105 | 106 | process (Clk) 107 | begin 108 | if rising_edge(Clk) then 109 | if DIRSet = '1' then 110 | RegsL(0) <= DIR( 7 downto 0); 111 | RegsH(0) <= DIR( 15 downto 8); 112 | 113 | RegsL(1) <= DIR( 23 downto 16); 114 | RegsH(1) <= DIR( 31 downto 24); 115 | 116 | RegsL(2) <= DIR( 39 downto 32); 117 | RegsH(2) <= DIR( 47 downto 40); 118 | 119 | RegsL(3) <= DIR( 55 downto 48); 120 | RegsH(3) <= DIR( 63 downto 56); 121 | 122 | RegsL(4) <= DIR( 71 downto 64); 123 | RegsH(4) <= DIR( 79 downto 72); 124 | 125 | RegsL(5) <= DIR( 87 downto 80); 126 | RegsH(5) <= DIR( 95 downto 88); 127 | 128 | RegsL(6) <= DIR(103 downto 96); 129 | RegsH(6) <= DIR(111 downto 104); 130 | 131 | RegsL(7) <= DIR(119 downto 112); 132 | RegsH(7) <= DIR(127 downto 120); 133 | elsif CEN = '1' then 134 | if WEH = '1' then 135 | RegsH(to_integer(unsigned(AddrA))) <= DIH; 136 | end if; 137 | if WEL = '1' then 138 | RegsL(to_integer(unsigned(AddrA))) <= DIL; 139 | end if; 140 | end if; 141 | end if; 142 | end process; 143 | 144 | DOAH <= RegsH(to_integer(unsigned(AddrA))); 145 | DOAL <= RegsL(to_integer(unsigned(AddrA))); 146 | DOBH <= RegsH(to_integer(unsigned(AddrB))); 147 | DOBL <= RegsL(to_integer(unsigned(AddrB))); 148 | DOCH <= RegsH(to_integer(unsigned(AddrC))); 149 | DOCL <= RegsL(to_integer(unsigned(AddrC))); 150 | DOR <= RegsH(7) & RegsL(7) & RegsH(6) & RegsL(6) & RegsH(5) & RegsL(5) & RegsH(4) & RegsL(4) & RegsH(3) & RegsL(3) & RegsH(2) & RegsL(2) & RegsH(1) & RegsL(1) & RegsH(0) & RegsL(0); 151 | 152 | end; 153 | -------------------------------------------------------------------------------- /sys/video_mixer.sv: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2017,2021 Alexey Melnikov 4 | // 5 | // This program is GPL Licensed. See COPYING for the full license. 6 | // 7 | // 8 | //////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | `timescale 1ns / 1ps 11 | 12 | // 13 | // LINE_LENGTH: Length of display line in pixels when HBlank = 0; 14 | // HALF_DEPTH: If =1 then color dept is 4 bits per component 15 | // 16 | // altera message_off 10720 17 | // altera message_off 12161 18 | 19 | module video_mixer 20 | #( 21 | parameter LINE_LENGTH = 768, 22 | parameter HALF_DEPTH = 0, 23 | parameter GAMMA = 0 24 | ) 25 | ( 26 | input CLK_VIDEO, // should be multiple by (ce_pix*4) 27 | output reg CE_PIXEL, // output pixel clock enable 28 | 29 | input ce_pix, // input pixel clock or clock_enable 30 | 31 | input scandoubler, 32 | input hq2x, // high quality 2x scaling 33 | 34 | inout [21:0] gamma_bus, 35 | 36 | // color 37 | input [DWIDTH:0] R, 38 | input [DWIDTH:0] G, 39 | input [DWIDTH:0] B, 40 | 41 | // Positive pulses. 42 | input HSync, 43 | input VSync, 44 | input HBlank, 45 | input VBlank, 46 | 47 | // Freeze engine 48 | // HDMI: displays last frame 49 | // VGA: black screen with HSync and VSync 50 | input HDMI_FREEZE, 51 | output freeze_sync, 52 | 53 | // video output signals 54 | output reg [7:0] VGA_R, 55 | output reg [7:0] VGA_G, 56 | output reg [7:0] VGA_B, 57 | output reg VGA_VS, 58 | output reg VGA_HS, 59 | output reg VGA_DE 60 | ); 61 | 62 | localparam DWIDTH = HALF_DEPTH ? 3 : 7; 63 | localparam DWIDTH_SD = GAMMA ? 7 : DWIDTH; 64 | localparam HALF_DEPTH_SD = GAMMA ? 0 : HALF_DEPTH; 65 | 66 | wire frz_hs, frz_vs; 67 | wire frz_hbl, frz_vbl; 68 | video_freezer freezer 69 | ( 70 | .clk(CLK_VIDEO), 71 | .freeze(HDMI_FREEZE), 72 | .hs_in(HSync), 73 | .vs_in(VSync), 74 | .hbl_in(HBlank), 75 | .vbl_in(VBlank), 76 | .sync(freeze_sync), 77 | .hs_out(frz_hs), 78 | .vs_out(frz_vs), 79 | .hbl_out(frz_hbl), 80 | .vbl_out(frz_vbl) 81 | ); 82 | 83 | reg frz; 84 | always @(posedge CLK_VIDEO) begin 85 | reg frz1; 86 | 87 | frz1 <= HDMI_FREEZE; 88 | frz <= frz1; 89 | end 90 | 91 | generate 92 | if(GAMMA && HALF_DEPTH) begin 93 | wire [7:0] R_in = frz ? 8'd0 : {R,R}; 94 | wire [7:0] G_in = frz ? 8'd0 : {G,G}; 95 | wire [7:0] B_in = frz ? 8'd0 : {B,B}; 96 | end else begin 97 | wire [DWIDTH:0] R_in = frz ? 1'd0 : R; 98 | wire [DWIDTH:0] G_in = frz ? 1'd0 : G; 99 | wire [DWIDTH:0] B_in = frz ? 1'd0 : B; 100 | end 101 | endgenerate 102 | 103 | wire hs_g, vs_g; 104 | wire hb_g, vb_g; 105 | wire [DWIDTH_SD:0] R_gamma, G_gamma, B_gamma; 106 | 107 | generate 108 | if(GAMMA) begin 109 | assign gamma_bus[21] = 1; 110 | gamma_corr gamma( 111 | .clk_sys(gamma_bus[20]), 112 | .clk_vid(CLK_VIDEO), 113 | .ce_pix(ce_pix), 114 | 115 | .gamma_en(gamma_bus[19]), 116 | .gamma_wr(gamma_bus[18]), 117 | .gamma_wr_addr(gamma_bus[17:8]), 118 | .gamma_value(gamma_bus[7:0]), 119 | 120 | .HSync(frz_hs), 121 | .VSync(frz_vs), 122 | .HBlank(frz_hbl), 123 | .VBlank(frz_vbl), 124 | .RGB_in({R_in,G_in,B_in}), 125 | 126 | .HSync_out(hs_g), 127 | .VSync_out(vs_g), 128 | .HBlank_out(hb_g), 129 | .VBlank_out(vb_g), 130 | .RGB_out({R_gamma,G_gamma,B_gamma}) 131 | ); 132 | end else begin 133 | assign gamma_bus[21] = 0; 134 | assign {R_gamma,G_gamma,B_gamma} = {R_in,G_in,B_in}; 135 | assign {hs_g, vs_g, hb_g, vb_g} = {frz_hs, frz_vs, frz_hbl, frz_vbl}; 136 | end 137 | endgenerate 138 | 139 | wire [DWIDTH_SD:0] R_sd; 140 | wire [DWIDTH_SD:0] G_sd; 141 | wire [DWIDTH_SD:0] B_sd; 142 | wire hs_sd, vs_sd, hb_sd, vb_sd, ce_pix_sd; 143 | 144 | scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH_SD)) sd 145 | ( 146 | .clk_vid(CLK_VIDEO), 147 | .hq2x(hq2x), 148 | 149 | .ce_pix(ce_pix), 150 | .hs_in(hs_g), 151 | .vs_in(vs_g), 152 | .hb_in(hb_g), 153 | .vb_in(vb_g), 154 | .r_in(R_gamma), 155 | .g_in(G_gamma), 156 | .b_in(B_gamma), 157 | 158 | .ce_pix_out(ce_pix_sd), 159 | .hs_out(hs_sd), 160 | .vs_out(vs_sd), 161 | .hb_out(hb_sd), 162 | .vb_out(vb_sd), 163 | .r_out(R_sd), 164 | .g_out(G_sd), 165 | .b_out(B_sd) 166 | ); 167 | 168 | wire [DWIDTH_SD:0] rt = (scandoubler ? R_sd : R_gamma); 169 | wire [DWIDTH_SD:0] gt = (scandoubler ? G_sd : G_gamma); 170 | wire [DWIDTH_SD:0] bt = (scandoubler ? B_sd : B_gamma); 171 | 172 | always @(posedge CLK_VIDEO) begin 173 | reg [7:0] r,g,b; 174 | reg hde,vde,hs,vs, old_vs; 175 | reg old_hde; 176 | reg old_ce; 177 | reg ce_osc, fs_osc; 178 | 179 | old_ce <= ce_pix; 180 | ce_osc <= ce_osc | (old_ce ^ ce_pix); 181 | 182 | old_vs <= vs; 183 | if(~old_vs & vs) begin 184 | fs_osc <= ce_osc; 185 | ce_osc <= 0; 186 | end 187 | 188 | CE_PIXEL <= scandoubler ? ce_pix_sd : fs_osc ? (~old_ce & ce_pix) : ce_pix; 189 | 190 | if(!GAMMA && HALF_DEPTH) begin 191 | r <= {rt,rt}; 192 | g <= {gt,gt}; 193 | b <= {bt,bt}; 194 | end 195 | else begin 196 | r <= rt; 197 | g <= gt; 198 | b <= bt; 199 | end 200 | 201 | hde <= scandoubler ? ~hb_sd : ~hb_g; 202 | vde <= scandoubler ? ~vb_sd : ~vb_g; 203 | vs <= scandoubler ? vs_sd : vs_g; 204 | hs <= scandoubler ? hs_sd : hs_g; 205 | 206 | if(CE_PIXEL) begin 207 | VGA_R <= r; 208 | VGA_G <= g; 209 | VGA_B <= b; 210 | 211 | VGA_VS <= vs; 212 | VGA_HS <= hs; 213 | 214 | old_hde <= hde; 215 | if(old_hde ^ hde) VGA_DE <= vde & hde; 216 | end 217 | end 218 | 219 | endmodule 220 | -------------------------------------------------------------------------------- /rtl/z80_debugger.sv: -------------------------------------------------------------------------------- 1 | // 2 | // Z80 Register Debugger 3 | // 4 | // Copyright (c) 2020 Stephen Eddy 5 | // 6 | // All rights reserved 7 | // 8 | // Redistribution and use in source and synthezised forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // 11 | // * Redistributions of source code must retain the above copyright notice, 12 | // this list of conditions and the following disclaimer. 13 | // 14 | // * Redistributions in synthesized form must reproduce the above copyright 15 | // notice, this list of conditions and the following disclaimer in the 16 | // documentation and/or other materials provided with the distribution. 17 | // 18 | // * Neither the name of the author nor the names of other contributors may 19 | // be used to endorse or promote products derived from this software without 20 | // specific prior written agreement from the author. 21 | // 22 | // * License is granted for non-commercial use only. A fee may not be charged 23 | // for redistributions as source code or in synthesized/hardware form without 24 | // specific prior written agreement from the author. 25 | // 26 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 27 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 28 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 30 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | // POSSIBILITY OF SUCH DAMAGE. 37 | 38 | module z80_debugger 39 | ( 40 | input clk_sys, // System clock 41 | input ce, // Chip enable 42 | input m1_n, // M1 Instruction fetch signal 43 | // Signals to / from t80pa core 44 | input wire [211:0] REG_in, // Z80 Register set as defined in T80pa / T80 45 | output logic [15:0] PC, // Program Counter 46 | output logic [15:0] SP, // Stack Pointer 47 | output logic [7:0] AC, // Accumulator 48 | output logic [15:0] BC, // BC Register 49 | output logic [15:0] DE, // DE Register 50 | output logic [15:0] HL, // HL Register 51 | output logic [15:0] IX, // IX Register 52 | output logic [15:0] IY, // IY Register 53 | // Flag enables 54 | output logic Z, // Zero 55 | output logic N, // Negative 56 | output logic P, // Parity / Overflow 57 | output logic C // Carry 58 | ); 59 | 60 | localparam FLAG_CARRY = 0; 61 | localparam FLAG_PARITY = 2; 62 | localparam FLAG_ZERO = 6; 63 | localparam FLAG_SIGN = 7; 64 | 65 | logic [15:0] reg_PC; 66 | logic [15:0] reg_SP; 67 | logic [7:0] reg_AC; 68 | logic [15:0] reg_BC; 69 | logic [15:0] reg_DE; 70 | logic [15:0] reg_HL; 71 | logic [15:0] reg_IX; 72 | logic [15:0] reg_IY; 73 | logic reg_Z; 74 | logic reg_N; 75 | logic reg_P; 76 | logic reg_C; 77 | logic [7:0] reg_flags; 78 | 79 | always @(posedge clk_sys) 80 | begin 81 | if(ce && ~m1_n) 82 | begin 83 | reg_PC <= REG_in[79:64]; 84 | reg_SP <= REG_in[63:48]; 85 | reg_AC <= REG_in[7:0]; 86 | reg_BC <= REG_in[95:80]; 87 | reg_DE <= REG_in[111:96]; 88 | reg_HL <= REG_in[127:112]; 89 | reg_IX <= REG_in[143:128]; 90 | reg_IY <= REG_in[207:192]; 91 | reg_flags <= REG_in[15:8]; 92 | end 93 | end 94 | 95 | assign PC = reg_PC; 96 | assign SP = reg_SP; 97 | assign AC = reg_AC; 98 | assign BC = reg_BC; 99 | assign DE = reg_DE; 100 | assign HL = reg_HL; 101 | assign IX = reg_IX; 102 | assign IY = reg_IY; 103 | 104 | assign Z = reg_flags[FLAG_ZERO]; 105 | assign N = reg_flags[FLAG_SIGN]; 106 | assign P = reg_flags[FLAG_PARITY]; 107 | assign C = reg_flags[FLAG_CARRY]; 108 | 109 | // REG_in bit locations for various flags 110 | // 211-210 - IFF2, IFF1 111 | // 209-208 - IM 112 | // 207-192 - I,Y 113 | // 191-176 - H',L' 114 | // 175-160 - D',E' 115 | // 159-144 - B',C' 116 | // 143-128 - I,X 117 | // 127-112 - H,L 118 | // 111-096 - D,E 119 | // 095-080 - B,C 120 | // 079-064 - PCH, PCL 121 | // 063-048 - SPH, SPL 122 | // 047-040 - R 123 | // 039-032 - I 124 | // 031-024 - Flags' 125 | // 023-016 - ACC' 126 | // 015-008 - Flags 127 | // 007-000 - ACC 128 | 129 | /* wire ADDRESS_JOYSTICK = ( CPU_A[7:4] == 4'b0010 )?1'b1:1'b0; 130 | wire ADDRESS_JOYSTICK_1_A = (ADDRESS_JOYSTICK & (CPU_A[0] == 1'b0))?1'b1:1'b0; 131 | wire [7:0] JOYSTICK_1_DATA_A = { 3'b111, ~fire_1, ~right_1, ~left_1,~down_1,~up_1 }; 132 | wire ADDRESS_JOYSTICK_1_B = (ADDRESS_JOYSTICK & (CPU_A[1] == 1'b0))?1'b1:1'b0; 133 | wire [7:0] JOYSTICK_1_DATA_B = { 3'b111, ~arm_1, 4'b1111}; 134 | wire ADDRESS_JOYSTICK_2_A = (ADDRESS_JOYSTICK & (CPU_A[2] == 1'b0))?1'b1:1'b0; 135 | wire [7:0] JOYSTICK_2_DATA_A = { 3'b111, ~fire_2, ~right_2, ~left_2,~down_2,~up_2 }; 136 | wire ADDRESS_JOYSTICK_2_B = (ADDRESS_JOYSTICK & (CPU_A[3] == 1'b0))?1'b1:1'b0; 137 | wire [7:0] JOYSTICK_2_DATA_B = { 3'b111, ~arm_2, 4'b1111}; 138 | 139 | wire [7:0] CPU_D_INPORT = 140 | (ADDRESS_JOYSTICK_1_A ? JOYSTICK_1_DATA_A : 'b1) & 141 | (ADDRESS_JOYSTICK_1_B ? JOYSTICK_1_DATA_B : 'b1) & 142 | (ADDRESS_JOYSTICK_2_A ? JOYSTICK_2_DATA_A : 'b1) & 143 | (ADDRESS_JOYSTICK_2_B ? JOYSTICK_2_DATA_B : 'b1); */ 144 | 145 | endmodule -------------------------------------------------------------------------------- /sys/audio_out.v: -------------------------------------------------------------------------------- 1 | 2 | module audio_out 3 | #( 4 | parameter CLK_RATE = 24576000 5 | ) 6 | ( 7 | input reset, 8 | input clk, 9 | 10 | //0 - 48KHz, 1 - 96KHz 11 | input sample_rate, 12 | 13 | input [31:0] flt_rate, 14 | input [39:0] cx, 15 | input [7:0] cx0, 16 | input [7:0] cx1, 17 | input [7:0] cx2, 18 | input [23:0] cy0, 19 | input [23:0] cy1, 20 | input [23:0] cy2, 21 | 22 | input [4:0] att, 23 | input [1:0] mix, 24 | 25 | input is_signed, 26 | input [15:0] core_l, 27 | input [15:0] core_r, 28 | 29 | input [15:0] alsa_l, 30 | input [15:0] alsa_r, 31 | 32 | // I2S 33 | output i2s_bclk, 34 | output i2s_lrclk, 35 | output i2s_data, 36 | 37 | // SPDIF 38 | output spdif, 39 | 40 | // Sigma-Delta DAC 41 | output dac_l, 42 | output dac_r 43 | ); 44 | 45 | localparam AUDIO_RATE = 48000; 46 | localparam AUDIO_DW = 16; 47 | 48 | localparam CE_RATE = AUDIO_RATE*AUDIO_DW*8; 49 | localparam FILTER_DIV = (CE_RATE/(AUDIO_RATE*32))-1; 50 | 51 | wire [31:0] real_ce = sample_rate ? {CE_RATE[30:0],1'b0} : CE_RATE[31:0]; 52 | 53 | reg mclk_ce; 54 | always @(posedge clk) begin 55 | reg [31:0] cnt; 56 | 57 | mclk_ce = 0; 58 | cnt = cnt + real_ce; 59 | if(cnt >= CLK_RATE) begin 60 | cnt = cnt - CLK_RATE; 61 | mclk_ce = 1; 62 | end 63 | end 64 | 65 | reg i2s_ce; 66 | always @(posedge clk) begin 67 | reg div; 68 | i2s_ce <= 0; 69 | if(mclk_ce) begin 70 | div <= ~div; 71 | i2s_ce <= div; 72 | end 73 | end 74 | 75 | i2s i2s 76 | ( 77 | .reset(reset), 78 | 79 | .clk(clk), 80 | .ce(i2s_ce), 81 | 82 | .sclk(i2s_bclk), 83 | .lrclk(i2s_lrclk), 84 | .sdata(i2s_data), 85 | 86 | .left_chan(al), 87 | .right_chan(ar) 88 | ); 89 | 90 | spdif toslink 91 | ( 92 | .rst_i(reset), 93 | 94 | .clk_i(clk), 95 | .bit_out_en_i(mclk_ce), 96 | 97 | .sample_i({ar,al}), 98 | .spdif_o(spdif) 99 | ); 100 | 101 | sigma_delta_dac #(15) sd_l 102 | ( 103 | .CLK(clk), 104 | .RESET(reset), 105 | .DACin({~al[15], al[14:0]}), 106 | .DACout(dac_l) 107 | ); 108 | 109 | sigma_delta_dac #(15) sd_r 110 | ( 111 | .CLK(clk), 112 | .RESET(reset), 113 | .DACin({~ar[15], ar[14:0]}), 114 | .DACout(dac_r) 115 | ); 116 | 117 | reg sample_ce; 118 | always @(posedge clk) begin 119 | reg [8:0] div = 0; 120 | reg [1:0] add = 0; 121 | 122 | div <= div + add; 123 | if(!div) begin 124 | div <= 2'd1 << sample_rate; 125 | add <= 2'd1 << sample_rate; 126 | end 127 | 128 | sample_ce <= !div; 129 | end 130 | 131 | reg flt_ce; 132 | always @(posedge clk) begin 133 | reg [31:0] cnt = 0; 134 | 135 | flt_ce = 0; 136 | cnt = cnt + {flt_rate[30:0],1'b0}; 137 | if(cnt >= CLK_RATE) begin 138 | cnt = cnt - CLK_RATE; 139 | flt_ce = 1; 140 | end 141 | end 142 | 143 | reg [15:0] cl,cr; 144 | always @(posedge clk) begin 145 | reg [15:0] cl1,cl2; 146 | reg [15:0] cr1,cr2; 147 | 148 | cl1 <= core_l; cl2 <= cl1; 149 | if(cl2 == cl1) cl <= cl2; 150 | 151 | cr1 <= core_r; cr2 <= cr1; 152 | if(cr2 == cr1) cr <= cr2; 153 | end 154 | 155 | reg a_en1 = 0, a_en2 = 0; 156 | always @(posedge clk, posedge reset) begin 157 | reg [1:0] dly1 = 0; 158 | reg [14:0] dly2 = 0; 159 | 160 | if(reset) begin 161 | dly1 <= 0; 162 | dly2 <= 0; 163 | a_en1 <= 0; 164 | a_en2 <= 0; 165 | end 166 | else begin 167 | if(flt_ce) begin 168 | if(~&dly1) dly1 <= dly1 + 1'd1; 169 | else a_en1 <= 1; 170 | end 171 | 172 | if(sample_ce) begin 173 | if(!dly2[13+sample_rate]) dly2 <= dly2 + 1'd1; 174 | else a_en2 <= 1; 175 | end 176 | end 177 | end 178 | 179 | wire [15:0] acl, acr; 180 | IIR_filter #(.use_params(0)) IIR_filter 181 | ( 182 | .clk(clk), 183 | .reset(reset), 184 | 185 | .ce(flt_ce & a_en1), 186 | .sample_ce(sample_ce), 187 | 188 | .cx(cx), 189 | .cx0(cx0), 190 | .cx1(cx1), 191 | .cx2(cx2), 192 | .cy0(cy0), 193 | .cy1(cy1), 194 | .cy2(cy2), 195 | 196 | .input_l({~is_signed ^ cl[15], cl[14:0]}), 197 | .input_r({~is_signed ^ cr[15], cr[14:0]}), 198 | .output_l(acl), 199 | .output_r(acr) 200 | ); 201 | 202 | wire [15:0] adl; 203 | DC_blocker dcb_l 204 | ( 205 | .clk(clk), 206 | .ce(sample_ce), 207 | .sample_rate(sample_rate), 208 | .mute(~a_en2), 209 | .din(acl), 210 | .dout(adl) 211 | ); 212 | 213 | wire [15:0] adr; 214 | DC_blocker dcb_r 215 | ( 216 | .clk(clk), 217 | .ce(sample_ce), 218 | .sample_rate(sample_rate), 219 | .mute(~a_en2), 220 | .din(acr), 221 | .dout(adr) 222 | ); 223 | 224 | wire [15:0] al, audio_l_pre; 225 | aud_mix_top audmix_l 226 | ( 227 | .clk(clk), 228 | .ce(sample_ce), 229 | .att(att), 230 | .mix(mix), 231 | 232 | .core_audio(adl), 233 | .pre_in(audio_r_pre), 234 | .linux_audio(alsa_l), 235 | 236 | .pre_out(audio_l_pre), 237 | .out(al) 238 | ); 239 | 240 | wire [15:0] ar, audio_r_pre; 241 | aud_mix_top audmix_r 242 | ( 243 | .clk(clk), 244 | .ce(sample_ce), 245 | .att(att), 246 | .mix(mix), 247 | 248 | .core_audio(adr), 249 | .pre_in(audio_l_pre), 250 | .linux_audio(alsa_r), 251 | 252 | .pre_out(audio_r_pre), 253 | .out(ar) 254 | ); 255 | 256 | endmodule 257 | 258 | module aud_mix_top 259 | ( 260 | input clk, 261 | input ce, 262 | 263 | input [4:0] att, 264 | input [1:0] mix, 265 | 266 | input [15:0] core_audio, 267 | input [15:0] linux_audio, 268 | input [15:0] pre_in, 269 | 270 | output reg [15:0] pre_out = 0, 271 | output reg [15:0] out = 0 272 | ); 273 | 274 | reg signed [16:0] a1, a2, a3, a4; 275 | always @(posedge clk) if (ce) begin 276 | 277 | a1 <= {core_audio[15],core_audio}; 278 | a2 <= a1 + {linux_audio[15],linux_audio}; 279 | 280 | pre_out <= a2[16:1]; 281 | 282 | case(mix) 283 | 0: a3 <= a2; 284 | 1: a3 <= $signed(a2) - $signed(a2[16:3]) + $signed(pre_in[15:2]); 285 | 2: a3 <= $signed(a2) - $signed(a2[16:2]) + $signed(pre_in[15:1]); 286 | 3: a3 <= {a2[16],a2[16:1]} + {pre_in[15],pre_in}; 287 | endcase 288 | 289 | if(att[4]) a4 <= 0; 290 | else a4 <= a3 >>> att[3:0]; 291 | 292 | //clamping 293 | out <= ^a4[16:15] ? {a4[16],{15{a4[15]}}} : a4[15:0]; 294 | end 295 | 296 | endmodule 297 | -------------------------------------------------------------------------------- /rtl/T80/T80sed.vhd: -------------------------------------------------------------------------------- 1 | -- **** 2 | -- T80(b) core. In an effort to merge and maintain bug fixes .... 3 | -- 4 | -- 5 | -- Ver 300 started tidyup 6 | -- MikeJ March 2005 7 | -- Latest version from www.fpgaarcade.com (original www.opencores.org) 8 | -- 9 | -- **** 10 | -- ** CUSTOM 2 CLOCK MEMORY ACCESS FOR PACMAN, MIKEJ ** 11 | -- 12 | -- Z80 compatible microprocessor core, synchronous top level with clock enable 13 | -- Different timing than the original z80 14 | -- Inputs needs to be synchronous and outputs may glitch 15 | -- 16 | -- Version : 0238 17 | -- 18 | -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) 19 | -- 20 | -- All rights reserved 21 | -- 22 | -- Redistribution and use in source and synthezised forms, with or without 23 | -- modification, are permitted provided that the following conditions are met: 24 | -- 25 | -- Redistributions of source code must retain the above copyright notice, 26 | -- this list of conditions and the following disclaimer. 27 | -- 28 | -- Redistributions in synthesized form must reproduce the above copyright 29 | -- notice, this list of conditions and the following disclaimer in the 30 | -- documentation and/or other materials provided with the distribution. 31 | -- 32 | -- Neither the name of the author nor the names of other contributors may 33 | -- be used to endorse or promote products derived from this software without 34 | -- specific prior written permission. 35 | -- 36 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 37 | -- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 38 | -- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39 | -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 40 | -- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 41 | -- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 42 | -- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 43 | -- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 44 | -- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 45 | -- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 46 | -- POSSIBILITY OF SUCH DAMAGE. 47 | -- 48 | -- Please report bugs to the author, but before you do so, please 49 | -- make sure that this is not a derivative work and that 50 | -- you have the latest version of this file. 51 | -- 52 | -- The latest version of this file can be found at: 53 | -- http://www.opencores.org/cvsweb.shtml/t80/ 54 | -- 55 | -- Limitations : 56 | -- 57 | -- File history : 58 | -- 59 | -- 0235 : First release 60 | -- 61 | -- 0236 : Added T2Write generic 62 | -- 63 | -- 0237 : Fixed T2Write with wait state 64 | -- 65 | -- 0238 : Updated for T80 interface change 66 | -- 67 | -- 0242 : Updated for T80 interface change 68 | -- 69 | 70 | library IEEE; 71 | use IEEE.std_logic_1164.all; 72 | use IEEE.numeric_std.all; 73 | use work.T80_Pack.all; 74 | 75 | entity T80sed is 76 | port( 77 | RESET_n : in std_logic; 78 | CLK_n : in std_logic; 79 | CLKEN : in std_logic; 80 | WAIT_n : in std_logic; 81 | INT_n : in std_logic; 82 | NMI_n : in std_logic; 83 | BUSRQ_n : in std_logic; 84 | M1_n : out std_logic; 85 | MREQ_n : out std_logic; 86 | IORQ_n : out std_logic; 87 | RD_n : out std_logic; 88 | WR_n : out std_logic; 89 | RFSH_n : out std_logic; 90 | HALT_n : out std_logic; 91 | BUSAK_n : out std_logic; 92 | A : out std_logic_vector(15 downto 0); 93 | DI : in std_logic_vector(7 downto 0); 94 | DO : out std_logic_vector(7 downto 0) 95 | ); 96 | end T80sed; 97 | 98 | architecture rtl of T80sed is 99 | 100 | signal IntCycle_n : std_logic; 101 | signal NoRead : std_logic; 102 | signal Write : std_logic; 103 | signal IORQ : std_logic; 104 | signal DI_Reg : std_logic_vector(7 downto 0); 105 | signal MCycle : std_logic_vector(2 downto 0); 106 | signal TState : std_logic_vector(2 downto 0); 107 | 108 | begin 109 | 110 | u0 : T80 111 | generic map( 112 | Mode => 0, 113 | IOWait => 1) 114 | port map( 115 | CEN => CLKEN, 116 | M1_n => M1_n, 117 | IORQ => IORQ, 118 | NoRead => NoRead, 119 | Write => Write, 120 | RFSH_n => RFSH_n, 121 | HALT_n => HALT_n, 122 | WAIT_n => Wait_n, 123 | INT_n => INT_n, 124 | NMI_n => NMI_n, 125 | RESET_n => RESET_n, 126 | BUSRQ_n => BUSRQ_n, 127 | BUSAK_n => BUSAK_n, 128 | CLK_n => CLK_n, 129 | A => A, 130 | DInst => DI, 131 | DI => DI_Reg, 132 | DO => DO, 133 | MC => MCycle, 134 | TS => TState, 135 | IntCycle_n => IntCycle_n); 136 | 137 | process (RESET_n, CLK_n) 138 | begin 139 | if RESET_n = '0' then 140 | RD_n <= '1'; 141 | WR_n <= '1'; 142 | IORQ_n <= '1'; 143 | MREQ_n <= '1'; 144 | DI_Reg <= "00000000"; 145 | elsif CLK_n'event and CLK_n = '1' then 146 | if CLKEN = '1' then 147 | RD_n <= '1'; 148 | WR_n <= '1'; 149 | IORQ_n <= '1'; 150 | MREQ_n <= '1'; 151 | if MCycle = "001" then 152 | if TState = "001" or (TState = "010" and Wait_n = '0') then 153 | RD_n <= not IntCycle_n; 154 | MREQ_n <= not IntCycle_n; 155 | IORQ_n <= IntCycle_n; 156 | end if; 157 | if TState = "011" then 158 | MREQ_n <= '0'; 159 | end if; 160 | else 161 | if (TState = "001" or TState = "010") and NoRead = '0' and Write = '0' then 162 | RD_n <= '0'; 163 | IORQ_n <= not IORQ; 164 | MREQ_n <= IORQ; 165 | end if; 166 | if ((TState = "001") or (TState = "010")) and Write = '1' then 167 | WR_n <= '0'; 168 | IORQ_n <= not IORQ; 169 | MREQ_n <= IORQ; 170 | end if; 171 | end if; 172 | if TState = "010" and Wait_n = '1' then 173 | DI_Reg <= DI; 174 | end if; 175 | end if; 176 | end if; 177 | end process; 178 | 179 | end; 180 | -------------------------------------------------------------------------------- /rtl/T80/T80s.vhd: -------------------------------------------------------------------------------- 1 | -- 2 | -- Z80 compatible microprocessor core, synchronous top level 3 | -- Different timing than the original z80 4 | -- Inputs needs to be synchronous and outputs may glitch 5 | -- 6 | -- Version : 0242 7 | -- 8 | -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) 9 | -- 10 | -- All rights reserved 11 | -- 12 | -- Redistribution and use in source and synthezised forms, with or without 13 | -- modification, are permitted provided that the following conditions are met: 14 | -- 15 | -- Redistributions of source code must retain the above copyright notice, 16 | -- this list of conditions and the following disclaimer. 17 | -- 18 | -- Redistributions in synthesized form must reproduce the above copyright 19 | -- notice, this list of conditions and the following disclaimer in the 20 | -- documentation and/or other materials provided with the distribution. 21 | -- 22 | -- Neither the name of the author nor the names of other contributors may 23 | -- be used to endorse or promote products derived from this software without 24 | -- specific prior written permission. 25 | -- 26 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 27 | -- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 28 | -- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 | -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 30 | -- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | -- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 | -- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | -- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | -- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | -- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | -- POSSIBILITY OF SUCH DAMAGE. 37 | -- 38 | -- Please report bugs to the author, but before you do so, please 39 | -- make sure that this is not a derivative work and that 40 | -- you have the latest version of this file. 41 | -- 42 | -- The latest version of this file can be found at: 43 | -- http://www.opencores.org/cvsweb.shtml/t80/ 44 | -- 45 | -- Limitations : 46 | -- 47 | -- File history : 48 | -- 49 | -- 0208 : First complete release 50 | -- 51 | -- 0210 : Fixed read with wait 52 | -- 53 | -- 0211 : Fixed interrupt cycle 54 | -- 55 | -- 0235 : Updated for T80 interface change 56 | -- 57 | -- 0236 : Added T2Write generic 58 | -- 59 | -- 0237 : Fixed T2Write with wait state 60 | -- 61 | -- 0238 : Updated for T80 interface change 62 | -- 63 | -- 0240 : Updated for T80 interface change 64 | -- 65 | -- 0242 : Updated for T80 interface change 66 | -- 67 | 68 | library IEEE; 69 | use IEEE.std_logic_1164.all; 70 | use IEEE.numeric_std.all; 71 | use IEEE.STD_LOGIC_UNSIGNED.all; 72 | use work.T80_Pack.all; 73 | 74 | entity T80s is 75 | generic( 76 | Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB 77 | T2Write : integer := 1; -- 0 => WR_n active in T3, /=0 => WR_n active in T2 78 | IOWait : integer := 1 -- 0 => Single cycle I/O, 1 => Std I/O cycle 79 | ); 80 | port( 81 | RESET_n : in std_logic; 82 | CLK : in std_logic; 83 | CEN : in std_logic := '1'; 84 | WAIT_n : in std_logic := '1'; 85 | INT_n : in std_logic := '1'; 86 | NMI_n : in std_logic := '1'; 87 | BUSRQ_n : in std_logic := '1'; 88 | M1_n : out std_logic; 89 | MREQ_n : out std_logic; 90 | IORQ_n : out std_logic; 91 | RD_n : out std_logic; 92 | WR_n : out std_logic; 93 | RFSH_n : out std_logic; 94 | HALT_n : out std_logic; 95 | BUSAK_n : out std_logic; 96 | OUT0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255 97 | A : out std_logic_vector(15 downto 0); 98 | DI : in std_logic_vector(7 downto 0); 99 | DO : out std_logic_vector(7 downto 0) 100 | ); 101 | end T80s; 102 | 103 | architecture rtl of T80s is 104 | 105 | signal IntCycle_n : std_logic; 106 | signal NoRead : std_logic; 107 | signal Write : std_logic; 108 | signal IORQ : std_logic; 109 | signal DI_Reg : std_logic_vector(7 downto 0); 110 | signal MCycle : std_logic_vector(2 downto 0); 111 | signal TState : std_logic_vector(2 downto 0); 112 | 113 | begin 114 | 115 | u0 : T80 116 | generic map( 117 | Mode => Mode, 118 | IOWait => IOWait) 119 | port map( 120 | CEN => CEN, 121 | M1_n => M1_n, 122 | IORQ => IORQ, 123 | NoRead => NoRead, 124 | Write => Write, 125 | RFSH_n => RFSH_n, 126 | HALT_n => HALT_n, 127 | WAIT_n => Wait_n, 128 | INT_n => INT_n, 129 | NMI_n => NMI_n, 130 | RESET_n => RESET_n, 131 | BUSRQ_n => BUSRQ_n, 132 | BUSAK_n => BUSAK_n, 133 | CLK_n => CLK, 134 | A => A, 135 | DInst => DI, 136 | DI => DI_Reg, 137 | DO => DO, 138 | MC => MCycle, 139 | TS => TState, 140 | OUT0 => OUT0, 141 | IntCycle_n => IntCycle_n 142 | ); 143 | 144 | process (RESET_n, CLK) 145 | begin 146 | if RESET_n = '0' then 147 | RD_n <= '1'; 148 | WR_n <= '1'; 149 | IORQ_n <= '1'; 150 | MREQ_n <= '1'; 151 | DI_Reg <= "00000000"; 152 | elsif rising_edge(CLK) then 153 | if CEN = '1' then 154 | RD_n <= '1'; 155 | WR_n <= '1'; 156 | IORQ_n <= '1'; 157 | MREQ_n <= '1'; 158 | if MCycle = 1 then 159 | if TState = 1 or (TState = 2 and Wait_n = '0') then 160 | RD_n <= not IntCycle_n; 161 | MREQ_n <= not IntCycle_n; 162 | IORQ_n <= IntCycle_n; 163 | end if; 164 | if TState = 3 then 165 | MREQ_n <= '0'; 166 | end if; 167 | else 168 | if (TState = 1 or (TState = 2 and Wait_n = '0')) and NoRead = '0' and Write = '0' then 169 | RD_n <= '0'; 170 | IORQ_n <= not IORQ; 171 | MREQ_n <= IORQ; 172 | end if; 173 | if T2Write = 0 then 174 | if TState = 2 and Write = '1' then 175 | WR_n <= '0'; 176 | IORQ_n <= not IORQ; 177 | MREQ_n <= IORQ; 178 | end if; 179 | else 180 | if (TState = 1 or (TState = 2 and Wait_n = '0')) and Write = '1' then 181 | WR_n <= '0'; 182 | IORQ_n <= not IORQ; 183 | MREQ_n <= IORQ; 184 | end if; 185 | end if; 186 | end if; 187 | if TState = 2 and Wait_n = '1' then 188 | DI_Reg <= DI; 189 | end if; 190 | end if; 191 | end if; 192 | end process; 193 | end; 194 | -------------------------------------------------------------------------------- /rtl/T80/T80se.vhd: -------------------------------------------------------------------------------- 1 | -- **** 2 | -- T80(b) core. In an effort to merge and maintain bug fixes .... 3 | -- 4 | -- 5 | -- Ver 300 started tidyup 6 | -- MikeJ March 2005 7 | -- Latest version from www.fpgaarcade.com (original www.opencores.org) 8 | -- 9 | -- **** 10 | -- 11 | -- Z80 compatible microprocessor core, synchronous top level with clock enable 12 | -- Different timing than the original z80 13 | -- Inputs needs to be synchronous and outputs may glitch 14 | -- 15 | -- Version : 0240 16 | -- 17 | -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) 18 | -- 19 | -- All rights reserved 20 | -- 21 | -- Redistribution and use in source and synthezised forms, with or without 22 | -- modification, are permitted provided that the following conditions are met: 23 | -- 24 | -- Redistributions of source code must retain the above copyright notice, 25 | -- this list of conditions and the following disclaimer. 26 | -- 27 | -- Redistributions in synthesized form must reproduce the above copyright 28 | -- notice, this list of conditions and the following disclaimer in the 29 | -- documentation and/or other materials provided with the distribution. 30 | -- 31 | -- Neither the name of the author nor the names of other contributors may 32 | -- be used to endorse or promote products derived from this software without 33 | -- specific prior written permission. 34 | -- 35 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 36 | -- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 37 | -- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38 | -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 39 | -- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 40 | -- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 41 | -- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 42 | -- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 43 | -- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 44 | -- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 45 | -- POSSIBILITY OF SUCH DAMAGE. 46 | -- 47 | -- Please report bugs to the author, but before you do so, please 48 | -- make sure that this is not a derivative work and that 49 | -- you have the latest version of this file. 50 | -- 51 | -- The latest version of this file can be found at: 52 | -- http://www.opencores.org/cvsweb.shtml/t80/ 53 | -- 54 | -- Limitations : 55 | -- 56 | -- File history : 57 | -- 58 | -- 0235 : First release 59 | -- 60 | -- 0236 : Added T2Write generic 61 | -- 62 | -- 0237 : Fixed T2Write with wait state 63 | -- 64 | -- 0238 : Updated for T80 interface change 65 | -- 66 | -- 0240 : Updated for T80 interface change 67 | -- 68 | -- 0242 : Updated for T80 interface change 69 | -- 70 | library IEEE; 71 | use IEEE.std_logic_1164.all; 72 | use IEEE.numeric_std.all; 73 | use work.T80_Pack.all; 74 | 75 | entity T80se is 76 | generic( 77 | Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB 78 | T2Write : integer := 0; -- 0 => WR_n active in T3, /=0 => WR_n active in T2 79 | IOWait : integer := 1 -- 0 => Single cycle I/O, 1 => Std I/O cycle 80 | ); 81 | port( 82 | RESET_n : in std_logic; 83 | CLK_n : in std_logic; 84 | CLKEN : in std_logic; 85 | WAIT_n : in std_logic; 86 | INT_n : in std_logic; 87 | NMI_n : in std_logic; 88 | BUSRQ_n : in std_logic; 89 | M1_n : out std_logic; 90 | MREQ_n : out std_logic; 91 | IORQ_n : out std_logic; 92 | RD_n : out std_logic; 93 | WR_n : out std_logic; 94 | RFSH_n : out std_logic; 95 | HALT_n : out std_logic; 96 | BUSAK_n : out std_logic; 97 | A : out std_logic_vector(15 downto 0); 98 | DI : in std_logic_vector(7 downto 0); 99 | DO : out std_logic_vector(7 downto 0) 100 | ); 101 | end T80se; 102 | 103 | architecture rtl of T80se is 104 | 105 | signal IntCycle_n : std_logic; 106 | signal NoRead : std_logic; 107 | signal Write : std_logic; 108 | signal IORQ : std_logic; 109 | signal DI_Reg : std_logic_vector(7 downto 0); 110 | signal MCycle : std_logic_vector(2 downto 0); 111 | signal TState : std_logic_vector(2 downto 0); 112 | 113 | begin 114 | 115 | u0 : T80 116 | generic map( 117 | Mode => Mode, 118 | IOWait => IOWait) 119 | port map( 120 | CEN => CLKEN, 121 | M1_n => M1_n, 122 | IORQ => IORQ, 123 | NoRead => NoRead, 124 | Write => Write, 125 | RFSH_n => RFSH_n, 126 | HALT_n => HALT_n, 127 | WAIT_n => Wait_n, 128 | INT_n => INT_n, 129 | NMI_n => NMI_n, 130 | RESET_n => RESET_n, 131 | BUSRQ_n => BUSRQ_n, 132 | BUSAK_n => BUSAK_n, 133 | CLK_n => CLK_n, 134 | A => A, 135 | DInst => DI, 136 | DI => DI_Reg, 137 | DO => DO, 138 | MC => MCycle, 139 | TS => TState, 140 | IntCycle_n => IntCycle_n); 141 | 142 | process (RESET_n, CLK_n) 143 | begin 144 | if RESET_n = '0' then 145 | RD_n <= '1'; 146 | WR_n <= '1'; 147 | IORQ_n <= '1'; 148 | MREQ_n <= '1'; 149 | DI_Reg <= "00000000"; 150 | elsif CLK_n'event and CLK_n = '1' then 151 | if CLKEN = '1' then 152 | RD_n <= '1'; 153 | WR_n <= '1'; 154 | IORQ_n <= '1'; 155 | MREQ_n <= '1'; 156 | if MCycle = "001" then 157 | if TState = "001" or (TState = "010" and Wait_n = '0') then 158 | RD_n <= not IntCycle_n; 159 | MREQ_n <= not IntCycle_n; 160 | IORQ_n <= IntCycle_n; 161 | end if; 162 | if TState = "011" then 163 | MREQ_n <= '0'; 164 | end if; 165 | else 166 | if (TState = "001" or (TState = "010" and Wait_n = '0')) and NoRead = '0' and Write = '0' then 167 | RD_n <= '0'; 168 | IORQ_n <= not IORQ; 169 | MREQ_n <= IORQ; 170 | end if; 171 | if T2Write = 0 then 172 | if TState = "010" and Write = '1' then 173 | WR_n <= '0'; 174 | IORQ_n <= not IORQ; 175 | MREQ_n <= IORQ; 176 | end if; 177 | else 178 | if (TState = "001" or (TState = "010" and Wait_n = '0')) and Write = '1' then 179 | WR_n <= '0'; 180 | IORQ_n <= not IORQ; 181 | MREQ_n <= IORQ; 182 | end if; 183 | end if; 184 | end if; 185 | if TState = "010" and Wait_n = '1' then 186 | DI_Reg <= DI; 187 | end if; 188 | end if; 189 | end if; 190 | end process; 191 | 192 | end; 193 | -------------------------------------------------------------------------------- /sys/iir_filter.v: -------------------------------------------------------------------------------- 1 | 2 | // 3-tap IIR filter for 2 channels. 3 | // Copyright (C) 2020 Sorgelig 4 | // 5 | // This program is free software; you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by the Free 7 | // Software Foundation; either version 2 of the License, or (at your option) 8 | // any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, but WITHOUT 11 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 | // more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 | 19 | // 20 | // Can be converted to 2-tap (coeff_x2 = 0, coeff_y2 = 0) or 1-tap (coeff_x1,2 = 0, coeff_y1,2 = 0) 21 | // 22 | module IIR_filter 23 | #( 24 | parameter use_params = 1, // set to 1 to use following parameters, 0 for input port variables. 25 | parameter stereo = 1, // 0 for mono (input_l) 26 | 27 | parameter coeff_x = 0.00000774701983513660, // Base gain value for X. Float. Range: 0.0 ... 0.999(9) 28 | parameter coeff_x0 = 3, // Gain scale factor for X0. Integer. Range -7 ... +7 29 | parameter coeff_x1 = 3, // Gain scale factor for X1. Integer. Range -7 ... +7 30 | parameter coeff_x2 = 1, // Gain scale factor for X2. Integer. Range -7 ... +7 31 | parameter coeff_y0 = -2.96438150626551080000, // Coefficient for Y0. Float. Range -3.999(9) ... 3.999(9) 32 | parameter coeff_y1 = 2.92939452735121100000, // Coefficient for Y1. Float. Range -3.999(9) ... 3.999(9) 33 | parameter coeff_y2 = -0.96500747158831091000 // Coefficient for Y2. Float. Range -3.999(9) ... 3.999(9) 34 | ) 35 | ( 36 | input clk, 37 | input reset, 38 | 39 | input ce, // must be double of calculated rate for stereo! 40 | input sample_ce, // desired output sample rate 41 | 42 | input [39:0] cx, 43 | input [7:0] cx0, 44 | input [7:0] cx1, 45 | input [7:0] cx2, 46 | input [23:0] cy0, 47 | input [23:0] cy1, 48 | input [23:0] cy2, 49 | 50 | input [15:0] input_l, input_r, // signed samples 51 | output [15:0] output_l, output_r // signed samples 52 | ); 53 | 54 | localparam [39:0] pcoeff_x = coeff_x * 40'h8000000000; 55 | localparam [31:0] pcoeff_y0 = coeff_y0 * 24'h200000; 56 | localparam [31:0] pcoeff_y1 = coeff_y1 * 24'h200000; 57 | localparam [31:0] pcoeff_y2 = coeff_y2 * 24'h200000; 58 | 59 | wire [39:0] vcoeff = use_params ? pcoeff_x : cx; 60 | wire [23:0] vcoeff_y0 = use_params ? pcoeff_y0[23:0] : cy0; 61 | wire [23:0] vcoeff_y1 = use_params ? pcoeff_y1[23:0] : cy1; 62 | wire [23:0] vcoeff_y2 = use_params ? pcoeff_y2[23:0] : cy2; 63 | 64 | wire [59:0] inp_mul = $signed(inp) * $signed(vcoeff); 65 | 66 | wire [39:0] x = inp_mul[59:20]; 67 | wire [39:0] y = x + tap0; 68 | 69 | wire [39:0] tap0; 70 | iir_filter_tap iir_tap_0 71 | ( 72 | .clk(clk), 73 | .reset(reset), 74 | .ce(ce), 75 | .ch(ch), 76 | .cx(use_params ? coeff_x0[7:0] : cx0), 77 | .cy(vcoeff_y0), 78 | .x(x), 79 | .y(y), 80 | .z(tap1), 81 | .tap(tap0) 82 | ); 83 | 84 | wire [39:0] tap1; 85 | iir_filter_tap iir_tap_1 86 | ( 87 | .clk(clk), 88 | .reset(reset), 89 | .ce(ce), 90 | .ch(ch), 91 | .cx(use_params ? coeff_x1[7:0] : cx1), 92 | .cy(vcoeff_y1), 93 | .x(x), 94 | .y(y), 95 | .z(tap2), 96 | .tap(tap1) 97 | ); 98 | 99 | wire [39:0] tap2; 100 | iir_filter_tap iir_tap_2 101 | ( 102 | .clk(clk), 103 | .reset(reset), 104 | .ce(ce), 105 | .ch(ch), 106 | .cx(use_params ? coeff_x2[7:0] : cx2), 107 | .cy(vcoeff_y2), 108 | .x(x), 109 | .y(y), 110 | .z(0), 111 | .tap(tap2) 112 | ); 113 | 114 | wire [15:0] y_clamp = (~y[39] & |y[38:35]) ? 16'h7FFF : (y[39] & ~&y[38:35]) ? 16'h8000 : y[35:20]; 115 | 116 | reg ch = 0; 117 | reg [15:0] out_l, out_r, out_m; 118 | reg [15:0] inp, inp_m; 119 | always @(posedge clk) if (ce) begin 120 | if(!stereo) begin 121 | ch <= 0; 122 | inp <= input_l; 123 | out_l <= y_clamp; 124 | out_r <= y_clamp; 125 | end 126 | else begin 127 | ch <= ~ch; 128 | if(ch) begin 129 | out_m <= y_clamp; 130 | inp <= inp_m; 131 | end 132 | else begin 133 | out_l <= out_m; 134 | out_r <= y_clamp; 135 | inp <= input_l; 136 | inp_m <= input_r; 137 | end 138 | end 139 | end 140 | 141 | reg [31:0] out; 142 | always @(posedge clk) if (sample_ce) out <= {out_l, out_r}; 143 | 144 | assign {output_l, output_r} = out; 145 | 146 | endmodule 147 | 148 | module iir_filter_tap 149 | ( 150 | input clk, 151 | input reset, 152 | 153 | input ce, 154 | input ch, 155 | 156 | input [7:0] cx, 157 | input [23:0] cy, 158 | 159 | input [39:0] x, 160 | input [39:0] y, 161 | input [39:0] z, 162 | output [39:0] tap 163 | ); 164 | 165 | wire signed [60:0] y_mul = $signed(y[36:0]) * $signed(cy); 166 | 167 | function [39:0] x_mul; 168 | input [39:0] x; 169 | begin 170 | x_mul = 0; 171 | if(cx[0]) x_mul = x_mul + {{4{x[39]}}, x[39:4]}; 172 | if(cx[1]) x_mul = x_mul + {{3{x[39]}}, x[39:3]}; 173 | if(cx[2]) x_mul = x_mul + {{2{x[39]}}, x[39:2]}; 174 | if(cx[7]) x_mul = ~x_mul; //cheap NEG 175 | end 176 | endfunction 177 | 178 | (* ramstyle = "logic" *) reg [39:0] intreg[2]; 179 | always @(posedge clk, posedge reset) begin 180 | if(reset) {intreg[0],intreg[1]} <= 80'd0; 181 | else if(ce) intreg[ch] <= x_mul(x) - y_mul[60:21] + z; 182 | end 183 | 184 | assign tap = intreg[ch]; 185 | 186 | endmodule 187 | 188 | // simplified IIR 1-tap. 189 | module DC_blocker 190 | ( 191 | input clk, 192 | input ce, // 48/96 KHz 193 | input mute, 194 | 195 | input sample_rate, 196 | input [15:0] din, 197 | output [15:0] dout 198 | ); 199 | 200 | wire [39:0] x = {din[15], din, 23'd0}; 201 | wire [39:0] x0 = x - (sample_rate ? {{11{x[39]}}, x[39:11]} : {{10{x[39]}}, x[39:10]}); 202 | wire [39:0] y1 = y - (sample_rate ? {{10{y[39]}}, y[39:10]} : {{09{y[39]}}, y[39:09]}); 203 | wire [39:0] y0 = x0 - x1 + y1; 204 | 205 | reg [39:0] x1, y; 206 | always @(posedge clk) if(ce) begin 207 | x1 <= x0; 208 | y <= ^y0[39:38] ? {{2{y0[39]}},{38{y0[38]}}} : y0; 209 | end 210 | 211 | assign dout = mute ? 16'd0 : y[38:23]; 212 | 213 | endmodule 214 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Amstrad PCW MiSTer Core 2 | Gnome Ranger 3 | 4 | Gnome Ranger running on the Amstrad PCW core by [steddyman](https://twitter.com/steddyman) 5 | ## Overview 6 | The Amstrad PCW was a line of computers released by Amstrad UK in the mid 1980's to provide a cheaper alternative to owning an IBM PC for word processing and simple office type applications. It was supplied with a detachable keyboard, printer, a disk drive and a high resolution monitor. This monitor allowed the PCW to display sharp monochrome graphics at a resolution of 720 x 256. 7 | 8 | Despite the intended market being business applications and home office users, the computer sold over 8 million units and quite a number of games were also developed for the machine as well as third party addons such as sound cards, joystick adapters and mice. The Amstrad PCW was also sold as the Schneider Joyce in Europe. 9 | 10 | The PCW came with 256k or 512k and was expandable upto 2MB of memory. The high resolution display and large amount of memory for the time, makes the PCW the perfect CP/M machine and an ideal system for playing early text and graphic adventures. 11 | 12 | ## Features 13 | * Amstrad PCW with Z80 CPU operating at 4Mhz 14 | * Turbo support to 8Mhz (2x), 16 Mhz(4x) or 32 Mhz (8x) 15 | * Expanded memory support to a maximum of 2MB 16 | * 3" and 3.5" Disk Drives with read and write support 17 | * Compatible with standard emulator DSK format 18 | * PAL (720x256) or NTSC (720x200) resolution support 19 | * Full PC Keyboard mapping 20 | * Joystick support for the following types of joystick: 21 | * Kempston Joystick 22 | * Spectravideo Joystick 23 | * Cascade Joystick 24 | * DKTronics Joystick 25 | * Mouse support for the following types of mice: 26 | * AMX Mouse 27 | * Kempston Mouse 28 | * Keymouse 29 | * Regular PCW Beeper sound and DKTronics Sound Generator (AY-3-8912) support 30 | * Configurable colour mode 31 | 32 | 33 | ## Using the core 34 | 35 | Unlike many home comptuters of the mid 80's, the Amstrad PCW always included a disk drive and monitor and all PCW software is supplied in disk format only. The emulator supports the standard DSK format images used by the two main PCW emulators, Joyce by John Elliot and CPM/Box by Habisoft. 36 | 37 | The PCW also doesn't have a BOOT ROM but instead streams a small boot routine from the keyboard controller at power-up time. The PCW core recreates this boot sequence and does not require any external ROM files to boot. Just place your DSK images in the **/Games/Amstrad PCW/** directory in the root of the SD card. 38 | 39 | Games are usually supplied on two disks, normally the first disk is a CP/M boot disk. Insert this boot disk into the A: drive using the Menu, then select **RESET** from the OSD menu to load the disk. Once the boot disk has finished booting, you will be prompted by the PCW change the disk to the second disk and press return. 40 | 41 | ![](./docs/images/change_disk.jpg) 42 | 43 | The main operating system the PCW used was called CP/M which was developed by Digital Research and was one of the worlds first cross platform operating systems. More infomation about CP/M and some common commands available are documented on [The CP/M Wiki article](https://en.wikipedia.org/wiki/CP/M) 44 | 45 | ## PCW Models 46 | 47 | The PCW core emulates two different models of the PCW: 48 | * **PCW8256/8512** - Drive A 3" 180k (CF2), Drive B 3" 720k (CF2DD) 49 | * **PCW9256/9512+** - Both drives 3.5" 720k (MF2DD) 50 | 51 | These two different models of the PCW require different boot disks. This is because each model has a different bootrom, which looks for different checksums on the boot sector of the disk. If you get the wrong one it will just beep three times indicating the disk is not recognized. 52 | 53 | ## Fake colour mode 54 | 55 | Like the CP/M Box and Joyce emulators and a couple of add-on boards, this core now supports colour modes. Unlike on those emulators, this does not have to encompass the entire screen, and it is configurable from software should authors of new games wish to make use of it. 56 | 57 | Gnome Ranger 58 | 59 | Many PCW adventure games contain graphics at the top, with a text interface before. Once Fake Colour mode is enabled, you can use the following keys to control it: 60 | 61 | * **F9** - Move colour line enable line up 62 | * **F10** - Move colour line enable line down 63 | * **F11** - Toggle full screen colour mode on/off 64 | 65 | The mode allows loading 4-bit colour palettes, in the same format as the Gameboy core (GBP) or select PCWPlus support modes 1,2 and 3 in games that allow this colour modes. 66 | PCWPlus mode need to be activate before a compatible game load. 67 | 68 | ## Current issue 69 | * SymbOS does not work correctly 70 | * PSI-5 Trading Company - Requires SCAN_EQUAL disk command which is not implemented 71 | * APPLE JACK not working 72 | 73 | # Changes from previous release 74 | * Support for PCW9512+ Mode and 3.5" drives 75 | * Support for two disk drives 76 | * SDRAM support to provide upto 2MB memory 77 | * Colour mode with configurable starting point 78 | * CPC paging mode. Fixes issues with various games (e.g. Abadia, Head over Heels) 79 | * Mouse movement improvements 80 | * Daisywheel port emulation to allow PCW915+ CPM to boot 81 | * Fixed issues with disk corruption and boot errors 82 | * Fixed corruption issue with RAMtest 83 | * F2/F4/F6/F8 no longer require you to press shift 84 | 85 | All the new features are demonstrated in the following video: 86 | [![Watch the video](https://img.youtube.com/vi/z-IoDr81xjE/hqdefault.jpg)](https://youtu.be/z-IoDr81xjE) 87 | 88 | ## Upcoming features 89 | The following features are coming shortly 90 | * Support for SymbOS 91 | 92 | ## Game Notes 93 | * Blagger - Will move left unless Joystick is set to Cascade 94 | 95 | ## Thanks 96 | Special thanks to the following people: 97 | * John Elliott for the fantastic [PCW Hardware guide](https://www.seasip.info/Unix/Joyce/hardware.pdf), the [Joyce emulator](https://www.seasip.info/Unix/Joyce/) and for answering my emails 98 | * Javier Chocano from Habisoft for the [CP/M Box emulator](http://www.habisoft.com/pcw/) and early guidance , and PCWPlus modes 99 | * [@zigazou](https://twitter.com/zigazou) for his detailed [wiki article](https://github.com/Zigazou/amstrad-pcw-technical-info/tree/master/video-memory) on the PCW screen memory structure 100 | * [@asicguy](https://github.com/asicguy), [@alanswx](https://github.com/alanswx) and [@dshadoff](https://github.com/dshadoff) for the help, eoncouragment and support developing the core 101 | * [@sorgelig](https://github.com/sorgelig) for the fantastic MiSTer project and work 102 | 103 | -------------------------------------------------------------------------------- /rtl/T80/GBse.vhd: -------------------------------------------------------------------------------- 1 | -- **** 2 | -- T80(b) core. In an effort to merge and maintain bug fixes .... 3 | -- 4 | -- 5 | -- Ver 300 started tidyup 6 | -- MikeJ March 2005 7 | -- Latest version from www.fpgaarcade.com (original www.opencores.org) 8 | -- 9 | -- **** 10 | -- 11 | -- Z80 compatible microprocessor core, synchronous top level with clock enable 12 | -- Different timing than the original z80 13 | -- Inputs needs to be synchronous and outputs may glitch 14 | -- 15 | -- Version : 0240 16 | -- 17 | -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) 18 | -- 19 | -- All rights reserved 20 | -- 21 | -- Redistribution and use in source and synthezised forms, with or without 22 | -- modification, are permitted provided that the following conditions are met: 23 | -- 24 | -- Redistributions of source code must retain the above copyright notice, 25 | -- this list of conditions and the following disclaimer. 26 | -- 27 | -- Redistributions in synthesized form must reproduce the above copyright 28 | -- notice, this list of conditions and the following disclaimer in the 29 | -- documentation and/or other materials provided with the distribution. 30 | -- 31 | -- Neither the name of the author nor the names of other contributors may 32 | -- be used to endorse or promote products derived from this software without 33 | -- specific prior written permission. 34 | -- 35 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 36 | -- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 37 | -- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38 | -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 39 | -- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 40 | -- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 41 | -- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 42 | -- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 43 | -- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 44 | -- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 45 | -- POSSIBILITY OF SUCH DAMAGE. 46 | -- 47 | -- Please report bugs to the author, but before you do so, please 48 | -- make sure that this is not a derivative work and that 49 | -- you have the latest version of this file. 50 | -- 51 | -- The latest version of this file can be found at: 52 | -- http://www.opencores.org/cvsweb.shtml/t80/ 53 | -- 54 | -- Limitations : 55 | -- 56 | -- File history : 57 | -- 58 | -- 0235 : First release 59 | -- 60 | -- 0236 : Added T2Write generic 61 | -- 62 | -- 0237 : Fixed T2Write with wait state 63 | -- 64 | -- 0238 : Updated for T80 interface change 65 | -- 66 | -- 0240 : Updated for T80 interface change 67 | -- 68 | -- 0242 : Updated for T80 interface change 69 | -- 70 | library IEEE; 71 | use IEEE.std_logic_1164.all; 72 | use IEEE.numeric_std.all; 73 | use work.T80_Pack.all; 74 | 75 | entity GBse is 76 | generic( 77 | T2Write : integer := 1; -- 0 => WR_n active in T3, /=0 => WR_n active in T2 78 | IOWait : integer := 1 -- 0 => Single cycle I/O, 1 => Std I/O cycle 79 | ); 80 | port( 81 | RESET_n : in std_logic; 82 | CLK_n : in std_logic; 83 | CLKEN : in std_logic; 84 | WAIT_n : in std_logic; 85 | INT_n : in std_logic; 86 | NMI_n : in std_logic; 87 | BUSRQ_n : in std_logic; 88 | M1_n : out std_logic; 89 | MREQ_n : out std_logic; 90 | IORQ_n : out std_logic; 91 | RD_n : out std_logic; 92 | WR_n : out std_logic; 93 | RFSH_n : out std_logic; 94 | HALT_n : out std_logic; 95 | BUSAK_n : out std_logic; 96 | STOP : out std_logic; 97 | A : out std_logic_vector(15 downto 0); 98 | DI : in std_logic_vector(7 downto 0); 99 | DO : out std_logic_vector(7 downto 0) 100 | ); 101 | end GBse; 102 | 103 | architecture rtl of GBse is 104 | 105 | signal IntCycle_n : std_logic; 106 | signal NoRead : std_logic; 107 | signal Write : std_logic; 108 | signal IORQ : std_logic; 109 | signal DI_Reg : std_logic_vector(7 downto 0); 110 | signal MCycle : std_logic_vector(2 downto 0); 111 | signal TState : std_logic_vector(2 downto 0); 112 | 113 | begin 114 | 115 | u0 : T80 116 | generic map( 117 | Mode => 3, 118 | IOWait => IOWait, 119 | Flag_S => 0, 120 | Flag_P => 0, 121 | Flag_X => 0, 122 | Flag_Y => 0, 123 | Flag_C => 4, 124 | Flag_H => 5, 125 | Flag_N => 6, 126 | Flag_Z => 7 127 | ) 128 | port map( 129 | CEN => CLKEN, 130 | M1_n => M1_n, 131 | IORQ => IORQ, 132 | NoRead => NoRead, 133 | Write => Write, 134 | RFSH_n => RFSH_n, 135 | HALT_n => HALT_n, 136 | Stop => STOP, 137 | WAIT_n => Wait_n, 138 | INT_n => INT_n, 139 | NMI_n => NMI_n, 140 | RESET_n => RESET_n, 141 | BUSRQ_n => BUSRQ_n, 142 | BUSAK_n => BUSAK_n, 143 | CLK_n => CLK_n, 144 | A => A, 145 | DInst => DI, 146 | DI => DI_Reg, 147 | DO => DO, 148 | MC => MCycle, 149 | TS => TState, 150 | IntCycle_n => IntCycle_n); 151 | 152 | process (RESET_n, CLK_n) 153 | begin 154 | if RESET_n = '0' then 155 | RD_n <= '1'; 156 | WR_n <= '1'; 157 | IORQ_n <= '1'; 158 | MREQ_n <= '1'; 159 | DI_Reg <= "00000000"; 160 | elsif CLK_n'event and CLK_n = '1' then 161 | if CLKEN = '1' then 162 | RD_n <= '1'; 163 | WR_n <= '1'; 164 | IORQ_n <= '1'; 165 | MREQ_n <= '1'; 166 | if MCycle = "001" then 167 | if TState = "001" or (TState = "010" and Wait_n = '0') then 168 | RD_n <= not IntCycle_n; 169 | MREQ_n <= not IntCycle_n; 170 | end if; 171 | if TState = "011" then 172 | MREQ_n <= '0'; 173 | end if; 174 | elsif MCycle = "011" and IntCycle_n = '0' then 175 | if TState = "001" then 176 | IORQ_n <= '0'; -- Acknowledge IRQ 177 | end if; 178 | else 179 | if (TState = "001" or (TState = "010" and Wait_n = '0')) and NoRead = '0' and Write = '0' then 180 | RD_n <= '0'; 181 | IORQ_n <= not IORQ; 182 | MREQ_n <= IORQ; 183 | end if; 184 | if T2Write = 0 then 185 | if TState = "010" and Write = '1' then 186 | WR_n <= '0'; 187 | IORQ_n <= not IORQ; 188 | MREQ_n <= IORQ; 189 | end if; 190 | else 191 | if (TState = "001" or (TState = "010" and Wait_n = '0')) and Write = '1' then 192 | WR_n <= '0'; 193 | IORQ_n <= not IORQ; 194 | MREQ_n <= IORQ; 195 | end if; 196 | end if; 197 | end if; 198 | if TState = "010" and Wait_n = '1' then 199 | DI_Reg <= DI; 200 | end if; 201 | end if; 202 | end if; 203 | end process; 204 | 205 | end; 206 | -------------------------------------------------------------------------------- /rtl/T80/T8080se.vhd: -------------------------------------------------------------------------------- 1 | -- **** 2 | -- T80(b) core. In an effort to merge and maintain bug fixes .... 3 | -- 4 | -- 5 | -- Ver 300 started tidyup 6 | -- MikeJ March 2005 7 | -- Latest version from www.fpgaarcade.com (original www.opencores.org) 8 | -- 9 | -- **** 10 | -- 11 | -- 8080 compatible microprocessor core, synchronous top level with clock enable 12 | -- Different timing than the original 8080 13 | -- Inputs needs to be synchronous and outputs may glitch 14 | -- 15 | -- Version : 0242 16 | -- 17 | -- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) 18 | -- 19 | -- All rights reserved 20 | -- 21 | -- Redistribution and use in source and synthezised forms, with or without 22 | -- modification, are permitted provided that the following conditions are met: 23 | -- 24 | -- Redistributions of source code must retain the above copyright notice, 25 | -- this list of conditions and the following disclaimer. 26 | -- 27 | -- Redistributions in synthesized form must reproduce the above copyright 28 | -- notice, this list of conditions and the following disclaimer in the 29 | -- documentation and/or other materials provided with the distribution. 30 | -- 31 | -- Neither the name of the author nor the names of other contributors may 32 | -- be used to endorse or promote products derived from this software without 33 | -- specific prior written permission. 34 | -- 35 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 36 | -- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 37 | -- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38 | -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 39 | -- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 40 | -- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 41 | -- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 42 | -- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 43 | -- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 44 | -- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 45 | -- POSSIBILITY OF SUCH DAMAGE. 46 | -- 47 | -- Please report bugs to the author, but before you do so, please 48 | -- make sure that this is not a derivative work and that 49 | -- you have the latest version of this file. 50 | -- 51 | -- The latest version of this file can be found at: 52 | -- http://www.opencores.org/cvsweb.shtml/t80/ 53 | -- 54 | -- Limitations : 55 | -- STACK status output not supported 56 | -- 57 | -- File history : 58 | -- 59 | -- 0237 : First version 60 | -- 61 | -- 0238 : Updated for T80 interface change 62 | -- 63 | -- 0240 : Updated for T80 interface change 64 | -- 65 | -- 0242 : Updated for T80 interface change 66 | -- 67 | 68 | library IEEE; 69 | use IEEE.std_logic_1164.all; 70 | use IEEE.numeric_std.all; 71 | use work.T80_Pack.all; 72 | 73 | entity T8080se is 74 | generic( 75 | Mode : integer := 2; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB 76 | T2Write : integer := 0 -- 0 => WR_n active in T3, /=0 => WR_n active in T2 77 | ); 78 | port( 79 | RESET_n : in std_logic; 80 | CLK : in std_logic; 81 | CLKEN : in std_logic; 82 | READY : in std_logic; 83 | HOLD : in std_logic; 84 | INT : in std_logic; 85 | INTE : out std_logic; 86 | DBIN : out std_logic; 87 | SYNC : out std_logic; 88 | VAIT : out std_logic; 89 | HLDA : out std_logic; 90 | WR_n : out std_logic; 91 | A : out std_logic_vector(15 downto 0); 92 | DI : in std_logic_vector(7 downto 0); 93 | DO : out std_logic_vector(7 downto 0) 94 | ); 95 | end T8080se; 96 | 97 | architecture rtl of T8080se is 98 | 99 | signal IntCycle_n : std_logic; 100 | signal NoRead : std_logic; 101 | signal Write : std_logic; 102 | signal IORQ : std_logic; 103 | signal INT_n : std_logic; 104 | signal HALT_n : std_logic; 105 | signal BUSRQ_n : std_logic; 106 | signal BUSAK_n : std_logic; 107 | signal DO_i : std_logic_vector(7 downto 0); 108 | signal DI_Reg : std_logic_vector(7 downto 0); 109 | signal MCycle : std_logic_vector(2 downto 0); 110 | signal TState : std_logic_vector(2 downto 0); 111 | signal One : std_logic; 112 | 113 | begin 114 | 115 | INT_n <= not INT; 116 | BUSRQ_n <= HOLD; 117 | HLDA <= not BUSAK_n; 118 | SYNC <= '1' when TState = "001" else '0'; 119 | VAIT <= '1' when TState = "010" else '0'; 120 | One <= '1'; 121 | 122 | DO(0) <= not IntCycle_n when TState = "001" else DO_i(0); -- INTA 123 | DO(1) <= Write when TState = "001" else DO_i(1); -- WO_n 124 | DO(2) <= DO_i(2); -- STACK not supported !!!!!!!!!! 125 | DO(3) <= not HALT_n when TState = "001" else DO_i(3); -- HLTA 126 | DO(4) <= IORQ and Write when TState = "001" else DO_i(4); -- OUT 127 | DO(5) <= DO_i(5) when TState /= "001" else '1' when MCycle = "001" else '0'; -- M1 128 | DO(6) <= IORQ and not Write when TState = "001" else DO_i(6); -- INP 129 | DO(7) <= not IORQ and not Write and IntCycle_n when TState = "001" else DO_i(7); -- MEMR 130 | 131 | u0 : T80 132 | generic map( 133 | Mode => Mode, 134 | IOWait => 0) 135 | port map( 136 | CEN => CLKEN, 137 | M1_n => open, 138 | IORQ => IORQ, 139 | NoRead => NoRead, 140 | Write => Write, 141 | RFSH_n => open, 142 | HALT_n => HALT_n, 143 | WAIT_n => READY, 144 | INT_n => INT_n, 145 | NMI_n => One, 146 | RESET_n => RESET_n, 147 | BUSRQ_n => One, 148 | BUSAK_n => BUSAK_n, 149 | CLK_n => CLK, 150 | A => A, 151 | DInst => DI, 152 | DI => DI_Reg, 153 | DO => DO_i, 154 | MC => MCycle, 155 | TS => TState, 156 | IntCycle_n => IntCycle_n, 157 | IntE => INTE); 158 | 159 | process (RESET_n, CLK) 160 | begin 161 | if RESET_n = '0' then 162 | DBIN <= '0'; 163 | WR_n <= '1'; 164 | DI_Reg <= "00000000"; 165 | elsif CLK'event and CLK = '1' then 166 | if CLKEN = '1' then 167 | DBIN <= '0'; 168 | WR_n <= '1'; 169 | if MCycle = "001" then 170 | if TState = "001" or (TState = "010" and READY = '0') then 171 | DBIN <= IntCycle_n; 172 | end if; 173 | else 174 | if (TState = "001" or (TState = "010" and READY = '0')) and NoRead = '0' and Write = '0' then 175 | DBIN <= '1'; 176 | end if; 177 | if T2Write = 0 then 178 | if TState = "010" and Write = '1' then 179 | WR_n <= '0'; 180 | end if; 181 | else 182 | if (TState = "001" or (TState = "010" and READY = '0')) and Write = '1' then 183 | WR_n <= '0'; 184 | end if; 185 | end if; 186 | end if; 187 | if TState = "010" and READY = '1' then 188 | DI_Reg <= DI; 189 | end if; 190 | end if; 191 | end if; 192 | end process; 193 | 194 | end; 195 | -------------------------------------------------------------------------------- /sys/mt32pi.sv: -------------------------------------------------------------------------------- 1 | // 2 | // Communication module to MT32-pi (external MIDI emulator on RPi) 3 | // (C) 2020 Sorgelig, Kitrinx 4 | // 5 | // https://github.com/dwhinham/mt32-pi 6 | // 7 | 8 | module mt32pi 9 | ( 10 | input CLK_AUDIO, 11 | 12 | input CLK_VIDEO, 13 | input CE_PIXEL, 14 | input VGA_VS, 15 | input VGA_DE, 16 | 17 | input [6:0] USER_IN, 18 | output [6:0] USER_OUT, 19 | 20 | input reset, 21 | input midi_tx, 22 | output midi_rx, 23 | 24 | output reg [15:0] mt32_i2s_r, 25 | output reg [15:0] mt32_i2s_l, 26 | 27 | output reg mt32_available, 28 | 29 | input mt32_mode_req, 30 | input [1:0] mt32_rom_req, 31 | input [7:0] mt32_sf_req, 32 | 33 | output reg [7:0] mt32_mode, 34 | output reg [7:0] mt32_rom, 35 | output reg [7:0] mt32_sf, 36 | output reg mt32_newmode, 37 | 38 | output reg mt32_lcd_en, 39 | output reg mt32_lcd_pix, 40 | output reg mt32_lcd_update 41 | ); 42 | 43 | // 44 | // Pin | USB Name | Signal 45 | // ----+----------+-------------- 46 | // 0 | D+ | I/O I2C_SDA / RX (midi in) 47 | // 1 | D- | O TX (midi out) 48 | // 2 | TX- | I I2S_WS (1 == right) 49 | // 3 | GND_d | I I2C_SCL 50 | // 4 | RX+ | I I2S_BCLK 51 | // 5 | RX- | I I2S_DAT 52 | // 6 | TX+ | - none 53 | // 54 | 55 | assign USER_OUT[0] = sda_out; 56 | assign USER_OUT[1] = midi_tx; 57 | assign USER_OUT[6:2] = '1; 58 | 59 | 60 | // 61 | // crossed/straight cable selection 62 | // 63 | 64 | generate 65 | genvar i; 66 | for(i = 0; i<2; i++) begin : clk_rate 67 | wire clk_in = i ? USER_IN[6] : USER_IN[4]; 68 | reg [4:0] cnt; 69 | always @(posedge CLK_AUDIO) begin : clkr 70 | reg clk_sr, clk, old_clk; 71 | reg [4:0] cnt_tmp; 72 | 73 | clk_sr <= clk_in; 74 | if (clk_sr == clk_in) clk <= clk_sr; 75 | 76 | if(~&cnt_tmp) cnt_tmp <= cnt_tmp + 1'd1; 77 | else cnt <= '1; 78 | 79 | old_clk <= clk; 80 | if(~old_clk & clk) begin 81 | cnt <= cnt_tmp; 82 | cnt_tmp <= 0; 83 | end 84 | end 85 | end 86 | 87 | reg crossed; 88 | always @(posedge CLK_AUDIO) crossed <= (clk_rate[0].cnt <= clk_rate[1].cnt); 89 | endgenerate 90 | 91 | wire i2s_ws = crossed ? USER_IN[2] : USER_IN[5]; 92 | wire i2s_data = crossed ? USER_IN[5] : USER_IN[2]; 93 | wire i2s_bclk = crossed ? USER_IN[4] : USER_IN[6]; 94 | assign midi_rx = ~mt32_available ? USER_IN[0] : crossed ? USER_IN[6] : USER_IN[4]; 95 | 96 | 97 | // 98 | // i2s receiver 99 | // 100 | 101 | always @(posedge CLK_AUDIO) begin : i2s_proc 102 | reg [15:0] i2s_buf = 0; 103 | reg [4:0] i2s_cnt = 0; 104 | reg clk_sr; 105 | reg i2s_clk = 0; 106 | reg old_clk, old_ws; 107 | reg i2s_next = 0; 108 | 109 | // Debounce clock 110 | clk_sr <= i2s_bclk; 111 | if (clk_sr == i2s_bclk) i2s_clk <= clk_sr; 112 | 113 | // Latch data and ws on rising edge 114 | old_clk <= i2s_clk; 115 | if (i2s_clk && ~old_clk) begin 116 | 117 | if (~i2s_cnt[4]) begin 118 | i2s_cnt <= i2s_cnt + 1'd1; 119 | i2s_buf[~i2s_cnt[3:0]] <= i2s_data; 120 | end 121 | 122 | // Word Select will change 1 clock before the new word starts 123 | old_ws <= i2s_ws; 124 | if (old_ws != i2s_ws) i2s_next <= 1; 125 | end 126 | 127 | if (i2s_next) begin 128 | i2s_next <= 0; 129 | i2s_cnt <= 0; 130 | i2s_buf <= 0; 131 | 132 | if (i2s_ws) mt32_i2s_l <= i2s_buf; 133 | else mt32_i2s_r <= i2s_buf; 134 | end 135 | 136 | if (reset) begin 137 | i2s_buf <= 0; 138 | mt32_i2s_l <= 0; 139 | mt32_i2s_r <= 0; 140 | end 141 | end 142 | 143 | 144 | // 145 | // i2c slave 146 | // 147 | 148 | reg sda_out; 149 | reg [7:0] lcd_data[1024]; 150 | reg lcd_sz; 151 | 152 | reg reset_r = 0; 153 | wire [7:0] mode_req = reset_r ? 8'hA0 : mt32_mode_req ? 8'hA2 : 8'hA1; 154 | wire [7:0] rom_req = {6'd0, mt32_rom_req}; 155 | 156 | always @(posedge CLK_AUDIO) begin : i2c_slave 157 | reg sda_sr, scl_sr; 158 | reg old_sda, old_scl; 159 | reg sda, scl; 160 | reg [7:0] tmp; 161 | reg [3:0] cnt = 0; 162 | reg [10:0] bcnt = 0; 163 | reg ack; 164 | reg i2c_rw; 165 | reg disp, dispdata; 166 | reg [2:0] div; 167 | reg old_reset; 168 | 169 | old_reset <= reset; 170 | if(old_reset & ~reset) sda_out <= 1; 171 | 172 | div <= div + 1'd1; 173 | if(!div) begin 174 | sda_sr <= USER_IN[0]; 175 | if(sda_sr == USER_IN[0]) sda <= sda_sr; 176 | old_sda <= sda; 177 | 178 | scl_sr <= USER_IN[3]; 179 | if(scl_sr == USER_IN[3]) scl <= scl_sr; 180 | old_scl <= scl; 181 | 182 | //start 183 | if(old_scl & scl & old_sda & ~sda) begin 184 | cnt <= 9; 185 | bcnt <= 0; 186 | ack <= 0; 187 | i2c_rw <= 0; 188 | disp <= 0; 189 | dispdata <= 0; 190 | end 191 | 192 | //stop 193 | if(old_scl & scl & ~old_sda & sda) begin 194 | cnt <= 0; 195 | if(dispdata) begin 196 | lcd_sz <= ~bcnt[9]; 197 | mt32_lcd_update <= ~mt32_lcd_update; 198 | end 199 | end 200 | 201 | //data latch 202 | if(~old_scl && scl && cnt) begin 203 | tmp <= {tmp[6:0], sda}; 204 | cnt <= cnt - 1'd1; 205 | end 206 | 207 | if(!cnt) sda_out <= 1; 208 | 209 | //data set 210 | if(old_scl && ~scl) begin 211 | sda_out <= 1; 212 | if(cnt == 1) begin 213 | if(!bcnt) begin 214 | if(tmp[7:1] == 'h45 || tmp[7:1] == 'h3c) begin 215 | disp <= (tmp[7:1] == 'h3c); 216 | sda_out <= 0; 217 | mt32_available <= 1; 218 | ack <= 1; 219 | i2c_rw <= tmp[0]; 220 | bcnt <= bcnt + 1'd1; 221 | cnt <= 10; 222 | end 223 | else begin 224 | // wrong address, stop 225 | cnt <= 0; 226 | end 227 | end 228 | else if(ack) begin 229 | if(~i2c_rw) begin 230 | if(disp) begin 231 | if(bcnt == 1) dispdata <= (tmp[7:6] == 2'b01); 232 | else if(dispdata) lcd_data[bcnt[9:0] - 2'd2] <= tmp; 233 | end 234 | else begin 235 | if(bcnt == 1) mt32_mode <= tmp; 236 | if(bcnt == 2) mt32_rom <= tmp; 237 | if(bcnt == 3) mt32_sf <= tmp; 238 | if(bcnt == 3) mt32_newmode <= ~mt32_newmode; 239 | end 240 | end 241 | if(~&bcnt) bcnt <= bcnt + 1'd1; 242 | sda_out <= 0; 243 | cnt <= 10; 244 | end 245 | end 246 | else if(i2c_rw && ack && cnt && ~disp) begin 247 | if(bcnt == 1) sda_out <= mode_req[cnt[2:0] - 2'd2]; 248 | if(bcnt == 2) sda_out <= rom_req[cnt[2:0] - 2'd2]; 249 | if(bcnt == 3) sda_out <= mt32_sf_req[cnt[2:0] - 2'd2]; 250 | if(bcnt == 3) reset_r <= 0; 251 | end 252 | end 253 | end 254 | 255 | if(reset) begin 256 | reset_r <= 1; 257 | mt32_available <= 0; 258 | end 259 | end 260 | 261 | always @(posedge CLK_VIDEO) begin 262 | reg old_de, old_vs; 263 | reg [7:0] hcnt; 264 | reg [6:0] vcnt; 265 | reg [7:0] sh; 266 | 267 | if(CE_PIXEL) begin 268 | old_de <= VGA_DE; 269 | old_vs <= VGA_VS; 270 | 271 | if(~&hcnt) hcnt <= hcnt + 1'd1; 272 | sh <= (sh << 1) | (~old_de & VGA_DE); 273 | if(sh[7]) hcnt <= 0; 274 | 275 | if(old_de & ~VGA_DE & ~&vcnt) vcnt <= vcnt + 1'd1; 276 | if(~old_vs & VGA_VS) vcnt <= 0; 277 | 278 | mt32_lcd_en <= mt32_available & ~hcnt[7] && (lcd_sz ? !vcnt[6] : !vcnt[6:5]); 279 | mt32_lcd_pix <= lcd_data[{vcnt[5:3],hcnt[6:0]}][vcnt[2:0]]; 280 | end 281 | end 282 | 283 | endmodule 284 | -------------------------------------------------------------------------------- /sys/pll_hdmi/pll_hdmi_0002.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/10ps 2 | module pll_hdmi_0002( 3 | 4 | // interface 'refclk' 5 | input wire refclk, 6 | 7 | // interface 'reset' 8 | input wire rst, 9 | 10 | // interface 'outclk0' 11 | output wire outclk_0, 12 | 13 | // interface 'locked' 14 | output wire locked, 15 | 16 | // interface 'reconfig_to_pll' 17 | input wire [63:0] reconfig_to_pll, 18 | 19 | // interface 'reconfig_from_pll' 20 | output wire [63:0] reconfig_from_pll 21 | ); 22 | 23 | altera_pll #( 24 | .fractional_vco_multiplier("true"), 25 | .reference_clock_frequency("50.0 MHz"), 26 | .pll_fractional_cout(32), 27 | .pll_dsm_out_sel("1st_order"), 28 | .operation_mode("direct"), 29 | .number_of_clocks(1), 30 | .output_clock_frequency0("148.500000 MHz"), 31 | .phase_shift0("0 ps"), 32 | .duty_cycle0(50), 33 | .output_clock_frequency1("0 MHz"), 34 | .phase_shift1("0 ps"), 35 | .duty_cycle1(50), 36 | .output_clock_frequency2("0 MHz"), 37 | .phase_shift2("0 ps"), 38 | .duty_cycle2(50), 39 | .output_clock_frequency3("0 MHz"), 40 | .phase_shift3("0 ps"), 41 | .duty_cycle3(50), 42 | .output_clock_frequency4("0 MHz"), 43 | .phase_shift4("0 ps"), 44 | .duty_cycle4(50), 45 | .output_clock_frequency5("0 MHz"), 46 | .phase_shift5("0 ps"), 47 | .duty_cycle5(50), 48 | .output_clock_frequency6("0 MHz"), 49 | .phase_shift6("0 ps"), 50 | .duty_cycle6(50), 51 | .output_clock_frequency7("0 MHz"), 52 | .phase_shift7("0 ps"), 53 | .duty_cycle7(50), 54 | .output_clock_frequency8("0 MHz"), 55 | .phase_shift8("0 ps"), 56 | .duty_cycle8(50), 57 | .output_clock_frequency9("0 MHz"), 58 | .phase_shift9("0 ps"), 59 | .duty_cycle9(50), 60 | .output_clock_frequency10("0 MHz"), 61 | .phase_shift10("0 ps"), 62 | .duty_cycle10(50), 63 | .output_clock_frequency11("0 MHz"), 64 | .phase_shift11("0 ps"), 65 | .duty_cycle11(50), 66 | .output_clock_frequency12("0 MHz"), 67 | .phase_shift12("0 ps"), 68 | .duty_cycle12(50), 69 | .output_clock_frequency13("0 MHz"), 70 | .phase_shift13("0 ps"), 71 | .duty_cycle13(50), 72 | .output_clock_frequency14("0 MHz"), 73 | .phase_shift14("0 ps"), 74 | .duty_cycle14(50), 75 | .output_clock_frequency15("0 MHz"), 76 | .phase_shift15("0 ps"), 77 | .duty_cycle15(50), 78 | .output_clock_frequency16("0 MHz"), 79 | .phase_shift16("0 ps"), 80 | .duty_cycle16(50), 81 | .output_clock_frequency17("0 MHz"), 82 | .phase_shift17("0 ps"), 83 | .duty_cycle17(50), 84 | .pll_type("Cyclone V"), 85 | .pll_subtype("Reconfigurable"), 86 | .m_cnt_hi_div(4), 87 | .m_cnt_lo_div(4), 88 | .n_cnt_hi_div(256), 89 | .n_cnt_lo_div(256), 90 | .m_cnt_bypass_en("false"), 91 | .n_cnt_bypass_en("true"), 92 | .m_cnt_odd_div_duty_en("false"), 93 | .n_cnt_odd_div_duty_en("false"), 94 | .c_cnt_hi_div0(2), 95 | .c_cnt_lo_div0(1), 96 | .c_cnt_prst0(1), 97 | .c_cnt_ph_mux_prst0(0), 98 | .c_cnt_in_src0("ph_mux_clk"), 99 | .c_cnt_bypass_en0("false"), 100 | .c_cnt_odd_div_duty_en0("true"), 101 | .c_cnt_hi_div1(1), 102 | .c_cnt_lo_div1(1), 103 | .c_cnt_prst1(1), 104 | .c_cnt_ph_mux_prst1(0), 105 | .c_cnt_in_src1("ph_mux_clk"), 106 | .c_cnt_bypass_en1("true"), 107 | .c_cnt_odd_div_duty_en1("false"), 108 | .c_cnt_hi_div2(1), 109 | .c_cnt_lo_div2(1), 110 | .c_cnt_prst2(1), 111 | .c_cnt_ph_mux_prst2(0), 112 | .c_cnt_in_src2("ph_mux_clk"), 113 | .c_cnt_bypass_en2("true"), 114 | .c_cnt_odd_div_duty_en2("false"), 115 | .c_cnt_hi_div3(1), 116 | .c_cnt_lo_div3(1), 117 | .c_cnt_prst3(1), 118 | .c_cnt_ph_mux_prst3(0), 119 | .c_cnt_in_src3("ph_mux_clk"), 120 | .c_cnt_bypass_en3("true"), 121 | .c_cnt_odd_div_duty_en3("false"), 122 | .c_cnt_hi_div4(1), 123 | .c_cnt_lo_div4(1), 124 | .c_cnt_prst4(1), 125 | .c_cnt_ph_mux_prst4(0), 126 | .c_cnt_in_src4("ph_mux_clk"), 127 | .c_cnt_bypass_en4("true"), 128 | .c_cnt_odd_div_duty_en4("false"), 129 | .c_cnt_hi_div5(1), 130 | .c_cnt_lo_div5(1), 131 | .c_cnt_prst5(1), 132 | .c_cnt_ph_mux_prst5(0), 133 | .c_cnt_in_src5("ph_mux_clk"), 134 | .c_cnt_bypass_en5("true"), 135 | .c_cnt_odd_div_duty_en5("false"), 136 | .c_cnt_hi_div6(1), 137 | .c_cnt_lo_div6(1), 138 | .c_cnt_prst6(1), 139 | .c_cnt_ph_mux_prst6(0), 140 | .c_cnt_in_src6("ph_mux_clk"), 141 | .c_cnt_bypass_en6("true"), 142 | .c_cnt_odd_div_duty_en6("false"), 143 | .c_cnt_hi_div7(1), 144 | .c_cnt_lo_div7(1), 145 | .c_cnt_prst7(1), 146 | .c_cnt_ph_mux_prst7(0), 147 | .c_cnt_in_src7("ph_mux_clk"), 148 | .c_cnt_bypass_en7("true"), 149 | .c_cnt_odd_div_duty_en7("false"), 150 | .c_cnt_hi_div8(1), 151 | .c_cnt_lo_div8(1), 152 | .c_cnt_prst8(1), 153 | .c_cnt_ph_mux_prst8(0), 154 | .c_cnt_in_src8("ph_mux_clk"), 155 | .c_cnt_bypass_en8("true"), 156 | .c_cnt_odd_div_duty_en8("false"), 157 | .c_cnt_hi_div9(1), 158 | .c_cnt_lo_div9(1), 159 | .c_cnt_prst9(1), 160 | .c_cnt_ph_mux_prst9(0), 161 | .c_cnt_in_src9("ph_mux_clk"), 162 | .c_cnt_bypass_en9("true"), 163 | .c_cnt_odd_div_duty_en9("false"), 164 | .c_cnt_hi_div10(1), 165 | .c_cnt_lo_div10(1), 166 | .c_cnt_prst10(1), 167 | .c_cnt_ph_mux_prst10(0), 168 | .c_cnt_in_src10("ph_mux_clk"), 169 | .c_cnt_bypass_en10("true"), 170 | .c_cnt_odd_div_duty_en10("false"), 171 | .c_cnt_hi_div11(1), 172 | .c_cnt_lo_div11(1), 173 | .c_cnt_prst11(1), 174 | .c_cnt_ph_mux_prst11(0), 175 | .c_cnt_in_src11("ph_mux_clk"), 176 | .c_cnt_bypass_en11("true"), 177 | .c_cnt_odd_div_duty_en11("false"), 178 | .c_cnt_hi_div12(1), 179 | .c_cnt_lo_div12(1), 180 | .c_cnt_prst12(1), 181 | .c_cnt_ph_mux_prst12(0), 182 | .c_cnt_in_src12("ph_mux_clk"), 183 | .c_cnt_bypass_en12("true"), 184 | .c_cnt_odd_div_duty_en12("false"), 185 | .c_cnt_hi_div13(1), 186 | .c_cnt_lo_div13(1), 187 | .c_cnt_prst13(1), 188 | .c_cnt_ph_mux_prst13(0), 189 | .c_cnt_in_src13("ph_mux_clk"), 190 | .c_cnt_bypass_en13("true"), 191 | .c_cnt_odd_div_duty_en13("false"), 192 | .c_cnt_hi_div14(1), 193 | .c_cnt_lo_div14(1), 194 | .c_cnt_prst14(1), 195 | .c_cnt_ph_mux_prst14(0), 196 | .c_cnt_in_src14("ph_mux_clk"), 197 | .c_cnt_bypass_en14("true"), 198 | .c_cnt_odd_div_duty_en14("false"), 199 | .c_cnt_hi_div15(1), 200 | .c_cnt_lo_div15(1), 201 | .c_cnt_prst15(1), 202 | .c_cnt_ph_mux_prst15(0), 203 | .c_cnt_in_src15("ph_mux_clk"), 204 | .c_cnt_bypass_en15("true"), 205 | .c_cnt_odd_div_duty_en15("false"), 206 | .c_cnt_hi_div16(1), 207 | .c_cnt_lo_div16(1), 208 | .c_cnt_prst16(1), 209 | .c_cnt_ph_mux_prst16(0), 210 | .c_cnt_in_src16("ph_mux_clk"), 211 | .c_cnt_bypass_en16("true"), 212 | .c_cnt_odd_div_duty_en16("false"), 213 | .c_cnt_hi_div17(1), 214 | .c_cnt_lo_div17(1), 215 | .c_cnt_prst17(1), 216 | .c_cnt_ph_mux_prst17(0), 217 | .c_cnt_in_src17("ph_mux_clk"), 218 | .c_cnt_bypass_en17("true"), 219 | .c_cnt_odd_div_duty_en17("false"), 220 | .pll_vco_div(2), 221 | .pll_cp_current(20), 222 | .pll_bwctrl(4000), 223 | .pll_output_clk_frequency("445.499999 MHz"), 224 | .pll_fractional_division("3908420153"), 225 | .mimic_fbclk_type("none"), 226 | .pll_fbclk_mux_1("glb"), 227 | .pll_fbclk_mux_2("m_cnt"), 228 | .pll_m_cnt_in_src("ph_mux_clk"), 229 | .pll_slf_rst("true") 230 | ) altera_pll_i ( 231 | .rst (rst), 232 | .outclk ({outclk_0}), 233 | .locked (locked), 234 | .reconfig_to_pll (reconfig_to_pll), 235 | .fboutclk ( ), 236 | .fbclk (1'b0), 237 | .refclk (refclk), 238 | .reconfig_from_pll (reconfig_from_pll) 239 | ); 240 | endmodule 241 | 242 | --------------------------------------------------------------------------------