├── .gitattributes ├── .gitignore ├── .gitmodules ├── Arcade-atarisys1.qpf ├── Arcade-atarisys1.qsf ├── Arcade-atarisys1.sv ├── LICENSE ├── README.md ├── clean.bat ├── doc ├── Atari_Cart_Indiana_Jones_Temple.jpg ├── Atari_Cart_Marble_Madness.jpg ├── Atari_Cart_Peter_Pack_Rat.jpg ├── Atari_Cart_Road_Blasters.jpg ├── Atari_Cart_Road_Runner.jpg ├── Atari_Sys1+RoadBlasters.jpg ├── Atari_Sys1-0.jpg ├── Atari_Sys1-1.jpg ├── Atari_Sys1-2.jpg ├── Atari_Sys1-3.jpg ├── SP-276 MARBLE MADNESS 1ST PRINTING.pdf ├── SP-277 ATARI SYSTEM 1 1ST PRINTING SCHEMATIC PACKAGE U.pdf ├── SP-280_Atari_System_Cartridge_1st_Printing.pdf ├── SP-282_Indiana_Jones_and_the_Temple_of_Doom_1st_Printing.pdf ├── SP-286 ATARI SYSTEM 1 1ST PRINTING.PDF ├── SP-298_Road_Blasters_1st_Printing_for_System_1.pdf ├── SP-299_Road_Blasters_Cockpit_1st_Printing.pdf ├── TM-276 Marble Madness.pdf ├── TM-280 Peter Pack-Rat - 1984 - Atari.pdf ├── TM-282 Indiana Jones and the Temple of Doom (1st Printing).pdf ├── TM-285 Road Runner (1st Printing).pdf ├── TM-286 Atari System1 (1st printing).pdf └── TM-298 Road Blasters.pdf ├── files.qip ├── releases ├── Arcade-atarisys1_20231130.rbf ├── Arcade-atarisys1_20231212.rbf ├── Arcade-atarisys1_20240410.rbf ├── Indiana Jones (set 4).mra ├── Marble Madness (set 5 - LSI).mra ├── Peter Pack Rat.mra ├── Road Blasters (upright, rev 4).mra ├── Road Runner (rev 2).mra └── _alternatives │ ├── _Indiana_Jones │ ├── Indiana Jones (cocktail).mra │ ├── Indiana Jones (german).mra │ ├── Indiana Jones (set 1).mra │ ├── Indiana Jones (set 2).mra │ └── Indiana Jones (set 3).mra │ ├── _Marble_Madness │ ├── Marble Madness (set 1).mra │ ├── Marble Madness (set 2).mra │ ├── Marble Madness (set 3).mra │ └── Marble Madness (set 4).mra │ ├── _Road_Blasters │ ├── Road Blasters (cockpit, German, rev 1).mra │ ├── Road Blasters (cockpit, rev 1).mra │ ├── Road Blasters (cockpit, rev 2).mra │ ├── Road Blasters (upright, German, rev 1).mra │ ├── Road Blasters (upright, German, rev 2).mra │ ├── Road Blasters (upright, German, rev 3)).mra │ ├── Road Blasters (upright, German, rev X).mra │ ├── Road Blasters (upright, rev 1).mra │ ├── Road Blasters (upright, rev 2).mra │ └── Road Blasters (upright, rev 3)).mra │ └── _Road_Runner │ ├── Road Runner (rev 1).mra │ └── Road Runner (rev 1p).mra ├── rtl ├── atarisys1 │ ├── ATARISYS1.vhd │ ├── AUDIO.vhd │ ├── CART.vhd │ ├── CRAMS.vhd │ ├── GPC.vhd │ ├── LINEBUF.vhd │ ├── LINECTR.vhd │ ├── LS299.vhd │ ├── MAIN.vhd │ ├── MOHLB_LSI.vhd │ ├── MOHLB_TTL.vhd │ ├── PFHS.vhd │ ├── PROM_5E.VHD │ ├── RAM_2K8.vhd │ ├── RGBI.vhd │ ├── SLAGS.vhd │ ├── SLAPSTIC.vhd │ ├── SYNGEN.vhd │ ├── TMS5220.vhd │ ├── VIDEO.vhd │ └── VRAMS.vhd ├── lib │ ├── POKEY.vhd │ ├── T65 │ │ ├── T65.vhd │ │ ├── T65_ALU.vhd │ │ ├── T65_MCode.vhd │ │ └── T65_Pack.vhd │ ├── TG68K │ │ ├── README.md │ │ ├── TG68K.vhd │ │ ├── TG68K_ALU.vhd │ │ ├── TG68K_Pack.vhd │ │ └── TG68KdotC_Kernel.vhd │ ├── bitmap │ │ ├── bmp_out.vhd │ │ ├── bmp_pkg.vhd │ │ ├── bmp_sink.vhd │ │ ├── bmp_source.vhd │ │ └── vga_bmp_sink.vhd │ ├── bootstrap.vhd │ ├── dac.vhd │ ├── dvid.vhd │ ├── gamecube │ │ ├── Nintendo Gamecube Controller Protocol.pdf │ │ ├── gamecube.vhd │ │ ├── pulseview_capture.sr │ │ └── tb_gc.vhd │ ├── leta_rep.vhd │ ├── m6522.vhd │ ├── mem │ │ ├── dpram.vhd │ │ ├── mt48lc16m16a2.v │ │ ├── sdram.sdc │ │ └── sdram.vhd │ ├── quad.vhd │ ├── scan_converter.vhd │ ├── spi_flash.vhd │ └── tmds_encoder.vhd ├── pll.qip ├── pll.v └── pll │ ├── pll_0002.qip │ └── pll_0002.v └── sys ├── alsa.sv ├── arcade_video.v ├── ascal.vhd ├── audio_out.v ├── build_id.tcl ├── ddr_svc.sv ├── f2sdram_safe_terminator.sv ├── gamma_corr.sv ├── hps_io.sv ├── hq2x.sv ├── i2c.v ├── i2s.v ├── iir_filter.v ├── ltc2308.sv ├── math.sv ├── mcp23009.sv ├── mt32pi.sv ├── osd.v ├── pll.13.qip ├── pll_audio.13.qip ├── pll_audio.qip ├── pll_audio.v ├── pll_audio ├── pll_audio_0002.qip └── pll_audio_0002.v ├── pll_cfg.qip ├── pll_cfg ├── altera_pll_reconfig_core.v ├── altera_pll_reconfig_top.v ├── pll_cfg.v └── pll_cfg_hdmi.v ├── pll_hdmi.13.qip ├── pll_hdmi.qip ├── pll_hdmi.v ├── pll_hdmi ├── pll_hdmi_0002.qip └── pll_hdmi_0002.v ├── pll_hdmi_adj.vhd ├── pll_q13.qip ├── pll_q17.qip ├── scandoubler.v ├── scanlines.v ├── sd_card.sv ├── shadowmask.sv ├── sigma_delta_dac.v ├── spdif.v ├── sys.qip ├── sys.tcl ├── sys_analog.tcl ├── sys_dual_sdram.tcl ├── sys_top.sdc ├── sys_top.v ├── sysmem.sv ├── vga_out.sv ├── video_cleaner.sv ├── video_freak.sv ├── video_freezer.sv ├── video_mixer.sv └── yc_out.sv /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | db 2 | tb 3 | debug 4 | doc 5 | incremental_db 6 | output_files* 7 | build_id.v 8 | c5_pin_model_dump.txt 9 | *.cdf 10 | *.stp 11 | *.qws -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "rtl/lib/jt51"] 2 | path = rtl/lib/jt51 3 | url = https://github.com/jotego/jt51.git 4 | -------------------------------------------------------------------------------- /Arcade-atarisys1.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 Standard Edition 22 | # Date created = 12:12:12 January 24, 2021 23 | # 24 | # -------------------------------------------------------------------------- # 25 | 26 | QUARTUS_VERSION = "17.0" 27 | DATE = "11:11:11 November 11, 2022" 28 | 29 | # Revisions 30 | 31 | PROJECT_REVISION = "Arcade-atarisys1" 32 | -------------------------------------------------------------------------------- /Arcade-atarisys1.qsf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- 2 | # 3 | # MiSTer project 4 | # 5 | # WARNING WARNING WARNING: 6 | # Do not add files to project in Quartus IDE! It will mess this file! 7 | # Add the files manually to files.qip file. 8 | # 9 | # -------------------------------------------------------------------------- 10 | 11 | set_global_assignment -name TOP_LEVEL_ENTITY sys_top 12 | set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top 13 | set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top 14 | set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top 15 | 16 | set_global_assignment -name LAST_QUARTUS_VERSION "17.0.2 Standard Edition" 17 | 18 | set_global_assignment -name GENERATE_RBF_FILE ON 19 | set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files 20 | set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL 21 | set_global_assignment -name SAVE_DISK_SPACE OFF 22 | set_global_assignment -name SMART_RECOMPILE ON 23 | set_global_assignment -name MIN_CORE_JUNCTION_TEMP "-40" 24 | set_global_assignment -name MAX_CORE_JUNCTION_TEMP 100 25 | set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" 26 | set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" 27 | set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS OFF 28 | set_global_assignment -name OPTIMIZE_POWER_DURING_FITTING OFF 29 | set_global_assignment -name FINAL_PLACEMENT_OPTIMIZATION ALWAYS 30 | set_global_assignment -name FITTER_EFFORT "STANDARD FIT" 31 | set_global_assignment -name OPTIMIZATION_MODE "HIGH PERFORMANCE EFFORT" 32 | set_global_assignment -name ALLOW_POWER_UP_DONT_CARE ON 33 | set_global_assignment -name QII_AUTO_PACKED_REGISTERS NORMAL 34 | set_global_assignment -name ROUTER_LCELL_INSERTION_AND_LOGIC_DUPLICATION ON 35 | set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC ON 36 | set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON 37 | set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON 38 | set_global_assignment -name OPTIMIZATION_TECHNIQUE SPEED 39 | set_global_assignment -name MUX_RESTRUCTURE ON 40 | set_global_assignment -name REMOVE_REDUNDANT_LOGIC_CELLS ON 41 | set_global_assignment -name AUTO_DELAY_CHAINS_FOR_HIGH_FANOUT_INPUT_PINS ON 42 | set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC_FOR_AREA ON 43 | set_global_assignment -name ADV_NETLIST_OPT_SYNTH_WYSIWYG_REMAP ON 44 | set_global_assignment -name SYNTH_GATED_CLOCK_CONVERSION ON 45 | set_global_assignment -name PRE_MAPPING_RESYNTHESIS ON 46 | set_global_assignment -name ROUTER_CLOCKING_TOPOLOGY_ANALYSIS ON 47 | set_global_assignment -name ECO_OPTIMIZE_TIMING ON 48 | set_global_assignment -name PERIPHERY_TO_CORE_PLACEMENT_AND_ROUTING_OPTIMIZATION ON 49 | set_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING ON 50 | set_global_assignment -name ALM_REGISTER_PACKING_EFFORT MEDIUM 51 | set_global_assignment -name SEED 1 52 | 53 | #set_global_assignment -name VERILOG_MACRO "MISTER_FB=1" 54 | 55 | #enable it only if 8bit indexed mode is used in core 56 | #set_global_assignment -name VERILOG_MACRO "MISTER_FB_PALETTE=1" 57 | 58 | #do not enable DEBUG_NOHDMI in release! 59 | #set_global_assignment -name VERILOG_MACRO "MISTER_DEBUG_NOHDMI=1" 60 | 61 | # disable bilinear filtering when downscaling 62 | #set_global_assignment -name VERILOG_MACRO "MISTER_DOWNSCALE_NN=1" 63 | 64 | # disable adaptive scanline filtering 65 | #set_global_assignment -name VERILOG_MACRO "MISTER_DISABLE_ADAPTIVE=1" 66 | 67 | #use only 1MB per frame for scaler to free ~21MB DDR3 RAM 68 | #set_global_assignment -name VERILOG_MACRO "MISTER_SMALL_VBUF=1" 69 | 70 | # Disable YC / Composite output to save some resources 71 | #set_global_assignment -name VERILOG_MACRO "MISTER_DISABLE_YC=1" 72 | 73 | # Disable ALSA audio output to save some resources 74 | #set_global_assignment -name VERILOG_MACRO "MISTER_DISABLE_ALSA=1" 75 | 76 | source sys/sys.tcl 77 | source sys/sys_analog.tcl 78 | source files.qip 79 | set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Atari System-1 FPGA Arcade 2 | 3 | ## About 4 | FPGA implementation of Atari's System 1 (LSI version) arcade platform from 1984. 5 | Based primarily on the SP-280, SP-286 schematics with additional support from SP-277, SP-298 6 | 7 | System-1 supported game cartridges according to MAME 8 | * Marble Madness (1984) 9 | * Peter Pack Rat (1985) 10 | * Road Runner (1985) 11 | * Indiana Jones and the Temple of Doom (1985) 12 | * RoadBlasters (1987) 13 | 14 | ## Known Issues 15 | The following mra files don't work as expected. 16 | * Indiana Jones (cocktail).mra graphics tiles incorrectly offset, directional controls not working. 17 | * Indiana Jones (set 3).mra upside down corrupt or missing graphics, text is OK. 18 | 19 | ## Building 20 | The project files are setup for Quartus 17 21 | -------------------------------------------------------------------------------- /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 | for /d %%i in (sys\*_sim) do rmdir /s /q "%%i" 17 | for /d %%i in (rtl\*_sim) do rmdir /s /q "%%i" 18 | del build_id.v 19 | del c5_pin_model_dump.txt 20 | del PLLJ_PLLSPE_INFO.txt 21 | del /s *.json 22 | del /s *.qws 23 | del /s *.ppf 24 | del /s *.ddb 25 | del /s *.csv 26 | del /s *.cmp 27 | del /s *.sip 28 | del /s *.spd 29 | del /s *.bsf 30 | rem del /s *.f 31 | del /s *.sopcinfo 32 | del /s *.xml 33 | del *.cdf 34 | del *.rpt 35 | del /s new_rtl_netlist 36 | del /s old_rtl_netlist 37 | pause 38 | -------------------------------------------------------------------------------- /doc/Atari_Cart_Indiana_Jones_Temple.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/Atari_Cart_Indiana_Jones_Temple.jpg -------------------------------------------------------------------------------- /doc/Atari_Cart_Marble_Madness.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/Atari_Cart_Marble_Madness.jpg -------------------------------------------------------------------------------- /doc/Atari_Cart_Peter_Pack_Rat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/Atari_Cart_Peter_Pack_Rat.jpg -------------------------------------------------------------------------------- /doc/Atari_Cart_Road_Blasters.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/Atari_Cart_Road_Blasters.jpg -------------------------------------------------------------------------------- /doc/Atari_Cart_Road_Runner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/Atari_Cart_Road_Runner.jpg -------------------------------------------------------------------------------- /doc/Atari_Sys1+RoadBlasters.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/Atari_Sys1+RoadBlasters.jpg -------------------------------------------------------------------------------- /doc/Atari_Sys1-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/Atari_Sys1-0.jpg -------------------------------------------------------------------------------- /doc/Atari_Sys1-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/Atari_Sys1-1.jpg -------------------------------------------------------------------------------- /doc/Atari_Sys1-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/Atari_Sys1-2.jpg -------------------------------------------------------------------------------- /doc/Atari_Sys1-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/Atari_Sys1-3.jpg -------------------------------------------------------------------------------- /doc/SP-276 MARBLE MADNESS 1ST PRINTING.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/SP-276 MARBLE MADNESS 1ST PRINTING.pdf -------------------------------------------------------------------------------- /doc/SP-277 ATARI SYSTEM 1 1ST PRINTING SCHEMATIC PACKAGE U.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/SP-277 ATARI SYSTEM 1 1ST PRINTING SCHEMATIC PACKAGE U.pdf -------------------------------------------------------------------------------- /doc/SP-280_Atari_System_Cartridge_1st_Printing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/SP-280_Atari_System_Cartridge_1st_Printing.pdf -------------------------------------------------------------------------------- /doc/SP-282_Indiana_Jones_and_the_Temple_of_Doom_1st_Printing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/SP-282_Indiana_Jones_and_the_Temple_of_Doom_1st_Printing.pdf -------------------------------------------------------------------------------- /doc/SP-286 ATARI SYSTEM 1 1ST PRINTING.PDF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/SP-286 ATARI SYSTEM 1 1ST PRINTING.PDF -------------------------------------------------------------------------------- /doc/SP-298_Road_Blasters_1st_Printing_for_System_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/SP-298_Road_Blasters_1st_Printing_for_System_1.pdf -------------------------------------------------------------------------------- /doc/SP-299_Road_Blasters_Cockpit_1st_Printing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/SP-299_Road_Blasters_Cockpit_1st_Printing.pdf -------------------------------------------------------------------------------- /doc/TM-276 Marble Madness.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/TM-276 Marble Madness.pdf -------------------------------------------------------------------------------- /doc/TM-280 Peter Pack-Rat - 1984 - Atari.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/TM-280 Peter Pack-Rat - 1984 - Atari.pdf -------------------------------------------------------------------------------- /doc/TM-282 Indiana Jones and the Temple of Doom (1st Printing).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/TM-282 Indiana Jones and the Temple of Doom (1st Printing).pdf -------------------------------------------------------------------------------- /doc/TM-285 Road Runner (1st Printing).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/TM-285 Road Runner (1st Printing).pdf -------------------------------------------------------------------------------- /doc/TM-286 Atari System1 (1st printing).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/TM-286 Atari System1 (1st printing).pdf -------------------------------------------------------------------------------- /doc/TM-298 Road Blasters.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/doc/TM-298 Road Blasters.pdf -------------------------------------------------------------------------------- /files.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name SYSTEMVERILOG_FILE Arcade-atarisys1.sv 2 | set_global_assignment -name QIP_FILE rtl/lib/jt51/hdl/jt51.qip 3 | set_global_assignment -name VHDL_FILE rtl/lib/quad.vhd 4 | set_global_assignment -name VHDL_FILE rtl/lib/LETA_REP.vhd 5 | set_global_assignment -name VHDL_FILE rtl/lib/m6522.vhd 6 | set_global_assignment -name VHDL_FILE rtl/lib/POKEY.vhd 7 | set_global_assignment -name VHDL_FILE rtl/lib/T65/T65.vhd 8 | set_global_assignment -name VHDL_FILE rtl/lib/T65/T65_ALU.vhd 9 | set_global_assignment -name VHDL_FILE rtl/lib/T65/T65_MCode.vhd 10 | set_global_assignment -name VHDL_FILE rtl/lib/T65/T65_Pack.vhd 11 | set_global_assignment -name VHDL_FILE rtl/lib/TG68K/TG68K.vhd 12 | set_global_assignment -name VHDL_FILE rtl/lib/TG68K/TG68K_ALU.vhd 13 | set_global_assignment -name VHDL_FILE rtl/lib/TG68K/TG68K_Pack.vhd 14 | set_global_assignment -name VHDL_FILE rtl/lib/TG68K/TG68KdotC_Kernel.vhd 15 | set_global_assignment -name VHDL_FILE rtl/lib/mem/dpram.vhd 16 | set_global_assignment -name VHDL_FILE rtl/lib/mem/sdram.vhd 17 | set_global_assignment -name SDC_FILE rtl/lib/mem/sdram.sdc 18 | set_global_assignment -name VHDL_FILE rtl/atarisys1/PROM_5E.vhd 19 | set_global_assignment -name VHDL_FILE rtl/atarisys1/LS299.vhd 20 | set_global_assignment -name VHDL_FILE rtl/atarisys1/RAM_2K8.vhd 21 | set_global_assignment -name VHDL_FILE rtl/atarisys1/CRAMS.vhd 22 | set_global_assignment -name VHDL_FILE rtl/atarisys1/VRAMS.vhd 23 | set_global_assignment -name VHDL_FILE rtl/atarisys1/GPC.vhd 24 | set_global_assignment -name VHDL_FILE rtl/atarisys1/LINEBUF.vhd 25 | set_global_assignment -name VHDL_FILE rtl/atarisys1/LINECTR.vhd 26 | set_global_assignment -name VHDL_FILE rtl/atarisys1/MOHLB_LSI.vhd 27 | set_global_assignment -name VHDL_FILE rtl/atarisys1/PFHS.vhd 28 | set_global_assignment -name VHDL_FILE rtl/atarisys1/RGBI.vhd 29 | set_global_assignment -name VHDL_FILE rtl/atarisys1/SLAGS.vhd 30 | set_global_assignment -name VHDL_FILE rtl/atarisys1/SLAPSTIC.vhd 31 | set_global_assignment -name VHDL_FILE rtl/atarisys1/SYNGEN.vhd 32 | set_global_assignment -name VHDL_FILE rtl/atarisys1/TMS5220.vhd 33 | set_global_assignment -name VHDL_FILE rtl/atarisys1/MAIN.vhd 34 | set_global_assignment -name VHDL_FILE rtl/atarisys1/AUDIO.vhd 35 | set_global_assignment -name VHDL_FILE rtl/atarisys1/VIDEO.vhd 36 | set_global_assignment -name VHDL_FILE rtl/atarisys1/CART.vhd 37 | set_global_assignment -name VHDL_FILE rtl/atarisys1/ATARISYS1.vhd 38 | -------------------------------------------------------------------------------- /releases/Arcade-atarisys1_20231130.rbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/releases/Arcade-atarisys1_20231130.rbf -------------------------------------------------------------------------------- /releases/Arcade-atarisys1_20231212.rbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/releases/Arcade-atarisys1_20231212.rbf -------------------------------------------------------------------------------- /releases/Arcade-atarisys1_20240410.rbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/releases/Arcade-atarisys1_20240410.rbf -------------------------------------------------------------------------------- /releases/Marble Madness (set 5 - LSI).mra: -------------------------------------------------------------------------------- 1 | 2 | Marble Madness (set 5 - LSI Cartridge) 3 | 0254 4 | marble5 5 | 20230303000000 6 | 1984 7 | Atari Games 8 | Arcade 9 | atarisys1 10 | 11 | 12 | 13 | 14 | 15 | 16 | 67 17 | 18 | 19 | 20 | 21 | FF 22 | 23 | 24 | 25 | 26 | FF 27 | 28 | FF 29 | 30 | FF 31 | 32 | FF 33 | 34 | FF 35 | FF 36 | FF 37 | FF 38 | 39 | 40 | 41 | 42 | FF 43 | 44 | FF 45 | FF 46 | 47 | FF 48 | FF 49 | 50 | FF 51 | FF 52 | FF 53 | FF 54 | FF 55 | FF 56 | 57 | 58 | 59 | FF 60 | 61 | 62 | FF 63 | 64 | 65 | FF 66 | 67 | 68 | FF 69 | 70 | 71 | FF 72 | 73 | 74 | 75 | 76 | FF 77 | 78 | FF 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | FF 95 | 96 | 97 | FF 98 | 99 | 100 | FF 101 | 102 | 103 | FF 104 | 105 | 106 | FF 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 00 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | FF 124 | 125 | 126 | 127 | 128 | 129 | FF 00 0C 00 0C 00 00 00 0C 00 00 00 00 00 0C 60 130 | FD 63 00 9C FF 60 02 01 00 00 00 00 00 01 FF 00 131 | 0C 00 0C 00 00 00 0C 00 00 00 00 00 0C 60 FD 63 132 | 00 9C FF 60 02 01 00 00 00 00 00 01 01 4A BF 00 133 | 85 38 A4 12 EF D2 00 36 B0 84 3F E3 0F 2B 00 9D 134 | 34 BC 2D 56 5C 00 32 C8 78 88 FF 00 00 00 00 00 135 | 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 136 | 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 137 | 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 00 138 | 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 00 00 139 | 00 00 00 00 00 FF 00 00 00 00 00 00 00 00 00 00 140 | 00 00 00 00 FF 00 00 00 00 00 00 00 00 00 00 00 141 | 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF 142 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 143 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 144 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 145 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 146 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 147 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 148 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 149 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 150 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 151 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 152 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 153 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 154 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 155 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 156 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 157 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 158 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 159 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 160 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /rtl/atarisys1/CRAMS.vhd: -------------------------------------------------------------------------------- 1 | -- (c) 2020 d18c7db(a)hotmail 2 | -- 3 | -- This program is free software; you can redistribute it and/or modify it under 4 | -- the terms of the GNU General Public License version 3 or, at your option, 5 | -- any later version as published by the Free Software Foundation. 6 | -- 7 | -- This program is distributed in the hope that it will be useful, 8 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 10 | -- 11 | -- For full details, see the GNU General Public License at www.gnu.org/licenses 12 | -- 13 | 14 | library ieee; 15 | use ieee.std_logic_1164.all; 16 | use ieee.numeric_std.all; 17 | 18 | entity CRAMS is 19 | port( 20 | I_MCKR : in std_logic; 21 | I_WEn : in std_logic; 22 | I_CRA : in std_logic_vector( 9 downto 0); 23 | I_CRD : in std_logic_vector(15 downto 0); 24 | O_CRD : out std_logic_vector(15 downto 0) 25 | ); 26 | end CRAMS; 27 | 28 | architecture RTL of CRAMS is 29 | type RAM_ARRAY_1Kx16 is array (0 to 1023) of std_logic_vector(15 downto 0); 30 | signal RAM : RAM_ARRAY_1Kx16:=(others=>(others=>'0')); 31 | -- Ask Xilinx synthesis to use block RAMs if possible 32 | attribute ram_style : string; 33 | attribute ram_style of RAM : signal is "block"; 34 | -- Ask Quartus synthesis to use block RAMs if possible 35 | attribute ramstyle : string; 36 | attribute ramstyle of RAM : signal is "M10K"; 37 | 38 | begin 39 | p_CRAM : process 40 | begin 41 | wait until rising_edge(I_MCKR); 42 | if I_WEn = '0' then 43 | RAM(to_integer(unsigned(I_CRA))) <= I_CRD; 44 | else 45 | O_CRD <= RAM(to_integer(unsigned(I_CRA))); 46 | end if; 47 | end process; 48 | end RTL; 49 | -------------------------------------------------------------------------------- /rtl/atarisys1/GPC.vhd: -------------------------------------------------------------------------------- 1 | -- (c) 2020 d18c7db(a)hotmail 2 | -- 3 | -- This program is free software; you can redistribute it and/or modify it under 4 | -- the terms of the GNU General Public License version 3 or, at your option, 5 | -- any later version as published by the Free Software Foundation. 6 | -- 7 | -- This program is distributed in the hope that it will be useful, 8 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 10 | -- 11 | -- For full details, see the GNU General Public License at www.gnu.org/licenses 12 | -- 13 | -- Graphic Priority Control (Atari custom chip 137419-101) 14 | -- This GPC was derived from System I SP-277 schematic 15 | 16 | library ieee; 17 | use ieee.std_logic_1164.all; 18 | use ieee.std_logic_arith.all; 19 | use ieee.std_logic_unsigned.all; 20 | 21 | entity GPC is 22 | port( 23 | I_CK : in std_logic; -- MCKR 24 | I_PFM : in std_logic; -- PFSC/MO 25 | I_421H : in std_logic_vector(2 downto 0); -- 4H 2H 1H 26 | I_SEL : in std_logic; -- /CRAM 27 | I_AL : in std_logic_vector(1 downto 0); -- APIX 28 | I_MA : in std_logic_vector(1 downto 0); -- MA9, MA10 29 | I_D : in std_logic_vector(3 downto 0); -- VRD 30 | I_P : in std_logic_vector(7 downto 0); -- PFX 31 | I_M : in std_logic_vector(7 downto 0); -- MPX 32 | 33 | O_CA : out std_logic_vector(9 downto 0) -- CRA 34 | ); 35 | end GPC; 36 | 37 | architecture RTL of GPC is 38 | signal 39 | sl_gate, 40 | sl_8C6, 41 | sl_3F2, 42 | sl_1C12 43 | : std_logic := '1'; 44 | signal 45 | PROM_3E_data, 46 | slv_CRAS 47 | : std_logic_vector(1 downto 0) := (others=>'1'); 48 | signal 49 | slv_ALC 50 | : std_logic_vector(2 downto 0) := (others=>'1'); 51 | signal 52 | slv_3H 53 | : std_logic_vector(3 downto 0) := (others=>'1'); 54 | signal 55 | slv_9D 56 | : std_logic_vector(7 downto 0) := (others=>'1'); 57 | begin 58 | -- 8D tristate buffers 59 | O_CA <= I_MA & "00000000" when I_SEL = '0' else slv_CRAS & slv_9D; 60 | 61 | -- gate 8C output 6 (PFX7..3) 62 | sl_8C6 <= (not (I_P(7) or I_P(6) or I_P(5) or I_P(4) or I_P(3))); 63 | 64 | -- gate 1C output 12 (MPX3..1) 65 | sl_1C12 <= (not (I_M(3) and I_M(2) and I_M(1))); 66 | 67 | -- when any of these are high, PROM output is all low 68 | sl_gate <= not (sl_3F2 or I_AL(1) or I_AL(0)); 69 | 70 | -- These equations describe the PROM 3E contents, 71 | -- top 2 data bits are the same as bottom 2 data bits as can be seen in PROM dump 72 | PROM_3E_data(1) <= sl_gate and ((sl_8C6 and I_PFM) or (not I_M(7)) or (I_M(0) and (not sl_1C12)) ); 73 | PROM_3E_data(0) <= sl_gate and not ((sl_8C6 and I_PFM) or (((not I_M(7)) or (I_M(0))) and (not sl_1C12)) ); 74 | 75 | -- Graphic Priority Control selection 76 | -- 3C9 3C7 4C7 4C9 7C7 7C9 6C7 6C9 case 77 | -- GND GND GND ALC2 ALC1 ALC0 APIX1 APIX0 0 78 | -- GND /MPX6 /MPX5 /MPX4 /MPX3 /MPX2 /MPX1 /MPX0 1 79 | -- PFX7 PFX6 PFX5 PFX4 PFX3 PFX2 PFX1 PFX0 2 80 | -- PFX3 PFX2 PFX1 PFX0 /MPX3 /MPX2 /MPX1 /MPX0 3 81 | 82 | -- 9D latch 83 | p_9D : process 84 | begin 85 | wait until falling_edge(I_CK); 86 | if I_SEL = '1' then 87 | -- 3C, 4C, 7C, 6C dual 4:1 muxes 88 | case PROM_3E_data is 89 | when "00" => slv_9D <= "000" & slv_ALC & I_AL; 90 | when "01" => slv_9D <= '0' & not I_M(6 downto 0); 91 | when "10" => slv_9D <= I_P; 92 | when "11" => slv_9D <= I_P(3 downto 0) & not I_M(3 downto 0); 93 | when others => slv_9D <= (others=>'1'); 94 | end case; 95 | end if; 96 | end process; 97 | 98 | -- 3H latch 99 | p_3H : process 100 | begin 101 | wait until rising_edge(I_CK); 102 | if (I_421H="011") then -- rising edge 4H 103 | slv_3H <= I_D; 104 | end if; 105 | end process; 106 | 107 | -- 3F latch 108 | p_3F : process 109 | begin 110 | wait until falling_edge(I_CK); 111 | if I_421H(1 downto 0)="11" then -- 3H 112 | sl_3F2 <= slv_3H(3); 113 | slv_ALC <= slv_3H(2 downto 0); 114 | end if; 115 | end process; 116 | 117 | -- 1B, 5B latch 118 | p_1B_5B : process 119 | begin 120 | wait until falling_edge(I_CK); 121 | slv_CRAS <= PROM_3E_data; 122 | end process; 123 | end RTL; 124 | -------------------------------------------------------------------------------- /rtl/atarisys1/LINEBUF.vhd: -------------------------------------------------------------------------------- 1 | -- (c) 2020 d18c7db(a)hotmail 2 | -- 3 | -- This program is free software; you can redistribute it and/or modify it under 4 | -- the terms of the GNU General Public License version 3 or, at your option, 5 | -- any later version as published by the Free Software Foundation. 6 | -- 7 | -- This program is distributed in the hope that it will be useful, 8 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 10 | -- 11 | -- For full details, see the GNU General Public License at www.gnu.org/licenses 12 | -- 13 | -- Line Buffer used in Motion Object Horizontal Line Buffer module 14 | 15 | library ieee; 16 | use ieee.std_logic_1164.all; 17 | use ieee.std_logic_unsigned.all; 18 | use ieee.numeric_std.all; 19 | 20 | entity LINEBUF is 21 | port( 22 | I_MCKR : in std_logic; 23 | I_FLBn : in std_logic; 24 | I_CSn : in std_logic; 25 | 26 | I_HPOS : in std_logic_vector(8 downto 0); 27 | I_MOSR : in std_logic_vector(7 downto 0); 28 | 29 | O_MPX : out std_logic_vector(7 downto 0) 30 | ); 31 | end LINEBUF; 32 | 33 | architecture RTL of LINEBUF is 34 | type RAM_ARRAY is array (0 to 511) of std_logic_vector(7 downto 0); 35 | signal RAM : RAM_ARRAY := ((others=>(others=>'1'))); 36 | -- Ask Xilinx synthesis to use block RAMs if possible 37 | attribute ram_style : string; 38 | attribute ram_style of RAM : signal is "block"; 39 | -- Ask Quartus synthesis to use block RAMs if possible 40 | attribute ramstyle : string; 41 | attribute ramstyle of RAM : signal is "M10K"; 42 | 43 | signal 44 | slv_LBD 45 | : std_logic_vector( 7 downto 0) := (others=>'1'); 46 | signal 47 | slv_LB 48 | : std_logic_vector( 8 downto 0) := (others=>'1'); 49 | begin 50 | slv_LB <= I_HPOS; 51 | 52 | p_rams : process 53 | begin 54 | wait until falling_edge(I_MCKR); 55 | if I_CSn = '0' then 56 | RAM(to_integer(unsigned(slv_LB))) <= slv_LBD; 57 | O_MPX <= RAM(to_integer(unsigned(slv_LB))); 58 | else 59 | O_MPX <= (others=>'1'); 60 | end if; 61 | end process; 62 | 63 | slv_LBD <= I_MOSR when I_FLBn = '0' else (others=>'1'); 64 | end RTL; 65 | -------------------------------------------------------------------------------- /rtl/atarisys1/LINECTR.vhd: -------------------------------------------------------------------------------- 1 | -- (c) 2020 d18c7db(a)hotmail 2 | -- 3 | -- This program is free software; you can redistribute it and/or modify it under 4 | -- the terms of the GNU General Public License version 3 or, at your option, 5 | -- any later version as published by the Free Software Foundation. 6 | -- 7 | -- This program is distributed in the hope that it will be useful, 8 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 10 | -- 11 | -- For full details, see the GNU General Public License at www.gnu.org/licenses 12 | -- 13 | -- Custom chip LBC 137419-102 14 | 15 | library ieee; 16 | use ieee.std_logic_1164.all; 17 | use ieee.std_logic_unsigned.all; 18 | use ieee.numeric_std.all; 19 | 20 | entity LINECTR is 21 | port( 22 | I_MCKR : in std_logic; 23 | I_VRD : in std_logic_vector(15 downto 5); 24 | I_NXLn : in std_logic; 25 | I_421H : in std_logic_vector( 2 downto 0); -- 4H 2H 1H 26 | 27 | O_BQ : out std_logic_vector(8 downto 0); 28 | O_PA : out std_logic; 29 | O_PAn : out std_logic; 30 | O_GLDn : out std_logic; 31 | O_MOn : out std_logic 32 | ); 33 | end LINECTR; 34 | 35 | architecture RTL of LINECTR is 36 | signal 37 | sl_LDn, 38 | sl_PAD, 39 | sl_NXLn, 40 | sl_CLRn, 41 | sl_MOSR7D, 42 | sl_BUFCLRn, 43 | sl_MOn 44 | : std_logic := '1'; 45 | signal 46 | slv_NXL_delay 47 | : std_logic_vector( 7 downto 0) := (others=>'1'); 48 | signal 49 | slv_LB, 50 | slv_3J 51 | : std_logic_vector( 8 downto 0) := (others=>'1'); 52 | begin 53 | O_GLDn <= (I_421H(1) or I_421H(0)); 54 | O_PAn <= not sl_PAD; 55 | O_PA <= sl_PAD; 56 | O_BQ <= slv_LB; 57 | O_MOn <= sl_MOn; 58 | sl_NXLn <= I_NXLn; 59 | sl_BUFCLRn <= slv_NXL_delay(7); 60 | sl_CLRn <= sl_PAD or sl_BUFCLRn; 61 | 62 | -- generate some internal signals 63 | p_nxl : process 64 | begin 65 | wait until rising_edge(I_MCKR); 66 | -- /BUFCLR signal is just /NXL delayed 8 clocks 67 | slv_NXL_delay <= slv_NXL_delay(6 downto 0) & sl_NXLn; 68 | -- create PADB signal from recovered /BUFCLRN 69 | sl_PAD <= (not sl_PAD) xor sl_BUFCLRn; 70 | end process; 71 | 72 | -- 4J, 3D on SP-277 schema sheet 8 73 | sl_LDn <= I_421H(2) or ((not I_421H(1)) or (I_421H(0))) or sl_PAD; 74 | 75 | -- 3T, 3R, 3W, 3U, 3S, 3X counters 76 | p_ctrs : process 77 | begin 78 | wait until rising_edge(I_MCKR); 79 | if sl_CLRn = '0' then 80 | slv_LB <= (others=>'0'); 81 | elsif sl_LDn = '0' then 82 | slv_LB <= slv_3J; 83 | else 84 | slv_LB <= slv_LB + 1; 85 | end if; 86 | end process; 87 | 88 | p_MOSR7 : process 89 | begin 90 | wait until rising_edge(I_MCKR); 91 | if (I_421H = "101") then -- rising 4HDD 92 | sl_MOSR7D <= I_VRD(15); 93 | slv_3J <= I_VRD(13 downto 5); -- latch 3J 94 | end if; 95 | if (I_421H = "010") then -- rising /4HD3 96 | sl_MOn <= sl_MOSR7D; -- VRD15 delayed by 4HDD and then by /4HD3 97 | end if; 98 | end process; 99 | end RTL; 100 | -------------------------------------------------------------------------------- /rtl/atarisys1/LS299.vhd: -------------------------------------------------------------------------------- 1 | -- (c) 2020 d18c7db(a)hotmail 2 | -- 3 | -- This program is free software; you can redistribute it and/or modify it under 4 | -- the terms of the GNU General Public License version 3 or, at your option, 5 | -- any later version as published by the Free Software Foundation. 6 | -- 7 | -- This program is distributed in the hope that it will be useful, 8 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 10 | -- 11 | -- For full details, see the GNU General Public License at www.gnu.org/licenses 12 | -- 13 | 14 | library ieee; 15 | use ieee.std_logic_1164.all; 16 | 17 | -- simplified 74LS299 shifter as used in SLAGS 18 | entity LS299 is 19 | port( 20 | I_CK : in std_logic; -- Clock 21 | I_DATA : in std_logic_vector(7 downto 0); -- parallel input 22 | I_SEL : in std_logic_vector(1 downto 0); -- S1 S0 23 | I_SL : in std_logic; -- SL shift left input 24 | I_SR : in std_logic; -- SR shift right input 25 | O_SL : out std_logic; -- QA shift left output 26 | O_SR : out std_logic -- QH shift right output 27 | ); 28 | end LS299; 29 | 30 | architecture RTL of LS299 is 31 | signal slv_shifter : std_logic_vector(7 downto 0) := (others=>'0'); 32 | begin 33 | O_SR <= slv_shifter(7); 34 | O_SL <= slv_shifter(0); 35 | 36 | -- LS299 shifter, datasheet "right" means shift lsb towards msb, "left" is the reverse 37 | p_shift : process 38 | begin 39 | wait until rising_edge(I_CK); 40 | case I_SEL is 41 | when "11" => slv_shifter <= I_DATA; -- load 42 | when "10" => slv_shifter <= I_SL & slv_shifter(7 downto 1); -- left 43 | when "01" => slv_shifter <= slv_shifter(6 downto 0) & I_SR ; -- right 44 | when "00" => -- hold 45 | when others => null; 46 | end case; 47 | end process; 48 | end RTL; 49 | -------------------------------------------------------------------------------- /rtl/atarisys1/MOHLB_LSI.vhd: -------------------------------------------------------------------------------- 1 | -- (c) 2020 d18c7db(a)hotmail 2 | -- 3 | -- This program is free software; you can redistribute it and/or modify it under 4 | -- the terms of the GNU General Public License version 3 or, at your option, 5 | -- any later version as published by the Free Software Foundation. 6 | -- 7 | -- This program is distributed in the hope that it will be useful, 8 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 10 | -- 11 | -- For full details, see the GNU General Public License at www.gnu.org/licenses 12 | -- 13 | -- Motion Object Horizontal Line Buffer based on SP-286 schematic sheet 7 14 | 15 | library ieee; 16 | use ieee.std_logic_1164.all; 17 | 18 | entity MOHLB_LSI is 19 | port( 20 | I_MCKR : in std_logic; 21 | I_NXLn : in std_logic; 22 | I_LMPDn : in std_logic; 23 | I_421H : in std_logic_vector( 2 downto 0); -- 4H 2H 1H 24 | I_VRD : in std_logic_vector(15 downto 0); 25 | I_MOSR : in std_logic_vector( 6 downto 0); 26 | O_MPX : out std_logic_vector( 7 downto 0); 27 | O_GLDn : out std_logic 28 | ); 29 | end MOHLB_LSI; 30 | 31 | architecture RTL of MOHLB_LSI is 32 | signal 33 | sl_NXL_B, 34 | sl_LMPDn, 35 | sl_PA, 36 | sl_PADBn, 37 | sl_PADB, 38 | sl_ACSn, 39 | sl_BCSn, 40 | sl_MOn, 41 | sl_NXLn, 42 | sl_GLDn 43 | : std_logic := '0'; 44 | 45 | signal 46 | slv_MPX, 47 | slv_MOSR, 48 | slv_MPXA, 49 | slv_MPXB 50 | : std_logic_vector( 7 downto 0) := (others=>'0'); 51 | signal 52 | slv_BQA, 53 | slv_BQB 54 | : std_logic_vector( 8 downto 0) := (others=>'0'); 55 | signal 56 | slv_VRD 57 | : std_logic_vector(15 downto 0) := (others=>'0'); 58 | begin 59 | sl_NXLn <= I_NXLn; 60 | slv_VRD <= I_VRD; 61 | sl_LMPDn <= I_LMPDn; 62 | 63 | O_MPX <= slv_MPX; 64 | O_GLDn <= sl_GLDn; 65 | 66 | ------------- 67 | -- sheet 7 -- 68 | ------------- 69 | 70 | -- Custom chip 5/6 J/K (LBC 137419-102) 71 | u_LINECTRA : entity work.LINECTR 72 | port map ( 73 | I_MCKR => I_MCKR, 74 | I_VRD => slv_VRD(15 downto 5), 75 | I_NXLn => sl_NXLn, 76 | I_421H => I_421H, 77 | 78 | O_BQ => slv_BQA, 79 | O_PA => sl_PADBn, 80 | O_PAn => sl_PADB, 81 | O_GLDn => sl_GLDn, 82 | O_MOn => sl_MOn 83 | ); 84 | 85 | -- Line Buffer A 86 | u_LINBUFA : entity work.LINEBUF 87 | port map ( 88 | I_MCKR => I_MCKR, 89 | I_FLBn => sl_PADBn, 90 | I_CSn => sl_ACSn, 91 | I_HPOS => slv_BQA, 92 | I_MOSR => slv_MOSR, 93 | O_MPX => slv_MPXA 94 | ); 95 | 96 | -- Custom chip 5 J/K (LBC 137419-102) 97 | u_LINECTRB : entity work.LINECTR 98 | port map ( 99 | I_MCKR => I_MCKR, 100 | I_VRD => slv_VRD(15 downto 5), 101 | I_NXLn => sl_NXL_B, 102 | I_421H => I_421H, 103 | 104 | O_BQ => slv_BQB, 105 | O_PA => open, 106 | O_PAn => sl_PA, 107 | O_GLDn => open, 108 | O_MOn => open 109 | ); 110 | 111 | -- Line Buffer B 112 | u_LINBUFB : entity work.LINEBUF 113 | port map ( 114 | I_MCKR => I_MCKR, 115 | I_FLBn => sl_PADB, 116 | I_CSn => sl_BCSn, 117 | I_HPOS => slv_BQB, 118 | I_MOSR => slv_MOSR, 119 | O_MPX => slv_MPXB 120 | ); 121 | 122 | -- gate 1L generates top bit of MOSR 123 | slv_MOSR <= (not sl_MOn) & I_MOSR; 124 | 125 | -- gates 5J/K - the function of this circuit is to ensure that if the two LBC chips start synchronized 126 | -- a single NXL pulse is skipped to one of them and they become unsynced, so they capture alternate lines 127 | sl_NXL_B <= (sl_PADB xnor sl_PA) or sl_NXLn; 128 | 129 | -- gates 4L, 5L, 1L (and MCKR goes to the RAM clock) 130 | sl_ACSn <= ( sl_PADB ) and not (sl_LMPDn and (not (slv_MOSR(3) and slv_MOSR(2) and slv_MOSR(1) and slv_MOSR(0)))); 131 | sl_BCSn <= ( sl_PADBn) and not (sl_LMPDn and (not (slv_MOSR(3) and slv_MOSR(2) and slv_MOSR(1) and slv_MOSR(0)))); 132 | 133 | -- selectors 2K, 2J 134 | p_2K_2J : process 135 | begin 136 | wait until falling_edge(I_MCKR); 137 | if sl_PADB = '0' then 138 | slv_MPX <= slv_MPXA; 139 | else 140 | slv_MPX <= slv_MPXB; 141 | end if; 142 | end process; 143 | end RTL; 144 | -------------------------------------------------------------------------------- /rtl/atarisys1/MOHLB_TTL.vhd: -------------------------------------------------------------------------------- 1 | -- (c) 2020 d18c7db(a)hotmail 2 | -- 3 | -- This program is free software; you can redistribute it and/or modify it under 4 | -- the terms of the GNU General Public License version 3 or, at your option, 5 | -- any later version as published by the Free Software Foundation. 6 | -- 7 | -- This program is distributed in the hope that it will be useful, 8 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 10 | -- 11 | -- For full details, see the GNU General Public License at www.gnu.org/licenses 12 | -- 13 | -- Motion Object Horizontal Line Buffer based on SP-277 schematic sheet 9A 14 | 15 | library ieee; 16 | use ieee.std_logic_1164.all; 17 | use ieee.std_logic_unsigned.all; 18 | use ieee.numeric_std.all; 19 | 20 | entity MOHLB_TTL is 21 | port( 22 | I_MCKR : in std_logic; 23 | I_NXLn : in std_logic; 24 | I_LMPDn : in std_logic; 25 | I_421H : in std_logic_vector( 2 downto 0); -- 4H 2H 1H 26 | I_VRD : in std_logic_vector(15 downto 0); 27 | I_MOSR : in std_logic_vector( 6 downto 0); 28 | O_MPX : out std_logic_vector( 7 downto 0); 29 | O_GLDn : out std_logic 30 | ); 31 | end MOHLB_TTL; 32 | 33 | architecture RTL of MOHLB_TTL is 34 | signal 35 | sl_T1, 36 | sl_MOn, 37 | sl_LMPDn, 38 | sl_BUFCLRn, 39 | sl_PADB, 40 | sl_ACSn, 41 | sl_BCSn, 42 | sl_NXLn, 43 | sl_LDAn, 44 | sl_LDBn, 45 | sl_1H, 46 | sl_2H, 47 | sl_4H, 48 | sl_4HD3n, 49 | sl_4HD, 50 | sl_4HDD, 51 | sl_CLRAn, 52 | sl_CLRBn 53 | : std_logic := '0'; 54 | 55 | signal 56 | slv_MPX, 57 | slv_MOSR, 58 | slv_RAMAI, 59 | slv_MPXA, 60 | slv_RAMBI, 61 | slv_MPXB, 62 | slv_NXLD 63 | : std_logic_vector( 7 downto 0) := (others=>'0'); 64 | signal 65 | slv_BQA, 66 | slv_BQB, 67 | slv_3J 68 | : std_logic_vector( 8 downto 0) := (others=>'0'); 69 | signal 70 | slv_VRD 71 | : std_logic_vector(15 downto 0) := (others=>'0'); 72 | 73 | type RAM_ARRAY is array (0 to 511) of std_logic_vector(7 downto 0); 74 | signal RAMA : RAM_ARRAY := ((others=>(others=>'1'))); 75 | signal RAMB : RAM_ARRAY := ((others=>(others=>'1'))); 76 | attribute ram_style : string; 77 | attribute ram_style of RAMA : signal is "block"; 78 | attribute ram_style of RAMB : signal is "block"; 79 | 80 | begin 81 | sl_NXLn <= I_NXLn; 82 | slv_VRD <= I_VRD; 83 | sl_LMPDn <= I_LMPDn; 84 | sl_4H <= I_421H(2); 85 | sl_2H <= I_421H(1); 86 | sl_1H <= I_421H(0); 87 | 88 | O_MPX <= slv_MPX; 89 | O_GLDn <= sl_2H or sl_1H; 90 | 91 | slv_MOSR <= (not sl_MOn) & I_MOSR; 92 | 93 | sl_LDAn <= sl_4H or (not sl_2H) or sl_1H or (not sl_PADB) ; 94 | sl_LDBn <= sl_4H or (not sl_2H) or sl_1H or ( sl_PADB) ; 95 | 96 | sl_ACSn <= ( sl_PADB ) and not (sl_LMPDn and ( not ( slv_MOSR(3) and slv_MOSR(2) and slv_MOSR(1) and slv_MOSR(0) ) ) ); 97 | sl_BCSn <= (not sl_PADB ) and not (sl_LMPDn and ( not ( slv_MOSR(3) and slv_MOSR(2) and slv_MOSR(1) and slv_MOSR(0) ) ) ); 98 | 99 | sl_BUFCLRn <= slv_NXLD(7); 100 | sl_CLRAn <= (not sl_PADB) or sl_BUFCLRn; 101 | sl_CLRBn <= ( sl_PADB) or sl_BUFCLRn; 102 | 103 | p_hcnt : process 104 | begin 105 | wait until rising_edge(I_MCKR); 106 | sl_4HD <= sl_4H; 107 | sl_4HDD <= sl_4HD; 108 | sl_4HD3n <= not sl_4HDD; 109 | slv_NXLD <= slv_NXLD(6 downto 0) & sl_NXLn; 110 | sl_PADB <= (not sl_PADB) xor sl_BUFCLRn; 111 | end process; 112 | 113 | p_3J : process 114 | begin 115 | wait until rising_edge(sl_4HDD); 116 | slv_3J <= slv_VRD(13 downto 5); 117 | sl_T1 <= slv_VRD(15); 118 | end process; 119 | 120 | p_1K : process 121 | begin 122 | wait until rising_edge(sl_4HD3n); 123 | sl_MOn <= sl_T1; 124 | end process; 125 | 126 | p_2J_2H_2F : process 127 | begin 128 | wait until rising_edge(I_MCKR); 129 | if sl_CLRAn = '0' then 130 | slv_BQA <= (others=>'0'); 131 | elsif sl_LDAn = '0' then 132 | slv_BQA <= slv_3J; 133 | else 134 | slv_BQA <= slv_BQA + 1; 135 | end if; 136 | end process; 137 | 138 | p_1J_1H_1F : process 139 | begin 140 | wait until rising_edge(I_MCKR); 141 | if sl_CLRBn = '0' then 142 | slv_BQB <= (others=>'0'); 143 | elsif sl_LDBn = '0' then 144 | slv_BQB <= slv_3J; 145 | else 146 | slv_BQB <= slv_BQB + 1; 147 | end if; 148 | end process; 149 | 150 | p_RAMA : process 151 | begin 152 | wait until falling_edge(I_MCKR); 153 | if sl_ACSn = '0' then 154 | RAMA(to_integer(unsigned(slv_BQA))) <= slv_RAMAI; 155 | slv_MPXA <= RAMA(to_integer(unsigned(slv_BQA))); 156 | else 157 | slv_MPXA <= (others=>'1'); 158 | end if; 159 | end process; 160 | 161 | p_RAMB : process 162 | begin 163 | wait until falling_edge(I_MCKR); 164 | if sl_BCSn = '0' then 165 | RAMB(to_integer(unsigned(slv_BQB))) <= slv_RAMBI; 166 | slv_MPXB <= RAMB(to_integer(unsigned(slv_BQB))); 167 | else 168 | slv_MPXB <= (others=>'1'); 169 | end if; 170 | end process; 171 | 172 | slv_RAMAI <= slv_MOSR when sl_PADB = '1' else (others=>'1'); 173 | slv_RAMBI <= slv_MOSR when sl_PADB = '0' else (others=>'1'); 174 | 175 | p_2K_3K : process 176 | begin 177 | wait until falling_edge(I_MCKR); 178 | if sl_PADB = '0' then 179 | slv_MPX <= slv_MPXA; 180 | else 181 | slv_MPX <= slv_MPXB; 182 | end if; 183 | end process; 184 | end RTL; 185 | -------------------------------------------------------------------------------- /rtl/atarisys1/PFHS.vhd: -------------------------------------------------------------------------------- 1 | -- (c) 2020 d18c7db(a)hotmail 2 | -- 3 | -- This program is free software; you can redistribute it and/or modify it under 4 | -- the terms of the GNU General Public License version 3 or, at your option, 5 | -- any later version as published by the Free Software Foundation. 6 | -- 7 | -- This program is distributed in the hope that it will be useful, 8 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 10 | -- 11 | -- For full details, see the GNU General Public License at www.gnu.org/licenses 12 | -- 13 | -- Play Field Horizontal Scroll (Atari custom chip 137419-104) 14 | -- This PFHS was derived from System I SP-277 schematic 15 | 16 | library ieee; 17 | use ieee.std_logic_1164.all; 18 | use ieee.std_logic_unsigned.all; 19 | use ieee.numeric_std.all; 20 | 21 | entity PFHS is 22 | port( 23 | I_CK : in std_logic; -- MCKR 24 | I_ST : in std_logic; -- PFHST 25 | I_CTF : in std_logic; -- CTF (when '1' inverts O_PFH) 26 | I_421H : in std_logic_vector(2 downto 0); -- 4H 2H 1H 27 | I_HS : in std_logic; -- HSCRLD 28 | I_SPC : in std_logic; -- PFSPC 29 | I_D : in std_logic_vector(8 downto 0); -- VBD 30 | I_PS : in std_logic_vector(7 downto 0); -- PFSR 31 | 32 | O_PFM : out std_logic; -- PFSC/MO 33 | O_PFH : out std_logic_vector(5 downto 0); -- PF8H..PH256H 34 | O_XP : out std_logic_vector(7 downto 0) -- PFX 35 | ); 36 | end PFHS; 37 | 38 | architecture RTL of PFHS is 39 | type RAM_ARRAY is array (0 to 7) of std_logic_vector(7 downto 0); 40 | signal 41 | RAM_4M_5M_addr 42 | : std_logic_vector(2 downto 0) := (others=>'1'); 43 | signal 44 | slv_8E_9B 45 | : std_logic_vector(5 downto 0) := (others=>'1'); 46 | signal 47 | slv_4D 48 | : std_logic_vector(7 downto 0) := (others=>'1'); 49 | signal 50 | slv_10F, 51 | slv_11E 52 | : std_logic_vector(8 downto 0) := (others=>'1'); 53 | begin 54 | O_PFH <= slv_8E_9B when I_CTF = '0' else not slv_8E_9B; 55 | O_XP <= slv_4D; 56 | 57 | -- 10F and 1B latches 58 | p_10F_1B : process 59 | begin 60 | -- until rising edge I_HS in schema 61 | wait until rising_edge(I_CK); 62 | if (I_HS = '0') then 63 | slv_10F <= I_D; 64 | end if; 65 | end process; 66 | 67 | -- 11E latch 68 | p_11E : process 69 | begin 70 | -- until rising edge I_SPC in schema 71 | wait until rising_edge(I_CK); 72 | if (I_SPC = '0') then 73 | slv_11E <= I_D; 74 | end if; 75 | end process; 76 | 77 | -- 12E 8:1 mux 78 | O_PFM <= slv_11E(to_integer(unsigned(slv_4D(2 downto 0)))); 79 | 80 | -- two 74LS189 16x4 bit RAMs, arranged as one 16x8 RAM 81 | -- but only 3 address lines used, so really one 8x8 RAM 82 | -- IMPORTANT: data out is the COMPLEMENT of data in!!! 83 | p_4M_5M : process 84 | variable RAM : RAM_ARRAY; 85 | -- Ask Xilinx synthesis to use distributed logic RAMs if possible 86 | attribute ram_style : string; 87 | attribute ram_style of RAM : variable is "distributed"; 88 | -- Ask Quartus synthesis to use distributed logic RAMs if possible 89 | attribute ramstyle : string; 90 | attribute ramstyle of RAM : variable is "logic"; 91 | begin 92 | wait until falling_edge(I_CK); 93 | slv_4D <= RAM(to_integer(unsigned(RAM_4M_5M_addr))); -- 4D latch 94 | RAM(to_integer(unsigned(RAM_4M_5M_addr))) := not I_PS; 95 | end process; 96 | 97 | -- 6D counter 98 | p_6D : process 99 | begin 100 | wait until rising_edge(I_CK); 101 | if I_ST = '0' or RAM_4M_5M_addr = "111" then 102 | RAM_4M_5M_addr <= slv_10F(2 downto 0); 103 | else 104 | RAM_4M_5M_addr <= RAM_4M_5M_addr + 1; 105 | end if; 106 | end process; 107 | 108 | -- 8E, 9B counters 109 | p_8E_9B : process 110 | begin 111 | wait until rising_edge(I_CK); 112 | if I_421H = "011" then -- rising edge 4H 113 | if I_ST = '0' then 114 | slv_8E_9B <= slv_10F(8 downto 3); 115 | else 116 | slv_8E_9B <= slv_8E_9B + 1; 117 | end if; 118 | end if; 119 | end process; 120 | end RTL; 121 | -------------------------------------------------------------------------------- /rtl/atarisys1/PROM_5E.VHD: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | entity PROM_5E is 6 | port ( 7 | CLK : in std_logic; 8 | ADDR : in std_logic_vector(7 downto 0); 9 | DATA : out std_logic_vector(3 downto 0) := (others=>'1') 10 | ); 11 | end entity; 12 | 13 | architecture RTL of PROM_5E is 14 | type ROM_ARRAY is array (0 to 255) of std_logic_vector(3 downto 0); 15 | signal ROM : ROM_ARRAY := ( 16 | x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3", -- 0x0000 17 | x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3", -- 0x0010 18 | x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3", -- 0x0020 19 | x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3", -- 0x0030 20 | x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3", -- 0x0040 21 | x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3", -- 0x0050 22 | x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"B", -- 0x0060 23 | x"B",x"B",x"B",x"9",x"9",x"9",x"9",x"B",x"B",x"B",x"B",x"B",x"B",x"B",x"B",x"F", -- 0x0070 24 | x"F",x"F",x"F",x"F",x"F",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E", -- 0x0080 25 | x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E", -- 0x0090 26 | x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E", -- 0x00A0 27 | x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E", -- 0x00B0 28 | x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E", -- 0x00C0 29 | x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E", -- 0x00D0 30 | x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E", -- 0x00E0 31 | x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"3" -- 0x00F0 32 | ); 33 | attribute ram_style : string; 34 | attribute ram_style of ROM : signal is "distributed"; 35 | begin 36 | mem_proc : process 37 | begin 38 | wait until rising_edge(CLK); 39 | DATA <= ROM(to_integer(unsigned(ADDR))); 40 | end process; 41 | end RTL; 42 | -------------------------------------------------------------------------------- /rtl/atarisys1/RAM_2K8.vhd: -------------------------------------------------------------------------------- 1 | -- (c) 2020 d18c7db(a)hotmail 2 | -- 3 | -- This program is free software; you can redistribute it and/or modify it under 4 | -- the terms of the GNU General Public License version 3 or, at your option, 5 | -- any later version as published by the Free Software Foundation. 6 | -- 7 | -- This program is distributed in the hope that it will be useful, 8 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 10 | -- 11 | -- For full details, see the GNU General Public License at www.gnu.org/licenses 12 | -- 13 | -- generic 2K x 8 RAM definition 14 | 15 | library ieee; 16 | use ieee.std_logic_1164.all; 17 | use ieee.numeric_std.all; 18 | 19 | entity RAM_2K8 is 20 | port( 21 | I_MCKR : in std_logic; 22 | I_EN : in std_logic; 23 | I_WR : in std_logic; 24 | I_ADDR : in std_logic_vector(10 downto 0); 25 | I_DATA : in std_logic_vector( 7 downto 0); 26 | O_DATA : out std_logic_vector( 7 downto 0) 27 | ); 28 | end RAM_2K8; 29 | 30 | architecture RTL of RAM_2K8 is 31 | type RAM_ARRAY_2Kx8 is array (0 to 2047) of std_logic_vector(7 downto 0); 32 | signal RAM : RAM_ARRAY_2Kx8 := (others=>(others=>'0')); 33 | 34 | -- Ask Xilinx synthesis to use block RAMs if possible 35 | attribute ram_style : string; 36 | attribute ram_style of RAM : signal is "block"; 37 | -- Ask Quartus synthesis to use block RAMs if possible 38 | attribute ramstyle : string; 39 | attribute ramstyle of RAM : signal is "M10K"; 40 | 41 | begin 42 | p_RAM : process 43 | begin 44 | wait until rising_edge(I_MCKR); 45 | if I_EN ='1' then 46 | if I_WR = '1' then 47 | RAM(to_integer(unsigned(I_ADDR))) <= I_DATA; 48 | else 49 | O_DATA <= RAM(to_integer(unsigned(I_ADDR))); 50 | end if; 51 | end if; 52 | end process; 53 | end RTL; 54 | -------------------------------------------------------------------------------- /rtl/atarisys1/RGBI.vhd: -------------------------------------------------------------------------------- 1 | -- (c) 2020 d18c7db(a)hotmail 2 | -- 3 | -- This program is free software; you can redistribute it and/or modify it under 4 | -- the terms of the GNU General Public License version 3 or, at your option, 5 | -- any later version as published by the Free Software Foundation. 6 | -- 7 | -- This program is distributed in the hope that it will be useful, 8 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 10 | -- 11 | -- For full details, see the GNU General Public License at www.gnu.org/licenses 12 | -- 13 | 14 | library ieee; 15 | use ieee.std_logic_1164.all; 16 | use ieee.numeric_std.all; 17 | 18 | -- RGBI to RGB lookup table 19 | -- Implements function (Intensity * Color) / 16 rounded to nearest integer 20 | entity RGBI is 21 | port( 22 | ADDR : in std_logic_vector(7 downto 0); 23 | DATA : out std_logic_vector(3 downto 0) 24 | ); 25 | end RGBI; 26 | 27 | architecture RTL of RGBI is 28 | type ROM_ARRAY is array (0 to 255) of std_logic_vector(3 downto 0); 29 | signal ROM : ROM_ARRAY := ( 30 | x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", 31 | x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"1", x"1", x"1", x"1", x"1", x"1", x"1", x"1", 32 | x"0", x"0", x"0", x"0", x"1", x"1", x"1", x"1", x"1", x"1", x"1", x"1", x"2", x"2", x"2", x"2", 33 | x"0", x"0", x"0", x"1", x"1", x"1", x"1", x"1", x"2", x"2", x"2", x"2", x"2", x"3", x"3", x"3", 34 | x"0", x"0", x"1", x"1", x"1", x"1", x"2", x"2", x"2", x"2", x"3", x"3", x"3", x"3", x"4", x"4", 35 | x"0", x"0", x"1", x"1", x"1", x"2", x"2", x"2", x"3", x"3", x"3", x"4", x"4", x"4", x"5", x"5", 36 | x"0", x"0", x"1", x"1", x"2", x"2", x"2", x"3", x"3", x"4", x"4", x"4", x"5", x"5", x"6", x"6", 37 | x"0", x"0", x"1", x"1", x"2", x"2", x"3", x"3", x"4", x"4", x"5", x"5", x"6", x"6", x"7", x"7", 38 | x"0", x"1", x"1", x"2", x"2", x"3", x"3", x"4", x"4", x"5", x"5", x"6", x"6", x"7", x"7", x"8", 39 | x"0", x"1", x"1", x"2", x"2", x"3", x"4", x"4", x"5", x"5", x"6", x"7", x"7", x"8", x"8", x"9", 40 | x"0", x"1", x"1", x"2", x"3", x"3", x"4", x"5", x"5", x"6", x"7", x"7", x"8", x"9", x"9", x"A", 41 | x"0", x"1", x"1", x"2", x"3", x"4", x"4", x"5", x"6", x"7", x"7", x"8", x"9", x"A", x"A", x"B", 42 | x"0", x"1", x"2", x"2", x"3", x"4", x"5", x"6", x"6", x"7", x"8", x"9", x"A", x"A", x"B", x"C", 43 | x"0", x"1", x"2", x"3", x"3", x"4", x"5", x"6", x"7", x"8", x"9", x"A", x"A", x"B", x"C", x"D", 44 | x"0", x"1", x"2", x"3", x"4", x"5", x"6", x"7", x"7", x"8", x"9", x"A", x"B", x"C", x"D", x"E", 45 | x"0", x"1", x"2", x"3", x"4", x"5", x"6", x"7", x"8", x"9", x"A", x"B", x"C", x"D", x"E", x"F" 46 | ); 47 | attribute ram_style : string; -- for Xilinx ISE 48 | attribute ram_style of ROM : signal is "distributed"; 49 | attribute ramstyle : string; -- for Intel Quartus 50 | attribute ramstyle of ROM : signal is "logic"; 51 | begin 52 | -- rgbi_proc : process(ADDR) 53 | -- begin 54 | DATA <= ROM(to_integer(unsigned(ADDR))); 55 | -- end process; 56 | end RTL; 57 | -------------------------------------------------------------------------------- /rtl/atarisys1/SLAGS.vhd: -------------------------------------------------------------------------------- 1 | -- (c) 2020 d18c7db(a)hotmail 2 | -- 3 | -- This program is free software; you can redistribute it and/or modify it under 4 | -- the terms of the GNU General Public License version 3 or, at your option, 5 | -- any later version as published by the Free Software Foundation. 6 | -- 7 | -- This program is distributed in the hope that it will be useful, 8 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 10 | -- 11 | -- For full details, see the GNU General Public License at www.gnu.org/licenses 12 | -- 13 | -- Storage/Logic Array Graphics Shifter (Atari custom chip 137415-101) 14 | -- This SLAGS was derived from Marble Madness SP-276 schematic 15 | 16 | library ieee; 17 | use ieee.std_logic_1164.all; 18 | 19 | entity SLAGS is 20 | port( 21 | I_MCKR : in std_logic; -- RCLOCK 22 | I_A : in std_logic_vector(7 downto 0); 23 | I_B : in std_logic_vector(7 downto 0); 24 | I_HLDAn : in std_logic; -- /HOLDA 25 | I_HLDBn : in std_logic; -- /HOLDB 26 | I_FLP : in std_logic; -- MGHF 27 | I_MO_PFn : in std_logic; -- MO/ /PF 28 | I_LDn : in std_logic; -- /GLD 29 | O_PFDA : out std_logic; -- PFSR Play Field Shift Register 30 | O_PFDB : out std_logic; -- PFSR Play Field Shift Register 31 | O_MODA : out std_logic; -- MOSR Motion Object Shift Register 32 | O_MODB : out std_logic -- MOSR Motion Object Shift Register 33 | ); 34 | end SLAGS; 35 | 36 | architecture RTL of SLAGS is 37 | signal 38 | sl_MOFDA, 39 | sl_MOSDA, 40 | sl_MOFDB, 41 | sl_MOSDB, 42 | sl_PFFDA, 43 | sl_PFSDA, 44 | sl_PFFDB, 45 | sl_PFSDB, 46 | 47 | sl_LDMOn, 48 | sl_LDPFn, 49 | sl_MOFLP, 50 | sl_MO_HLDAn, 51 | sl_MO_HLDBn, 52 | sl_PFFLP, 53 | sl_PF_HLDAn, 54 | sl_PF_HLDBn 55 | : std_logic := '1'; 56 | signal 57 | slv_1B_4B, 58 | slv_1A_5B, 59 | sel_MOSA, 60 | sel_MOSB, 61 | sel_PFSA, 62 | sel_PFSB, 63 | slv_2A, 64 | slv_2B, 65 | slv_3A, 66 | slv_3B 67 | : std_logic_vector(1 downto 0) := (others=>'1'); 68 | begin 69 | -- gates 6B, 12A - shifter controls MO /PF 70 | sl_LDPFn <= I_LDn or ( I_MO_PFn); 71 | sl_LDMOn <= I_LDn or (not I_MO_PFn); 72 | 73 | -- In schema SP-276 when /NOROM signals are asserted they cause the shifters to hold their state and also they 74 | -- cause /CPAL signals to pull low the D0/D7 lines of the ROMS (which are not fitted to PCB, hence the /NOROM signal) 75 | -- the final effect of that is to bring low the MOSR lines when FLIP is asserted 76 | -- In later schemas such as SP-282, SP-298 using LSI chips, the pulldown on D0 line of the ROMs is removed 77 | -- this causes incorrect SLAGS output when both /HOLD and FLIP are asserted because MOSR is taken from the wrong end 78 | -- of the shifter, so without detailed knowledge of the internals of the LSI, the best guess is to cancel the FLIP 79 | -- signal when /HOLD is asserted by logical and-ing them together 80 | 81 | -- latch 8B 82 | p_8B : process 83 | begin 84 | wait until rising_edge(I_MCKR); 85 | if sl_LDPFn = '0' then 86 | sl_PFFLP <= I_FLP and I_HLDAn; -- see note above 87 | sl_PF_HLDAn <= I_HLDAn; 88 | sl_PF_HLDBn <= I_HLDBn; 89 | end if; 90 | end process; 91 | 92 | -- latch 11A 93 | p_11A : process 94 | begin 95 | wait until rising_edge(I_MCKR); 96 | if sl_LDMOn = '0' then 97 | sl_MOFLP <= I_FLP and I_HLDBn; -- see note above 98 | sl_MO_HLDAn <= I_HLDAn; 99 | sl_MO_HLDBn <= I_HLDBn; 100 | end if; 101 | end process; 102 | 103 | -- shift register select signals 104 | sel_MOSB(0) <= not (sl_LDMOn and not (sl_MO_HLDBn and (not sl_MOFLP))); 105 | sel_MOSB(1) <= not (sl_LDMOn and not (sl_MO_HLDBn and ( sl_MOFLP))); 106 | 107 | sel_MOSA(0) <= not (sl_LDMOn and not (sl_MO_HLDAn and (not sl_MOFLP))); 108 | sel_MOSA(1) <= not (sl_LDMOn and not (sl_MO_HLDAn and ( sl_MOFLP))); 109 | 110 | sel_PFSB(0) <= not (sl_LDPFn and not (sl_PF_HLDBn and (not sl_PFFLP))); 111 | sel_PFSB(1) <= not (sl_LDPFn and not (sl_PF_HLDBn and ( sl_PFFLP))); 112 | 113 | sel_PFSA(0) <= not (sl_LDPFn and not (sl_PF_HLDAn and (not sl_PFFLP))); 114 | sel_PFSA(1) <= not (sl_LDPFn and not (sl_PF_HLDAn and ( sl_PFFLP))); 115 | 116 | -- LS299 shifters 117 | u_MOSB : entity work.LS299 port map ( I_CK=>I_MCKR, I_DATA=>I_B, I_SL=>'0', I_SR=>'0', I_SEL=>sel_MOSB, O_SL=>sl_MOFDB, O_SR=>sl_MOSDB ); 118 | u_MOSA : entity work.LS299 port map ( I_CK=>I_MCKR, I_DATA=>I_A, I_SL=>'0', I_SR=>'0', I_SEL=>sel_MOSA, O_SL=>sl_MOFDA, O_SR=>sl_MOSDA ); 119 | u_PFSB : entity work.LS299 port map ( I_CK=>I_MCKR, I_DATA=>I_B, I_SL=>'0', I_SR=>'0', I_SEL=>sel_PFSB, O_SL=>sl_PFFDB, O_SR=>sl_PFSDB ); 120 | u_PFSA : entity work.LS299 port map ( I_CK=>I_MCKR, I_DATA=>I_A, I_SL=>'0', I_SR=>'0', I_SEL=>sel_PFSA, O_SL=>sl_PFFDA, O_SR=>sl_PFSDA ); 121 | 122 | -- selectors 1A, 1B, 4B, 5B 0=A 1=B 123 | -- selects left or right shifter outputs based on FLP 124 | slv_1B_4B <= sl_PFFDB & sl_PFFDA when sl_PFFLP = '1' else sl_PFSDB & sl_PFSDA; 125 | slv_1A_5B <= sl_MOFDB & sl_MOFDA when sl_MOFLP = '1' else sl_MOSDB & sl_MOSDA; 126 | 127 | -- latches 2A, 2B, 3A, 3B 128 | -- 2 clock cycle delay line 129 | p_2A_2B_3A_3B : process 130 | begin 131 | wait until rising_edge(I_MCKR); 132 | slv_3B <= slv_1B_4B; 133 | slv_3A <= slv_3B; 134 | slv_2B <= slv_1A_5B; 135 | slv_2A <= slv_2B; 136 | end process; 137 | 138 | -- outputs 139 | O_MODB <= slv_2A(1); 140 | O_MODA <= slv_2A(0); 141 | O_PFDB <= slv_3A(1); 142 | O_PFDA <= slv_3A(0); 143 | end RTL; 144 | -------------------------------------------------------------------------------- /rtl/atarisys1/VRAMS.vhd: -------------------------------------------------------------------------------- 1 | -- (c) 2020 d18c7db(a)hotmail 2 | -- 3 | -- This program is free software; you can redistribute it and/or modify it under 4 | -- the terms of the GNU General Public License version 3 or, at your option, 5 | -- any later version as published by the Free Software Foundation. 6 | -- 7 | -- This program is distributed in the hope that it will be useful, 8 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 10 | -- 11 | -- For full details, see the GNU General Public License at www.gnu.org/licenses 12 | -- 13 | 14 | library ieee; 15 | use ieee.std_logic_1164.all; 16 | use ieee.numeric_std.all; 17 | 18 | entity VRAMS is 19 | port( 20 | I_MCKR : in std_logic; 21 | I_WEn : in std_logic; 22 | I_VRA : in std_logic_vector(12 downto 0); 23 | I_VRD : in std_logic_vector(15 downto 0); 24 | O_VRD : out std_logic_vector(15 downto 0) 25 | ); 26 | end VRAMS; 27 | 28 | architecture RTL of VRAMS is 29 | type RAM_ARRAY_8Kx16 is array (0 to 8191) of std_logic_vector(15 downto 0); 30 | signal RAM : RAM_ARRAY_8Kx16:=(others=>(others=>'0')); 31 | 32 | -- Ask Xilinx synthesis to use block RAMs if possible 33 | attribute ram_style : string; 34 | attribute ram_style of RAM : signal is "block"; 35 | -- Ask Quartus synthesis to use block RAMs if possible 36 | attribute ramstyle : string; 37 | attribute ramstyle of RAM : signal is "M10K"; 38 | 39 | begin 40 | p_VRAM : process 41 | begin 42 | wait until rising_edge(I_MCKR); 43 | if I_WEn = '0' then 44 | RAM(to_integer(unsigned(I_VRA))) <= I_VRD; 45 | else 46 | O_VRD <= RAM(to_integer(unsigned(I_VRA))); 47 | end if; 48 | end process; 49 | end RTL; 50 | -------------------------------------------------------------------------------- /rtl/lib/T65/T65_Pack.vhd: -------------------------------------------------------------------------------- 1 | -- **** 2 | -- T65(b) core. In an effort to merge and maintain bug fixes .... 3 | -- 4 | -- See list of changes in T65 top file (T65.vhd)... 5 | -- 6 | -- **** 7 | -- 65xx compatible microprocessor core 8 | -- 9 | -- FPGAARCADE SVN: $Id: T65_Pack.vhd 1234 2015-02-28 20:14:50Z wolfgang.scherr $ 10 | -- 11 | -- Copyright (c) 2002...2015 12 | -- Daniel Wallner (jesus opencores org) 13 | -- Mike Johnson (mikej fpgaarcade com) 14 | -- Wolfgang Scherr (WoS pin4 at> 15 | -- Morten Leikvoll () 16 | -- 17 | -- All rights reserved 18 | -- 19 | -- Redistribution and use in source and synthezised forms, with or without 20 | -- modification, are permitted provided that the following conditions are met: 21 | -- 22 | -- Redistributions of source code must retain the above copyright notice, 23 | -- this list of conditions and the following disclaimer. 24 | -- 25 | -- Redistributions in synthesized form must reproduce the above copyright 26 | -- notice, this list of conditions and the following disclaimer in the 27 | -- documentation and/or other materials provided with the distribution. 28 | -- 29 | -- Neither the name of the author nor the names of other contributors may 30 | -- be used to endorse or promote products derived from this software without 31 | -- specific prior written permission. 32 | -- 33 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 34 | -- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 35 | -- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 36 | -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 37 | -- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 38 | -- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 39 | -- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 40 | -- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 41 | -- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 42 | -- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 43 | -- POSSIBILITY OF SUCH DAMAGE. 44 | -- 45 | -- Please report bugs to the author(s), but before you do so, please 46 | -- make sure that this is not a derivative work and that 47 | -- you have the latest version of this file. 48 | -- 49 | -- Limitations : 50 | -- See in T65 top file (T65.vhd)... 51 | 52 | library IEEE; 53 | use IEEE.std_logic_1164.all; 54 | 55 | package T65_Pack is 56 | 57 | constant Flag_C : integer := 0; 58 | constant Flag_Z : integer := 1; 59 | constant Flag_I : integer := 2; 60 | constant Flag_D : integer := 3; 61 | constant Flag_B : integer := 4; 62 | constant Flag_1 : integer := 5; 63 | constant Flag_V : integer := 6; 64 | constant Flag_N : integer := 7; 65 | 66 | subtype T_Lcycle is std_logic_vector(2 downto 0); 67 | constant Cycle_sync :T_Lcycle:="000"; 68 | constant Cycle_1 :T_Lcycle:="001"; 69 | constant Cycle_2 :T_Lcycle:="010"; 70 | constant Cycle_3 :T_Lcycle:="011"; 71 | constant Cycle_4 :T_Lcycle:="100"; 72 | constant Cycle_5 :T_Lcycle:="101"; 73 | constant Cycle_6 :T_Lcycle:="110"; 74 | constant Cycle_7 :T_Lcycle:="111"; 75 | 76 | function CycleNext(c:T_Lcycle) return T_Lcycle; 77 | 78 | type T_Set_BusA_To is 79 | ( 80 | Set_BusA_To_DI, 81 | Set_BusA_To_ABC, 82 | Set_BusA_To_X, 83 | Set_BusA_To_Y, 84 | Set_BusA_To_S, 85 | Set_BusA_To_P, 86 | Set_BusA_To_DA, 87 | Set_BusA_To_DAO, 88 | Set_BusA_To_DAX, 89 | Set_BusA_To_AAX, 90 | Set_BusA_To_DONTCARE 91 | ); 92 | 93 | type T_Set_Addr_To is 94 | ( 95 | Set_Addr_To_SP, 96 | Set_Addr_To_ZPG, 97 | Set_Addr_To_PBR, 98 | Set_Addr_To_BA 99 | ); 100 | 101 | type T_Write_Data is 102 | ( 103 | Write_Data_DL, 104 | Write_Data_ABC, 105 | Write_Data_X, 106 | Write_Data_Y, 107 | Write_Data_S, 108 | Write_Data_P, 109 | Write_Data_PCL, 110 | Write_Data_PCH, 111 | Write_Data_AX, 112 | Write_Data_AXB, 113 | Write_Data_XB, 114 | Write_Data_YB, 115 | Write_Data_DONTCARE 116 | ); 117 | 118 | type T_ALU_OP is 119 | ( 120 | ALU_OP_OR, --"0000" 121 | ALU_OP_AND, --"0001" 122 | ALU_OP_EOR, --"0010" 123 | ALU_OP_ADC, --"0011" 124 | ALU_OP_EQ1, --"0100" EQ1 does not change N,Z flags, EQ2/3 does. 125 | ALU_OP_EQ2, --"0101" Not sure yet whats the difference between EQ2&3. They seem to do the same ALU op 126 | ALU_OP_CMP, --"0110" 127 | ALU_OP_SBC, --"0111" 128 | ALU_OP_ASL, --"1000" 129 | ALU_OP_ROL, --"1001" 130 | ALU_OP_LSR, --"1010" 131 | ALU_OP_ROR, --"1011" 132 | ALU_OP_BIT, --"1100" 133 | -- ALU_OP_EQ3, --"1101" 134 | ALU_OP_DEC, --"1110" 135 | ALU_OP_INC, --"1111" 136 | ALU_OP_ARR, 137 | ALU_OP_ANC, 138 | ALU_OP_SAX, 139 | ALU_OP_XAA 140 | -- ALU_OP_UNDEF--"----"--may be replaced with any? 141 | ); 142 | 143 | type T_t65_dbg is record 144 | I : std_logic_vector(7 downto 0); -- instruction 145 | A : std_logic_vector(7 downto 0); -- A reg 146 | X : std_logic_vector(7 downto 0); -- X reg 147 | Y : std_logic_vector(7 downto 0); -- Y reg 148 | S : std_logic_vector(7 downto 0); -- stack pointer 149 | P : std_logic_vector(7 downto 0); -- processor flags 150 | end record; 151 | 152 | end; 153 | 154 | package body T65_Pack is 155 | 156 | function CycleNext(c:T_Lcycle) return T_Lcycle is 157 | begin 158 | case(c) is 159 | when Cycle_sync=> 160 | return Cycle_1; 161 | when Cycle_1=> 162 | return Cycle_2; 163 | when Cycle_2=> 164 | return Cycle_3; 165 | when Cycle_3=> 166 | return Cycle_4; 167 | when Cycle_4=> 168 | return Cycle_5; 169 | when Cycle_5=> 170 | return Cycle_6; 171 | when Cycle_6=> 172 | return Cycle_7; 173 | when Cycle_7=> 174 | return Cycle_sync; 175 | when others=> 176 | return Cycle_sync; 177 | end case; 178 | end CycleNext; 179 | 180 | end T65_Pack; -------------------------------------------------------------------------------- /rtl/lib/TG68K/README.md: -------------------------------------------------------------------------------- 1 | # TG68K.C 2 | 3 | switchable 68K CPU-Core 4 | 5 | The TG68K.C is an IP core for FPGAs. It can be easily switched between a 68000, a 68010 and a 68020. 6 | There are now many projects in the retro computer area that use this core. There was a lot of feedback from this area. So the core could develop very well. Many bugs could also be eliminated. 7 | The core does not value cycle accuracy. The core saves the FPGA resources with a good execution speed. 8 | 9 | 10 | 11 | Der TG68K.C ist ein IP Core fuer FPGAs. Er kann auf einfache Weise zwischen einem 68000, einem 68010 und einem 68020 umgeschaltet werden. 12 | Es gibt inzwischen viele Projekte im Retrocomputer Bereich die diesen Core verwenden. Aus diesem Bereich gab es viele Rückmeldungen. So konnte der Core sehr gut weiter entwickelt werden. Ebenso konnten dadurch viele Bugs beseitigt werden. 13 | Der Core legt keinen Wert auf Zyklusgenauigkeit. Der Core schont die FPGA Resourcen bei einer guten Ausführungsgeschwindigkeit. 14 | -------------------------------------------------------------------------------- /rtl/lib/bitmap/bmp_out.vhd: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------ 2 | -- File : bmp_out.vhd 3 | ------------------------------------------------------------------ 4 | -- Description: Takes a data stream and saves it to a bitmap image 5 | -- Target: Simulator 6 | -- Dependencies: bmp_pkg.vhd 7 | ------------------------------------------------------------------ 8 | 9 | library ieee; 10 | use ieee.std_logic_1164.all; 11 | use ieee.numeric_std.all; 12 | use std.textio.all; 13 | 14 | use work.bmp_pkg.all; 15 | 16 | entity bmp_out is 17 | generic ( 18 | FILENAME : string 19 | ); 20 | port ( 21 | clk_i : in std_logic; 22 | dat_i : in std_logic_vector(23 downto 0); 23 | vs_i : in std_logic; 24 | hs_i : in std_logic 25 | ); 26 | end entity; 27 | 28 | architecture behavioural of bmp_out is 29 | signal x, y : natural := 0; 30 | signal iteration : integer := 10000; 31 | signal eol, eof, hs_last, vs_last : std_logic; 32 | begin 33 | sink_process : process( clk_i ) 34 | variable sink_bmp : bmp_ptr; 35 | variable sink_pix : bmp_pix; 36 | variable bmp_created : boolean := false; 37 | variable s : line; 38 | begin 39 | if bmp_created = false then 40 | sink_bmp := new bmp; 41 | bmp_created := true; 42 | -- initialize buffer 43 | line : for y in 0 to BMP_MAX_HEIGHT-1 loop 44 | pix : for x in 0 to BMP_MAX_WIDTH-1 loop 45 | sink_bmp.data(y)(x) := ((others=>'0'), (others=>'0'), (others=>'0')); 46 | end loop; 47 | end loop; 48 | end if; 49 | 50 | if rising_edge( clk_i ) then 51 | hs_last <= hs_i; 52 | vs_last <= vs_i; 53 | 54 | sink_pix.r := dat_i(23 downto 16); 55 | sink_pix.g := dat_i(15 downto 8); 56 | sink_pix.b := dat_i(7 downto 0); 57 | bmp_set_pix( sink_bmp, x, y, sink_pix ); 58 | 59 | if (hs_last = '0') and (hs_i = '1') then 60 | x <= 0; 61 | y <= y + 1; 62 | else 63 | x <= x + 1; 64 | end if; 65 | 66 | if (vs_last = '0') and (vs_i = '1') then 67 | y <= 0; 68 | write(s,string'(FILENAME)); write(s,iteration); write(s,string'(".bmp")); 69 | bmp_save( sink_bmp, s.all ); 70 | -- bmp_save( sink_bmp, FILENAME & "_" & INTEGER'IMAGE(iteration) & ".bmp" ); 71 | writeline(output, s); 72 | iteration <= iteration + 1; 73 | end if; 74 | end if; 75 | end process; 76 | end architecture; 77 | -------------------------------------------------------------------------------- /rtl/lib/bitmap/bmp_sink.vhd: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- File : bmp_sink.vhd 3 | -- Author : mr-kenhoff 4 | ------------------------------------------------------------------------------- 5 | -- Description: 6 | -- Takes a data stream and saves it to a bitmap image 7 | 8 | -- Target: Simulator 9 | -- Dependencies: bmp_pkg.vhd 10 | ------------------------------------------------------------------------------- 11 | 12 | library ieee; 13 | use ieee.std_logic_1164.all; 14 | use ieee.numeric_std.all; 15 | 16 | use work.bmp_pkg.all; 17 | 18 | entity bmp_sink is 19 | generic ( 20 | FILENAME : string; 21 | SEQUENCE : string := "TRUE" 22 | ); 23 | port ( 24 | clk_i : in std_logic; 25 | rst_i : in std_logic; 26 | 27 | val_i : in std_logic; 28 | dat_i : in std_logic_vector(23 downto 0); 29 | rdy_o : out std_logic := '1'; 30 | eol_i : in std_logic; 31 | eof_i : in std_logic; 32 | 33 | halt_i : in std_logic 34 | ); 35 | end entity; 36 | 37 | architecture behavioural of bmp_sink is 38 | 39 | signal x : natural := 0; 40 | signal y : natural := 0; 41 | signal iteration : integer := 0; 42 | 43 | begin 44 | 45 | rdy_o <= not halt_i when rising_edge(clk_i); 46 | 47 | sink_process : process( clk_i ) 48 | variable sink_bmp : bmp_ptr; 49 | variable sink_pix : bmp_pix; 50 | variable is_bmp_created : boolean := false; 51 | variable is_bmp_saved : boolean := false; 52 | begin 53 | 54 | -- Create bitmap on startup 55 | if is_bmp_created = false then 56 | sink_bmp := new bmp; 57 | is_bmp_created := true; 58 | end if; 59 | 60 | if rising_edge( clk_i ) then 61 | if rst_i = '1' then 62 | x <= 0; 63 | y <= 0; 64 | else 65 | if val_i = '1' and halt_i = '0' then 66 | sink_pix.r := dat_i(23 downto 16); 67 | sink_pix.g := dat_i(15 downto 8); 68 | sink_pix.b := dat_i(7 downto 0); 69 | 70 | bmp_set_pix( sink_bmp, x, y, sink_pix ); 71 | 72 | if eol_i = '1' then 73 | x <= 0; 74 | if eof_i = '1' then 75 | y <= 0; 76 | -- Frame completed. Save to bitmap.. 77 | if SEQUENCE = "FALSE" then 78 | if is_bmp_saved = false then 79 | bmp_save( sink_bmp, FILENAME & ".bmp" ); 80 | is_bmp_saved := true; 81 | end if; 82 | elsif SEQUENCE = "TRUE" then 83 | bmp_save( sink_bmp, FILENAME & "_" & INTEGER'IMAGE(iteration) & ".bmp" ); 84 | is_bmp_saved := true; 85 | end if; 86 | iteration <= iteration + 1; 87 | else 88 | y <= y + 1; 89 | end if; 90 | else 91 | x <= x + 1; 92 | end if; 93 | end if; 94 | end if; 95 | end if; 96 | end process; 97 | 98 | 99 | end architecture; 100 | 101 | -------------------------------------------------------------------------------- /rtl/lib/bitmap/bmp_source.vhd: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- File : bmp_source.vhd 3 | -- Author : mr-kenhoff 4 | ------------------------------------------------------------------------------- 5 | -- Description: 6 | -- Outputs a bitmap image as a data stream 7 | -- Target: Simulator 8 | -- Dependencies: bmp_pkg.vhd 9 | ------------------------------------------------------------------------------- 10 | 11 | library ieee; 12 | use ieee.std_logic_1164.all; 13 | use ieee.numeric_std.all; 14 | 15 | use work.bmp_pkg.all; 16 | 17 | entity bmp_source is 18 | generic ( 19 | FILENAME : string; 20 | ITERATIONS : natural; 21 | BACKPRESSURE_EN : boolean := false 22 | ); 23 | port ( 24 | clk_i : in std_logic; 25 | rst_i : in std_logic; 26 | 27 | val_o : out std_logic := '0'; 28 | dat_o : out std_logic_vector(23 downto 0) := (others => '0'); 29 | rdy_i : in std_logic; 30 | eol_o : out std_logic := '0'; 31 | eof_o : out std_logic := '0' 32 | ); 33 | end entity; 34 | 35 | architecture behavioural of bmp_source is 36 | 37 | begin 38 | 39 | 40 | 41 | source_process : process( clk_i ) 42 | variable source_bmp : bmp_ptr; 43 | variable source_pix : bmp_pix; 44 | variable is_bmp_loaded : boolean := false; 45 | 46 | variable iteration : natural := 0; 47 | variable x : natural := 0; 48 | variable y : natural := 0; 49 | begin 50 | 51 | if is_bmp_loaded = false then 52 | source_bmp := new bmp; 53 | bmp_open(source_bmp, FILENAME); 54 | is_bmp_loaded := true; 55 | end if; 56 | 57 | if rising_edge( clk_i ) then 58 | 59 | eol_o <= '0'; 60 | eof_o <= '0'; 61 | val_o <= '0'; 62 | 63 | if rst_i = '1' then 64 | iteration := 0; 65 | x := 0; 66 | y := 0; 67 | else 68 | 69 | 70 | 71 | if (BACKPRESSURE_EN and rdy_i = '1') or not BACKPRESSURE_EN then 72 | 73 | if iteration < ITERATIONS then 74 | 75 | bmp_get_pix( source_bmp, x, y, source_pix ); 76 | dat_o(23 downto 16) <= source_pix.r; 77 | dat_o(15 downto 8) <= source_pix.g; 78 | dat_o(7 downto 0) <= source_pix.b; 79 | 80 | val_o <= '1'; 81 | 82 | 83 | 84 | if x = source_bmp.meta.width-1 then -- EOL 85 | eol_o <= '1'; 86 | x := 0; 87 | if y = source_bmp.meta.height-1 then -- EOF 88 | eof_o <= '1'; 89 | y := 0; 90 | iteration := iteration + 1; 91 | else -- Not EOF 92 | y := y + 1; 93 | end if; 94 | else -- Not EOL 95 | x := x + 1; 96 | end if; 97 | 98 | end if; -- if iteration < ITERATIONS 99 | 100 | end if; 101 | 102 | 103 | 104 | end if; 105 | end if; 106 | 107 | end process; 108 | 109 | 110 | end architecture; 111 | -------------------------------------------------------------------------------- /rtl/lib/bitmap/vga_bmp_sink.vhd: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- File : vga_bmp_sink.vhd 3 | -- Author : mr-kenhoff 4 | ------------------------------------------------------------------------------- 5 | -- Description: 6 | -- Saves a conventional VGA-Standard input into a .bmp File 7 | -- 8 | -- Target: Simulator 9 | -- Dependencies: bmp_pkg.vhd 10 | ------------------------------------------------------------------------------- 11 | 12 | library IEEE; 13 | use IEEE.STD_LOGIC_1164.ALL; 14 | 15 | use work.bmp_pkg.all; 16 | 17 | entity vga_bmp_sink is 18 | generic ( 19 | FILENAME : string 20 | ); 21 | port ( 22 | clk_i : in std_logic; 23 | 24 | dat_i : in std_logic_vector(23 downto 0); 25 | active_vid_i : in std_logic; 26 | h_sync_i : in std_logic; 27 | v_sync_i : in std_logic 28 | 29 | ); 30 | end vga_bmp_sink; 31 | 32 | architecture Behavioral of vga_bmp_sink is 33 | 34 | signal h_sync_dly : std_logic := '0'; 35 | signal v_sync_dly : std_logic := '0'; 36 | 37 | signal eol : std_logic := '0'; 38 | signal eof : std_logic := '0'; 39 | 40 | signal x : natural := 0; 41 | signal y : natural := 0; 42 | 43 | signal is_active_line : std_logic := '0'; 44 | signal is_active_frame : std_logic := '0'; 45 | 46 | begin 47 | 48 | h_sync_dly <= h_sync_i when rising_edge(clk_i); 49 | v_sync_dly <= v_sync_i when rising_edge(clk_i); 50 | 51 | eol_eof_gen_process : process(clk_i) 52 | begin 53 | if rising_edge(clk_i) then 54 | -- EOL 55 | if h_sync_dly = '0' and h_sync_i = '1' then 56 | eol <= '1'; 57 | else 58 | eol <= '0'; 59 | end if; 60 | 61 | -- EOF 62 | if v_sync_dly = '0' and v_sync_i = '1' then 63 | eof <= '1'; 64 | else 65 | eof <= '0'; 66 | end if; 67 | end if; 68 | end process; 69 | 70 | sink_process : process( clk_i ) 71 | variable sink_bmp : bmp_ptr; 72 | variable sink_pix : bmp_pix; 73 | variable is_bmp_created : boolean := false; 74 | variable is_bmp_saved : boolean := false; 75 | begin 76 | 77 | -- Create bitmap on startup 78 | if is_bmp_created = false then 79 | sink_bmp := new bmp; 80 | is_bmp_created := true; 81 | end if; 82 | 83 | if rising_edge( clk_i ) then 84 | 85 | if active_vid_i = '1' then 86 | sink_pix.r := dat_i(23 downto 16); 87 | sink_pix.g := dat_i(15 downto 8); 88 | sink_pix.b := dat_i(7 downto 0); 89 | 90 | bmp_set_pix( sink_bmp, x, y, sink_pix ); 91 | 92 | x <= x + 1; 93 | is_active_line <= '1'; 94 | is_active_frame <= '1'; 95 | else 96 | if eol = '1' then 97 | x <= 0; 98 | if is_active_line = '1' then 99 | y <= y + 1; 100 | end if; 101 | is_active_line <= '0'; 102 | end if; 103 | 104 | if eof = '1' then 105 | y <= 0; 106 | if is_active_frame = '1' then 107 | bmp_save( sink_bmp, FILENAME ); 108 | end if; 109 | is_active_frame <= '0'; 110 | end if; 111 | end if; 112 | end if; 113 | end process; 114 | 115 | end Behavioral; 116 | -------------------------------------------------------------------------------- /rtl/lib/dac.vhd: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------- 2 | -- Delta-Sigma DAC 3 | -- $Id: dac.vhd,v 1.1 2006/05/10 20:57:06 arnim Exp $ 4 | -- Refer to Xilinx Application Note XAPP154. 5 | -- This DAC requires an external RC low-pass filter: 6 | -- 7 | -- dac_o 0---/\/\/\---+---0 analog audio 8 | -- 3k3 | 9 | -- === 4n7 10 | -- | 11 | -- GND 12 | ----------------------------------------------------- 13 | 14 | library ieee; 15 | use ieee.std_logic_1164.all; 16 | use ieee.numeric_std.all; 17 | 18 | entity dac is 19 | generic ( 20 | msbi_g : integer := 7 21 | ); 22 | port ( 23 | clk_i : in std_logic; 24 | res_i : in std_logic; 25 | dac_i : in std_logic_vector(msbi_g downto 0); 26 | dac_o : out std_logic 27 | ); 28 | end dac; 29 | 30 | architecture rtl of dac is 31 | signal SigmaLatch_q : unsigned(msbi_g+2 downto 0) := (others=>'0'); 32 | begin 33 | seq : process (clk_i, res_i) 34 | begin 35 | if res_i = '1' then 36 | dac_o <= '0'; 37 | SigmaLatch_q <= (others=>'0'); 38 | SigmaLatch_q(SigmaLatch_q'left-1) <= '1'; 39 | elsif rising_edge(clk_i) then 40 | SigmaLatch_q <= SigmaLatch_q + unsigned(SigmaLatch_q(msbi_g+2) & SigmaLatch_q(msbi_g+2) & dac_i); 41 | dac_o <= SigmaLatch_q(msbi_g+2); 42 | end if; 43 | end process seq; 44 | end rtl; 45 | -------------------------------------------------------------------------------- /rtl/lib/dvid.vhd: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- Engineer: Mike Field 3 | -- Description: Converts VGA signals into DVID bitstreams. 4 | -- 5 | -- 'clk_p' and 'clk_n' should be 5x clk_pixel. 6 | -- 7 | -- 'blank' should be asserted during the non-display 8 | -- portions of the frame 9 | -------------------------------------------------------------------------------- 10 | library ieee; 11 | use ieee.std_logic_1164.all; 12 | library unisim; 13 | use unisim.vcomponents.all; 14 | 15 | entity dvid is 16 | port ( 17 | clk_p : in STD_LOGIC; 18 | clk_n : in STD_LOGIC; 19 | clk_pixel : in STD_LOGIC; 20 | red_p : in STD_LOGIC_VECTOR (7 downto 0); 21 | grn_p : in STD_LOGIC_VECTOR (7 downto 0); 22 | blu_p : in STD_LOGIC_VECTOR (7 downto 0); 23 | blank : in STD_LOGIC; 24 | hsync : in STD_LOGIC; 25 | vsync : in STD_LOGIC; 26 | tmds_p : out STD_LOGIC_VECTOR (3 downto 0); 27 | tmds_n : out STD_LOGIC_VECTOR (3 downto 0) 28 | ); 29 | end dvid; 30 | 31 | architecture RTL of dvid is 32 | signal encoded_red, encoded_grn, encoded_blu : std_logic_vector(9 downto 0) := (others => '0'); 33 | signal latched_red, latched_grn, latched_blu : std_logic_vector(9 downto 0) := (others => '0'); 34 | signal shift_red, shift_grn, shift_blu : std_logic_vector(9 downto 0) := (others => '0'); 35 | 36 | signal shift_clk : std_logic_vector(9 downto 0) := "0000011111"; 37 | 38 | constant c_red : std_logic_vector(1 downto 0) := (others => '0'); 39 | constant c_grn : std_logic_vector(1 downto 0) := (others => '0'); 40 | signal c_blu : std_logic_vector(1 downto 0) := (others => '0'); 41 | signal 42 | clk_s, 43 | red_s, 44 | grn_s, 45 | blu_s 46 | : std_logic := '1'; 47 | begin 48 | c_blu <= vsync & hsync; 49 | 50 | OBUFDS_clk : OBUFDS port map ( O => tmds_p(3), OB => tmds_n(3), I => clk_s ); 51 | OBUFDS_grn : OBUFDS port map ( O => tmds_p(2), OB => tmds_n(2), I => red_s ); 52 | OBUFDS_red : OBUFDS port map ( O => tmds_p(1), OB => tmds_n(1), I => grn_s ); 53 | OBUFDS_blu : OBUFDS port map ( O => tmds_p(0), OB => tmds_n(0), I => blu_s ); 54 | 55 | TMDS_encoder_red: entity work.TMDS_encoder PORT MAP(clk => clk_pixel, data => red_p, c => c_red, blank => blank, encoded => encoded_red); 56 | TMDS_encoder_grn: entity work.TMDS_encoder PORT MAP(clk => clk_pixel, data => grn_p, c => c_grn, blank => blank, encoded => encoded_grn); 57 | TMDS_encoder_blu: entity work.TMDS_encoder PORT MAP(clk => clk_pixel, data => blu_p, c => c_blu, blank => blank, encoded => encoded_blu); 58 | 59 | ODDR2_red : ODDR2 generic map( DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC") 60 | port map (Q => red_s, D0 => shift_red(0), D1 => shift_red(1), C0 => clk_p, C1 => clk_n, CE => '1', R => '0', S => '0'); 61 | 62 | ODDR2_grn : ODDR2 generic map( DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC") 63 | port map (Q => grn_s, D0 => shift_grn(0), D1 => shift_grn(1), C0 => clk_p, C1 => clk_n, CE => '1', R => '0', S => '0'); 64 | 65 | ODDR2_blu : ODDR2 generic map( DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC") 66 | port map (Q => blu_s, D0 => shift_blu(0), D1 => shift_blu(1), C0 => clk_p, C1 => clk_n, CE => '1', R => '0', S => '0'); 67 | 68 | ODDR2_clk : ODDR2 generic map( DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC") 69 | port map (Q => clk_s, D0 => shift_clk(0), D1 => shift_clk(1), C0 => clk_p, C1 => clk_n, CE => '1', R => '0', S => '0'); 70 | 71 | process 72 | begin 73 | wait until rising_edge(clk_pixel); 74 | latched_red <= encoded_red; 75 | latched_grn <= encoded_grn; 76 | latched_blu <= encoded_blu; 77 | end process; 78 | 79 | process 80 | begin 81 | wait until rising_edge(clk_p); 82 | if shift_clk = "0000011111" then 83 | shift_red <= latched_red; 84 | shift_grn <= latched_grn; 85 | shift_blu <= latched_blu; 86 | else 87 | shift_red <= "00" & shift_red(9 downto 2); 88 | shift_grn <= "00" & shift_grn(9 downto 2); 89 | shift_blu <= "00" & shift_blu(9 downto 2); 90 | end if; 91 | shift_clk <= shift_clk(1 downto 0) & shift_clk(9 downto 2); 92 | end process; 93 | 94 | end RTL; 95 | -------------------------------------------------------------------------------- /rtl/lib/gamecube/Nintendo Gamecube Controller Protocol.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/rtl/lib/gamecube/Nintendo Gamecube Controller Protocol.pdf -------------------------------------------------------------------------------- /rtl/lib/gamecube/pulseview_capture.sr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/rtl/lib/gamecube/pulseview_capture.sr -------------------------------------------------------------------------------- /rtl/lib/leta_rep.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Create Date: 22:38:01 1/11/2007 3 | -- Design Name: 4 | -- Module Name: LETA_REP - Behavioral 5 | -- Project Name: LETA on a CPLD 6 | -- Target Devices: XC95108 7 | -- Tool versions: webpack ise 9.1.03i 8 | -- Description: Atari Leta replacement *Freeware* !! 9 | -- 10 | -- Additional Comments: 11 | -- another fun project from JROK 12 | -- 13 | ---------------------------------------------------------------------------------- 14 | library ieee; 15 | use ieee.std_logic_1164.all; 16 | use ieee.std_logic_arith.all; 17 | use ieee.std_logic_unsigned.all; 18 | 19 | entity LETA_REP is 20 | port ( 21 | clk : in std_logic; -- system wide clock 22 | ck : in std_logic; -- LETA clock 23 | resoln : in std_logic; 24 | cs : in std_logic; 25 | test : in std_logic; 26 | ad : in std_logic_vector (1 downto 0); 27 | clks : in std_logic_vector (3 downto 0); 28 | dirs : in std_logic_vector (3 downto 0); 29 | db : out std_logic_vector (7 downto 0) 30 | ); 31 | end LETA_REP; 32 | 33 | architecture Behavioral of LETA_REP is 34 | 35 | -- 8 bit counter register 36 | type cnt_reg is array( 0 to 3 ) of std_logic_vector( 7 downto 0 ); 37 | signal count_register : cnt_reg := (others=>(others=>'0')); 38 | 39 | -- 3 bit temp storage 40 | type tmp_inputs is array( 0 to 3 ) of std_logic_vector( 2 downto 0 ); 41 | signal clks_tmp: tmp_inputs := (others=>(others=>'0')); 42 | signal dirs_tmp: tmp_inputs := (others=>(others=>'0')); 43 | 44 | signal clks_last_bit : std_logic_vector( 3 downto 0 ) := (others=>'0'); 45 | signal dirs_last_bit : std_logic_vector( 3 downto 0 ) := (others=>'0'); 46 | signal ck_last : std_logic := '0'; 47 | 48 | begin 49 | -- 0 1 1 0 count up 0 1 1 0 count down 50 | -- 0 0 1 1 1 1 0 0 51 | ---------------------------------------------------------- 52 | process( clk) 53 | begin 54 | if ( rising_edge( clk ) ) then 55 | ck_last <= ck; 56 | if ck_last = '0' and ck = '1' then 57 | for cntr in 3 downto 0 loop 58 | if ( test = '1' ) then 59 | -- test mode clear the states of DIR and CLK and ALL the counts 60 | clks_tmp( cntr ) <= (others=>'0'); 61 | dirs_tmp( cntr ) <= (others=>'0'); 62 | count_register( cntr ) <= (others=>'0'); 63 | clks_last_bit( cntr ) <= '0'; 64 | dirs_last_bit( cntr ) <= '0'; 65 | else 66 | -- shift the bits left and store the current state in bit '0' 67 | clks_tmp( cntr ) <= clks_tmp( cntr )( 1 downto 0 ) & clks( cntr ); 68 | dirs_tmp( cntr ) <= dirs_tmp( cntr )( 1 downto 0 ) & dirs( cntr ); 69 | -- test mode = '0' so normal counting operation 70 | -- 3 bits of CLK or DIR have to be the same 71 | if ( clks_tmp( cntr ) = "000" ) then 72 | clks_last_bit( cntr ) <= '0'; 73 | elsif ( clks_tmp( cntr ) = "111" ) then 74 | clks_last_bit( cntr ) <= '1'; 75 | end if; 76 | if ( dirs_tmp( cntr ) = "000" ) then 77 | dirs_last_bit( cntr ) <= '0'; 78 | elsif ( dirs_tmp( cntr ) = "111" ) then 79 | dirs_last_bit( cntr ) <= '1'; 80 | end if; 81 | -- check for a new state of DIR & CLK then take a counting action depending on the previous state 82 | -- state 10 83 | if ( clks_tmp( cntr ) = "111" and dirs_tmp( cntr ) = "000" ) then 84 | if ( clks_last_bit( cntr ) ='1' and dirs_last_bit( cntr ) ='1' ) then 85 | count_register(cntr) <= count_register(cntr)-1; 86 | end if; 87 | if ( clks_last_bit( cntr ) ='0' and dirs_last_bit( cntr ) ='0' and resoln = '1' ) then 88 | count_register(cntr) <= count_register(cntr)+1; 89 | end if; 90 | end if; 91 | -- state 11 92 | if ( clks_tmp( cntr ) = "111" and dirs_tmp( cntr ) = "111" ) then 93 | if ( clks_last_bit( cntr ) ='1' and dirs_last_bit( cntr ) ='0' ) then 94 | count_register(cntr) <= count_register(cntr)+1; 95 | end if; 96 | if ( clks_last_bit( cntr ) ='0' and dirs_last_bit( cntr ) ='1' and resoln = '1' ) then 97 | count_register(cntr) <= count_register(cntr)-1; 98 | end if; 99 | end if; 100 | -- state 01 101 | if ( clks_tmp( cntr ) = "000" and dirs_tmp( cntr ) = "111" ) then 102 | if ( clks_last_bit( cntr ) ='0' and dirs_last_bit( cntr ) ='0' ) then 103 | count_register(cntr) <= count_register(cntr)-1; 104 | end if; 105 | if ( clks_last_bit( cntr ) ='1' and dirs_last_bit( cntr ) ='1' and resoln = '1' ) then 106 | count_register(cntr) <= count_register(cntr)+1; 107 | end if; 108 | end if; 109 | -- state 00 110 | if ( clks_tmp( cntr ) = "000" and dirs_tmp( cntr ) = "000" ) then 111 | if ( clks_last_bit( cntr ) ='0' and dirs_last_bit( cntr ) ='1' ) then 112 | count_register(cntr) <= count_register(cntr)+1; 113 | end if; 114 | if ( clks_last_bit( cntr ) ='1' and dirs_last_bit( cntr ) ='0' and resoln = '1') then 115 | count_register(cntr) <= count_register(cntr)-1; 116 | end if; 117 | end if; 118 | end if; 119 | end loop; 120 | end if; 121 | end if; 122 | end process; 123 | ---------------------------------------------------------- 124 | process( cs, count_register, ad, test,dirs, clks ) 125 | begin 126 | if ( cs = '1' ) then 127 | db <= "ZZZZZZZZ"; 128 | else 129 | if ( test = '0' ) then 130 | -- put the register pointed to by A0 & A1 onto the databus 131 | db <= count_register( conv_integer( ad ) ) ; 132 | else 133 | -- test mode so just pass thru' the INVERTED states of the dir and clk inputs 134 | -- A0/A1 are irrelevant 135 | db <= not (clks(3) & dirs(3) & clks(2) & dirs(2) & clks(1) & dirs(1) & clks(0) & dirs(0)); 136 | end if; 137 | end if; 138 | end process; 139 | 140 | end Behavioral; 141 | -------------------------------------------------------------------------------- /rtl/lib/mem/dpram.vhd: -------------------------------------------------------------------------------- 1 | LIBRARY ieee; 2 | USE ieee.std_logic_1164.all; 3 | 4 | LIBRARY altera_mf; 5 | USE altera_mf.altera_mf_components.all; 6 | 7 | entity dpram is 8 | generic ( 9 | addr_width_g : integer := 8; 10 | data_width_g : integer := 8 11 | ); 12 | PORT 13 | ( 14 | address_a : IN STD_LOGIC_VECTOR (addr_width_g-1 DOWNTO 0); 15 | address_b : IN STD_LOGIC_VECTOR (addr_width_g-1 DOWNTO 0); 16 | clock_a : IN STD_LOGIC := '1'; 17 | clock_b : IN STD_LOGIC ; 18 | data_a : IN STD_LOGIC_VECTOR (data_width_g-1 DOWNTO 0); 19 | data_b : IN STD_LOGIC_VECTOR (data_width_g-1 DOWNTO 0) := (others => '0'); 20 | enable_a : IN STD_LOGIC := '1'; 21 | enable_b : IN STD_LOGIC := '1'; 22 | wren_a : IN STD_LOGIC := '0'; 23 | wren_b : IN STD_LOGIC := '0'; 24 | q_a : OUT STD_LOGIC_VECTOR (data_width_g-1 DOWNTO 0); 25 | q_b : OUT STD_LOGIC_VECTOR (data_width_g-1 DOWNTO 0) 26 | ); 27 | END dpram; 28 | 29 | 30 | ARCHITECTURE SYN OF dpram IS 31 | BEGIN 32 | altsyncram_component : altsyncram 33 | GENERIC MAP ( 34 | address_reg_b => "CLOCK1", 35 | clock_enable_input_a => "NORMAL", 36 | clock_enable_input_b => "NORMAL", 37 | clock_enable_output_a => "BYPASS", 38 | clock_enable_output_b => "BYPASS", 39 | indata_reg_b => "CLOCK1", 40 | intended_device_family => "Cyclone V", 41 | lpm_type => "altsyncram", 42 | numwords_a => 2**addr_width_g, 43 | numwords_b => 2**addr_width_g, 44 | operation_mode => "BIDIR_DUAL_PORT", 45 | outdata_aclr_a => "NONE", 46 | outdata_aclr_b => "NONE", 47 | outdata_reg_a => "UNREGISTERED", 48 | outdata_reg_b => "UNREGISTERED", 49 | power_up_uninitialized => "FALSE", 50 | read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", 51 | read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ", 52 | widthad_a => addr_width_g, 53 | widthad_b => addr_width_g, 54 | width_a => data_width_g, 55 | width_b => data_width_g, 56 | width_byteena_a => 1, 57 | width_byteena_b => 1, 58 | wrcontrol_wraddress_reg_b => "CLOCK1" 59 | ) 60 | PORT MAP ( 61 | address_a => address_a, 62 | address_b => address_b, 63 | clock0 => clock_a, 64 | clock1 => clock_b, 65 | clocken0 => enable_a, 66 | clocken1 => enable_b, 67 | data_a => data_a, 68 | data_b => data_b, 69 | wren_a => wren_a, 70 | wren_b => wren_b, 71 | q_a => q_a, 72 | q_b => q_b 73 | ); 74 | 75 | END SYN; 76 | -------------------------------------------------------------------------------- /rtl/lib/mem/mt48lc16m16a2.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d18c7db/atari_system1_fpga/8a8d3c3914c1a0f53be7ec228093a947806e0e1c/rtl/lib/mem/mt48lc16m16a2.v -------------------------------------------------------------------------------- /rtl/lib/mem/sdram.sdc: -------------------------------------------------------------------------------- 1 | create_generated_clock -name SDRAM_CLK \ 2 | -source [get_pins -compatibility_mode {emu|pll|pll_inst|altera_pll_i|general[4].gpll~PLL_OUTPUT_COUNTER|divclk}] \ 3 | [get_ports {SDRAM_CLK}] 4 | 5 | #set_clock_groups -exclusive -group [get_clocks { SDRAM_CLK }] 6 | 7 | #set_clock_groups -exclusive -group [get_clocks {emu|pll|pll_inst|altera_pll_i|general[3].gpll~PLL_OUTPUT_COUNTER|divclk}] 8 | 9 | #set_false_path \ 10 | #-from {emu|pll|pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk} \ 11 | #-to {emu|pll|pll_inst|altera_pll_i|general[3].gpll~PLL_OUTPUT_COUNTER|divclk} 12 | 13 | #set_false_path \ 14 | #-from {emu|pll|pll_inst|altera_pll_i|general[1].gpll~PLL_OUTPUT_COUNTER|divclk} \ 15 | #-to {emu|pll|pll_inst|altera_pll_i|general[3].gpll~PLL_OUTPUT_COUNTER|divclk} 16 | 17 | # data access delay (tAC) 18 | set_input_delay -clock SDRAM_CLK -max 6.0 [get_ports {SDRAM_DQ[*]}] 19 | 20 | # data output hold time (tOH) 21 | set_input_delay -clock SDRAM_CLK -min 2.5 [get_ports {SDRAM_DQ[*]}] 22 | 23 | # data input setup time (tIS) 24 | set_output_delay -clock SDRAM_CLK -max 1.5 [get_ports {SDRAM_A[*] SDRAM_BA[*] SDRAM_DQ* SDRAM_n* SDRAM_CKE}] 25 | 26 | # data input hold time (tIH) 27 | set_output_delay -clock SDRAM_CLK -min -0.8 [get_ports {SDRAM_A[*] SDRAM_BA[*] SDRAM_DQ* SDRAM_n* SDRAM_CKE}] 28 | 29 | # use proper edges for the timing calculations 30 | set_multicycle_path -setup -end \ 31 | -rise_from [get_clocks {SDRAM_CLK}] \ 32 | -rise_to [get_clocks {emu|pll|pll_inst|altera_pll_i|general[3].gpll~PLL_OUTPUT_COUNTER|divclk}] 2 33 | -------------------------------------------------------------------------------- /rtl/lib/quad.vhd: -------------------------------------------------------------------------------- 1 | -- (c) 2020 d18c7db(a)hotmail 2 | -- 3 | -- This program is free software; you can redistribute it and/or modify it under 4 | -- the terms of the GNU General Public License version 3 or, at your option, 5 | -- any later version as published by the Free Software Foundation. 6 | -- 7 | -- This program is distributed in the hope that it will be useful, 8 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 10 | -- 11 | -- For full details, see the GNU General Public License at www.gnu.org/licenses 12 | 13 | -- Convert mouse or joystick inputs to quadrature outputs for driving LETA 14 | -- Wheel mode simulates a wheel which turns 90 degrees CW or CCW from a center idle position (only outputs on quadrature channel X) 15 | 16 | library ieee; 17 | use ieee.std_logic_1164.all; 18 | use ieee.std_logic_unsigned.all; 19 | use ieee.numeric_std.all; 20 | 21 | entity QUAD is 22 | port( 23 | clk : in std_logic; 24 | mode : in std_logic; -- 1 = wheel mode, 0 = joy/mouse 25 | joy : in std_logic_vector(15 downto 0); 26 | mouse : in std_logic_vector(24 downto 0); 27 | speed : in std_logic_vector( 1 downto 0); 28 | 29 | -- quadrature outputs 30 | XA : out std_logic := '0'; -- horizontal movement and wheel turns 31 | XB : out std_logic := '0'; -- horizontal movement and wheel turns 32 | YA : out std_logic := '0'; -- vertical movement 33 | YB : out std_logic := '0' -- vertical movement 34 | ); 35 | end QUAD; 36 | 37 | architecture RTL of QUAD is 38 | constant sample_interval : natural range 0 to 31 := 15; -- number of timer timeouts before joystick inputs are sampled 39 | signal sample : natural range 0 to 31:= sample_interval; 40 | signal idx : natural range 0 to 15 := 12; -- controls sensitivity 41 | 42 | alias mclk : std_logic is mouse(24); 43 | signal mclk_last : std_logic := '0'; 44 | signal x_dir, y_dir : std_logic := '0'; 45 | signal timer : std_logic_vector(13 downto 0) := (others => '0'); -- clocked at 7.159Mhz gives 437 rollovers / second 46 | signal wheel : signed( 3 downto 0) := (others => '0'); 47 | signal x_ctr, y_ctr : signed( 7 downto 0) := (others => '0'); 48 | signal joy_h_xlat, joy_v_xlat : signed( 8 downto 0) := (others => '0'); 49 | signal mouse_h_xlat, mouse_v_xlat : signed( 9 downto 0) := (others => '0'); 50 | begin 51 | -- index into timer counter for generating quadrature signals, lower index = more pulses/second 52 | idx <= 53 | 10 when (mode = '0' and speed = "00") else -- 1:1 fastest 54 | 11 when (mode = '0' and speed = "01") else -- 1:2 fast 55 | 12 when (mode = '0' and speed = "10") else -- 1:4 medium 56 | 13 when (mode = '0' and speed = "11") else -- 1:8 slow 57 | 11; -- when in wheel mode 58 | 59 | -- Translate joy coordinates on the Cartesian plane to remove 45 degree trackball rotation 60 | -- x1 = x0*cos(45) – y0*sin(45) , y1 = x0*sin(45) + y0*cos(45) 61 | -- at 45 degrees cos(45) = sin(45) = 0.707 so we remove that common factor and scale the vectors later to suit 62 | joy_h_xlat <= signed(joy(7) & joy( 7 downto 0)) - signed(joy(15) & joy(15 downto 8)); 63 | joy_v_xlat <= signed(joy(7) & joy( 7 downto 0)) + signed(joy(15) & joy(15 downto 8)); 64 | -- Translate mouse coordinates on the Cartesian plane to remove 45 degree trackball rotation (also invert Y axis to match joystick) 65 | mouse_h_xlat <= signed((mouse(4) & mouse(4) & mouse(15 downto 8))) + signed((mouse(5) & mouse(5) & mouse(23 downto 16))); 66 | mouse_v_xlat <= signed((mouse(4) & mouse(4) & mouse(15 downto 8))) - signed((mouse(5) & mouse(5) & mouse(23 downto 16))); 67 | 68 | -- generate horizontal quadrature outputs 69 | p_QX : process 70 | begin 71 | wait until rising_edge(clk); 72 | if (x_ctr /= 0) then 73 | XA <= timer(idx) xor ( ( x_dir) and timer(idx-1) ); 74 | XB <= timer(idx) xor ( (not x_dir) and timer(idx-1) ); 75 | end if; 76 | end process; 77 | 78 | -- generate vertical quadrature outputs 79 | p_QY : process 80 | begin 81 | wait until rising_edge(clk); 82 | if (y_ctr /= 0) then 83 | YA <= timer(idx) xor ( ( y_dir) and timer(idx-1) ); 84 | YB <= timer(idx) xor ( (not y_dir) and timer(idx-1) ); 85 | end if; 86 | end process; 87 | 88 | -- scans joystick inputs for changes 89 | p_inputs : process 90 | begin 91 | wait until rising_edge(clk); 92 | timer <= timer - 1; 93 | -- mouse input is not sampled because it provides us with a clock for each event 94 | if (mode = '0') then -- if mouse mode 95 | mclk_last <= mclk; -- mouse clock seems to run at 62 Hz 96 | if (mclk_last /= mclk) then 97 | timer <= (others=>'1'); 98 | sample <= sample_interval; 99 | -- Horizontal mouse movement 100 | x_dir <= mouse_h_xlat(mouse_h_xlat'LEFT); -- 1=L 0=R 101 | x_ctr <= abs(mouse_h_xlat(mouse_h_xlat'LEFT downto mouse_h_xlat'LEFT - x_ctr'LEFT)); 102 | -- Vertical mouse movement 103 | y_dir <= mouse_v_xlat(mouse_v_xlat'LEFT); -- 1=U 0=D 104 | y_ctr <= abs(mouse_v_xlat(mouse_v_xlat'LEFT downto mouse_v_xlat'LEFT - y_ctr'LEFT)); 105 | end if; 106 | end if; 107 | 108 | -- on timer rollover update x/y and sample counters 109 | if (timer = 0) then 110 | if (sample = 0) then 111 | sample <= sample_interval; 112 | else 113 | sample <= sample - 1; 114 | end if; 115 | if (x_ctr /= 0) then 116 | x_ctr <= x_ctr - 1; 117 | end if; 118 | if (y_ctr /= 0) then 119 | y_ctr <= y_ctr - 1; 120 | end if; 121 | 122 | -- joystick is sampled every 7.158Mhz/(timer*sample_interval) = about 27Hz 123 | if (sample = 0) then 124 | if (mode = '1') then -- if weel mode 125 | if (wheel = signed(joy(7 downto 4))) then 126 | x_ctr <= (others => '0'); 127 | y_ctr <= (others => '0'); 128 | elsif (wheel > signed(joy(7 downto 4))) then 129 | x_dir <= '1'; -- 1=L 130 | x_ctr <= x"01"; 131 | wheel <= wheel - 1; 132 | elsif (wheel < signed(joy(7 downto 4))) then 133 | x_dir <= '0'; -- 0=R 134 | x_ctr <= x"01"; 135 | wheel <= wheel + 1; 136 | end if; 137 | else -- else mouse/joystick mode 138 | x_dir <= joy_h_xlat(joy_h_xlat'LEFT); -- 1=L 0=R 139 | x_ctr <= abs(joy_h_xlat(joy_h_xlat'LEFT downto joy_h_xlat'LEFT - x_ctr'LEFT))/2; 140 | y_dir <= joy_v_xlat(joy_v_xlat'LEFT); -- 1=U 0=D 141 | y_ctr <= abs(joy_v_xlat(joy_v_xlat'LEFT downto joy_v_xlat'LEFT - y_ctr'LEFT))/2; 142 | end if; 143 | end if; 144 | end if; 145 | end process; 146 | end RTL; 147 | -------------------------------------------------------------------------------- /rtl/lib/tmds_encoder.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Engineer: Mike Field 3 | -- 4 | -- Description: TMDS Encoder 5 | -- 8 bits colour, 2 control bits and one blanking bits in 6 | -- 10 bits of TMDS encoded data out 7 | -- Clocked at the pixel clock 8 | -- 9 | ---------------------------------------------------------------------------------- 10 | library ieee; 11 | use ieee.std_logic_1164.all; 12 | use ieee.std_logic_unsigned.all; 13 | 14 | entity TMDS_encoder is 15 | port ( 16 | clk : in std_logic; 17 | data : in std_logic_vector (7 downto 0); 18 | c : in std_logic_vector (1 downto 0); 19 | blank : in std_logic; 20 | encoded : out std_logic_vector (9 downto 0) := (others => '0') 21 | ); 22 | end TMDS_encoder; 23 | 24 | architecture RTL of TMDS_encoder is 25 | signal xored : std_logic_vector (8 downto 0) := (others => '0'); 26 | signal xnored : std_logic_vector (8 downto 0) := (others => '0'); 27 | 28 | signal ones : std_logic_vector (3 downto 0) := (others => '0'); 29 | signal data_word : std_logic_vector (8 downto 0) := (others => '0'); 30 | signal data_word_inv : std_logic_vector (8 downto 0) := (others => '0'); 31 | signal data_word_disparity : std_logic_vector (3 downto 0) := (others => '0'); 32 | signal dc_bias : std_logic_vector (3 downto 0) := (others => '0'); 33 | begin 34 | -- Work our the two different encodings for the byte 35 | xored(0) <= data(0); 36 | xored(1) <= data(1) xor xored(0); 37 | xored(2) <= data(2) xor xored(1); 38 | xored(3) <= data(3) xor xored(2); 39 | xored(4) <= data(4) xor xored(3); 40 | xored(5) <= data(5) xor xored(4); 41 | xored(6) <= data(6) xor xored(5); 42 | xored(7) <= data(7) xor xored(6); 43 | xored(8) <= '1'; 44 | 45 | xnored(0) <= data(0); 46 | xnored(1) <= data(1) xnor xnored(0); 47 | xnored(2) <= data(2) xnor xnored(1); 48 | xnored(3) <= data(3) xnor xnored(2); 49 | xnored(4) <= data(4) xnor xnored(3); 50 | xnored(5) <= data(5) xnor xnored(4); 51 | xnored(6) <= data(6) xnor xnored(5); 52 | xnored(7) <= data(7) xnor xnored(6); 53 | xnored(8) <= '0'; 54 | 55 | -- Count how many ones are set in data 56 | ones <= "0000" 57 | + data(0) + data(1) + data(2) + data(3) 58 | + data(4) + data(5) + data(6) + data(7); 59 | 60 | -- Decide which encoding to use 61 | process(ones, data(0), xnored, xored) 62 | begin 63 | if ones > 4 or (ones = 4 and data(0) = '0') then 64 | data_word <= xnored; 65 | data_word_inv <= not(xnored); 66 | else 67 | data_word <= xored; 68 | data_word_inv <= not(xored); 69 | end if; 70 | end process; 71 | 72 | -- Work out the DC bias of the dataword; 73 | data_word_disparity <= "1100" 74 | + data_word(0) + data_word(1) + data_word(2) + data_word(3) 75 | + data_word(4) + data_word(5) + data_word(6) + data_word(7); 76 | 77 | -- Now work out what the output should be 78 | process(clk) 79 | begin 80 | if rising_edge(clk) then 81 | if blank = '1' then 82 | -- In the control periods, all values have and have balanced bit count 83 | case c is 84 | when "00" => encoded <= "1101010100"; 85 | when "01" => encoded <= "0010101011"; 86 | when "10" => encoded <= "0101010100"; 87 | when others => encoded <= "1010101011"; 88 | end case; 89 | dc_bias <= (others => '0'); 90 | else 91 | if dc_bias = "00000" or data_word_disparity = 0 then 92 | -- dataword has no disparity 93 | if data_word(8) = '1' then 94 | encoded <= "01" & data_word(7 downto 0); 95 | dc_bias <= dc_bias + data_word_disparity; 96 | else 97 | encoded <= "10" & data_word_inv(7 downto 0); 98 | dc_bias <= dc_bias - data_word_disparity; 99 | end if; 100 | elsif (dc_bias(3) = '0' and data_word_disparity(3) = '0') or 101 | (dc_bias(3) = '1' and data_word_disparity(3) = '1') then 102 | encoded <= '1' & data_word(8) & data_word_inv(7 downto 0); 103 | dc_bias <= dc_bias + data_word(8) - data_word_disparity; 104 | else 105 | encoded <= '0' & data_word; 106 | dc_bias <= dc_bias - data_word_inv(8) + data_word_disparity; 107 | end if; 108 | end if; 109 | end if; 110 | end process; 111 | end RTL; 112 | -------------------------------------------------------------------------------- /rtl/pll.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name SYNTHESIS_ONLY_QIP ON 2 | set_global_assignment -library "pll" -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"] 3 | set_global_assignment -library "pll" -name VERILOG_FILE [file join $::quartus(qip_path) "pll/pll_0002.v"] 4 | set_global_assignment -library "pll" -name QIP_FILE [file join $::quartus(qip_path) "pll/pll_0002.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_AUTO_RESET ON -to "*pll_0002*|altera_pll:altera_pll_i*|*" 3 | set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*" 4 | -------------------------------------------------------------------------------- /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 'outclk1' 14 | output wire outclk_1, 15 | 16 | // interface 'outclk2' 17 | output wire outclk_2, 18 | 19 | // interface 'outclk3' 20 | output wire outclk_3, 21 | 22 | // interface 'outclk4' 23 | output wire outclk_4, 24 | 25 | // interface 'locked' 26 | output wire locked 27 | ); 28 | 29 | altera_pll #( 30 | .fractional_vco_multiplier("true"), 31 | .reference_clock_frequency("50.0 MHz"), 32 | .operation_mode("direct"), 33 | .number_of_clocks(5), 34 | .output_clock_frequency0("7.159090 MHz"), 35 | .phase_shift0("69841 ps"), 36 | .duty_cycle0(50), 37 | .output_clock_frequency1("14.318180 MHz"), 38 | .phase_shift1("34921 ps"), 39 | .duty_cycle1(50), 40 | .output_clock_frequency2("57.272720 MHz"), 41 | .phase_shift2("8730 ps"), 42 | .duty_cycle2(50), 43 | .output_clock_frequency3("93.068170 MHz"), 44 | .phase_shift3("5372 ps"), 45 | .duty_cycle3(50), 46 | .output_clock_frequency4("93.068170 MHz"), 47 | .phase_shift4("2686 ps"), 48 | .duty_cycle4(50), 49 | .output_clock_frequency5("0 MHz"), 50 | .phase_shift5("0 ps"), 51 | .duty_cycle5(50), 52 | .output_clock_frequency6("0 MHz"), 53 | .phase_shift6("0 ps"), 54 | .duty_cycle6(50), 55 | .output_clock_frequency7("0 MHz"), 56 | .phase_shift7("0 ps"), 57 | .duty_cycle7(50), 58 | .output_clock_frequency8("0 MHz"), 59 | .phase_shift8("0 ps"), 60 | .duty_cycle8(50), 61 | .output_clock_frequency9("0 MHz"), 62 | .phase_shift9("0 ps"), 63 | .duty_cycle9(50), 64 | .output_clock_frequency10("0 MHz"), 65 | .phase_shift10("0 ps"), 66 | .duty_cycle10(50), 67 | .output_clock_frequency11("0 MHz"), 68 | .phase_shift11("0 ps"), 69 | .duty_cycle11(50), 70 | .output_clock_frequency12("0 MHz"), 71 | .phase_shift12("0 ps"), 72 | .duty_cycle12(50), 73 | .output_clock_frequency13("0 MHz"), 74 | .phase_shift13("0 ps"), 75 | .duty_cycle13(50), 76 | .output_clock_frequency14("0 MHz"), 77 | .phase_shift14("0 ps"), 78 | .duty_cycle14(50), 79 | .output_clock_frequency15("0 MHz"), 80 | .phase_shift15("0 ps"), 81 | .duty_cycle15(50), 82 | .output_clock_frequency16("0 MHz"), 83 | .phase_shift16("0 ps"), 84 | .duty_cycle16(50), 85 | .output_clock_frequency17("0 MHz"), 86 | .phase_shift17("0 ps"), 87 | .duty_cycle17(50), 88 | .pll_type("General"), 89 | .pll_subtype("General") 90 | ) altera_pll_i ( 91 | .rst (rst), 92 | .outclk ({outclk_4, outclk_3, outclk_2, outclk_1, outclk_0}), 93 | .locked (locked), 94 | .fboutclk ( ), 95 | .fbclk (1'b0), 96 | .refclk (refclk) 97 | ); 98 | endmodule 99 | 100 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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'b0, 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/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/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 | -------------------------------------------------------------------------------- /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/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/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/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.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 | -------------------------------------------------------------------------------- /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/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_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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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_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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 {LED[*]}] 28 | set_false_path -to [get_ports {HDMI_*}] 29 | set_false_path -to [get_ports {IO_SCL IO_SDA SD_SPI_CS SDCD_SPDIF}] 30 | set_false_path -from [get_ports {HDMI_I2C_SDA HDMI_TX_INT IO_SDA VGA_EN}] 31 | set_false_path -to [get_ports {USER_IO[*]}] 32 | set_false_path -to [get_ports {VGA_*}] 33 | set_false_path -to [get_ports {AUDIO_SPDIF}] 34 | set_false_path -to [get_ports {AUDIO_L}] 35 | set_false_path -to [get_ports {AUDIO_R}] 36 | set_false_path -from {get_ports {SW[*]}} 37 | set_false_path -to {cfg[*]} 38 | set_false_path -from {cfg[*]} 39 | set_false_path -from {VSET[*]} 40 | set_false_path -to {wcalc[*] hcalc[*]} 41 | set_false_path -to {hdmi_width[*] hdmi_height[*]} 42 | set_false_path -to {deb_* btn_en btn_up} 43 | 44 | set_multicycle_path -to {*_osd|osd_vcnt*} -setup 2 45 | set_multicycle_path -to {*_osd|osd_vcnt*} -hold 1 46 | 47 | set_false_path -to {*_osd|v_cnt*} 48 | set_false_path -to {*_osd|v_osd_start*} 49 | set_false_path -to {*_osd|v_info_start*} 50 | set_false_path -to {*_osd|h_osd_start*} 51 | set_false_path -from {*_osd|v_osd_start*} 52 | set_false_path -from {*_osd|v_info_start*} 53 | set_false_path -from {*_osd|h_osd_start*} 54 | set_false_path -from {*_osd|rot*} 55 | set_false_path -from {*_osd|dsp_width*} 56 | set_false_path -to {*_osd|half} 57 | 58 | set_false_path -to {WIDTH[*] HFP[*] HS[*] HBP[*] HEIGHT[*] VFP[*] VS[*] VBP[*]} 59 | set_false_path -from {WIDTH[*] HFP[*] HS[*] HBP[*] HEIGHT[*] VFP[*] VS[*] VBP[*]} 60 | set_false_path -to {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*] LFB_HMAX[*] LFB_VMIN[*] LFB_VMAX[*]} 61 | set_false_path -from {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*] LFB_HMAX[*] LFB_VMIN[*] LFB_VMAX[*]} 62 | set_false_path -to {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]} 63 | set_false_path -from {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]} 64 | set_false_path -from {aflt_* acx* acy* areset* arc*} 65 | set_false_path -from {arx* ary*} 66 | set_false_path -from {vs_line*} 67 | 68 | set_false_path -from {ascal|o_ihsize*} 69 | set_false_path -from {ascal|o_ivsize*} 70 | set_false_path -from {ascal|o_format*} 71 | set_false_path -from {ascal|o_hdown} 72 | set_false_path -from {ascal|o_vdown} 73 | set_false_path -from {ascal|o_hmin* ascal|o_hmax* ascal|o_vmin* ascal|o_vmax* ascal|o_vrrmax* ascal|o_vrr} 74 | set_false_path -from {ascal|o_hdisp* ascal|o_vdisp*} 75 | set_false_path -from {ascal|o_htotal* ascal|o_vtotal*} 76 | set_false_path -from {ascal|o_hsstart* ascal|o_vsstart* ascal|o_hsend* ascal|o_vsend*} 77 | set_false_path -from {ascal|o_hsize* ascal|o_vsize*} 78 | 79 | set_false_path -from {mcp23009|flg_*} 80 | set_false_path -to {sysmem|fpga_interfaces|clocks_resets*} 81 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | // video output signals 30 | output reg [7:0] VGA_R, 31 | output reg [7:0] VGA_G, 32 | output reg [7:0] VGA_B, 33 | output reg VGA_VS, 34 | output reg VGA_HS, 35 | output VGA_DE, 36 | 37 | // optional aligned blank 38 | output reg HBlank_out, 39 | output reg VBlank_out, 40 | 41 | // optional aligned de 42 | output reg DE_out 43 | ); 44 | 45 | wire hs, vs; 46 | s_fix sync_v(clk_vid, HSync, hs); 47 | s_fix sync_h(clk_vid, VSync, vs); 48 | 49 | wire hbl = hs | HBlank; 50 | wire vbl = vs | VBlank; 51 | 52 | assign VGA_DE = ~(HBlank_out | VBlank_out); 53 | 54 | always @(posedge clk_vid) begin 55 | if(ce_pix) begin 56 | HBlank_out <= hbl; 57 | 58 | VGA_HS <= hs; 59 | if(~VGA_HS & hs) VGA_VS <= vs; 60 | 61 | VGA_R <= R; 62 | VGA_G <= G; 63 | VGA_B <= B; 64 | DE_out <= DE_in; 65 | 66 | if(HBlank_out & ~hbl) VBlank_out <= vbl; 67 | end 68 | end 69 | 70 | endmodule 71 | 72 | module s_fix 73 | ( 74 | input clk, 75 | 76 | input sync_in, 77 | output sync_out 78 | ); 79 | 80 | assign sync_out = sync_in ^ pol; 81 | 82 | reg pol; 83 | always @(posedge clk) begin 84 | integer pos = 0, neg = 0, cnt = 0; 85 | reg s1,s2; 86 | 87 | s1 <= sync_in; 88 | s2 <= s1; 89 | 90 | if(~s2 & s1) neg <= cnt; 91 | if(s2 & ~s1) pos <= cnt; 92 | 93 | cnt <= cnt + 1; 94 | if(s2 != s1) cnt <= 0; 95 | 96 | pol <= pos > neg; 97 | end 98 | 99 | endmodule 100 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------