├── 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 |
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 | 
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 |
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 | [](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 |
--------------------------------------------------------------------------------