1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-03-06 19:11:02 +00:00
This commit is contained in:
Marcel
2023-05-18 14:10:30 +02:00
parent cdd9fe0bb4
commit 437759735a
22 changed files with 4135 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 1991-2014 Altera Corporation
# Your use of Altera Corporation's design tools, logic functions
# and other software and tools, and its AMPP partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License
# Subscription Agreement, Altera MegaCore Function License
# Agreement, or other applicable license agreement, including,
# without limitation, that your use is for the sole purpose of
# programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the
# applicable agreement for further details.
#
# -------------------------------------------------------------------------- #
#
# Quartus II 64-Bit
# Version 13.1.4 Build 182 03/12/2014 SJ Full Version
# Date created = 16:01:18 November 25, 2020
#
# -------------------------------------------------------------------------- #
QUARTUS_VERSION = "13.1"
DATE = "16:01:18 November 25, 2020"
# Revisions
PROJECT_REVISION = "MyVision"

View File

@@ -0,0 +1,251 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 1991-2014 Altera Corporation
# Your use of Altera Corporation's design tools, logic functions
# and other software and tools, and its AMPP partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License
# Subscription Agreement, Altera MegaCore Function License
# Agreement, or other applicable license agreement, including,
# without limitation, that your use is for the sole purpose of
# programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the
# applicable agreement for further details.
#
# -------------------------------------------------------------------------- #
#
# Quartus II 64-Bit
# Version 13.1.4 Build 182 03/12/2014 SJ Full Version
# Date created = 14:04:16 May 18, 2023
#
# -------------------------------------------------------------------------- #
#
# Notes:
#
# 1) The default values for assignments are stored in the file:
# MyVision_assignment_defaults.qdf
# If this file doesn't exist, see file:
# assignment_defaults.qdf
#
# 2) Altera recommends that you do not modify this file. This
# file is updated automatically by the Quartus II software
# and any changes you make may be lost or overwritten.
#
# -------------------------------------------------------------------------- #
# Project-Wide Assignments
# ========================
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl"
set_global_assignment -name SMART_RECOMPILE ON
set_global_assignment -name SYSTEMVERILOG_FILE rtl/MyVision.sv
set_global_assignment -name VERILOG_FILE rtl/MyVision_top.v
set_global_assignment -name VERILOG_FILE rtl/cpu_z80.v
set_global_assignment -name VHDL_FILE rtl/spram.vhd
set_global_assignment -name QIP_FILE "D:/GitHub/Mist_FPGA/common/mist/mist.qip"
set_global_assignment -name QIP_FILE "D:/GitHub/Mist_FPGA/common/CPU/T80/T80.qip"
set_global_assignment -name VHDL_FILE "D:/GitHub/Mist_FPGA/common/Sound/ym2149/YM2149.vhd"
set_global_assignment -name VHDL_FILE "D:/GitHub/Mist_FPGA/common/Sound/ym2149/vol_table_array.vhd"
set_global_assignment -name SYSTEMVERILOG_FILE rtl/vdp18v/vdp18_sprite.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/vdp18v/vdp18_pkg.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/vdp18v/vdp18_pattern.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/vdp18v/vdp18_hor_vert.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/vdp18v/vdp18_ctrl.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/vdp18v/vdp18_cpuio.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/vdp18v/vdp18_core.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/vdp18v/vdp18_col_mux.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/vdp18v/vdp18_clk_gen.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/vdp18v/vdp18_addr_mux.sv
set_global_assignment -name VERILOG_FILE rtl/pll.v
# Pin & Location Assignments
# ==========================
set_location_assignment PIN_7 -to LED
set_location_assignment PIN_54 -to CLOCK_27
set_location_assignment PIN_144 -to VGA_R[5]
set_location_assignment PIN_143 -to VGA_R[4]
set_location_assignment PIN_142 -to VGA_R[3]
set_location_assignment PIN_141 -to VGA_R[2]
set_location_assignment PIN_137 -to VGA_R[1]
set_location_assignment PIN_135 -to VGA_R[0]
set_location_assignment PIN_133 -to VGA_B[5]
set_location_assignment PIN_132 -to VGA_B[4]
set_location_assignment PIN_125 -to VGA_B[3]
set_location_assignment PIN_121 -to VGA_B[2]
set_location_assignment PIN_120 -to VGA_B[1]
set_location_assignment PIN_115 -to VGA_B[0]
set_location_assignment PIN_114 -to VGA_G[5]
set_location_assignment PIN_113 -to VGA_G[4]
set_location_assignment PIN_112 -to VGA_G[3]
set_location_assignment PIN_111 -to VGA_G[2]
set_location_assignment PIN_110 -to VGA_G[1]
set_location_assignment PIN_106 -to VGA_G[0]
set_location_assignment PIN_136 -to VGA_VS
set_location_assignment PIN_119 -to VGA_HS
set_location_assignment PIN_65 -to AUDIO_L
set_location_assignment PIN_80 -to AUDIO_R
set_location_assignment PIN_105 -to SPI_DO
set_location_assignment PIN_88 -to SPI_DI
set_location_assignment PIN_126 -to SPI_SCK
set_location_assignment PIN_127 -to SPI_SS2
set_location_assignment PIN_91 -to SPI_SS3
set_location_assignment PIN_13 -to CONF_DATA0
set_location_assignment PIN_49 -to SDRAM_A[0]
set_location_assignment PIN_44 -to SDRAM_A[1]
set_location_assignment PIN_42 -to SDRAM_A[2]
set_location_assignment PIN_39 -to SDRAM_A[3]
set_location_assignment PIN_4 -to SDRAM_A[4]
set_location_assignment PIN_6 -to SDRAM_A[5]
set_location_assignment PIN_8 -to SDRAM_A[6]
set_location_assignment PIN_10 -to SDRAM_A[7]
set_location_assignment PIN_11 -to SDRAM_A[8]
set_location_assignment PIN_28 -to SDRAM_A[9]
set_location_assignment PIN_50 -to SDRAM_A[10]
set_location_assignment PIN_30 -to SDRAM_A[11]
set_location_assignment PIN_32 -to SDRAM_A[12]
set_location_assignment PIN_83 -to SDRAM_DQ[0]
set_location_assignment PIN_79 -to SDRAM_DQ[1]
set_location_assignment PIN_77 -to SDRAM_DQ[2]
set_location_assignment PIN_76 -to SDRAM_DQ[3]
set_location_assignment PIN_72 -to SDRAM_DQ[4]
set_location_assignment PIN_71 -to SDRAM_DQ[5]
set_location_assignment PIN_69 -to SDRAM_DQ[6]
set_location_assignment PIN_68 -to SDRAM_DQ[7]
set_location_assignment PIN_86 -to SDRAM_DQ[8]
set_location_assignment PIN_87 -to SDRAM_DQ[9]
set_location_assignment PIN_98 -to SDRAM_DQ[10]
set_location_assignment PIN_99 -to SDRAM_DQ[11]
set_location_assignment PIN_100 -to SDRAM_DQ[12]
set_location_assignment PIN_101 -to SDRAM_DQ[13]
set_location_assignment PIN_103 -to SDRAM_DQ[14]
set_location_assignment PIN_104 -to SDRAM_DQ[15]
set_location_assignment PIN_58 -to SDRAM_BA[0]
set_location_assignment PIN_51 -to SDRAM_BA[1]
set_location_assignment PIN_85 -to SDRAM_DQMH
set_location_assignment PIN_67 -to SDRAM_DQML
set_location_assignment PIN_60 -to SDRAM_nRAS
set_location_assignment PIN_64 -to SDRAM_nCAS
set_location_assignment PIN_66 -to SDRAM_nWE
set_location_assignment PIN_59 -to SDRAM_nCS
set_location_assignment PIN_33 -to SDRAM_CKE
set_location_assignment PIN_43 -to SDRAM_CLK
set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component"
# Classic Timing Assignments
# ==========================
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON
# Analysis & Synthesis Assignments
# ================================
set_global_assignment -name FAMILY "Cyclone III"
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8
set_global_assignment -name DEVICE_FILTER_PACKAGE TQFP
set_global_assignment -name TOP_LEVEL_ENTITY MyVision
set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
# Fitter Assignments
# ==================
set_global_assignment -name DEVICE EP3C25E144C8
set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
set_global_assignment -name ENABLE_NCE_PIN OFF
set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL"
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON
set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC_FOR_AREA ON
set_global_assignment -name PHYSICAL_SYNTHESIS_MAP_LOGIC_TO_MEMORY_FOR_AREA ON
# Assembler Assignments
# =====================
set_global_assignment -name GENERATE_RBF_FILE ON
set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
# SignalTap II Assignments
# ========================
set_global_assignment -name ENABLE_SIGNALTAP OFF
set_global_assignment -name USE_SIGNALTAP_FILE output_files/dect.stp
# Power Estimation Assignments
# ============================
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW"
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
# Advanced I/O Timing Assignments
# ===============================
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall
# ----------------------
# start ENTITY(MyVision)
# Pin & Location Assignments
# ==========================
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[*]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[*]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[0]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[1]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQMH
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQML
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nRAS
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCAS
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nWE
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCS
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[*]
# Fitter Assignments
# ==================
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[*]
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[*]
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_BA[*]
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQML
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQMH
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nRAS
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCAS
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nWE
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCS
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CKE
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CLK
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_R[*]
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_G[*]
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_B[*]
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_HS
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_VS
set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_L
set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_R
set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SPI_DO
# start DESIGN_PARTITION(Top)
# ---------------------------
# Incremental Compilation Assignments
# ===================================
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
# end DESIGN_PARTITION(Top)
# -------------------------
# end ENTITY(MyVision)
# --------------------
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -0,0 +1,32 @@
<p align="center">
<img style="width: 400px;" src="img/MyVision.gif">
</p>
# [My Vision](https://wikipedia.org/wiki/My_Vision) for [MiSTer](https://mister-devel.github.io/MkDocs_MiSTer/)
This is an FPGA implementation of the My Vision Console by Nichibutsu for the MiSTer FPGA platform.
## About the System
- Released only in Japan with only 6 Games/Cartridges only 4 are dumped.
- It did not use controllers, instead it had buttons on the console itself.
- The Direction Buttons (A,B,C & D) are mapped to the Cursor Keys, or you can use a Joystick
- The E button is mapped to the <kbd>Space Bar</kbd> or you can use the Fire Button on a Joystick.
Console Button to Keyboard Mapping
Console : |<kbd>1</kbd> | <kbd>2</kbd> | <kbd>3</kbd> | <kbd>4</kbd> | <kbd>5</kbd> | <kbd>6</kbd> | <kbd>7</kbd> | <kbd>8</kbd> | <kbd>9</kbd> | <kbd>10</kbd> | <kbd>11</kbd> | <kbd>12</kbd> | <kbd>13</kbd> | <kbd>14</kbd> | <kbd>A</kbd> | <kbd>B</kbd> | <kbd>C</kbd> | <kbd>D</kbd> | <kbd>E</kbd>
----------|-|-|-|-|-|-|-|-|-|--|--|--|--|--|-|-|-|-|-|
Option A : |<kbd>1</kbd> | <kbd>2</kbd> | <kbd>3</kbd> | <kbd>4</kbd> | <kbd>5</kbd> | <kbd>6</kbd> | <kbd>7</kbd> | <kbd>8</kbd> | <kbd>9</kbd> | <kbd>0</kbd> | <kbd>-</kbd> | <kbd>=</kbd> | <kbd>⌫</kbd> | <kbd>\\</kbd> | <kbd>←</kbd> | <kbd>↑</kbd> | <kbd>↓</kbd> | <kbd>→</kbd> | <kbd>Space</kbd>
Option B: |<kbd>A</kbd> | <kbd>B</kbd> | <kbd>C</kbd> | <kbd>D</kbd> | <kbd>E</kbd> | <kbd>F</kbd> | <kbd>G</kbd> | <kbd>H</kbd> | <kbd>I</kbd> | <kbd>J</kbd> | <kbd>K</kbd> | <kbd>L</kbd> | <kbd>M</kbd> | <kbd>N</kbd> | <kbd>←</kbd> | <kbd>↑</kbd> | <kbd>↓</kbd> | <kbd>→</kbd> | <kbd>Fire</kbd>
## Prepping Files
If your game is a zip and contains multiple files such as "f1" "f2" and so on, then you'll need to convert them to .bin for the core to be able to load it. First extract those files and then perform the following commands.
**Using MS-DOS/CMD:**
```
copy /B f1 + /B f2 + /B f3 Hanafuda.bin
```
**Using Linux/MiSTer:**
```
cat f1 f2 f3 > Hanafuda.bin
```

View File

@@ -0,0 +1,41 @@
@echo off
del /s *.bak
del /s *.orig
del /s *.rej
del /s *~
rmdir /s /q db
rmdir /s /q incremental_db
rmdir /s /q output_files
rmdir /s /q simulation
rmdir /s /q greybox_tmp
rmdir /s /q hc_output
rmdir /s /q .qsys_edit
rmdir /s /q hps_isw_handoff
rmdir /s /q sys\.qsys_edit
rmdir /s /q sys\vip
cd sys
for /d %%i in (*_sim) do rmdir /s /q "%%~nxi"
cd ..
for /d %%i in (*_sim) do rmdir /s /q "%%~nxi"
del build_id.v
del c5_pin_model_dump.txt
del PLLJ_PLLSPE_INFO.txt
del /s *.qws
del /s *.ppf
del /s *.ddb
del /s *.csv
del /s *.cmp
del /s *.sip
del /s *.spd
del /s *.bsf
del /s *.f
del /s *.sopcinfo
del /s *.xml
del *.cdf
del /s new_rtl_netlist
del /s old_rtl_netlist
del sys\vip.qip
del sys\sysmem.qip
del sys\sdram.sv
del sys\ddram.sv
pause

View File

@@ -0,0 +1,175 @@
module MyVision(
output LED,
output [5:0] VGA_R,
output [5:0] VGA_G,
output [5:0] VGA_B,
output VGA_HS,
output VGA_VS,
output AUDIO_L,
output AUDIO_R,
input SPI_SCK,
output SPI_DO,
input SPI_DI,
input SPI_SS2,
input SPI_SS3,
input CONF_DATA0,
input CLOCK_27
);
`include "rtl\build_id.v"
localparam CONF_STR = {
"MYVISION;bin;",
"O1,Joystick Swap,On,Off;",
// "O2,Joystick Control,Upright,Normal;",
"O34,Scandoubler Fx,None,CRT 25%,CRT 50%,CRT 75%;",
// "O5,Service,On,Off;",
"T0,Reset;",
"V,v1.00.",`BUILD_DATE
};
wire clk_sys, clk_3m58, pll_locked;
pll pll
(
.inclk0(CLOCK_27),
.areset(0),
.c0(clk_sys),//42.954545
.c1(clk_3m58),//3.579545
.locked(pll_locked)
);
wire [63:0] status;
wire [1:0] buttons;
wire [1:0] switches;
wire [31:0] joystick_0;
wire [31:0] joystick_1;
wire scandoublerD;
wire [1:0] scanlines = status[4:3];
wire [9:0] audio;
wire hsync,vsync;
assign LED = ~ioctl_downl;
wire blankn = ~(hb | vb);
wire hb, vb, hs, vs;
wire [7:0] r,b,g;
wire ypbpr;
wire no_csync;
wire key_strobe;
wire key_pressed;
wire [7:0] key_code;
wire key_extended;
mist_video #(
.COLOR_DEPTH(6),
.SD_HCNT_WIDTH(10))
mist_video(
.clk_sys(clk_sys),
.SPI_SCK(SPI_SCK),
.SPI_SS3(SPI_SS3),
.SPI_DI(SPI_DI),
.R(blankn ? r[7:2] : 0),
.G(blankn ? g[7:2] : 0),
.B(blankn ? b[7:2] : 0),
.HSync(hs),
.VSync(vs),
.VGA_R(VGA_R),
.VGA_G(VGA_G),
.VGA_B(VGA_B),
.VGA_VS(VGA_VS),
.VGA_HS(VGA_HS),
.ce_divider(1'b0),
.scandoubler_disable(scandoublerD),
.scanlines(scanlines),
.ypbpr(ypbpr)
);
user_io #(
.STRLEN($size(CONF_STR)>>3))
user_io(
.clk_sys (clk_sys ),
.conf_str (CONF_STR ),
.SPI_CLK (SPI_SCK ),
.SPI_SS_IO (CONF_DATA0 ),
.SPI_MISO (SPI_DO ),
.SPI_MOSI (SPI_DI ),
.buttons (buttons ),
.switches (switches ),
.scandoubler_disable (scandoublerD ),
.ypbpr (ypbpr ),
.key_strobe (key_strobe ),
.key_pressed (key_pressed ),
.key_code (key_code ),
.key_extended (key_extended ),
.joystick_0 (joystick_0 ),
.joystick_1 (joystick_1 ),
.status (status )
);
dac #(16) dac(
.clk_i(clk_sys),
.res_n_i(1),
.dac_i({audio,6'd0}),
.dac_o(AUDIO_L)
);
assign AUDIO_R = AUDIO_L;
wire [14:0] ram_a;
wire ram_we_n, ram_ce_n;
wire [7:0] ram_di;
wire [7:0] ram_do;
spram #(15, 8) ram//32k system uses only max 24k
(
.clock(clk_sys),
.address(ioctl_downl ? ioctl_addr[14:0] : ram_a),
.wren(ioctl_wr | ~ram_we_n),
.data(ioctl_downl ? ioctl_dout : ram_do),
.q(ram_di)
);
wire ioctl_downl;
wire [7:0] ioctl_index;
wire ioctl_wr;
wire [24:0] ioctl_addr;
wire [7:0] ioctl_dout;
data_io data_io(
.clk_sys ( clk_sys ),
.SPI_SCK ( SPI_SCK ),
.SPI_SS2 ( SPI_SS2 ),
.SPI_DI ( SPI_DI ),
.ioctl_download( ioctl_downl ),
.ioctl_index ( ioctl_index ),
.ioctl_wr ( ioctl_wr ),
.ioctl_addr ( ioctl_addr ),
.ioctl_dout ( ioctl_dout )
);
wire reset = status[0] | buttons[1] | ioctl_downl;
MyVision_top console(
.clk_3m58(clk_3m58),
.clk_sys(clk_sys),
.reset(reset),
.audio(audio),
////////////// CPU RAM Interface //////////////
.cpu_ram_a_o(ram_a),
.cpu_ram_ce_n_o(ram_ce_n),
.cpu_ram_we_n_o(ram_we_n),
.cpu_ram_d_i(ram_di),
.cpu_ram_d_o(ram_do),
.joy0(joystick_0),
.joy1(joystick_1),
.ps2_key({key_strobe,key_pressed,key_extended,key_code}),
.HBlank(hb),
.HSync(hs),
.VBlank(vb),
.VSync(vs),
.ce_pix(),
.rgb_r_o(r),
.rgb_g_o(g),
.rgb_b_o(b)
);
endmodule

View File

@@ -0,0 +1,292 @@
module MyVision_top
(
input clk_sys,
input clk_3m58,
input reset,
///////////// CPU RAM Interface /////////////
output [15:0] cpu_ram_a_o,
output reg cpu_ram_ce_n_o,
output reg cpu_ram_we_n_o,
input [7:0] cpu_ram_d_i,
output [7:0] cpu_ram_d_o,
//////////// Controller Interface /////////////
input [10:0] ps2_key,
input [31:0] joy0,
input [31:0] joy1,
////////////// AUDIO Interface //////////////
output [9:0] audio,
////////////// VIDEO Interface //////////////
output reg HBlank,
output reg HSync,
output reg VBlank,
output reg VSync,
output reg comp_sync_n_o,
output reg ce_pix,
output [7:0] rgb_r_o,
output [7:0] rgb_g_o,
output [7:0] rgb_b_o
);
reg nMEM;
reg nRD;
reg nWR;
reg nIRQ;
reg nINT;
reg nNMI;
reg nWAIT;
reg [15:0] cpu_addr;
reg [7:0] data_to_cpu;
reg [7:0] data_from_cpu;
cpu_z80 Z80CPU(
.CLK_4M(clk_3m58),
.nRESET(~reset),
.SDA(cpu_addr),
.SDD_IN(data_to_cpu),
.SDD_OUT(data_from_cpu),
.nIORQ(nIRQ),
.nMREQ(nMEM),
.nRD(nRD),
.nWR(nWR),
.nINT(nINT),
.nNMI(nNMI),
.nWAIT(nWAIT)
);
assign cpu_ram_we_n_o = (cpu_ram_a_o > 16'h7FFF && (~nMEM && ~nWR)) ? 1'b0 : 1'b1;
assign cpu_ram_ce_n_o = (~nMEM && !nRD) ? 1'b0 : 1'b1;
assign nWAIT = 1'b1;
assign nNMI = 1'b1;
assign cpu_ram_a_o = cpu_addr;
assign cpu_ram_d_o = data_from_cpu;
assign data_to_cpu = (cpu_addr[15:2] == 14'h3800 && ~nRD && ~nMEM) ? vdp_data_out :
(cpu_ram_a_o[7:0] == 8'h02 && ~nRD && ~nIRQ) ? ym_data_out :
cpu_ram_d_i;
///////////////////////////SOUND///////////////////////////
reg clk_snd;
reg [7:0] ym_data_out;
always @(posedge clk_3m58) begin
if(reset) clk_snd <= 1'b1;
else clk_snd <= ~clk_snd;
end
ym2149 sound
(
//Data BUS
.I_DA(data_from_cpu),
.O_DA(ym_data_out),
.O_DA_OE_L(),
//control
.I_A9_L((cpu_ram_a_o[7:2] == 6'h00 && (~nWR || ~nRD) && ~nIRQ) ? 1'b0 : 1'b1),
.I_A8(1'b1),
.I_BDIR((cpu_ram_a_o[7:2] == 6'h00 && ~nWR && ~nIRQ) ? 1'b1 : 1'b0),
.I_BC2((((cpu_ram_a_o[7:0] == 8'h01 && ~nWR) || (cpu_ram_a_o[7:0] == 8'h02 && ~nRD)) && ~nIRQ) ? 1'b1 : 1'b0),
.I_BC1((cpu_ram_a_o[7:0] == 8'h02 && ~nRD && ~nIRQ) ? 1'b1 : 1'b0),
.I_SEL_L(1'b1),
.O_AUDIO(audio),
//port a
.I_IOA(keydata),
.O_IOA(),
.O_IOA_OE_L(),
//port b
.I_IOB(8'hFF),
.O_IOB(key_column),
.O_IOB_OE_L(),
.ENA(1'b1),
.RESET_L(~reset),
.CLK(clk_snd)
);
/////////////////////////// IO ///////////////////////////
reg [7:0] io_data;
reg [7:0] io_regs[8];
reg [7:0] FD_data;
reg FD_buffer_flag;
reg [1:0] rd_sampler,wr_sampler;
reg [7:0] port_status;
always @(posedge clk_sys) begin
rd_sampler = {rd_sampler[0],~(~nRD && ~nMEM)};
wr_sampler = {wr_sampler[0],~(~nWR && ~nMEM)};
end
//Keyboard
wire pressed = ps2_key[9];
wire [8:0] code = ps2_key[8:0];
always @(posedge clk_3m58) begin
reg old_state;
old_state <= ps2_key[10];
if(old_state != ps2_key[10]) begin
casex(code[7:0])
//Left Controller
'hX16: btn_1 <= ~pressed; // 1
'hX1E: btn_2 <= ~pressed; // 2
'hX26: btn_3 <= ~pressed; // 3
'hX25: btn_4 <= ~pressed; // 4
'hX2E: btn_5 <= ~pressed; // 5
'hX36: btn_6 <= ~pressed; // 6
'hX3D: btn_7 <= ~pressed; // 7
'hX3E: btn_8 <= ~pressed; // 8
'hX46: btn_9 <= ~pressed; // 9
'hX45: btn_10 <= ~pressed; // 0
'hX4E: btn_11 <= ~pressed; // - => 11
'hX55: btn_12 <= ~pressed; // = => 12
'hX66: btn_13 <= ~pressed; // BackSpace => 13
'hX5D: btn_14 <= ~pressed; // \ => 14
'hX75: btn_up <= ~pressed; //B
'hX72: btn_down <= ~pressed; //C
'hX6B: btn_left <= ~pressed; //A
'hX74: btn_right <= ~pressed; //D
'hX29: btn_fire <= ~pressed; //Space <= E
'hX1C: btn_1 <= ~pressed; // a
'hX32: btn_2 <= ~pressed; // b
'hX21: btn_3 <= ~pressed; // c
'hX23: btn_4 <= ~pressed; // d
'hX24: btn_5 <= ~pressed; // e
'hX2B: btn_6 <= ~pressed; // f
'hX34: btn_7 <= ~pressed; // g
'hX33: btn_8 <= ~pressed; // h
'hX43: btn_9 <= ~pressed; // i
'hX3B: btn_10 <= ~pressed; // j
'hX42: btn_11 <= ~pressed; // k
'hX4B: btn_12 <= ~pressed; // l
'hX3A: btn_13 <= ~pressed; // m
'hX31: btn_14 <= ~pressed; // n
endcase
end
end
wire [7:0] key_row[4];
assign key_row[0] = { btn_1 , btn_5 , btn_9 , btn_down & ~joy0[2] , btn_13 , 3'b111 };
assign key_row[1] = { btn_4 , btn_8 , btn_12 , 1'b1 , btn_up & ~joy0[3] , 3'b111 };
assign key_row[2] = { btn_2 , btn_6 , btn_10 , btn_right & ~joy0[0] , btn_14 , 3'b111 };
assign key_row[3] = { btn_3 , btn_7 , btn_11 , btn_fire & ~joy0[4] , btn_left & ~joy0[1] , 3'b111 };
reg btn_1 = 1;
reg btn_2 = 1;
reg btn_3 = 1;
reg btn_4 = 1;
reg btn_5 = 1;
reg btn_6 = 1;
reg btn_7 = 1;
reg btn_8 = 1;
reg btn_9 = 1;
reg btn_10 = 1;
reg btn_11 = 1;
reg btn_12 = 1;
reg btn_13 = 1;
reg btn_14 = 1;
reg btn_up = 1;
reg btn_down = 1;
reg btn_left = 1;
reg btn_right = 1;
reg btn_fire = 1;
////////////////////////////PIA////////////////////////////
reg [7:0] ppi_dout, key_column;
reg [7:0] keydata;
reg [7:0] joydata;
assign keydata = 8'hFF & (key_column[7] ? 8'hFF : key_row[0]) & (key_column[6] ? 8'hFF : key_row[1]) & (key_column[5] ? 8'hFF : key_row[2]) & (key_column[4] ? 8'hFF : key_row[3]);
///////////////////////////VIDEO///////////////////////////
reg [7:0] R,G,B;
// -----------------------------------------------------------------------------
// -- TMS9928A Video Display Processor
// -----------------------------------------------------------------------------
// VDP read and write signals
wire vdp_wr;
wire vdp_rd;
wire [7:0] vdp_data_out;
reg hsync_n,vsync_n;
reg [3:0] col_o;
always @(posedge clk_sys) begin
if(ce_10m7) begin
vdp_wr <= 1'b0;
end
if(cpu_addr[15:2] == 14'h3800 && wr_sampler == 2'b10 && ~nMEM) vdp_wr <= 1'b1;
end
assign vdp_rd = (cpu_addr[15:2] == 14'h3800 && ~nRD && ~nMEM) ? 1'b1: 1'b0; // Should we also check if IAQS is low?
reg ce_10m7 = 0;
reg ce_5m3 = 0;
always @(posedge clk_sys) begin
reg [2:0] div;
div <= div+1'd1;
ce_10m7 <= !div[1:0];
ce_5m3 <= !div[2:0];
end
assign ce_pix = ce_5m3;
vdp18_core vdp
(
.clk_i(clk_sys),
.clk_en_10m7_i(ce_10m7),
.reset_n_i(~reset),
.csr_n_i(~vdp_rd),
.csw_n_i(~vdp_wr),
.mode_i(cpu_addr[1]),
.int_n_o(nINT),
.cd_i(data_from_cpu),
.cd_o(vdp_data_out),
.vram_we_o(vram_we_o),
.vram_a_o(vram_a_o),
.vram_d_o(vram_d_o),
.vram_d_i(vram_d_i),
.col_o(col_o),
.rgb_r_o(rgb_r_o),
.rgb_g_o(rgb_g_o),
.rgb_b_o(rgb_b_o),
.hsync_n_o(hsync_n),
.vsync_n_o(vsync_n),
.blank_n_o(),
.hblank_o(HBlank),
.vblank_o(VBlank),
.comp_sync_n_o(comp_sync_n_o)
);
assign HSync = ~hsync_n;
assign VSync = ~vsync_n;
reg [13:0] vram_a_o;
reg vram_we_o;
reg [7:0] vram_d_o;
reg [7:0] vram_d_i;
spram #(14, 8) vram
(
.clock(clk_sys),
.address(vram_a_o),
.wren(vram_we_o),
.data(vram_d_o),
.q(vram_d_i)
);
endmodule

View File

@@ -0,0 +1,35 @@
# ================================================================================
#
# Build ID Verilog Module Script
# Jeff Wiencrot - 8/1/2011
#
# Generates a Verilog module that contains a timestamp,
# from the current build. These values are available from the build_date, build_time,
# physical_address, and host_name output ports of the build_id module in the build_id.v
# Verilog source file.
#
# ================================================================================
proc generateBuildID_Verilog {} {
# Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html)
set buildDate [ clock format [ clock seconds ] -format %y%m%d ]
set buildTime [ clock format [ clock seconds ] -format %H%M%S ]
# Create a Verilog file for output
set outputFileName "rtl/build_id.v"
set outputFile [open $outputFileName "w"]
# Output the Verilog source
puts $outputFile "`define BUILD_DATE \"$buildDate\""
puts $outputFile "`define BUILD_TIME \"$buildTime\""
close $outputFile
# Send confirmation message to the Messages window
post_message "Generated build identification Verilog module: [pwd]/$outputFileName"
post_message "Date: $buildDate"
post_message "Time: $buildTime"
}
# Comment out this line to prevent the process from automatically executing when the file is sourced:
generateBuildID_Verilog

View File

@@ -0,0 +1,51 @@
// NeoGeo logic definition
// Copyright (C) 2018 Sean Gonsalves
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// Z80 CPU plug into TV80 core
module cpu_z80(
input CLK_4M,
input nRESET,
input [7:0] SDD_IN,
output [7:0] SDD_OUT,
output [15:0] SDA,
output reg nIORQ,
output nMREQ,
output reg nRD, nWR,
input nINT, nNMI, nWAIT
);
wire RFSH_n, MREQ_n;
assign nMREQ = MREQ_n | ~RFSH_n;
T80s cpu(
.RESET_n(nRESET),
.CLK(CLK_4M),
.CEN(1),
.WAIT_n(nWAIT),
.INT_n(nINT),
.NMI_n(nNMI),
.MREQ_n(MREQ_n),
.IORQ_n(nIORQ),
.RD_n(nRD),
.WR_n(nWR),
.RFSH_n(RFSH_n),
.A(SDA),
.DI(SDD_IN),
.DO(SDD_OUT)
);
endmodule

View File

@@ -0,0 +1,4 @@
set_global_assignment -name IP_TOOL_NAME "ALTPLL"
set_global_assignment -name IP_TOOL_VERSION "13.1"
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"]

View File

@@ -0,0 +1,348 @@
// megafunction wizard: %ALTPLL%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: altpll
// ============================================================
// File Name: pll.v
// Megafunction Name(s):
// altpll
//
// Simulation Library Files(s):
// altera_mf
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 13.1.4 Build 182 03/12/2014 SJ Full Version
// ************************************************************
//Copyright (C) 1991-2014 Altera Corporation
//Your use of Altera Corporation's design tools, logic functions
//and other software and tools, and its AMPP partner logic
//functions, and any output files from any of the foregoing
//(including device programming or simulation files), and any
//associated documentation or information are expressly subject
//to the terms and conditions of the Altera Program License
//Subscription Agreement, Altera MegaCore Function License
//Agreement, or other applicable license agreement, including,
//without limitation, that your use is for the sole purpose of
//programming logic devices manufactured by Altera and sold by
//Altera or its authorized distributors. Please refer to the
//applicable agreement for further details.
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module pll (
areset,
inclk0,
c0,
c1,
locked);
input areset;
input inclk0;
output c0;
output c1;
output locked;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
tri0 areset;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif
wire [4:0] sub_wire0;
wire sub_wire2;
wire [0:0] sub_wire6 = 1'h0;
wire [0:0] sub_wire3 = sub_wire0[0:0];
wire [1:1] sub_wire1 = sub_wire0[1:1];
wire c1 = sub_wire1;
wire locked = sub_wire2;
wire c0 = sub_wire3;
wire sub_wire4 = inclk0;
wire [1:0] sub_wire5 = {sub_wire6, sub_wire4};
altpll altpll_component (
.areset (areset),
.inclk (sub_wire5),
.clk (sub_wire0),
.locked (sub_wire2),
.activeclock (),
.clkbad (),
.clkena ({6{1'b1}}),
.clkloss (),
.clkswitch (1'b0),
.configupdate (1'b0),
.enable0 (),
.enable1 (),
.extclk (),
.extclkena ({4{1'b1}}),
.fbin (1'b1),
.fbmimicbidir (),
.fbout (),
.fref (),
.icdrclk (),
.pfdena (1'b1),
.phasecounterselect ({4{1'b1}}),
.phasedone (),
.phasestep (1'b1),
.phaseupdown (1'b1),
.pllena (1'b1),
.scanaclr (1'b0),
.scanclk (1'b0),
.scanclkena (1'b1),
.scandata (1'b0),
.scandataout (),
.scandone (),
.scanread (1'b0),
.scanwrite (1'b0),
.sclkout0 (),
.sclkout1 (),
.vcooverrange (),
.vcounderrange ());
defparam
altpll_component.bandwidth_type = "AUTO",
altpll_component.clk0_divide_by = 22,
altpll_component.clk0_duty_cycle = 50,
altpll_component.clk0_multiply_by = 35,
altpll_component.clk0_phase_shift = "0",
altpll_component.clk1_divide_by = 264,
altpll_component.clk1_duty_cycle = 50,
altpll_component.clk1_multiply_by = 35,
altpll_component.clk1_phase_shift = "0",
altpll_component.compensate_clock = "CLK0",
altpll_component.inclk0_input_frequency = 37037,
altpll_component.intended_device_family = "Cyclone III",
altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll",
altpll_component.lpm_type = "altpll",
altpll_component.operation_mode = "NORMAL",
altpll_component.pll_type = "AUTO",
altpll_component.port_activeclock = "PORT_UNUSED",
altpll_component.port_areset = "PORT_USED",
altpll_component.port_clkbad0 = "PORT_UNUSED",
altpll_component.port_clkbad1 = "PORT_UNUSED",
altpll_component.port_clkloss = "PORT_UNUSED",
altpll_component.port_clkswitch = "PORT_UNUSED",
altpll_component.port_configupdate = "PORT_UNUSED",
altpll_component.port_fbin = "PORT_UNUSED",
altpll_component.port_inclk0 = "PORT_USED",
altpll_component.port_inclk1 = "PORT_UNUSED",
altpll_component.port_locked = "PORT_USED",
altpll_component.port_pfdena = "PORT_UNUSED",
altpll_component.port_phasecounterselect = "PORT_UNUSED",
altpll_component.port_phasedone = "PORT_UNUSED",
altpll_component.port_phasestep = "PORT_UNUSED",
altpll_component.port_phaseupdown = "PORT_UNUSED",
altpll_component.port_pllena = "PORT_UNUSED",
altpll_component.port_scanaclr = "PORT_UNUSED",
altpll_component.port_scanclk = "PORT_UNUSED",
altpll_component.port_scanclkena = "PORT_UNUSED",
altpll_component.port_scandata = "PORT_UNUSED",
altpll_component.port_scandataout = "PORT_UNUSED",
altpll_component.port_scandone = "PORT_UNUSED",
altpll_component.port_scanread = "PORT_UNUSED",
altpll_component.port_scanwrite = "PORT_UNUSED",
altpll_component.port_clk0 = "PORT_USED",
altpll_component.port_clk1 = "PORT_USED",
altpll_component.port_clk2 = "PORT_UNUSED",
altpll_component.port_clk3 = "PORT_UNUSED",
altpll_component.port_clk4 = "PORT_UNUSED",
altpll_component.port_clk5 = "PORT_UNUSED",
altpll_component.port_clkena0 = "PORT_UNUSED",
altpll_component.port_clkena1 = "PORT_UNUSED",
altpll_component.port_clkena2 = "PORT_UNUSED",
altpll_component.port_clkena3 = "PORT_UNUSED",
altpll_component.port_clkena4 = "PORT_UNUSED",
altpll_component.port_clkena5 = "PORT_UNUSED",
altpll_component.port_extclk0 = "PORT_UNUSED",
altpll_component.port_extclk1 = "PORT_UNUSED",
altpll_component.port_extclk2 = "PORT_UNUSED",
altpll_component.port_extclk3 = "PORT_UNUSED",
altpll_component.self_reset_on_loss_lock = "OFF",
altpll_component.width_clock = 5;
endmodule
// ============================================================
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "22"
// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "264"
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "42.954544"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "3.579545"
// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000"
// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps"
// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "35"
// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "35"
// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "42.95454500"
// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "3.57954500"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"
// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1"
// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif"
// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
// Retrieval info: PRIVATE: SPREAD_USE STRING "0"
// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
// Retrieval info: PRIVATE: USE_CLK0 STRING "1"
// Retrieval info: PRIVATE: USE_CLK1 STRING "1"
// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "22"
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "35"
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "264"
// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "35"
// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"
// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF"
// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset"
// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0
// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf
// Retrieval info: CBX_MODULE_PREFIX: ON

View File

@@ -0,0 +1,57 @@
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.altera_mf_components.all;
ENTITY spram IS
GENERIC
(
widthad_a : natural;
width_a : natural := 8;
outdata_reg_a : string := "UNREGISTERED"
);
PORT
(
address : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
clock : IN STD_LOGIC ;
data : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
wren : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0)
);
END spram;
ARCHITECTURE SYN OF spram IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
BEGIN
q <= sub_wire0(width_a-1 DOWNTO 0);
altsyncram_component : altsyncram
GENERIC MAP (
clock_enable_input_a => "BYPASS",
clock_enable_output_a => "BYPASS",
intended_device_family => "Cyclone III",
-- lpm_hint => "ENABLE_RUNTIME_MOD=NO",
lpm_hint=> "ENABLE_RUNTIME_MOD=YES, INSTANCE_NAME=<FLAN>",
lpm_type => "altsyncram",
numwords_a => 2**widthad_a,
operation_mode => "SINGLE_PORT",
outdata_aclr_a => "NONE",
outdata_reg_a => outdata_reg_a,
power_up_uninitialized => "FALSE",
read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ",
widthad_a => widthad_a,
width_a => width_a,
width_byteena_a => 1
)
PORT MAP (
wren_a => wren,
clock0 => clock,
address_a => address,
data_a => data,
q_a => sub_wire0
);
END SYN;

View File

@@ -0,0 +1,46 @@
//-- pattern access
// -- read Pattern Name Table
parameter AC_PNT =0;
// -- read Pattern Generator Table
parameter AC_PGT =1;
//-- read Pattern Color Table
parameter AC_PCT=2;
//-- sprite access
//-- sprite test read (y coordinate)
parameter AC_STST=3;
//-- read Sprite Attribute Table/Y
parameter AC_SATY=4;
//-- read Sprite Attribute Table/X
parameter AC_SATX=5;
//-- read Sprite Attribute Table/N
parameter AC_SATN=6;
//-- read Sprite Attribute Table/C
parameter AC_SATC=7;
//-- read Sprite Pattern Table/high quadrant
parameter AC_SPTH=8;
//-- read Sprite Pattern Table/low quadrant
parameter AC_SPTL=9;
//--
//-- CPU access
parameter AC_CPU=10;
//--
//-- no access at all
parameter AC_NONE=11;
parameter OPMODE_GRAPH1 = 0;
parameter OPMODE_GRAPH2= 1;
parameter OPMODE_MULTIC= 2;
parameter OPMODE_TEXTM= 3;
parameter hv_first_line_ntsc_c = -40;
parameter hv_last_line_ntsc_c = 221;
parameter hv_first_line_pal_c = -65;
parameter hv_last_line_pal_c = 247;
parameter hv_first_pix_text_c = -102;
parameter hv_last_pix_text_c = 239;
parameter hv_first_pix_graph_c = -86;
parameter hv_last_pix_graph_c = 255;
parameter hv_vertical_inc_c = -32;
parameter hv_sprite_start_c = 247;

View File

@@ -0,0 +1,216 @@
//-----------------------------------------------------------------------------
//
// Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
//
// $Id: vdp18_addr_mux.vhd,v 1.10 2006/06/18 10:47:01 arnim Exp $
//
// Address Multiplexer / Generator
//
//-----------------------------------------------------------------------------
//
// Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
//
// All rights reserved
//
// Redistribution and use in source and synthezised forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// Redistributions in synthesized form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Please report bugs to the author, but before you do so, please
// make sure that this is not a derivative work and that
// you have the latest version of this file.
//
// SystemVerilog conversion (c) 2022 Frank Bruno (fbruno@asicsolutions.com)
//
//-----------------------------------------------------------------------------
import vdp18_pkg::*;
module vdp18_addr_mux
(
input access_t access_type_i,
input opmode_t opmode_i,
input signed [0:8] num_line_i,
input [0:3] reg_ntb_i,
input [0:7] reg_ctb_i,
input [0:2] reg_pgb_i,
input [0:6] reg_satb_i,
input [0:2] reg_spgb_i,
input reg_size1_i,
input [0:13] cpu_vram_a_i,
input [0:9] pat_table_i,
input [0:7] pat_name_i,
input [0:4] spr_num_i,
input [0:3] spr_line_i,
input [0:7] spr_name_i,
output logic [0:13] vram_a_o
);
//---------------------------------------------------------------------------
// Process mux
//
// Purpose:
// Generates the VRAM address based on the current access type.
//
always_comb
begin: mux
// default assignment
vram_a_o = '0;
case (access_type_i)
// CPU Access -----------------------------------------------------------
AC_CPU :
vram_a_o = cpu_vram_a_i;
// Pattern Name Table Access --------------------------------------------
AC_PNT :
begin
vram_a_o[0:3] = reg_ntb_i;
vram_a_o[4:13] = pat_table_i;
end
// Pattern Color Table Access -------------------------------------------
AC_PCT :
case (opmode_i)
OPMODE_GRAPH1 :
begin
vram_a_o[0:7] = reg_ctb_i;
vram_a_o[8] = '0;
vram_a_o[9:13] = pat_name_i[0:4];
end
OPMODE_GRAPH2 :
begin
vram_a_o[0] = reg_ctb_i[0];
// remaining bits in CTB mask color
// lookups
vram_a_o[1:2] = num_line_i[1:2] & {reg_ctb_i[1], reg_ctb_i[2]};
// remaining bits in CTB mask color
// lookups
vram_a_o[3:10] = pat_name_i & {reg_ctb_i[3], reg_ctb_i[4], reg_ctb_i[5], reg_ctb_i[6], reg_ctb_i[7], 3'b111};
vram_a_o[11:13] = num_line_i[6:8];
end
default: begin end
endcase
// Pattern Generator Table Access ---------------------------------------
AC_PGT :
case (opmode_i)
OPMODE_TEXTM, OPMODE_GRAPH1 :
begin
vram_a_o[0:2] = reg_pgb_i;
vram_a_o[3:10] = pat_name_i;
vram_a_o[11:13] = num_line_i[6:8];
end
OPMODE_MULTIC :
begin
vram_a_o[0:2] = reg_pgb_i;
vram_a_o[3:10] = pat_name_i;
vram_a_o[11:13] = num_line_i[4:6];
end
OPMODE_GRAPH2 :
begin
vram_a_o[0] = reg_pgb_i[0];
// remaining bits in PGB mask pattern
// lookups
vram_a_o[1:2] = num_line_i[1:2] & {reg_pgb_i[1], reg_pgb_i[2]};
// remaining bits in CTB mask pattern
// lookups
vram_a_o[3:10] = pat_name_i & {reg_ctb_i[3], reg_ctb_i[4], reg_ctb_i[5], reg_ctb_i[6], reg_ctb_i[7], 3'b111};
vram_a_o[11:13] = num_line_i[6:8];
end
endcase
// Sprite Test ----------------------------------------------------------
AC_STST, AC_SATY :
begin
vram_a_o[0:6] = reg_satb_i;
vram_a_o[7:11] = spr_num_i;
vram_a_o[12:13] = 2'b00;
end
// Sprite Attribute Table: X --------------------------------------------
AC_SATX :
begin
vram_a_o[0:6] = reg_satb_i;
vram_a_o[7:11] = spr_num_i;
vram_a_o[12:13] = 2'b01;
end
// Sprite Attribute Table: Name -----------------------------------------
AC_SATN :
begin
vram_a_o[0:6] = reg_satb_i;
vram_a_o[7:11] = spr_num_i;
vram_a_o[12:13] = 2'b10;
end
// Sprite Attribute Table: Color ----------------------------------------
AC_SATC :
begin
vram_a_o[0:6] = reg_satb_i;
vram_a_o[7:11] = spr_num_i;
vram_a_o[12:13] = 2'b11;
end
// Sprite Pattern, Upper Part -------------------------------------------
AC_SPTH :
begin
vram_a_o[0:2] = reg_spgb_i;
if (~reg_size1_i)
begin
// 8x8 sprite
vram_a_o[3:10] = spr_name_i;
vram_a_o[11:13] = spr_line_i[1:3];
end
else
begin
// 16x16 sprite
vram_a_o[3:8] = spr_name_i[0:5];
vram_a_o[9] = 1'b0;
vram_a_o[10:13] = spr_line_i;
end
end
// Sprite Pattern, Lower Part -------------------------------------------
AC_SPTL :
begin
vram_a_o[0:2] = reg_spgb_i;
vram_a_o[3:8] = spr_name_i[0:5];
vram_a_o[9] = 1'b1;
vram_a_o[10:13] = spr_line_i;
end
default: vram_a_o = '0;
endcase
end
endmodule
//
//---------------------------------------------------------------------------

View File

@@ -0,0 +1,134 @@
//-----------------------------------------------------------------------------
//
// Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
//
// $Id: vdp18_clk_gen.vhd,v 1.8 2006/06/18 10:47:01 arnim Exp $
//
// Clock Generator
//
//-----------------------------------------------------------------------------
//
// Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
//
// All rights reserved
//
// Redistribution and use in source and synthezised forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// Redistributions in synthesized form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Please report bugs to the author, but before you do so, please
// make sure that this is not a derivative work and that
// you have the latest version of this file.
//
// SystemVerilog conversion (c) 2022 Frank Bruno (fbruno@asicsolutions.com)
//
//-----------------------------------------------------------------------------
module vdp18_clk_gen
(
input clk_i,
input clk_en_10m7_i,
input reset_i,
output logic clk_en_5m37_o,
output logic clk_en_3m58_o,
output logic clk_en_2m68_o
);
logic [3:0] cnt_q;
//---------------------------------------------------------------------------
// Process seq
//
// Purpose:
// Implements the sequential elements.
// * clock counter
//
always @(posedge clk_i, posedge reset_i )
begin: seq
if (reset_i) cnt_q <= '0;
else
begin
if (clk_en_10m7_i)
begin
if (cnt_q == 11)
// wrap after counting 12 clocks
cnt_q <= '0;
else
cnt_q <= cnt_q + 1'b1;
end
end
end
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Process clk_en
//
// Purpose:
// Generates the derived clock enable signals.
//
always_comb
begin: clk_en
// 5.37 MHz clock enable --------------------------------------------------
if (clk_en_10m7_i)
case (cnt_q)
1, 3, 5, 7, 9, 11 :
clk_en_5m37_o = '1;
default :
clk_en_5m37_o = '0;
endcase
else
clk_en_5m37_o = '0;
// 3.58 MHz clock enable --------------------------------------------------
if (clk_en_10m7_i)
case (cnt_q)
2, 5, 8, 11 :
clk_en_3m58_o = '1;
default :
clk_en_3m58_o = '0;
endcase
else
clk_en_3m58_o = 1'b0;
// 2.68 MHz clock enable --------------------------------------------------
if (clk_en_10m7_i)
case (cnt_q)
3, 7, 11 :
clk_en_2m68_o = '1;
default :
clk_en_2m68_o = '0;
endcase
else
clk_en_2m68_o = '0;
end
endmodule
//
//---------------------------------------------------------------------------

View File

@@ -0,0 +1,210 @@
//-----------------------------------------------------------------------------
//
// Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
//
// $Id: vdp18_col_mux.vhd,v 1.10 2006/06/18 10:47:01 arnim Exp $
//
// Color Information Multiplexer
//
//-----------------------------------------------------------------------------
//
// Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
//
// All rights reserved
//
// Redistribution and use in source and synthezised forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// Redistributions in synthesized form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Please report bugs to the author, but before you do so, please
// make sure that this is not a derivative work and that
// you have the latest version of this file.
//
// SystemVerilog conversion (c) 2022 Frank Bruno (fbruno@asicsolutions.com)
//
//-----------------------------------------------------------------------------
module vdp18_col_mux
#
(
parameter compat_rgb_g = 0
)
(
input clk_i,
input clk_en_5m37_i,
input reset_i,
input vert_active_i,
input hor_active_i,
input border_i,
input blank_i,
input hblank_i,
input vblank_i,
output logic blank_n_o,
output logic hblank_n_o,
output logic vblank_n_o,
input [0:3] reg_col0_i,
input [0:3] pat_col_i,
input [0:3] spr0_col_i,
input [0:3] spr1_col_i,
input [0:3] spr2_col_i,
input [0:3] spr3_col_i,
output logic [0:3] col_o,
output logic [0:7] rgb_r_o,
output logic [0:7] rgb_g_o,
output logic [0:7] rgb_b_o
);
//---------------------------------------------------------------------------
// Process col_mux
//
// Purpose:
// Multiplexes the color information from different sources.
//
always_comb
begin: col_mux
if (~blank_i)
begin
if (hor_active_i & vert_active_i)
begin
// priority decoder
if (spr0_col_i != 4'b0000)
col_o = spr0_col_i;
else if (spr1_col_i != 4'b0000)
col_o = spr1_col_i;
else if (spr2_col_i != 4'b0000)
col_o = spr2_col_i;
else if (spr3_col_i != 4'b0000)
col_o = spr3_col_i;
else if (pat_col_i != 4'b0000)
col_o = pat_col_i;
else
col_o = reg_col0_i;
end
else
// display border
col_o = reg_col0_i;
end
else
// blank color channels during horizontal and vertical
// trace back
// required to initialize colors for each new scan line
col_o = '0;
end
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Process rgb_reg
//
// Purpose:
// Converts the color information to simple RGB and saves these in
// output registers.
//
const logic [7:0] compat_rgb_table_c[16][3] =
'{'{ 0, 0, 0}, // Transparent
'{ 0, 0, 0}, // Black
'{ 32, 192, 32}, // Medium Green
'{ 96, 224, 96}, // Light Green
'{ 32, 32, 224}, // Dark Blue
'{ 64, 96, 224}, // Light Blue
'{160, 32, 32}, // Dark Red
'{ 64, 192, 224}, // Cyan
'{224, 32, 32}, // Medium Red
'{224, 96, 96}, // Light Red
'{192, 192, 32}, // Dark Yellow
'{192, 192, 128}, // Light Yellow
'{ 32, 128, 32}, // Dark Green
'{192, 64, 160}, // Magenta
'{160, 160, 160}, // Gray
'{224, 224, 224}}; // White
//---------------------------------------------------------------------------
// Full RGB Value Array
//
// Refer to tms9928a.c of the MAME source distribution.
//
const logic [7:0] full_rgb_table_c[16][3] =
'{'{ 0, 0, 0}, // Transparent
'{ 0, 0, 0}, // Black
'{ 33, 200, 66}, // Medium Green
'{ 94, 220, 120}, // Light Green
'{ 84, 85, 237}, // Dark Blue
'{125, 118, 252}, // Light Blue
'{212, 82, 77}, // Dark Red
'{ 66, 235, 245}, // Cyan
'{252, 85, 84}, // Medium Red
'{255, 121, 120}, // Light Red
'{212, 193, 84}, // Dark Yellow
'{230, 206, 128}, // Light Yellow
'{ 33, 176, 59}, // Dark Green
'{201, 91, 186}, // Magenta
'{204, 204, 204}, // Gray
'{255, 255, 255}}; // White
always @(posedge clk_i, posedge reset_i )
begin: rgb_reg
if (reset_i)
begin
rgb_r_o <= '0;
rgb_g_o <= '0;
rgb_b_o <= '0;
end
else
begin
if (clk_en_5m37_i)
begin
// select requested RGB table
if (compat_rgb_g)
begin
rgb_r_o <= compat_rgb_table_c[col_o][0];
rgb_g_o <= compat_rgb_table_c[col_o][1];
rgb_b_o <= compat_rgb_table_c[col_o][2];
end
else
begin
rgb_r_o <= full_rgb_table_c[col_o][0];
rgb_g_o <= full_rgb_table_c[col_o][1];
rgb_b_o <= full_rgb_table_c[col_o][2];
end
blank_n_o <= ~blank_i;
if (~border_i)
begin
hblank_n_o <= hor_active_i;
vblank_n_o <= vert_active_i;
end
else
begin
hblank_n_o <= ~hblank_i;
vblank_n_o <= ~vblank_i;
end
end
end
end
endmodule

View File

@@ -0,0 +1,405 @@
//-----------------------------------------------------------------------------
//
// Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
//
// $Id: vdp18_core.vhd,v 1.28 2006/06/18 10:47:01 arnim Exp $
//
// Core Toplevel
//
// Notes:
// This core implements a simple VRAM interface which is suitable for a
// synchronous SRAM component. There is currently no support of the
// original DRAM interface.
//
// Please be aware that the colors might me slightly different from the
// original TMS9918. It is assumed that the simplified conversion to RGB
// encoding is equivalent to the compatability mode of the V9938.
// Implementing a 100% correct color encoding for RGB would require
// significantly more logic and 8-bit wide RGB DACs.
//
// References:
//
// * TI Data book TMS9918.pdf
// http://www.bitsavers.org/pdf/ti/_dataBooks/TMS9918.pdf
//
// * Sean Young's tech article:
// http://bifi.msxnet.org/msxnet/tech/tms9918a.txt
//
// * Paul Urbanus' discussion of the timing details
// http://bifi.msxnet.org/msxnet/tech/tmsposting.txt
//
// * Richard F. Drushel's article series
// "This Week With My Coleco ADAM"
// http://junior.apk.net/~drushel/pub/coleco/twwmca/index.html
//
//-----------------------------------------------------------------------------
//
// Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
//
// All rights reserved
//
// Redistribution and use in source and synthezised forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// Redistributions in synthesized form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Please report bugs to the author, but before you do so, please
// make sure that this is not a derivative work and that
// you have the latest version of this file.
//
// SystemVerilog conversion (c) 2022 Frank Bruno (fbruno@asicsolutions.com)
//
//-----------------------------------------------------------------------------
import vdp18_pkg::*;
module vdp18_core
#
(
parameter is_pal_g = 0,
parameter compat_rgb_g = 0
)
(
// Global Interface -------------------------------------------------------
input clk_i,
input clk_en_10m7_i,
input reset_n_i,
// CPU Interface ----------------------------------------------------------
input csr_n_i,
input csw_n_i,
input mode_i,
output int_n_o,
input [0:7] cd_i,
output [0:7] cd_o,
// VRAM Interface ---------------------------------------------------------
output vram_we_o,
output [0:13] vram_a_o,
output [0:7] vram_d_o,
input [0:7] vram_d_i,
// Video Interface --------------------------------------------------------
input border_i,
output [0:3] col_o,
output [0:7] rgb_r_o,
output [0:7] rgb_g_o,
output [0:7] rgb_b_o,
output hsync_n_o,
output vsync_n_o,
output blank_n_o,
output hblank_o,
output vblank_o,
output comp_sync_n_o,
output logic signed [0:8] num_pix_o,
output logic signed [0:8] num_line_o
);
logic reset_s;
logic clk_en_10m7_s;
logic clk_en_5m37_s;
logic clk_en_acc_s;
opmode_t opmode_s;
access_t access_type_s;
logic signed [0:8] num_pix_s;
logic signed [0:8] num_line_s;
logic hsync_n_s;
logic vsync_n_s;
logic blank_s;
logic hblank_s;
logic vblank_s;
logic vert_inc_s;
logic reg_blank_s;
logic reg_size1_s;
logic reg_mag1_s;
logic spr_5th_s;
logic [0:4] spr_5th_num_s;
logic stop_sprite_s;
logic vert_active_s;
logic hor_active_s;
logic rd_s;
logic wr_s;
logic [0:3] reg_ntb_s;
logic [0:7] reg_ctb_s;
logic [0:2] reg_pgb_s;
logic [0:6] reg_satb_s;
logic [0:2] reg_spgb_s;
logic [0:3] reg_col1_s;
logic [0:3] reg_col0_s;
logic [0:13] cpu_vram_a_s;
logic [0:9] pat_table_s;
logic [0:7] pat_name_s;
logic [0:3] pat_col_s;
logic [0:4] spr_num_s;
logic [0:3] spr_line_s;
logic [0:7] spr_name_s;
logic [0:3] spr0_col_s;
logic [0:3] spr1_col_s;
logic [0:3] spr2_col_s;
logic [0:3] spr3_col_s;
logic spr_coll_s;
logic irq_s;
logic blank_n;
logic hblank_n;
logic vblank_n;
assign clk_en_10m7_s = clk_en_10m7_i;
assign rd_s = ~csr_n_i;
assign wr_s = ~csw_n_i;
assign reset_s = reset_n_i == 1'b0;
assign num_pix_o = num_pix_s;
assign num_line_o = num_line_s;
//---------------------------------------------------------------------------
// Clock Generator
//---------------------------------------------------------------------------
vdp18_clk_gen clk_gen_b
(
.clk_i(clk_i),
.clk_en_10m7_i(clk_en_10m7_i),
.reset_i(reset_s),
.clk_en_5m37_o(clk_en_5m37_s),
.clk_en_2m68_o()
);
//---------------------------------------------------------------------------
// Horizontal and Vertical Timing Generator
//---------------------------------------------------------------------------
vdp18_hor_vert
#
(
.is_pal_g(is_pal_g)
)
hor_vert_b
(
.clk_i(clk_i),
.clk_en_5m37_i(clk_en_5m37_s),
.reset_i(reset_s),
.opmode_i(opmode_s),
.num_pix_o(num_pix_s),
.num_line_o(num_line_s),
.vert_inc_o(vert_inc_s),
.hsync_n_o(hsync_n_s),
.vsync_n_o(vsync_n_s),
.blank_o(blank_s),
.hblank_o(hblank_s),
.vblank_o(vblank_s)
);
assign hsync_n_o = hsync_n_s;
assign vsync_n_o = vsync_n_s;
assign comp_sync_n_o = (~(hsync_n_s ^ vsync_n_s));
//---------------------------------------------------------------------------
// Control Module
//---------------------------------------------------------------------------
vdp18_ctrl ctrl_b
(
.clk_i(clk_i),
.clk_en_5m37_i(clk_en_5m37_s),
.reset_i(reset_s),
.opmode_i(opmode_s),
.num_pix_i(num_pix_s),
.num_line_i(num_line_s),
.vert_inc_i(vert_inc_s),
.reg_blank_i(reg_blank_s),
.reg_size1_i(reg_size1_s),
.stop_sprite_i(stop_sprite_s),
.clk_en_acc_o(clk_en_acc_s),
.access_type_o(access_type_s),
.vert_active_o(vert_active_s),
.hor_active_o(hor_active_s),
.irq_o(irq_s)
);
//---------------------------------------------------------------------------
// CPU I/O Module
//---------------------------------------------------------------------------
vdp18_cpuio cpu_io_b
(
.clk_i(clk_i),
.clk_en_10m7_i(clk_en_10m7_s),
.clk_en_acc_i(clk_en_acc_s),
.reset_i(reset_s),
.rd_i(rd_s),
.wr_i(wr_s),
.mode_i(mode_i),
.cd_i(cd_i),
.cd_o(cd_o),
.cd_oe_o(),
.access_type_i(access_type_s),
.opmode_o(opmode_s),
.vram_we_o(vram_we_o),
.vram_a_o(cpu_vram_a_s),
.vram_d_o(vram_d_o),
.vram_d_i(vram_d_i),
.spr_coll_i(spr_coll_s),
.spr_5th_i(spr_5th_s),
.spr_5th_num_i(spr_5th_num_s),
.reg_ev_o(),
.reg_16k_o(),
.reg_blank_o(reg_blank_s),
.reg_size1_o(reg_size1_s),
.reg_mag1_o(reg_mag1_s),
.reg_ntb_o(reg_ntb_s),
.reg_ctb_o(reg_ctb_s),
.reg_pgb_o(reg_pgb_s),
.reg_satb_o(reg_satb_s),
.reg_spgb_o(reg_spgb_s),
.reg_col1_o(reg_col1_s),
.reg_col0_o(reg_col0_s),
.irq_i(irq_s),
.int_n_o(int_n_o)
);
//---------------------------------------------------------------------------
// VRAM Address Multiplexer
//---------------------------------------------------------------------------
vdp18_addr_mux addr_mux_b
(
.access_type_i(access_type_s),
.opmode_i(opmode_s),
.num_line_i(num_line_s),
.reg_ntb_i(reg_ntb_s),
.reg_ctb_i(reg_ctb_s),
.reg_pgb_i(reg_pgb_s),
.reg_satb_i(reg_satb_s),
.reg_spgb_i(reg_spgb_s),
.reg_size1_i(reg_size1_s),
.cpu_vram_a_i(cpu_vram_a_s),
.pat_table_i(pat_table_s),
.pat_name_i(pat_name_s),
.spr_num_i(spr_num_s),
.spr_line_i(spr_line_s),
.spr_name_i(spr_name_s),
.vram_a_o(vram_a_o)
);
//---------------------------------------------------------------------------
// Pattern Generator
//---------------------------------------------------------------------------
vdp18_pattern pattern_b
(
.clk_i(clk_i),
.clk_en_5m37_i(clk_en_5m37_s),
.clk_en_acc_i(clk_en_acc_s),
.reset_i(reset_s),
.opmode_i(opmode_s),
.access_type_i(access_type_s),
.num_line_i(num_line_s),
.vram_d_i(vram_d_i),
.vert_inc_i(vert_inc_s),
.vsync_n_i(vsync_n_s),
.reg_col1_i(reg_col1_s),
.reg_col0_i(reg_col0_s),
.pat_table_o(pat_table_s),
.pat_name_o(pat_name_s),
.pat_col_o(pat_col_s)
);
//---------------------------------------------------------------------------
// Sprite Generator
//---------------------------------------------------------------------------
vdp18_sprite sprite_b
(
.clk_i(clk_i),
.clk_en_5m37_i(clk_en_5m37_s),
.clk_en_acc_i(clk_en_acc_s),
.reset_i(reset_s),
.access_type_i(access_type_s),
.num_pix_i(num_pix_s),
.num_line_i(num_line_s),
.vram_d_i(vram_d_i),
.vert_inc_i(vert_inc_s),
.reg_size1_i(reg_size1_s),
.reg_mag1_i(reg_mag1_s),
.spr_5th_o(spr_5th_s),
.spr_5th_num_o(spr_5th_num_s),
.stop_sprite_o(stop_sprite_s),
.spr_coll_o(spr_coll_s),
.spr_num_o(spr_num_s),
.spr_line_o(spr_line_s),
.spr_name_o(spr_name_s),
.spr0_col_o(spr0_col_s),
.spr1_col_o(spr1_col_s),
.spr2_col_o(spr2_col_s),
.spr3_col_o(spr3_col_s)
);
//---------------------------------------------------------------------------
// Color Multiplexer
//---------------------------------------------------------------------------
vdp18_col_mux
#
(
.compat_rgb_g(compat_rgb_g)
)
col_mux_b
(
.clk_i(clk_i),
.clk_en_5m37_i(clk_en_5m37_s),
.reset_i(reset_s),
.vert_active_i(vert_active_s),
.hor_active_i(hor_active_s),
.border_i(border_i),
.blank_i(blank_s),
.hblank_i(hblank_s),
.vblank_i(vblank_s),
.reg_col0_i(reg_col0_s),
.pat_col_i(pat_col_s),
.spr0_col_i(spr0_col_s),
.spr1_col_i(spr1_col_s),
.spr2_col_i(spr2_col_s),
.spr3_col_i(spr3_col_s),
.col_o(col_o),
.blank_n_o(blank_n),
.hblank_n_o(hblank_n),
.vblank_n_o(vblank_n),
.rgb_r_o(rgb_r_o),
.rgb_g_o(rgb_g_o),
.rgb_b_o(rgb_b_o)
);
assign blank_n_o = (blank_n) ? 1'b1 : 1'b0;
assign hblank_o = (hblank_n) ? 1'b0 : 1'b1;
assign vblank_o = (vblank_n) ? 1'b0 : 1'b1;
endmodule

View File

@@ -0,0 +1,569 @@
//-----------------------------------------------------------------------------
//
// Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
//
// $Id: vdp18_cpuio.vhd,v 1.17 2006/06/18 10:47:01 arnim Exp $
//
// CPU I/O Interface Module
//
//-----------------------------------------------------------------------------
//
// Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
//
// All rights reserved
//
// Redistribution and use in source and synthezised forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// Redistributions in synthesized form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Please report bugs to the author, but before you do so, please
// make sure that this is not a derivative work and that
// you have the latest version of this file.
//
// SystemVerilog conversion (c) 2022 Frank Bruno (fbruno@asicsolutions.com)
//
//-----------------------------------------------------------------------------
import vdp18_pkg::*;
module vdp18_cpuio
(
input clk_i,
input clk_en_10m7_i,
input clk_en_acc_i,
input reset_i,
input rd_i,
input wr_i,
input mode_i,
input [0:7] cd_i,
output [0:7] cd_o,
output cd_oe_o,
input access_t access_type_i,
output opmode_t opmode_o,
output reg vram_we_o,
output [0:13] vram_a_o,
output [0:7] vram_d_o,
input [0:7] vram_d_i,
input spr_coll_i,
input spr_5th_i,
input [0:4] spr_5th_num_i,
output reg_ev_o,
output reg_16k_o,
output reg_blank_o,
output reg_size1_o,
output reg_mag1_o,
output [0:3] reg_ntb_o,
output [0:7] reg_ctb_o,
output [0:2] reg_pgb_o,
output [0:6] reg_satb_o,
output [0:2] reg_spgb_o,
output [0:3] reg_col1_o,
output [0:3] reg_col0_o,
input irq_i,
output int_n_o
);
typedef enum bit [3:0]
{
state_t_ST_IDLE = 4'd0,
state_t_ST_RD_MODE0 = 4'd1,
state_t_ST_WR_MODE0 = 4'd2,
state_t_ST_RD_MODE1 = 4'd3,
state_t_ST_WR_MODE1_1ST = 4'd4,
state_t_ST_WR_MODE1_1ST_IDLE = 4'd5,
state_t_ST_WR_MODE1_2ND_VREAD = 4'd6,
state_t_ST_WR_MODE1_2ND_VWRITE = 4'd7,
state_t_ST_WR_MODE1_2ND_RWRITE = 4'd8
} state_t;
state_t state_s;
state_t state_q;
logic [0:7] buffer_q;
logic [0:13] addr_q;
logic incr_addr_s;
logic load_addr_s;
logic wrbuf_cpu_s;
logic sched_rdvram_s;
logic rdvram_sched_q;
logic rdvram_q;
logic abort_wrvram_s;
logic sched_wrvram_s;
logic wrvram_sched_q;
logic wrvram_q;
logic write_tmp_s;
logic [0:7] tmp_q;
logic write_reg_s;
// control register bits ----------------------------------------------------
logic [0:7] ctrl_reg_q[7:0];
// status register ----------------------------------------------------------
logic [0:7] status_reg_s;
logic destr_rd_status_s;
logic sprite_5th_q;
logic [0:4] sprite_5th_num_q;
logic sprite_coll_q;
logic int_n_q;
typedef enum bit
{
read_mux_t_RDMUX_STATUS = 1'b0,
read_mux_t_RDMUX_READAHEAD = 1'b1
} read_mux_t;
read_mux_t read_mux_s;
//---------------------------------------------------------------------------
// Process seq
//
// Purpose:
// Implements the sequential elements.
//
always @(posedge clk_i, posedge reset_i )
begin: seq
logic incr_addr_v;
if (reset_i)
begin
state_q <= state_t_ST_IDLE;
buffer_q <= '0;
addr_q <= '0;
rdvram_sched_q <= '0;
rdvram_q <= '0;
wrvram_sched_q <= '0;
wrvram_q <= '0;
end
else
begin
// default assignments
incr_addr_v = incr_addr_s;
if (clk_en_10m7_i)
begin
// update state vector ------------------------------------------------
state_q <= state_s;
// buffer and flag control --------------------------------------------
if (wrbuf_cpu_s)
begin
// write read-ahead buffer from CPU bus
buffer_q <= cd_i;
// immediately stop read-ahead
rdvram_sched_q <= '0;
rdvram_q <= '0;
end
else if (clk_en_acc_i && rdvram_q && (access_type_i == AC_CPU))
begin
// write read-ahead buffer from VRAM during CPU access slot
buffer_q <= vram_d_i;
// stop scanning for CPU data
rdvram_q <= '0;
// increment read-ahead address
incr_addr_v = '1;
end
if (sched_rdvram_s)
begin
// immediately stop write-back
wrvram_sched_q <= '0;
wrvram_q <= '0;
// schedule read-ahead
rdvram_sched_q <= '1;
end
if (sched_wrvram_s)
// schedule write-back
wrvram_sched_q <= '1;
if (abort_wrvram_s)
// stop scanning for write-back
wrvram_q <= '0;
if (rdvram_sched_q && clk_en_acc_i)
begin
// align scheduled read-ahead with access slot phase
rdvram_sched_q <= '0;
rdvram_q <= '1;
end
if (wrvram_sched_q && clk_en_acc_i)
begin
// align scheduled write-back with access slot phase
wrvram_sched_q <= '0;
wrvram_q <= '1;
end
// manage address -----------------------------------------------------
if (load_addr_s)
begin
addr_q[6:13] <= tmp_q;
addr_q[0:5] <= cd_i[2:7];
end
else if (incr_addr_v)
addr_q <= addr_q + 1'b1;
end
end
end
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Process wback_ctrl
//
// Purpose:
// Write-back control.
//
always_comb
begin: wback_ctrl
// default assignments
abort_wrvram_s = '0;
incr_addr_s = '0;
vram_we_o = '0;
if (wrvram_q)
begin
if (access_type_i == AC_CPU)
begin
// signal write access to VRAM
vram_we_o = '1;
if (clk_en_acc_i)
begin
// clear write-back flag and increment address
abort_wrvram_s = '1;
incr_addr_s = '1;
end
end
end
end
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Process reg_if
//
// Purpose:
// Implements the register interface.
//
always @(posedge clk_i, posedge reset_i )
begin: reg_if
if (reset_i)
begin
tmp_q <= '0;
ctrl_reg_q <= '{default: '0};
sprite_coll_q <= '0;
sprite_5th_q <= '0;
sprite_5th_num_q <= '0;
int_n_q <= '1;
end
else
begin
if (clk_en_10m7_i)
begin
// Temporary register -------------------------------------------------
if (write_tmp_s)
tmp_q <= cd_i;
// Registers 0 to 7 ---------------------------------------------------
if (write_reg_s)
begin
ctrl_reg_q[cd_i[5:7]] <= tmp_q;
end
end
// Fifth sprite handling ------------------------------------------------
if (spr_5th_i && (~sprite_5th_q))
begin
sprite_5th_q <= '1;
sprite_5th_num_q <= spr_5th_num_i;
end
else if (destr_rd_status_s)
sprite_5th_q <= '0;
// Sprite collision flag ------------------------------------------------
if (spr_coll_i)
sprite_coll_q <= '1;
else if (destr_rd_status_s)
sprite_coll_q <= '0;
// Interrupt ------------------------------------------------------------
if (irq_i)
int_n_q <= '0;
else if (destr_rd_status_s)
int_n_q <= '1;
end
end
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Process access_ctrl
//
// Purpose:
// Implements the combinational logic for the CPU I/F FSM.
// Decodes the CPU I/F FSM state and generates the control signals for the
// register and VRAM logic.
//
typedef enum bit [2:0]
{
transfer_mode_t_TM_NONE = 3'd0,
transfer_mode_t_TM_RD_MODE0 = 3'd1,
transfer_mode_t_TM_WR_MODE0 = 3'd2,
transfer_mode_t_TM_RD_MODE1 = 3'd3,
transfer_mode_t_TM_WR_MODE1 = 3'd4
} transfer_mode_t;
transfer_mode_t transfer_mode_v;
always_comb
begin: access_ctrl
// default assignments
state_s = state_q;
sched_rdvram_s = '0;
sched_wrvram_s = '0;
wrbuf_cpu_s = '0;
write_tmp_s = '0;
write_reg_s = '0;
load_addr_s = '0;
read_mux_s = read_mux_t_RDMUX_STATUS;
destr_rd_status_s = '0;
// determine transfer mode
transfer_mode_v = transfer_mode_t_TM_NONE;
if (~mode_i)
begin
if (rd_i)
transfer_mode_v = transfer_mode_t_TM_RD_MODE0;
if (wr_i)
transfer_mode_v = transfer_mode_t_TM_WR_MODE0;
end
else
begin
if (rd_i)
transfer_mode_v = transfer_mode_t_TM_RD_MODE1;
if (wr_i)
transfer_mode_v = transfer_mode_t_TM_WR_MODE1;
end
// FSM state transitions
case (state_q)
// ST_IDLE: waiting for CPU access --------------------------------------
state_t_ST_IDLE :
case (transfer_mode_v)
transfer_mode_t_TM_RD_MODE0 :
state_s = state_t_ST_RD_MODE0;
transfer_mode_t_TM_WR_MODE0 :
state_s = state_t_ST_WR_MODE0;
transfer_mode_t_TM_RD_MODE1 :
state_s = state_t_ST_RD_MODE1;
transfer_mode_t_TM_WR_MODE1 :
state_s = state_t_ST_WR_MODE1_1ST;
default: begin end
endcase
// ST_RD_MODE0: read from VRAM ------------------------------------------
state_t_ST_RD_MODE0 :
begin
// set read mux
read_mux_s = read_mux_t_RDMUX_READAHEAD;
if (transfer_mode_v == transfer_mode_t_TM_NONE)
begin
// CPU finished read access:
// schedule new read-ahead and return to idle
state_s = state_t_ST_IDLE;
sched_rdvram_s = '1;
end
end
// ST_WR_MODE0: write to VRAM -------------------------------------------
state_t_ST_WR_MODE0 :
begin
// write data from CPU to write-back/read-ahead buffer
wrbuf_cpu_s = '1;
if (transfer_mode_v == transfer_mode_t_TM_NONE)
begin
// CPU finished write access:
// schedule new write-back and return to idle
state_s = state_t_ST_IDLE;
sched_wrvram_s = '1;
end
end
// ST_RD_MODE1: read from status register -------------------------------
state_t_ST_RD_MODE1 :
begin
// set read mux
read_mux_s = read_mux_t_RDMUX_STATUS;
if (transfer_mode_v == transfer_mode_t_TM_NONE)
begin
// CPU finished read access:
// destructive read of status register and return to IDLE
destr_rd_status_s = '1;
state_s = state_t_ST_IDLE;
end
end
// ST_WR_MODE1_1ST: save first byte -------------------------------------
state_t_ST_WR_MODE1_1ST :
begin
// update temp register
write_tmp_s = '1;
if (transfer_mode_v == transfer_mode_t_TM_NONE)
// CPU finished write access:
// become idle but remember that the first byte of a paired write
// has been written
state_s = state_t_ST_WR_MODE1_1ST_IDLE;
end
// ST_WR_MODE1_1ST_IDLE: wait for next access ---------------------------
state_t_ST_WR_MODE1_1ST_IDLE :
// determine type of next access
case (transfer_mode_v)
transfer_mode_t_TM_RD_MODE0 :
state_s = state_t_ST_RD_MODE0;
transfer_mode_t_TM_WR_MODE0 :
state_s = state_t_ST_WR_MODE0;
transfer_mode_t_TM_RD_MODE1 :
state_s = state_t_ST_RD_MODE1;
transfer_mode_t_TM_WR_MODE1 :
case (cd_i[0:1])
2'b00 :
state_s = state_t_ST_WR_MODE1_2ND_VREAD;
2'b01 :
state_s = state_t_ST_WR_MODE1_2ND_VWRITE;
2'b10, 2'b11 :
state_s = state_t_ST_WR_MODE1_2ND_RWRITE;
default: begin end
endcase
default: begin end
endcase
// ST_WR_MODE1_2ND_VREAD: write second byte of address, then read ahead -
state_t_ST_WR_MODE1_2ND_VREAD :
begin
load_addr_s = '1;
if (transfer_mode_v == transfer_mode_t_TM_NONE)
begin
// CPU finished write access:
// schedule new read-ahead and return to idle
sched_rdvram_s = '1;
state_s = state_t_ST_IDLE;
end
end
// ST_WR_MODE1_2ND_VWRITE: write second byte of address
state_t_ST_WR_MODE1_2ND_VWRITE :
begin
load_addr_s = '1;
if (transfer_mode_v == transfer_mode_t_TM_NONE)
// CPU finished write access:
// return to idle
state_s = state_t_ST_IDLE;
end
// ST_WR_MODE1_2ND_RWRITE: write to register ----------------------------
state_t_ST_WR_MODE1_2ND_RWRITE :
begin
write_reg_s = '1;
if (transfer_mode_v == transfer_mode_t_TM_NONE)
// CPU finished write access:
// return to idle
state_s = state_t_ST_IDLE;
end
default: begin end
endcase
end
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Process mode_decode
//
// Purpose:
// Decodes the display mode from the M1, M2, M3 bits.
//
always_comb
begin: mode_decode
case ({ctrl_reg_q[1][3], ctrl_reg_q[1][4], ctrl_reg_q[0][6]})
3'b000 :
opmode_o = OPMODE_GRAPH1;
3'b001 :
opmode_o = OPMODE_GRAPH2;
3'b010 :
opmode_o = OPMODE_MULTIC;
3'b100 :
opmode_o = OPMODE_TEXTM;
default :
opmode_o = OPMODE_TEXTM;
endcase
end
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Build status register
//---------------------------------------------------------------------------
assign status_reg_s = {(~int_n_q), sprite_5th_q, sprite_coll_q, sprite_5th_num_q};
//---------------------------------------------------------------------------
// Output mapping
//---------------------------------------------------------------------------
assign vram_a_o = addr_q;
assign vram_d_o = buffer_q;
assign cd_o = (read_mux_s == read_mux_t_RDMUX_READAHEAD) ? buffer_q : status_reg_s;
assign cd_oe_o = (rd_i) ? 1'b1 : 1'b0;
assign reg_ev_o = ctrl_reg_q[0][7];
assign reg_16k_o = ctrl_reg_q[1][0];
assign reg_blank_o = ~(ctrl_reg_q[1][1]);
assign reg_size1_o = ctrl_reg_q[1][6];
assign reg_mag1_o = ctrl_reg_q[1][7];
assign reg_ntb_o = ctrl_reg_q[2][4:7];
assign reg_ctb_o = ctrl_reg_q[3];
assign reg_pgb_o = ctrl_reg_q[4][5:7];
assign reg_satb_o = ctrl_reg_q[5][1:7];
assign reg_spgb_o = ctrl_reg_q[6][5:7];
assign reg_col1_o = ctrl_reg_q[7][0:3];
assign reg_col0_o = ctrl_reg_q[7][4:7];
assign int_n_o = int_n_q | (~ctrl_reg_q[1][2]);
endmodule

View File

@@ -0,0 +1,367 @@
//-----------------------------------------------------------------------------
//
// Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
//
// $Id: vdp18_ctrl.vhd,v 1.26 2006/06/18 10:47:01 arnim Exp $
//
// Timing Controller
//
//-----------------------------------------------------------------------------
//
// Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
//
// All rights reserved
//
// Redistribution and use in source and synthezised forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// Redistributions in synthesized form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Please report bugs to the author, but before you do so, please
// make sure that this is not a derivative work and that
// you have the latest version of this file.
//
// SystemVerilog conversion (c) 2022 Frank Bruno (fbruno@asicsolutions.com)
//
//-----------------------------------------------------------------------------
import vdp18_pkg::*;
module vdp18_ctrl
(
input clk_i,
input clk_en_5m37_i,
input reset_i,
input opmode_t opmode_i,
input signed [0:8] num_pix_i,
input signed [0:8] num_line_i,
input vert_inc_i,
input reg_blank_i,
input reg_size1_i,
input stop_sprite_i,
output logic clk_en_acc_o,
output access_t access_type_o,
output logic vert_active_o,
output logic hor_active_o,
output logic irq_o
);
//---------------------------------------------------------------------------
// This enables a workaround for a bug in XST.
// ISE 8.1.02i implements wrong functionality otherwise :-(
//
parameter xst_bug_wa_c = 1'b1;
//
//---------------------------------------------------------------------------
// pragma translate_off
// Testbench signals --------------------------------------------------------
//
logic [3:0] ac_s;
//
//---------------------------------------------------------------------------
// pragma translate_on
logic vert_active_q;
logic hor_active_q;
logic sprite_active_q;
logic sprite_line_act_q;
// pragma translate_off
// Testbench signals --------------------------------------------------------
//
//assign ac_s = enum_to_vec_f(access_type_s);
//
//---------------------------------------------------------------------------
// pragma translate_on
//---------------------------------------------------------------------------
// Process decode_access
//
// Purpose:
// Decode horizontal counter value to access type.
//
logic signed [0:8] num_pix_plus_6_v;
logic signed [0:8] num_pix_plus_8_v;
logic signed [0:8] num_pix_plus_32_v;
assign num_pix_plus_6_v = num_pix_i + 9'sd6;
assign num_pix_plus_8_v = num_pix_i + 9'sd8;
assign num_pix_plus_32_v = num_pix_i + 9'sd32;
logic signed [0:8] mod_6_v;
assign mod_6_v = mod_6_f(num_pix_plus_6_v);
// prepare number of pixels for pattern operations
logic signed [0:8] num_pix_spr_v;
assign num_pix_spr_v = num_pix_i & 9'b111111110;
always_comb
begin: decode_access
// default assignment
access_type_o = AC_CPU;
case (opmode_i)
// Graphics I, II and Multicolor Mode -----------------------------------
OPMODE_GRAPH1, OPMODE_GRAPH2, OPMODE_MULTIC :
begin
//
// Patterns
//
if (vert_active_q)
begin
if (num_pix_plus_8_v[0] == 1'b0)
begin
if (~xst_bug_wa_c)
// original code, we want this
case (num_pix_plus_8_v[6:7])
2'b01 :
access_type_o = AC_PNT;
2'b10 :
if (opmode_i != OPMODE_MULTIC)
// no access to pattern color table in multicolor mode
access_type_o = AC_PCT;
2'b11 :
access_type_o = AC_PGT;
default: begin end
endcase
else
// workaround for XST bug, we need this
if (num_pix_plus_8_v[6:7] == 2'b01)
access_type_o = AC_PNT;
else if (num_pix_plus_8_v[6:7] == 2'b10)
begin
if (opmode_i != OPMODE_MULTIC)
access_type_o = AC_PCT;
end
else if (num_pix_plus_8_v[6:7] == 2'b11)
access_type_o = AC_PGT;
end
end
//
// Sprite test
//
if (sprite_line_act_q)
begin
if (~num_pix_i[0] && (num_pix_i[0:5] != 6'b011111) && (num_pix_i[6:7] == 2'b00) && (num_pix_i[4:5] != 2'b00))
// sprite test interleaved with pattern accesses - 23 slots
access_type_o = AC_STST;
if ((num_pix_plus_32_v[0:4] == 5'b00000) || (num_pix_plus_32_v[0:7] == 8'b00001000))
// sprite tests before starting pattern phase - 9 slots
access_type_o = AC_STST;
//
// Sprite Attribute Table and Sprite Pattern Table
//
case (num_pix_spr_v)
250, -78, -62, -46 :
access_type_o = AC_SATY;
254, -76, -60, -44 :
access_type_o = AC_SATX;
252, -74, -58, -42 :
access_type_o = AC_SATN;
-86, -70, -54, -38 :
access_type_o = AC_SATC;
-84, -68, -52, -36 :
access_type_o = AC_SPTH;
-82, -66, -50, -34 :
if (reg_size1_i)
access_type_o = AC_SPTL;
default: begin end
endcase
end
end
// Text Mode ------------------------------------------------------------
OPMODE_TEXTM :
if (vert_active_q && ~num_pix_plus_6_v[0] && (num_pix_plus_6_v[0:4] != 5'b01111))
begin
case (mod_6_v[6:7])
2'b00 :
access_type_o = AC_PNT;
2'b10 :
access_type_o = AC_PGT;
default: begin end
endcase
end
default: begin end
endcase
end
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Process vert_flags
//
// Purpose:
// Track the vertical position with flags.
//
always @(posedge clk_i, posedge reset_i )
begin: vert_flags
if (reset_i)
begin
vert_active_q <= '0;
sprite_active_q <= '0;
sprite_line_act_q <= '0;
end
else
begin
if (clk_en_5m37_i)
begin
// line-local sprite processing
if (sprite_active_q)
begin
// sprites are globally enabled
if (vert_inc_i)
// reload at beginning of every new line
// => scan with STST
sprite_line_act_q <= '1;
if (num_pix_i == hv_sprite_start_c)
// reload when access to sprite memory starts
sprite_line_act_q <= '1;
end
if (vert_inc_i)
begin
// global sprite processing
if (reg_blank_i)
begin
sprite_active_q <= '0;
sprite_line_act_q <= '0;
end
else if (num_line_i == -2)
begin
// start at line -1
sprite_active_q <= '1;
// initialize immediately
sprite_line_act_q <= '1;
end
else if (num_line_i == 191)
begin
// stop at line 192
sprite_active_q <= '0;
// force stop
sprite_line_act_q <= '0;
end
// global vertical display
if (reg_blank_i)
vert_active_q <= '0;
else if (num_line_i == -1)
// start vertical display at line 0
vert_active_q <= '1;
else if (num_line_i == 191)
// stop at line 192
vert_active_q <= '0;
end
if (stop_sprite_i)
// stop processing of sprites in this line
sprite_line_act_q <= '0;
end
end
end
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Process hor_flags
//
// Purpose:
// Track the horizontal position.
//
always @(posedge clk_i, posedge reset_i )
begin: hor_flags
if (reset_i)
hor_active_q <= '0;
else
begin
if (clk_en_5m37_i)
begin
if ((~reg_blank_i) & num_pix_i == -1)
hor_active_q <= '1;
if (opmode_i == OPMODE_TEXTM)
begin
if (num_pix_i == 239)
hor_active_q <= '0;
end
else
if (num_pix_i == 255)
hor_active_q <= '0;
end
end
end
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Ouput mapping
//---------------------------------------------------------------------------
// generate clock enable for flip-flops working on access_type
assign clk_en_acc_o = clk_en_5m37_i & num_pix_i[8];
assign vert_active_o = vert_active_q;
assign hor_active_o = hor_active_q;
assign irq_o = vert_inc_i & (num_line_i == 191);
function signed [0:8] mod_6_f;
input signed [0:8] val;
begin
int mod_v;
logic signed [0:8] result_v;
mod_v = '0;
if (val > 0) begin
result_v = '0;
for (int idx = 0; idx < 256; idx++) begin
if (val == idx) begin
result_v = signed'(mod_v[8:0]);
end
if (mod_v < 5) begin
mod_v = mod_v + 1'b1;
end else begin
mod_v = '0;
end
end // for (int idx = 0; idx < 255)
end else begin
result_v = 'x;
end
return result_v;
end
endfunction // mod_6_f
endmodule

View File

@@ -0,0 +1,211 @@
//-----------------------------------------------------------------------------
//
// Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
//
// $Id: vdp18_hor_vert.vhd,v 1.11 2006/06/18 10:47:01 arnim Exp $
//
// Horizontal / Vertical Timing Generator
//
//-----------------------------------------------------------------------------
//
// Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
//
// All rights reserved
//
// Redistribution and use in source and synthezised forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// Redistributions in synthesized form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Please report bugs to the author, but before you do so, please
// make sure that this is not a derivative work and that
// you have the latest version of this file.
//
// SystemVerilog conversion (c) 2022 Frank Bruno (fbruno@asicsolutions.com)
//
//-----------------------------------------------------------------------------
import vdp18_pkg::*;
module vdp18_hor_vert
#
(
parameter is_pal_g = 0
)
(
input clk_i,
input clk_en_5m37_i,
input reset_i,
input opmode_t opmode_i,
output logic signed [0:8] num_pix_o,
output logic signed [0:8] num_line_o,
output logic vert_inc_o,
output logic hsync_n_o,
output logic vsync_n_o,
output logic blank_o,
output logic hblank_o,
output logic vblank_o
);
logic signed [0:8] last_line_s;
logic signed [0:8] first_line_s;
logic signed [0:8] first_pix_s;
logic signed [0:8] last_pix_s;
logic signed [0:8] cnt_hor_q;
logic signed [0:8] cnt_vert_q;
logic vert_inc_s;
logic hblank_q;
logic vblank_q;
//---------------------------------------------------------------------------
// Prepare comparison signals for NTSC and PAL.
//
always_comb begin
if (is_pal_g == 1)
begin : is_pal
first_line_s = hv_first_line_pal_c;
last_line_s = hv_last_line_pal_c;
end else begin : is_ntsc
first_line_s = hv_first_line_ntsc_c[8:0];
last_line_s = hv_last_line_ntsc_c[8:0];
end
end
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Process opmode_mux
//
// Purpose:
// Generates the horizontal counter limits based on the current operating
// mode.
//
always_comb
begin: opmode_mux
if (opmode_i == OPMODE_TEXTM)
begin
first_pix_s = hv_first_pix_text_c[8:0];
last_pix_s = hv_last_pix_text_c[8:0];
end
else
begin
first_pix_s = hv_first_pix_graph_c[8:0];
last_pix_s = hv_last_pix_graph_c[8:0];
end
end
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Process counters
//
// Purpose:
// Implements the horizontal and vertical counters.
//
always @(posedge clk_i, posedge reset_i )
begin: counters
if (reset_i)
begin
cnt_hor_q <= hv_first_pix_text_c[8:0];
cnt_vert_q <= first_line_s;
hsync_n_o <= 1'b1;
vsync_n_o <= 1'b1;
hblank_q <= 1'b0;
vblank_q <= 1'b0;
end
else
begin
if (clk_en_5m37_i)
begin
// The horizontal counter ---------------------------------------------
if (cnt_hor_q == last_pix_s)
cnt_hor_q <= first_pix_s;
else
cnt_hor_q <= cnt_hor_q + 1'b1;
// The vertical counter -----------------------------------------------
if (cnt_vert_q == last_line_s)
cnt_vert_q <= first_line_s;
else if (vert_inc_s)
// increment when horizontal counter is at trigger position
cnt_vert_q <= cnt_vert_q + 1'b1;
// Horizontal sync ----------------------------------------------------
if (cnt_hor_q == -64)
hsync_n_o <= 1'b0;
else if (cnt_hor_q == -38)
hsync_n_o <= 1'b1;
if (cnt_hor_q == -72)
hblank_q <= 1'b1;
else if (cnt_hor_q == -14)
hblank_q <= 1'b0;
// Vertical sync ------------------------------------------------------
if (is_pal_g == 1)
begin
if (cnt_vert_q == 244)
vsync_n_o <= 1'b0;
else if (cnt_vert_q == 247)
vsync_n_o <= 1'b1;
end
else
begin
if (cnt_vert_q == 218)
vsync_n_o <= 1'b0;
else if (cnt_vert_q == 221)
vsync_n_o <= 1'b1;
if (cnt_vert_q == 214)
vblank_q <= 1'b1;
else if (cnt_vert_q == first_line_s + 14)
vblank_q <= 1'b0;
end
end
end
end
//
//---------------------------------------------------------------------------
// comparator for vertical line increment
assign vert_inc_s = clk_en_5m37_i & cnt_hor_q == hv_vertical_inc_c;
//---------------------------------------------------------------------------
// Output mapping
//---------------------------------------------------------------------------
assign num_pix_o = cnt_hor_q;
assign num_line_o = cnt_vert_q;
assign vert_inc_o = vert_inc_s;
assign blank_o = hblank_q | vblank_q;
assign vblank_o = vblank_q;
assign hblank_o = hblank_q;
endmodule

View File

@@ -0,0 +1,200 @@
//-----------------------------------------------------------------------------
//
// Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
//
// $Id: vdp18_pattern.vhd,v 1.8 2006/06/18 10:47:06 arnim Exp $
//
// Pattern Generation Controller
//
//-----------------------------------------------------------------------------
//
// Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
//
// All rights reserved
//
// Redistribution and use in source and synthezised forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// Redistributions in synthesized form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Please report bugs to the author, but before you do so, please
// make sure that this is not a derivative work and that
// you have the latest version of this file.
//
// SystemVerilog conversion (c) 2022 Frank Bruno (fbruno@asicsolutions.com)
//
//-----------------------------------------------------------------------------
import vdp18_pkg::*;
module vdp18_pattern
(
input clk_i,
input clk_en_5m37_i,
input clk_en_acc_i,
input reset_i,
input opmode_t opmode_i,
input access_t access_type_i,
input signed [0:8] num_line_i,
input [0:7] vram_d_i,
input vert_inc_i,
input vsync_n_i,
input [0:3] reg_col1_i,
input [0:3] reg_col0_i,
output logic [0:9] pat_table_o,
output logic [0:7] pat_name_o,
output logic [0:3] pat_col_o
);
logic [0:7] pat_tmp_q;
logic [0:7] pat_shift_q;
logic [0:7] pat_col_q;
//---------------------------------------------------------------------------
// Process seq
//
// Purpose:
// Implements the sequential elements:
// * pattern shift register
// * pattern color register
// * pattern counter
//
always @(posedge clk_i, posedge reset_i )
begin: seq
if (reset_i)
begin
pat_table_o <= '0;
pat_name_o <= '0;
pat_tmp_q <= '0;
pat_shift_q <= '0;
pat_col_q <= '0;
end
else
begin
if (clk_en_5m37_i) begin
// shift pattern with every pixel clock
pat_shift_q[0:6] <= pat_shift_q[1:7];
end
if (clk_en_acc_i) begin
// determine register update based on current access type -------------
case (access_type_i)
AC_PNT :
begin
// store pattern name
pat_name_o <= vram_d_i;
// increment pattern counter
pat_table_o<= pat_table_o + 1'b1;
end
AC_PCT : begin
// store pattern color in temporary register
pat_tmp_q <= vram_d_i;
end
AC_PGT :
if (opmode_i == OPMODE_MULTIC)
begin
// set shift register to constant value
// this value generates 4 bits of color1
// followed by 4 bits of color0
pat_shift_q <= 8'b11110000;
// set pattern color from pattern generator memory
pat_col_q <= vram_d_i;
end
else
begin
// all other modes:
// store pattern line in shift register
pat_shift_q <= vram_d_i;
// move pattern color from temporary register to color register
pat_col_q <= pat_tmp_q;
end
default: begin end
endcase
end // if (clk_en_acc_i)
if (vert_inc_i)
begin
// redo patterns of if there are more lines inside this pattern
if (~num_line_i[0])
case (opmode_i)
OPMODE_TEXTM :
if (num_line_i[6:8] != 3'b111)
pat_table_o <= pat_table_o - 10'd40;
OPMODE_GRAPH1, OPMODE_GRAPH2, OPMODE_MULTIC :
if (num_line_i[6:8] != 3'b111)
pat_table_o <= pat_table_o - 10'd32;
default: begin end
endcase
end
if (vsync_n_i == 1'b0) begin
// reset pattern counter at end of active display area
pat_table_o <= '0;
end
end // else: !if(reset_i)
end
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Process col_gen
//
// Purpose:
// Generates the color of the current pattern pixel.
//
always_comb
begin: col_gen
// default assignment
pat_col_o = '0;
case (opmode_i)
// Text Mode ------------------------------------------------------------
OPMODE_TEXTM :
if (pat_shift_q[0])
pat_col_o = reg_col1_i;
else
pat_col_o = reg_col0_i;
// Graphics I, II and Multicolor Mode -----------------------------------
OPMODE_GRAPH1, OPMODE_GRAPH2, OPMODE_MULTIC :
if (pat_shift_q[0])
pat_col_o = pat_col_q[0:3];
else
pat_col_o = pat_col_q[4:7];
default: begin end
endcase
end
endmodule

View File

@@ -0,0 +1,56 @@
`ifndef _VDP18_PKG
`define _VDP18_PKG
package vdp18_pkg;
typedef enum bit [3:0]
{
// pattern access
// read Pattern Name Table
AC_PNT,// = 4'h1,
// read Pattern Generator Table
AC_PGT,// = 4'h2,
// read Pattern Color Table
AC_PCT,// = 4'h3,
// sprite access
// sprite test read (y coordinate)
AC_STST,// = 4'h4,
// read Sprite Attribute Table/Y
AC_SATY,// = 4'h5,
// read Sprite Attribute Table/X
AC_SATX,// = 4'h6,
// read Sprite Attribute Table/N
AC_SATN,// = 4'h7,
// read Sprite Attribute Table/C
AC_SATC,// = 4'h8,
// read Sprite Pattern Table/high quadrant
AC_SPTH,// = 4'hA,
// read Sprite Pattern Table/low quadrant
AC_SPTL,// = 4'h9,
//
// CPU access
AC_CPU,// = 4'hF,
//
// no access at all
AC_NONE// = 4'h0
} access_t;
typedef enum bit [1:0]
{
OPMODE_GRAPH1 = 2'h00,
OPMODE_GRAPH2 = 2'b01,
OPMODE_MULTIC = 2'b10,
OPMODE_TEXTM = 2'b11} opmode_t;
parameter hv_first_line_ntsc_c = -40;
parameter hv_last_line_ntsc_c = 221;
parameter hv_first_line_pal_c = -65;
parameter hv_last_line_pal_c = 247;
parameter hv_first_pix_text_c = -102;
parameter hv_last_pix_text_c = 239;
parameter hv_first_pix_graph_c = -86;
parameter hv_last_pix_graph_c = 255;
parameter hv_vertical_inc_c = -32;
parameter hv_sprite_start_c = 247;
endpackage // vdp18_pkg
`endif

View File

@@ -0,0 +1,405 @@
//-----------------------------------------------------------------------------
//
// Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
//
// $Id: vdp18_sprite.vhd,v 1.11 2006/06/18 10:47:06 arnim Exp $
//
// Sprite Generation Controller
//
// Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
//
// All rights reserved
//
// Redistribution and use in source and synthezised forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// Redistributions in synthesized form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Please report bugs to the author, but before you do so, please
// make sure that this is not a derivative work and that
// you have the latest version of this file.
//
// SystemVerilog conversion (c) 2022 Frank Bruno (fbruno@asicsolutions.com)
//
//-----------------------------------------------------------------------------
import vdp18_pkg::*;
module vdp18_sprite
(
input clk_i,
input clk_en_5m37_i,
input clk_en_acc_i,
input reset_i,
input access_t access_type_i,
input signed [0:8] num_pix_i,
input signed [0:8] num_line_i,
input [0:7] vram_d_i,
input vert_inc_i,
input reg_size1_i,
input reg_mag1_i,
output logic spr_5th_o,
output logic [0:4] spr_5th_num_o,
output logic stop_sprite_o,
output logic spr_coll_o,
output logic [0:4] spr_num_o,
output logic [0:3] spr_line_o,
output logic [0:7] spr_name_o,
output logic [0:3] spr0_col_o,
output logic [0:3] spr1_col_o,
output logic [0:3] spr2_col_o,
output logic [0:3] spr3_col_o
);
logic [0:4] sprite_numbers_q[0:3];
logic [0:4] sprite_num_q;
logic [0:2] sprite_idx_q;
logic [0:7] sprite_name_q;
logic [0:7] sprite_xpos_q[0:3];
logic [0:3] sprite_ec_q;
logic [0:3] sprite_xtog_q;
logic [0:3] sprite_cols_q[0:3];
logic [0:15] sprite_pats_q[0:3];
logic [0:3] sprite_line_s;
logic [0:3] sprite_line_q;
logic sprite_visible_s;
logic [0:2] sprite_idx_inc_v;
logic [0:2] sprite_idx_dec_v;
logic [1:0] sprite_idx_v;
// sprite index will be incremented during sprite tests
assign sprite_idx_inc_v = sprite_idx_q + 1'b1;
// sprite index will be decremented at end of sprite pattern data
assign sprite_idx_dec_v = sprite_idx_q - 1'b1;
// just save typing
assign sprite_idx_v = sprite_idx_q[1:2];
//---------------------------------------------------------------------------
// Process seq
//
// Purpose:
// Implements the sequential elements.
//
always @(posedge clk_i, posedge reset_i )
begin: seq
if (reset_i)
begin
sprite_numbers_q <= '{default: '0};
sprite_num_q <= '0;
sprite_idx_q <= '0;
sprite_line_q <= '0;
sprite_name_q <= '0;
sprite_cols_q <= '{default: '0};
sprite_xpos_q <= '{default: '0};
sprite_ec_q <= '0;
sprite_xtog_q <= '0;
sprite_pats_q <= '{default: '0};
end
else
begin
if (clk_en_5m37_i)
begin
// pre-decrement index counter when sprite reading starts
if ((num_pix_i == hv_sprite_start_c) && (sprite_idx_q > 0))
sprite_idx_q <= sprite_idx_dec_v;
//---------------------------------------------------------------------
// X position counters
//---------------------------------------------------------------------
for (int idx = 0; idx <= 3; idx++)
if (~num_pix_i[0] || (sprite_ec_q[idx] && (&num_pix_i[0:3])))
begin
if (sprite_xpos_q[idx])
// decrement counter until 0
sprite_xpos_q[idx] <= sprite_xpos_q[idx] - 1'b1;
else
// toggle magnification flag
sprite_xtog_q[idx] <= ~sprite_xtog_q[idx];
end
//---------------------------------------------------------------------
// Sprite pattern shift registers
//---------------------------------------------------------------------
for (int idx = 0; idx <= 3; idx++)
begin
if (sprite_xpos_q[idx] == '0) // x counter elapsed
begin
// decide when to shift pattern information
// case 1: pixel number is >= 0
// => active display area
// case 2: early clock bit is set and pixel number is between
// -32 and 0
// shift if
// magnification not enbled
// or
// magnification enabled and toggle marker true
if ((~num_pix_i[0] || (sprite_ec_q[idx] && (&num_pix_i[0:3]))) && (sprite_xtog_q[idx] || ~reg_mag1_i))
begin
//
// shift pattern left and fill vacated position with
// transparent information
sprite_pats_q[idx][0:14] <= sprite_pats_q[idx][1:15];
sprite_pats_q[idx][15] <= 1'b0;
end
end
// clear pattern at end of visible display
// this removes "left-overs" when a sprite overlaps the right border
if (num_pix_i == 9'b011111111)
sprite_pats_q[idx] <= '0;
end
end
if (vert_inc_i)
begin
// reset sprite num counter and sprite index counter
sprite_num_q <= '0;
sprite_idx_q <= '0;
end
else if (clk_en_acc_i)
case (access_type_i)
AC_STST :
begin
// increment sprite number counter
sprite_num_q <= sprite_num_q + 1'b1;
if (sprite_visible_s)
begin
if (sprite_idx_q < 4)
begin
// store sprite number
sprite_numbers_q[sprite_idx_v] <= sprite_num_q;
// and increment index counter
sprite_idx_q <= sprite_idx_inc_v;
end
end
end
AC_SATY :
// store sprite line
sprite_line_q <= sprite_line_s;
AC_SATX :
begin
// save x position
sprite_xpos_q[sprite_idx_v] <= vram_d_i;
// reset toggle flag for magnified sprites
sprite_xtog_q[sprite_idx_v] <= '0;
end
AC_SATN :
// save sprite name
sprite_name_q <= vram_d_i;
AC_SATC :
begin
// save sprite color
sprite_cols_q[sprite_idx_v] <= vram_d_i[4:7];
// and save early clock bit
sprite_ec_q[sprite_idx_v] <= vram_d_i[0];
end
AC_SPTH :
begin
// save upper pattern data
sprite_pats_q[sprite_idx_v][0:7] <= vram_d_i;
// set lower part to transparent
sprite_pats_q[sprite_idx_v][8:15] <= '0;
if (~reg_size1_i)
// decrement index counter in 8-bit mode
sprite_idx_q <= sprite_idx_dec_v;
end
AC_SPTL :
begin
// save lower pattern data
sprite_pats_q[sprite_idx_v][8:15] <= vram_d_i;
// always decrement index counter
sprite_idx_q <= sprite_idx_dec_v;
end
default: begin end
endcase
end
end
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Process calc_vert
//
// Purpose:
// Calculates the displayed line of the sprite and determines whether it
// is visible on the current line or not.
//
logic [0:8] sprite_line_v;
logic signed [0:8] vram_d_v;
always_comb
begin: calc_vert
// default assignments
sprite_visible_s = '0;
stop_sprite_o = '0;
vram_d_v = signed'(vram_d_i);
// determine if y information from VRAM should be treated
// as a signed or unsigned number
if (vram_d_v < -31)
// treat as unsigned number
vram_d_v[0] = 1'b0;
sprite_line_v = num_line_i - vram_d_v;
if (reg_mag1_i)
// unmagnify line number
sprite_line_v = {1'b0, sprite_line_v[0:7]};
// check result bounds
if (sprite_line_v >= 0)
begin
if (reg_size1_i)
begin
// double sized sprite: 16 data lines
if (sprite_line_v < 16)
sprite_visible_s = '1;
end
else
// standard sized sprite: 8 data lines
if (sprite_line_v < 8)
sprite_visible_s = '1;
end
// finally: line number of current sprite
sprite_line_s = sprite_line_v[5:8];
if (clk_en_acc_i)
begin
// determine when to stop sprite scanning
if (access_type_i == AC_STST)
begin
if (vram_d_v == 208)
// stop upon Y position 208
stop_sprite_o = '1;
if (sprite_idx_q == 4)
// stop when all sprite positions have been vacated
stop_sprite_o = '1;
if (sprite_num_q == 31)
// stop when all sprites have been read
stop_sprite_o = '1;
end
// stop sprite reading when last active sprite has been processed
if ((sprite_idx_q == 0) && ((access_type_i == AC_SPTL) || ((access_type_i == AC_SPTH) && ~reg_size1_i)))
stop_sprite_o = '1;
end
// stop sprite reading when no sprite is active on current line
if ((num_pix_i == hv_sprite_start_c) && (sprite_idx_q == 0))
stop_sprite_o = '1;
end
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Process fifth
//
// Purpose:
// Detects the fifth sprite.
//
always_comb
begin: fifth
// default assignments
spr_5th_o = '0;
spr_5th_num_o = '0;
if (clk_en_acc_i && (access_type_i == AC_STST))
begin
if (sprite_visible_s && (sprite_idx_q == 4))
begin
spr_5th_o = '1;
spr_5th_num_o = sprite_num_q;
end
end
end
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Process col_mux
//
// Purpose:
// Implements the color multiplexers.
//
logic [0:3] spr_col[0:3];
logic [0:2] num_spr_pix_v;
always_comb begin: col_mux
// default assignments
// sprite colors are set to transparent
spr_col = '{default: '0};
num_spr_pix_v = '0;
for (int i = 0; i < 4; i++) begin
if (~|sprite_xpos_q[i] && sprite_pats_q[i][0])
begin
spr_col[i] = sprite_cols_q[i];
num_spr_pix_v++;
end
end
end : col_mux
assign spr_coll_o = num_spr_pix_v > 1;
assign spr0_col_o = spr_col[0];
assign spr1_col_o = spr_col[1];
assign spr2_col_o = spr_col[2];
assign spr3_col_o = spr_col[3];
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Output mapping
//---------------------------------------------------------------------------
assign spr_num_o = (access_type_i == AC_STST) ? sprite_num_q :
(sprite_numbers_q[(sprite_idx_q[1:2])]);
assign spr_line_o = sprite_line_q;
assign spr_name_o = sprite_name_q;
endmodule