├── .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 |
--------------------------------------------------------------------------------