mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-02-04 23:34:44 +00:00
Atari 7800 New Attempt
This commit is contained in:
30
Atari - 7800_TeST/Atari7800.qpf
Normal file
30
Atari - 7800_TeST/Atari7800.qpf
Normal file
@@ -0,0 +1,30 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# Copyright (C) 1991-2013 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.0 Build 162 10/23/2013 SJ Web Edition
|
||||
# Date created = 23:59:05 March 16, 2017
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
|
||||
QUARTUS_VERSION = "13.1"
|
||||
DATE = "23:59:05 March 16, 2017"
|
||||
|
||||
# Revisions
|
||||
|
||||
PROJECT_REVISION = "Atari7800"
|
||||
231
Atari - 7800_TeST/Atari7800.qsf
Normal file
231
Atari - 7800_TeST/Atari7800.qsf
Normal file
@@ -0,0 +1,231 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# 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 Web Edition
|
||||
# Date created = 14:33:15 July 17, 2018
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# Notes:
|
||||
#
|
||||
# 1) The default values for assignments are stored in the file:
|
||||
# Atari7800_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 ORIGINAL_QUARTUS_VERSION 13.1
|
||||
set_global_assignment -name PROJECT_CREATION_TIME_DATE "23:59:05 MARCH 16, 2017"
|
||||
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
|
||||
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY Output_Files
|
||||
set_global_assignment -name VERILOG_INCLUDE_FILE rtl/atari7800.vh
|
||||
set_global_assignment -name VERILOG_INCLUDE_FILE rtl/tia.vh
|
||||
set_global_assignment -name VERILOG_INCLUDE_FILE rtl/riot.vh
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cart_top.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/Atari7800.sv
|
||||
set_global_assignment -name VERILOG_FILE rtl/BIOS_ROM.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/uv_to_vga.sv
|
||||
set_global_assignment -name VERILOG_FILE rtl/ram2k.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/maria.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/TIA.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/RIOT.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu_wrapper.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/line_ram.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/timing_ctrl.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory_map.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/dma_ctrl.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/audio.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/audio_xformer.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/ALU.sv
|
||||
set_global_assignment -name VERILOG_FILE rtl/pll.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/defender_rom.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sigma_delta_dac.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/video_mixer.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/osd.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/mist_io.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/scandoubler.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/hq2x.sv
|
||||
|
||||
# Pin & Location Assignments
|
||||
# ==========================
|
||||
set_location_assignment PIN_54 -to CLOCK_27
|
||||
set_location_assignment PIN_7 -to LED
|
||||
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_90 -to SPI_SS4
|
||||
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 PIN_31 -to UART_RX
|
||||
set_location_assignment PIN_46 -to UART_TX
|
||||
|
||||
# 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_DO_CCPP_REMOVAL ON
|
||||
|
||||
# Analysis & Synthesis Assignments
|
||||
# ================================
|
||||
set_global_assignment -name FAMILY "Cyclone III"
|
||||
set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005
|
||||
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
|
||||
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 cart_top
|
||||
|
||||
# Fitter Assignments
|
||||
# ==================
|
||||
set_global_assignment -name DEVICE EP3C25E144C8
|
||||
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1
|
||||
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
|
||||
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 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"
|
||||
|
||||
# EDA Netlist Writer Assignments
|
||||
# ==============================
|
||||
set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (VHDL)"
|
||||
|
||||
# Assembler Assignments
|
||||
# =====================
|
||||
set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
|
||||
set_global_assignment -name GENERATE_RBF_FILE ON
|
||||
|
||||
# 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 EDA_TOOL_SETTINGS(eda_simulation)
|
||||
# ---------------------------------------
|
||||
|
||||
# EDA Netlist Writer Assignments
|
||||
# ==============================
|
||||
set_global_assignment -name EDA_OUTPUT_DATA_FORMAT VHDL -section_id eda_simulation
|
||||
|
||||
# end EDA_TOOL_SETTINGS(eda_simulation)
|
||||
# -------------------------------------
|
||||
|
||||
# ----------------------
|
||||
# start ENTITY(cart_top)
|
||||
|
||||
# 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(cart_top)
|
||||
# --------------------
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
BIN
Atari - 7800_TeST/Atari7800.qws
Normal file
BIN
Atari - 7800_TeST/Atari7800.qws
Normal file
Binary file not shown.
2
Atari - 7800_TeST/Atari7800.srf
Normal file
2
Atari - 7800_TeST/Atari7800.srf
Normal file
@@ -0,0 +1,2 @@
|
||||
{ "" "" "" "*" { } { } 0 10230 "" 0 0 "Quartus II" 0 -1 0 ""}
|
||||
{ "" "" "" "*" { } { } 0 10036 "" 0 0 "Quartus II" 0 -1 0 ""}
|
||||
BIN
Atari - 7800_TeST/Snapshot/Atari7800.rbf
Normal file
BIN
Atari - 7800_TeST/Snapshot/Atari7800.rbf
Normal file
Binary file not shown.
37
Atari - 7800_TeST/clean.bat
Normal file
37
Atari - 7800_TeST/clean.bat
Normal file
@@ -0,0 +1,37 @@
|
||||
@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 /s new_rtl_netlist
|
||||
del /s old_rtl_netlist
|
||||
|
||||
pause
|
||||
110
Atari - 7800_TeST/rtl/ALU.sv
Normal file
110
Atari - 7800_TeST/rtl/ALU.sv
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* ALU.
|
||||
*
|
||||
* AI and BI are 8 bit inputs. Result in OUT.
|
||||
* CI is Carry In.
|
||||
* CO is Carry Out.
|
||||
*
|
||||
* op[3:0] is defined as follows:
|
||||
*
|
||||
* 0011 AI + BI
|
||||
* 0111 AI - BI
|
||||
* 1011 AI + AI
|
||||
* 1100 AI | BI
|
||||
* 1101 AI & BI
|
||||
* 1110 AI ^ BI
|
||||
* 1111 AI
|
||||
*
|
||||
*/
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
|
||||
module ALU( clk, op, right, AI, BI, CI, CO, BCD, OUT, V, Z, N, HC, RDY );
|
||||
input clk;
|
||||
input right;
|
||||
input [3:0] op; // operation
|
||||
input [7:0] AI;
|
||||
input [7:0] BI;
|
||||
input CI;
|
||||
input BCD; // BCD style carry
|
||||
output [7:0] OUT;
|
||||
output CO;
|
||||
output V;
|
||||
output Z;
|
||||
output N;
|
||||
output HC;
|
||||
input RDY;
|
||||
|
||||
reg [7:0] OUT;
|
||||
reg CO;
|
||||
wire V;
|
||||
wire Z;
|
||||
reg N;
|
||||
reg HC;
|
||||
|
||||
reg AI7;
|
||||
reg BI7;
|
||||
reg [8:0] temp_logic;
|
||||
reg [7:0] temp_BI;
|
||||
reg [4:0] temp_l;
|
||||
reg [4:0] temp_h;
|
||||
wire [8:0] temp = { temp_h, temp_l[3:0] };
|
||||
wire adder_CI = (right | (op[3:2] == 2'b11)) ? 0 : CI;
|
||||
|
||||
// calculate the logic operations. The 'case' can be done in 1 LUT per
|
||||
// bit. The 'right' shift is a simple mux that can be implemented by
|
||||
// F5MUX.
|
||||
always @* begin
|
||||
case( op[1:0] )
|
||||
2'b00: temp_logic = AI | BI;
|
||||
2'b01: temp_logic = AI & BI;
|
||||
2'b10: temp_logic = AI ^ BI;
|
||||
2'b11: temp_logic = AI;
|
||||
endcase
|
||||
|
||||
if( right )
|
||||
temp_logic = { AI[0], CI, AI[7:1] };
|
||||
end
|
||||
|
||||
// Add logic result to BI input. This only makes sense when logic = AI.
|
||||
// This stage can be done in 1 LUT per bit, using carry chain logic.
|
||||
always @* begin
|
||||
case( op[3:2] )
|
||||
2'b00: temp_BI = BI; // A+B
|
||||
2'b01: temp_BI = ~BI; // A-B
|
||||
2'b10: temp_BI = temp_logic; // A+A
|
||||
2'b11: temp_BI = 0; // A+0
|
||||
endcase
|
||||
end
|
||||
|
||||
// HC9 is the half carry bit when doing BCD add
|
||||
wire HC9 = BCD & (temp_l[3:1] >= 3'd5);
|
||||
|
||||
// CO9 is the carry-out bit when doing BCD add
|
||||
wire CO9 = BCD & (temp_h[3:1] >= 3'd5);
|
||||
|
||||
// combined half carry bit
|
||||
wire temp_HC = temp_l[4] | HC9;
|
||||
|
||||
// perform the addition as 2 separate nibble, so we get
|
||||
// access to the half carry flag
|
||||
always @* begin
|
||||
temp_l = temp_logic[3:0] + temp_BI[3:0] + adder_CI;
|
||||
temp_h = temp_logic[8:4] + temp_BI[7:4] + temp_HC;
|
||||
end
|
||||
|
||||
// calculate the flags
|
||||
always @(posedge clk)
|
||||
if( RDY ) begin
|
||||
AI7 <= AI[7];
|
||||
BI7 <= temp_BI[7];
|
||||
OUT <= temp[7:0];
|
||||
CO <= temp[8] | CO9;
|
||||
N <= temp[7];
|
||||
HC <= temp_HC;
|
||||
end
|
||||
|
||||
assign V = AI7 ^ BI7 ^ CO ^ N;
|
||||
assign Z = ~|OUT;
|
||||
|
||||
endmodule
|
||||
444
Atari - 7800_TeST/rtl/Atari7800.sv
Normal file
444
Atari - 7800_TeST/rtl/Atari7800.sv
Normal file
@@ -0,0 +1,444 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "atari7800.vh"
|
||||
|
||||
|
||||
|
||||
module Atari7800(
|
||||
input logic clock_25,
|
||||
input logic sysclk_7_143,
|
||||
input logic clock_divider_locked,
|
||||
|
||||
input logic reset,
|
||||
output logic [3:0] RED, GREEN, BLUE,
|
||||
output logic HSync, VSync,
|
||||
|
||||
output logic [15:0] aud_signal_out,
|
||||
|
||||
input logic [7:0] cart_DB_out,
|
||||
output logic [15:0] AB,
|
||||
output logic RW,
|
||||
output logic pclk_0,
|
||||
|
||||
output logic [7:0] ld,
|
||||
|
||||
// Tia inputs
|
||||
input logic [3:0] idump,
|
||||
input logic [1:0] ilatch,
|
||||
|
||||
output logic tia_en,
|
||||
|
||||
// Riot inputs
|
||||
input logic [7:0] PAin, PBin,
|
||||
output logic [7:0] PAout, PBout
|
||||
);
|
||||
|
||||
assign ld[0] = lock_ctrl;
|
||||
|
||||
//////////////
|
||||
// Signals //
|
||||
////////////
|
||||
|
||||
// Clock Signals
|
||||
|
||||
logic pclk_2, tia_clk, sel_slow_clock;
|
||||
|
||||
|
||||
// VGA Signals
|
||||
logic [9:0] vga_row, vga_col;
|
||||
logic tia_hsync, tia_vsync, vga_hsync, vga_vsync;
|
||||
|
||||
(* keep = "true" *) logic tia_hsync_kept;
|
||||
(* keep = "true" *) logic tia_vsync_kept;
|
||||
(* keep = "true" *) logic vga_hsync_kept;
|
||||
(* keep = "true" *) logic vga_vsync_kept;
|
||||
|
||||
assign tia_hsync_kept = ~tia_hsync;
|
||||
assign tia_vsync_kept = ~tia_vsync;
|
||||
assign vga_hsync_kept = vga_hsync;
|
||||
assign vga_vsync_kept = vga_vsync;
|
||||
|
||||
// MARIA Signals
|
||||
logic m_int_b, maria_RDY;
|
||||
logic maria_rw;
|
||||
logic halt_b, maria_drive_AB;
|
||||
logic [7:0] uv_display, uv_maria, uv_tia;
|
||||
logic [15:0] maria_AB_out;
|
||||
|
||||
|
||||
|
||||
// TIA Signals
|
||||
logic hblank_tia, vblank_tia, aud0, aud1, tia_RDY;
|
||||
logic [3:0] audv0, audv1;
|
||||
logic [7:0] tia_db_out;
|
||||
|
||||
// RIOT Signals
|
||||
logic riot_RS_b;
|
||||
|
||||
// 6502 Signals
|
||||
logic RDY, IRQ_n, CPU_NMI;
|
||||
logic [7:0] core_DB_out;
|
||||
logic [15:0] core_AB_out;
|
||||
|
||||
logic cpu_reset, core_halt_b, core_latch_data;
|
||||
logic [2:0] cpu_reset_counter;
|
||||
|
||||
assign IRQ_n = 1'b1;
|
||||
|
||||
//ctrl Signals
|
||||
logic maria_en, lock_ctrl, bios_en_b;
|
||||
logic [1:0] ctrl_writes;
|
||||
|
||||
// Buses
|
||||
// AB and RW defined in port declaration
|
||||
logic [7:0] read_DB, write_DB;
|
||||
|
||||
logic [7:0] tia_DB_out, riot_DB_out, maria_DB_out,
|
||||
ram0_DB_out, ram1_DB_out, bios_DB_out;
|
||||
|
||||
`chipselect CS_maria_buf, CS_core_buf, CS_buf, CS;
|
||||
|
||||
logic memclk;
|
||||
assign memclk = (~halt_b & maria_drive_AB) ? sysclk_7_143 : pclk_0;
|
||||
|
||||
/*always_ff @(posedge sysclk_7_143, posedge reset) begin
|
||||
if (reset) begin
|
||||
CS_maria_buf <= `CS_NONE;
|
||||
CS_core_buf <= `CS_NONE;
|
||||
end else begin
|
||||
CS_maria_buf <= CS;
|
||||
CS_core_buf <= CS;
|
||||
end
|
||||
end
|
||||
|
||||
assign CS_buf = maria_drive_AB ? CS_maria_buf : CS_core_buf;*/
|
||||
|
||||
always_ff @(posedge memclk, posedge reset)
|
||||
if (reset)
|
||||
CS_buf <= `CS_NONE;
|
||||
else
|
||||
CS_buf <= CS;
|
||||
|
||||
|
||||
//CS LOGIC
|
||||
logic ram0_cs, ram1_cs, bios_cs, tia_cs, riot_cs, riot_ram_cs;
|
||||
|
||||
always_comb begin
|
||||
ram0_cs = 1'b0;
|
||||
ram1_cs = 1'b0;
|
||||
bios_cs = 1'b0;
|
||||
tia_cs = 1'b0;
|
||||
riot_cs = 1'b0;
|
||||
riot_ram_cs = 1'b0;
|
||||
casex (CS)
|
||||
`CS_RAM0: ram0_cs = 1'b1;
|
||||
`CS_RAM1: ram1_cs = 1'b1;
|
||||
`CS_BIOS: bios_cs = 1'b1;
|
||||
`CS_TIA: tia_cs = 1'b1;
|
||||
`CS_RIOT_IO: riot_cs = 1'b1;
|
||||
`CS_RIOT_RAM: begin riot_cs = 1'b1; riot_ram_cs = 1'b1; end
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
always_comb begin
|
||||
casex (CS_buf)
|
||||
`CS_RAM0: read_DB = ram0_DB_out;
|
||||
`CS_RAM1: read_DB = ram1_DB_out;
|
||||
`CS_RIOT_IO,
|
||||
`CS_RIOT_RAM: read_DB = riot_DB_out;
|
||||
`CS_TIA: read_DB = tia_DB_out;
|
||||
`CS_BIOS: read_DB = bios_DB_out;
|
||||
`CS_MARIA: read_DB = maria_DB_out;
|
||||
`CS_CART: read_DB = cart_DB_out;
|
||||
// Otherwise, nothing is driving the data bus. THIS SHOULD NEVER HAPPEN
|
||||
default: read_DB = 8'h46;
|
||||
endcase
|
||||
|
||||
write_DB = core_DB_out;
|
||||
|
||||
AB = (maria_drive_AB) ? maria_AB_out : core_AB_out;
|
||||
end
|
||||
/*
|
||||
(* ram_style = "distributed" *)
|
||||
reg [7:0] ram0 [2047:0];
|
||||
(* ram_style = "distributed" *)
|
||||
reg [7:0] ram1 [2047:0];
|
||||
integer cnt;
|
||||
always_ff @(posedge memclk) begin
|
||||
if (reset) begin
|
||||
for (cnt = 0; cnt < 2048;cnt = cnt + 1) begin
|
||||
ram0[cnt] <= 8'b0;
|
||||
ram1[cnt] <= 8'b0;
|
||||
end
|
||||
end
|
||||
else if(ram0_cs)
|
||||
if (RW)
|
||||
ram0_DB_out <= ram0[AB[10:0]];
|
||||
else
|
||||
ram0[AB[10:0]] <= write_DB;
|
||||
else if (ram1_cs)
|
||||
if (RW)
|
||||
ram1_DB_out <= ram1[AB[10:0]];
|
||||
else
|
||||
ram1[AB[10:0]] <= write_DB;
|
||||
end */
|
||||
|
||||
ram2k ram0_inst(
|
||||
.clock(memclk),
|
||||
//.ena(~ram0_cs_b),
|
||||
.clken(ram0_cs),
|
||||
.wren(~RW),
|
||||
.address(AB[10:0]),
|
||||
.data(write_DB),
|
||||
.q(ram0_DB_out)
|
||||
);
|
||||
|
||||
ram2k ram1_inst(
|
||||
.clock(memclk),
|
||||
//.ena(~ram1_cs_b),
|
||||
.clken(ram1_cs),
|
||||
.wren(~RW),
|
||||
.address(AB[10:0]),
|
||||
.data(write_DB),
|
||||
.q(ram1_DB_out)
|
||||
);
|
||||
|
||||
//assign bios_cs_b = ~(AB[15] & ~bios_en_b);
|
||||
|
||||
|
||||
BIOS_ROM BIOS_ROM(
|
||||
.clock(memclk),
|
||||
.clken(bios_cs),
|
||||
.address(AB[11:0]),
|
||||
.q(bios_DB_out)
|
||||
);
|
||||
|
||||
assign pclk_2 = ~pclk_0;
|
||||
// console_pll console_pll (
|
||||
// .inclk0(CLOCK_PLL),
|
||||
// .c0(clock_100),
|
||||
// .c1(clock_25), // 25 MHz
|
||||
// .c2(sysclk_7_143), // 7.143 MHz. Divide to 1.79 MHz
|
||||
// .locked(clock_divider_locked)
|
||||
// );
|
||||
|
||||
assign VSync = vga_vsync;
|
||||
assign HSync = vga_hsync;
|
||||
|
||||
// VGA
|
||||
uv_to_vga vga_out(
|
||||
.clk(clock_25), .reset(reset),
|
||||
.uv_in(uv_display),
|
||||
.row(vga_row), .col(vga_col),
|
||||
.RED(RED), .GREEN(GREEN), .BLUE(BLUE),
|
||||
.HSync(vga_hsync), .VSync(vga_vsync),
|
||||
.tia_en(tia_en),
|
||||
.tia_hblank(hblank_tia),
|
||||
.tia_vblank(vblank_tia),
|
||||
.tia_clk(tia_clk)
|
||||
);
|
||||
|
||||
// VIDEO
|
||||
always_comb case ({maria_en, tia_en})
|
||||
2'b00: uv_display = uv_maria;
|
||||
2'b01: uv_display = uv_tia;
|
||||
2'b10: uv_display = uv_maria;
|
||||
2'b11: uv_display = uv_tia;
|
||||
default: uv_display = uv_maria;
|
||||
endcase
|
||||
|
||||
// MARIA
|
||||
maria maria_inst(
|
||||
.AB_in(AB),
|
||||
.AB_out(maria_AB_out),
|
||||
.drive_AB(maria_drive_AB),
|
||||
.read_DB_in(read_DB),
|
||||
.write_DB_in(write_DB),
|
||||
.DB_out(maria_DB_out),
|
||||
.bios_en(~bios_en_b),
|
||||
.reset(reset),
|
||||
.sysclk(sysclk_7_143),
|
||||
.pclk_2(pclk_2),
|
||||
.sel_slow_clock(sel_slow_clock),
|
||||
.core_latch_data(core_latch_data),
|
||||
.tia_en(tia_en),
|
||||
.tia_clk(tia_clk),
|
||||
.pclk_0(pclk_0),
|
||||
.CS(CS),
|
||||
//.ram0_b(ram0_cs_b),
|
||||
//.ram1_b(ram1_cs_b),
|
||||
//.p6532_b(riot_cs_b),
|
||||
//.tia_b(tia_cs_b),
|
||||
//.riot_ram_b(riot_RS_b),
|
||||
.RW(RW),
|
||||
.enable(maria_en),
|
||||
.vga_row(vga_row),
|
||||
.vga_col(vga_col),
|
||||
.UV_out(uv_maria),
|
||||
.int_b(m_int_b),
|
||||
.halt_b(halt_b),
|
||||
.ready(maria_RDY)
|
||||
);
|
||||
|
||||
// TIA
|
||||
TIA tia_inst(.A({(AB[5] & tia_en), AB[4:0]}), // Address bus input
|
||||
.Din(write_DB), // Data bus input
|
||||
.Dout(tia_DB_out), // Data bus output
|
||||
.CS_n({2'b0,~tia_cs}), // Active low chip select input
|
||||
.CS(tia_cs), // Chip select input
|
||||
.R_W_n(RW), // Active low read/write input
|
||||
.RDY(tia_RDY), // CPU ready output
|
||||
.MASTERCLK(tia_clk), // 3.58 Mhz pixel clock input
|
||||
.CLK2(pclk_0), // 1.19 Mhz bus clock input
|
||||
.idump_in(idump), // Dumped I/O
|
||||
.Ilatch(ilatch), // Latched I/O
|
||||
.HSYNC(tia_hsync), // Video horizontal sync output
|
||||
.HBLANK(hblank_tia), // Video horizontal blank output
|
||||
.VSYNC(tia_vsync), // Video vertical sync output
|
||||
.VBLANK(vblank_tia), // Video vertical sync output
|
||||
.COLOROUT(uv_tia), // Indexed color output
|
||||
.RES_n(~reset), // Active low reset input
|
||||
.AUD0(aud0), //audio pin 0
|
||||
.AUD1(aud1), //audio pin 1
|
||||
.audv0(audv0), //audio volume for use with external xformer module
|
||||
.audv1(audv1) //audio volume for use with external xformer module
|
||||
);
|
||||
|
||||
audio_xformer audio_xform(.AUD0(aud0), .AUD1(aud1), .AUDV0(audv0),
|
||||
.AUDV1(audv1), .AUD_SIGNAL(aud_signal_out));
|
||||
|
||||
//RIOT
|
||||
RIOT riot_inst(.A(AB[6:0]), // Address bus input
|
||||
.Din(write_DB), // Data bus input
|
||||
.Dout(riot_DB_out), // Data bus output
|
||||
.CS(riot_cs), // Chip select input
|
||||
.CS_n(~riot_cs), // Active low chip select input
|
||||
.R_W_n(RW), // Active high read, active low write input
|
||||
.RS_n(~riot_ram_cs), // Active low rom select input
|
||||
.RES_n(~reset), // Active low reset input
|
||||
.IRQ_n(), // Active low interrupt output
|
||||
.CLK(pclk_0), // Clock input
|
||||
.PAin(PAin), // 8 bit port A input
|
||||
.PAout(PAout), // 8 bit port A output
|
||||
.PBin(PBin), // 8 bit port B input
|
||||
.PBout(PBout)); // 8 bit port B output
|
||||
|
||||
//6502
|
||||
assign cpu_reset = cpu_reset_counter != 3'b111;
|
||||
|
||||
always_ff @(posedge pclk_0, posedge reset) begin
|
||||
if (reset) begin
|
||||
cpu_reset_counter <= 3'b0;
|
||||
end else begin
|
||||
if (cpu_reset_counter != 3'b111)
|
||||
cpu_reset_counter <= cpu_reset_counter + 3'b001;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
assign RDY = maria_en ? maria_RDY : ((tia_en) ? tia_RDY : clock_divider_locked);
|
||||
|
||||
assign core_halt_b = (ctrl_writes == 2'd2) ? halt_b : 1'b1;
|
||||
|
||||
/// DEBUG ///////////////////////////////////////////
|
||||
`ifndef SIM
|
||||
|
||||
(* keep = "true" *)
|
||||
logic [15:0] pc_temp;
|
||||
|
||||
assign ld[1] = pc_reached_230a;
|
||||
assign ld[2] = pc_reached_26bc;
|
||||
//assign ld[3] = pc_reached_fbad;
|
||||
assign ld[4] = pc_reached_fbbd;
|
||||
assign ld[5] = pc_reached_faaf;
|
||||
|
||||
|
||||
assign ld[6] = tia_en;
|
||||
assign ld[7] = maria_en;
|
||||
|
||||
logic pc_reached_230a; // Beginning of RAM code
|
||||
logic pc_reached_26bc; // Exit BIOS
|
||||
logic pc_reached_fbad; // waiting for VSYNC
|
||||
logic pc_reached_fbbd; // done waiting for VSYNC
|
||||
logic pc_reached_faaf; // NMI handler
|
||||
|
||||
always_ff @(posedge sysclk_7_143, posedge reset) begin
|
||||
if (reset) begin
|
||||
pc_reached_230a <= 1'b0;
|
||||
pc_reached_26bc <= 1'b0;
|
||||
pc_reached_fbad <= 1'b0;
|
||||
pc_reached_fbbd <= 1'b0;
|
||||
pc_reached_faaf <= 1'b0;
|
||||
end else begin
|
||||
if (pc_temp == 16'h230a)
|
||||
pc_reached_230a <= 1'b1;
|
||||
if (pc_temp == 16'h23ee)
|
||||
pc_reached_26bc <= 1'b1;
|
||||
if (pc_temp == 16'hfbad)
|
||||
pc_reached_fbad <= 1'b1;
|
||||
if (pc_temp == 16'hfbbd)
|
||||
pc_reached_fbbd <= 1'b1;
|
||||
if (pc_temp == 16'hfaaf)
|
||||
pc_reached_faaf <= 1'b1;
|
||||
end
|
||||
end
|
||||
`endif
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
assign CPU_NMI = (lock_ctrl) ? (~m_int_b) : (~m_int_b & ~bios_en_b);
|
||||
|
||||
cpu_wrapper cpu_inst(.clk(pclk_0),
|
||||
.core_latch_data(core_latch_data),
|
||||
.sysclk(sysclk_7_143),
|
||||
.reset(cpu_reset),
|
||||
.AB(core_AB_out),
|
||||
.DB_IN(read_DB),
|
||||
.DB_OUT(core_DB_out),
|
||||
.RD(RW),
|
||||
.IRQ(~IRQ_n),
|
||||
.NMI(CPU_NMI),
|
||||
.RDY(RDY),
|
||||
.halt_b(core_halt_b),
|
||||
.pc_temp(pc_temp));
|
||||
|
||||
|
||||
|
||||
ctrl_reg ctrl(.clk(pclk_0),
|
||||
.lock_in(write_DB[0]),
|
||||
.maria_en_in(write_DB[1]),
|
||||
.bios_en_in(write_DB[2]),
|
||||
.tia_en_in(write_DB[3]),
|
||||
.latch_b(RW | ~tia_cs | lock_ctrl),
|
||||
.rst(reset),
|
||||
.lock_out(lock_ctrl),
|
||||
.maria_en_out(maria_en),
|
||||
.bios_en_out(bios_en_b),
|
||||
.tia_en_out(tia_en),
|
||||
.writes(ctrl_writes));
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
module ctrl_reg(input logic clk, lock_in, maria_en_in, bios_en_in, tia_en_in, latch_b, rst,
|
||||
output logic lock_out, maria_en_out, bios_en_out, tia_en_out,
|
||||
output logic [1:0] writes);
|
||||
|
||||
|
||||
always_ff @(posedge clk, posedge rst) begin
|
||||
if (rst) begin
|
||||
lock_out <= 0;
|
||||
maria_en_out <= 0;
|
||||
bios_en_out <= 0;
|
||||
tia_en_out <= 0;
|
||||
writes <= 0;
|
||||
end
|
||||
else if (~latch_b) begin
|
||||
lock_out <= lock_in;
|
||||
maria_en_out <= maria_en_in;
|
||||
bios_en_out <= bios_en_in;
|
||||
tia_en_out <= tia_en_in;
|
||||
if (writes < 2'd2)
|
||||
writes <= writes + 1;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
169
Atari - 7800_TeST/rtl/BIOS_ROM.v
Normal file
169
Atari - 7800_TeST/rtl/BIOS_ROM.v
Normal file
@@ -0,0 +1,169 @@
|
||||
// megafunction wizard: %ROM: 1-PORT%
|
||||
// GENERATION: STANDARD
|
||||
// VERSION: WM1.0
|
||||
// MODULE: altsyncram
|
||||
|
||||
// ============================================================
|
||||
// File Name: BIOS_ROM.v
|
||||
// Megafunction Name(s):
|
||||
// altsyncram
|
||||
//
|
||||
// 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 Web Edition
|
||||
// ************************************************************
|
||||
|
||||
|
||||
//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 BIOS_ROM (
|
||||
address,
|
||||
clken,
|
||||
clock,
|
||||
q);
|
||||
|
||||
input [11:0] address;
|
||||
input clken;
|
||||
input clock;
|
||||
output [7:0] q;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_off
|
||||
`endif
|
||||
tri1 clken;
|
||||
tri1 clock;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_on
|
||||
`endif
|
||||
|
||||
wire [7:0] sub_wire0;
|
||||
wire [7:0] q = sub_wire0[7:0];
|
||||
|
||||
altsyncram altsyncram_component (
|
||||
.address_a (address),
|
||||
.clock0 (clock),
|
||||
.clocken0 (clken),
|
||||
.q_a (sub_wire0),
|
||||
.aclr0 (1'b0),
|
||||
.aclr1 (1'b0),
|
||||
.address_b (1'b1),
|
||||
.addressstall_a (1'b0),
|
||||
.addressstall_b (1'b0),
|
||||
.byteena_a (1'b1),
|
||||
.byteena_b (1'b1),
|
||||
.clock1 (1'b1),
|
||||
.clocken1 (1'b1),
|
||||
.clocken2 (1'b1),
|
||||
.clocken3 (1'b1),
|
||||
.data_a ({8{1'b1}}),
|
||||
.data_b (1'b1),
|
||||
.eccstatus (),
|
||||
.q_b (),
|
||||
.rden_a (1'b1),
|
||||
.rden_b (1'b1),
|
||||
.wren_a (1'b0),
|
||||
.wren_b (1'b0));
|
||||
defparam
|
||||
altsyncram_component.address_aclr_a = "NONE",
|
||||
altsyncram_component.clock_enable_input_a = "NORMAL",
|
||||
altsyncram_component.clock_enable_output_a = "NORMAL",
|
||||
`ifdef NO_PLI
|
||||
altsyncram_component.init_file = "../rtl/rom/7800ntsc.rif"
|
||||
`else
|
||||
altsyncram_component.init_file = "../rtl/rom/7800ntsc.hex"
|
||||
`endif
|
||||
,
|
||||
altsyncram_component.intended_device_family = "Cyclone III",
|
||||
altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
|
||||
altsyncram_component.lpm_type = "altsyncram",
|
||||
altsyncram_component.numwords_a = 4096,
|
||||
altsyncram_component.operation_mode = "ROM",
|
||||
altsyncram_component.outdata_aclr_a = "NONE",
|
||||
altsyncram_component.outdata_reg_a = "CLOCK0",
|
||||
altsyncram_component.widthad_a = 12,
|
||||
altsyncram_component.width_a = 8,
|
||||
altsyncram_component.width_byteena_a = 1;
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
// ============================================================
|
||||
// CNX file retrieval info
|
||||
// ============================================================
|
||||
// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrAddr NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrByte NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrOutput NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: BlankMemory NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: Clken NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
|
||||
// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
|
||||
// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: MIFfilename STRING "../rtl/rom/7800ntsc.hex"
|
||||
// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "4096"
|
||||
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: RegAddr NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: RegOutput NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
|
||||
// Retrieval info: PRIVATE: SingleClock NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: UseDQRAM NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: WidthAddr NUMERIC "12"
|
||||
// Retrieval info: PRIVATE: WidthData NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: rden NUMERIC "0"
|
||||
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
||||
// Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE"
|
||||
// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "NORMAL"
|
||||
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "NORMAL"
|
||||
// Retrieval info: CONSTANT: INIT_FILE STRING "../rtl/rom/7800ntsc.hex"
|
||||
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO"
|
||||
// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
|
||||
// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "4096"
|
||||
// Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM"
|
||||
// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
|
||||
// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0"
|
||||
// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "12"
|
||||
// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
|
||||
// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
|
||||
// Retrieval info: USED_PORT: address 0 0 12 0 INPUT NODEFVAL "address[11..0]"
|
||||
// Retrieval info: USED_PORT: clken 0 0 0 0 INPUT VCC "clken"
|
||||
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
|
||||
// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]"
|
||||
// Retrieval info: CONNECT: @address_a 0 0 12 0 address 0 0 12 0
|
||||
// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
|
||||
// Retrieval info: CONNECT: @clocken0 0 0 0 0 clken 0 0 0 0
|
||||
// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL BIOS_ROM.v TRUE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL BIOS_ROM.inc FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL BIOS_ROM.cmp FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL BIOS_ROM.bsf FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL BIOS_ROM_inst.v FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL BIOS_ROM_bb.v FALSE
|
||||
// Retrieval info: LIB_FILE: altera_mf
|
||||
174
Atari - 7800_TeST/rtl/RIOT.sv
Normal file
174
Atari - 7800_TeST/rtl/RIOT.sv
Normal file
@@ -0,0 +1,174 @@
|
||||
/* Atari on an FPGA
|
||||
Masters of Engineering Project
|
||||
Cornell University, 2007
|
||||
Daniel Beer
|
||||
RIOT.v
|
||||
Redesign of the MOS 6532 chip. Provides RAM, I/O and timers to the Atari.
|
||||
*/
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
`include "riot.vh"
|
||||
module RIOT(A, // Address bus input
|
||||
Din, // Data bus input
|
||||
Dout, // Data bus output
|
||||
CS, // Chip select input
|
||||
CS_n, // Active low chip select input
|
||||
R_W_n, // Active low read/write input
|
||||
RS_n, // Active low rom select input
|
||||
RES_n, // Active low reset input
|
||||
IRQ_n, // Active low interrupt output
|
||||
CLK, // Clock input
|
||||
PAin, // 8 bit port A input
|
||||
PAout, // 8 bit port A output
|
||||
PBin, // 8 bit port B input
|
||||
PBout);// 8 bit port B output
|
||||
input [6:0] A;
|
||||
input [7:0] Din;
|
||||
output [7:0] Dout;
|
||||
input CS, CS_n, R_W_n, RS_n, RES_n, CLK;
|
||||
output IRQ_n;
|
||||
input [7:0] PAin, PBin;
|
||||
output [7:0] PAout, PBout; // Output register
|
||||
reg [7:0] Dout; // RAM allocation
|
||||
reg [7:0] RAM[127:0]; // I/O registers
|
||||
reg [7:0] DRA, DRB; // Data registers
|
||||
reg [7:0] DDRA, DDRB; // Data direction registers
|
||||
wire PA7;
|
||||
reg R_PA7;
|
||||
assign PA7 = (PAin[7] & ~DDRA[7]) | (DRA[7] & DDRA[7]);
|
||||
assign PAout = DRA & DDRA;
|
||||
assign PBout = DRB & DDRB;
|
||||
// Timer registers
|
||||
reg [8:0] Timer;
|
||||
reg [9:0] Prescaler;
|
||||
reg [1:0] Timer_Mode;
|
||||
reg Timer_Int_Flag, PA7_Int_Flag, Timer_Int_Enable, PA7_Int_Enable, PA7_Int_Mode; // Timer prescaler constants
|
||||
wire [9:0] PRESCALER_VALS[3:0];
|
||||
assign PRESCALER_VALS[0] = 10'd0;
|
||||
assign PRESCALER_VALS[1] = 10'd7;
|
||||
assign PRESCALER_VALS[2] = 10'd63;
|
||||
assign PRESCALER_VALS[3] = 10'd1023;
|
||||
// Interrupt
|
||||
assign IRQ_n = ~(Timer_Int_Flag & Timer_Int_Enable | PA7_Int_Flag & PA7_Int_Enable);
|
||||
// Operation decoding
|
||||
wire [6:0] op;
|
||||
reg [6:0] R_op;
|
||||
assign op = {RS_n, R_W_n, A[4:0]};
|
||||
// Registered data in
|
||||
reg [7:0] R_Din;
|
||||
integer cnt;
|
||||
// Software operations
|
||||
always @(posedge CLK)
|
||||
begin
|
||||
// Reset operation
|
||||
if (~RES_n) begin
|
||||
DRA <= 8'b0;
|
||||
DDRA <= 8'b0;
|
||||
DRB <= 8'b00010100;
|
||||
DDRB <= 8'b00010100;
|
||||
Timer_Int_Flag <= 1'b0;
|
||||
PA7_Int_Flag <= 1'b0;
|
||||
PA7_Int_Enable <= 1'b0;
|
||||
PA7_Int_Mode <= 1'b0;
|
||||
// Fill RAM with 0s
|
||||
for (cnt = 0; cnt < 128; cnt = cnt + 1)
|
||||
RAM[cnt] <= 8'b0;
|
||||
R_PA7 <= 1'b0;
|
||||
R_op <= `NOP;
|
||||
R_Din <= 8'b0;
|
||||
end
|
||||
// If the chip is enabled, execute an operation
|
||||
else if (CS & ~CS_n) begin
|
||||
// Register inputs for use later
|
||||
R_PA7 <= PA7;
|
||||
R_op <= op;
|
||||
R_Din <= Din;
|
||||
// Update the timer interrupt flag
|
||||
casex (op)
|
||||
`WRITE_TIMER: Timer_Int_Flag <= 1'b0;
|
||||
`READ_TIMER: Timer_Int_Flag <= 1'b0;
|
||||
default: if (Timer == 9'b111111111) Timer_Int_Flag <= 1'b1;
|
||||
endcase
|
||||
// Update the port A interrupt flag
|
||||
casex (op)
|
||||
`READ_INT_FLAG: PA7_Int_Flag <= 1'b0;
|
||||
default: PA7_Int_Flag <= PA7_Int_Flag | (PA7 != R_PA7 & PA7 == PA7_Int_Mode);
|
||||
endcase
|
||||
// Process the current operation
|
||||
casex(op) // RAM access
|
||||
`READ_RAM: Dout <= RAM[A];
|
||||
`WRITE_RAM: RAM[A] <= Din;
|
||||
// Port A data access
|
||||
`READ_DRA : Dout <= (PAin & ~DDRA) | (DRA & DDRA);
|
||||
`WRITE_DRA: DRA <= Din;
|
||||
// Port A direction register access
|
||||
`READ_DDRA: Dout <= DDRA;
|
||||
`WRITE_DDRA: DDRA <= Din;
|
||||
// Port B data access
|
||||
`READ_DRB: Dout <= (PBin & ~DDRB) | (DRB & DDRB);
|
||||
`WRITE_DRB: DRB <= Din;
|
||||
// Port B direction register access
|
||||
`READ_DDRB: Dout <= DDRB;
|
||||
`WRITE_DDRB: DDRB <= Din;
|
||||
// Timer access
|
||||
`READ_TIMER: Dout <= Timer[7:0];
|
||||
// Status register access
|
||||
`READ_INT_FLAG: Dout <= {Timer_Int_Flag, PA7_Int_Flag, 6'b0};
|
||||
// Enable the port A interrupt
|
||||
`WRITE_EDGE_DETECT: begin
|
||||
PA7_Int_Mode <= A[0]; PA7_Int_Enable <= A[1];
|
||||
end
|
||||
endcase
|
||||
end
|
||||
// Even if the chip is not enabled, update background functions
|
||||
else begin
|
||||
// Update the timer interrupt
|
||||
if (Timer == 9'b111111111)
|
||||
Timer_Int_Flag <= 1'b1;
|
||||
// Update the port A interrupt
|
||||
R_PA7 <= PA7;
|
||||
PA7_Int_Flag <= PA7_Int_Flag | (PA7 != R_PA7 & PA7 == PA7_Int_Mode);
|
||||
// Set the operation to a NOP
|
||||
R_op <=`NOP;
|
||||
end
|
||||
end
|
||||
// Update the timer at the negative edge of the clock
|
||||
always @(negedge CLK)begin
|
||||
// Reset operation
|
||||
if (~RES_n) begin
|
||||
Timer <= 9'b0;
|
||||
Timer_Mode <= 2'b0;
|
||||
Prescaler <= 10'b0;
|
||||
Timer_Int_Enable <= 1'b0;
|
||||
end
|
||||
// Otherwise, process timer operations
|
||||
else
|
||||
casex
|
||||
(R_op)
|
||||
// Write value to the timer and update the prescaler based on the address
|
||||
`WRITE_TIMER:begin
|
||||
Timer <= {1'b0, R_Din};
|
||||
Timer_Mode <= R_op[1:0];
|
||||
Prescaler <= PRESCALER_VALS[R_op[1:0]];
|
||||
Timer_Int_Enable <= R_op[3];
|
||||
end
|
||||
// Otherwise decrement the prescaler and if necessary the timer.
|
||||
// The prescaler holds a variable number of counts that must be
|
||||
// run before the timer is decremented
|
||||
default:if (Timer != 9'b100000000) begin
|
||||
if (Prescaler != 10'b0)
|
||||
Prescaler <= Prescaler - 10'b1;
|
||||
else begin
|
||||
if (Timer == 9'b0)
|
||||
begin
|
||||
Prescaler <= 10'b0;
|
||||
Timer_Mode <= 2'b0;
|
||||
end
|
||||
else
|
||||
Prescaler <= PRESCALER_VALS[Timer_Mode];
|
||||
Timer <= Timer - 9'b1;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
477
Atari - 7800_TeST/rtl/TIA.sv
Normal file
477
Atari - 7800_TeST/rtl/TIA.sv
Normal file
@@ -0,0 +1,477 @@
|
||||
/* Atari on an FPGA
|
||||
Masters of Engineering Project
|
||||
Cornell University, 2007
|
||||
Daniel Beer
|
||||
TIA.v
|
||||
Redesign of the Atari TIA chip. Provides the Atari with video generation,
|
||||
sound generation and I/O.
|
||||
*/
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
`include "tia.vh"
|
||||
module TIA(A, // Address bus input
|
||||
Din, // Data bus input
|
||||
Dout, // Data bus output
|
||||
CS_n, // Active low chip select input
|
||||
CS, // Chip select input
|
||||
R_W_n, // Active low read/write input
|
||||
RDY, // CPU ready output
|
||||
MASTERCLK, // 3.58 Mhz pixel clock input
|
||||
CLK2, // 1.19 Mhz bus clock input
|
||||
idump_in, // Dumped I/O
|
||||
Ilatch, // Latched I/O
|
||||
HSYNC, // Video horizontal sync output
|
||||
HBLANK, // Video horizontal blank output
|
||||
VSYNC, // Video vertical sync output
|
||||
VBLANK, // Video vertical sync output
|
||||
COLOROUT, // Indexed color output
|
||||
RES_n, // Active low reset input
|
||||
AUD0, //audio pin 0
|
||||
AUD1, //audio pin 1
|
||||
audv0, //audio volume for use with external xformer module
|
||||
audv1); //audio volume for use with external xformer module
|
||||
input [5:0] A;
|
||||
input [7:0] Din;
|
||||
output [7:0] Dout;
|
||||
input [2:0] CS_n;
|
||||
input CS;
|
||||
input R_W_n;
|
||||
output RDY;
|
||||
input MASTERCLK;
|
||||
input CLK2;
|
||||
input [1:0] Ilatch;
|
||||
input [3:0] idump_in;
|
||||
output HSYNC, HBLANK;
|
||||
output VSYNC, VBLANK;
|
||||
output [7:0] COLOROUT;
|
||||
input RES_n;
|
||||
output AUD0, AUD1;
|
||||
output reg [3:0] audv0, audv1;
|
||||
// Data output register
|
||||
reg [7:0] Dout;
|
||||
// Video control signal registers
|
||||
wire HSYNC;
|
||||
reg VSYNC, VBLANK;
|
||||
// Horizontal pixel counter
|
||||
reg [7:0] hCount;
|
||||
reg [3:0] hCountReset;
|
||||
reg clk_30;
|
||||
reg [7:0] clk_30_count;
|
||||
|
||||
wire [3:0] Idump;
|
||||
|
||||
// Pixel counter update
|
||||
always @(posedge MASTERCLK)
|
||||
begin
|
||||
// Reset operation
|
||||
if (~RES_n) begin
|
||||
hCount <= 8'd0;
|
||||
hCountReset[3:1] <= 3'd0;
|
||||
clk_30 <= 0;
|
||||
clk_30_count <= 0;
|
||||
latchedInputs <= 2'b11;
|
||||
end
|
||||
else begin
|
||||
if (inputLatchReset)
|
||||
latchedInputs <= 2'b11;
|
||||
else
|
||||
latchedInputs <= latchedInputs & Ilatch;
|
||||
|
||||
if (clk_30_count == 57) begin
|
||||
clk_30 <= ~clk_30;
|
||||
clk_30_count <= 0;
|
||||
end else begin
|
||||
clk_30_count <= clk_30_count + 1;
|
||||
end
|
||||
// Increment the count and reset if necessary
|
||||
if ((hCountReset[3]) ||(hCount == 8'd227))
|
||||
hCount <= 8'd0;
|
||||
else
|
||||
hCount <= hCount + 8'd1;
|
||||
// Software resets are delayed by three cycles
|
||||
hCountReset[3:1] <= hCountReset[2:0];
|
||||
end
|
||||
end
|
||||
assign HSYNC = (hCount >= 8'd20) && (hCount < 8'd36);
|
||||
assign HBLANK = (hCount < 8'd68);
|
||||
// Screen object registers
|
||||
// These registers are set by the software and used to generate pixels
|
||||
reg [7:0] player0Pos, player1Pos, missile0Pos, missile1Pos, ballPos;
|
||||
reg [4:0] player0Size, player1Size;
|
||||
reg [7:0] player0Color, player1Color, ballColor, pfColor, bgColor;
|
||||
reg [3:0] player0Motion, player1Motion, missile0Motion, missile1Motion,
|
||||
ballMotion;
|
||||
reg missile0Enable, missile1Enable, ballEnable, R_ballEnable;
|
||||
reg [1:0] ballSize;
|
||||
reg [19:0] pfGraphic;
|
||||
reg [7:0] player0Graphic, player1Graphic;
|
||||
reg [7:0] R_player0Graphic, R_player1Graphic;
|
||||
reg pfReflect, player0Reflect, player1Reflect;
|
||||
reg prioCtrl;
|
||||
reg pfColorCtrl;
|
||||
reg [14:0] collisionLatch;
|
||||
reg missile0Lock, missile1Lock;
|
||||
reg player0VertDelay, player1VertDelay, ballVertDelay;
|
||||
reg [3:0] audc0, audc1;
|
||||
reg [4:0] audf0, audf1;
|
||||
// Pixel number calculation
|
||||
wire [7:0] pixelNum;
|
||||
|
||||
|
||||
//audio control
|
||||
audio audio_ctrl(.AUDC0(audc0),
|
||||
.AUDC1(audc1),
|
||||
.AUDF0(audf0),
|
||||
.AUDF1(audf1),
|
||||
.CLK_30(clk_30), //30khz clock
|
||||
.AUD0(AUD0),
|
||||
.AUD1(AUD1));
|
||||
|
||||
assign pixelNum = (hCount >= 8'd68) ? (hCount - 8'd68) : 8'd227;
|
||||
|
||||
// Pixel tests. For each pixel and screen object, a test is done based on the
|
||||
// screen objects register to determine if the screen object should show on that
|
||||
// pixel. The results of all the tests are fed into logic to pick which displayed
|
||||
// object has priority and color the pixel the color of that object.
|
||||
// Playfield pixel test
|
||||
wire [5:0] pfPixelNum;
|
||||
wire pfPixelOn, pfLeftPixelVal, pfRightPixelVal;
|
||||
assign pfPixelNum = pixelNum[7:2];
|
||||
assign pfLeftPixelVal = pfGraphic[pfPixelNum];
|
||||
assign pfRightPixelVal = (pfReflect == 1'b0)? pfGraphic[pfPixelNum - 6'd20]:
|
||||
pfGraphic[6'd39 - pfPixelNum];
|
||||
assign pfPixelOn = (pfPixelNum < 6'd20)? pfLeftPixelVal : pfRightPixelVal;
|
||||
// Player 0 sprite pixel test
|
||||
wire pl0PixelOn;
|
||||
wire [7:0] pl0Mask, pl0MaskDel;
|
||||
assign pl0MaskDel = (player0VertDelay)? R_player0Graphic : player0Graphic;
|
||||
assign pl0Mask = (!player0Reflect)? pl0MaskDel : {pl0MaskDel[0], pl0MaskDel[1],
|
||||
pl0MaskDel[2], pl0MaskDel[3],
|
||||
pl0MaskDel[4], pl0MaskDel[5],
|
||||
pl0MaskDel[6], pl0MaskDel[7]};
|
||||
objPixelOn player0_test(pixelNum, player0Pos, player0Size[2:0], pl0Mask, pl0PixelOn);
|
||||
// Player 1 sprite pixel test
|
||||
wire pl1PixelOn;
|
||||
wire [7:0] pl1Mask, pl1MaskDel;
|
||||
assign pl1MaskDel = (player1VertDelay)? R_player1Graphic : player1Graphic;
|
||||
assign pl1Mask = (!player1Reflect)? pl1MaskDel : {pl1MaskDel[0], pl1MaskDel[1],
|
||||
pl1MaskDel[2], pl1MaskDel[3],
|
||||
pl1MaskDel[4], pl1MaskDel[5],
|
||||
pl1MaskDel[6], pl1MaskDel[7]};
|
||||
objPixelOn player1_test(pixelNum, player1Pos, player1Size[2:0], pl1Mask, pl1PixelOn);
|
||||
// Missile 0 pixel test
|
||||
wire mis0PixelOn, mis0PixelOut;
|
||||
wire [7:0] mis0ActualPos;
|
||||
reg [7:0] mis0Mask;
|
||||
always @(player0Size)
|
||||
begin
|
||||
case(player0Size[4:3])
|
||||
2'd0: mis0Mask <= 8'h01;
|
||||
2'd1: mis0Mask <= 8'h03;
|
||||
2'd2: mis0Mask <= 8'h0F;
|
||||
2'd3: mis0Mask <= 8'hFF;
|
||||
endcase
|
||||
end
|
||||
assign mis0ActualPos = (missile0Lock)? player0Pos : missile0Pos;
|
||||
objPixelOn missile0_test(pixelNum, mis0ActualPos, player0Size[2:0], mis0Mask, mis0PixelOut);
|
||||
assign mis0PixelOn = mis0PixelOut && missile0Enable;
|
||||
// Missile 1 pixel test
|
||||
wire mis1PixelOn, mis1PixelOut;
|
||||
wire [7:0] mis1ActualPos;
|
||||
reg [7:0] mis1Mask;
|
||||
always @(player1Size)
|
||||
begin
|
||||
case(player1Size[4:3])
|
||||
2'd0: mis1Mask <= 8'h01;
|
||||
2'd1: mis1Mask <= 8'h03;
|
||||
2'd2: mis1Mask <= 8'h0F;
|
||||
2'd3: mis1Mask <= 8'hFF;
|
||||
endcase
|
||||
end
|
||||
assign mis1ActualPos = (missile1Lock)? player1Pos : missile1Pos;
|
||||
objPixelOn missile1_test(pixelNum, mis1ActualPos, player1Size[2:0], mis1Mask, mis1PixelOut);
|
||||
assign mis1PixelOn = mis1PixelOut && missile1Enable;
|
||||
// Ball pixel test
|
||||
wire ballPixelOut, ballPixelOn, ballEnableDel;
|
||||
reg [7:0] ballMask;
|
||||
always @(ballSize)
|
||||
begin
|
||||
case(ballSize)
|
||||
2'd0: ballMask <= 8'h01;
|
||||
2'd1: ballMask <= 8'h03;
|
||||
2'd2: ballMask <= 8'h0F;
|
||||
2'd3: ballMask <= 8'hFF;
|
||||
endcase
|
||||
end
|
||||
objPixelOn ball_test(pixelNum, ballPos, 3'd0, ballMask, ballPixelOut);
|
||||
assign ballEnableDel = ((ballVertDelay)? R_ballEnable : ballEnable);
|
||||
assign ballPixelOn = ballPixelOut && ballEnableDel;
|
||||
// Playfield color selection
|
||||
// The programmer can select a unique color for the playfield or have it match
|
||||
// the player's sprites colors
|
||||
reg [7:0] pfActualColor;
|
||||
always @(pfColorCtrl, pfColor, player0Color, player1Color, pfPixelNum)
|
||||
begin
|
||||
if (pfColorCtrl)
|
||||
begin
|
||||
if (pfPixelNum < 6'd20)
|
||||
pfActualColor <= player0Color;
|
||||
else
|
||||
pfActualColor <= player1Color;
|
||||
end
|
||||
else
|
||||
pfActualColor <= pfColor;
|
||||
end
|
||||
// Final pixel color selection
|
||||
reg [7:0] pixelColor;
|
||||
assign COLOROUT = (HBLANK)? 8'b0 : pixelColor;
|
||||
// This combinational logic uses a priority encoder like structure to select
|
||||
// the highest priority screen object and color the pixel.
|
||||
always @(prioCtrl, pfPixelOn, pl0PixelOn, pl1PixelOn, mis0PixelOn, mis1PixelOn,
|
||||
ballPixelOn, pfActualColor, player0Color, player1Color, bgColor)
|
||||
begin
|
||||
// Show the playfield behind the players
|
||||
if (!prioCtrl)
|
||||
begin
|
||||
if (pl0PixelOn || mis0PixelOn)
|
||||
pixelColor <= player0Color;
|
||||
else if (pl1PixelOn || mis1PixelOn)
|
||||
pixelColor <= player1Color;
|
||||
else if (pfPixelOn)
|
||||
pixelColor <= pfActualColor;
|
||||
else
|
||||
pixelColor <= bgColor;
|
||||
end
|
||||
// Otherwise, show the playfield in front of the players
|
||||
else begin
|
||||
if (pfPixelOn)
|
||||
pixelColor <= pfActualColor;
|
||||
else if (pl0PixelOn || mis0PixelOn)
|
||||
pixelColor <= player0Color;
|
||||
else if (pl1PixelOn || mis1PixelOn)
|
||||
pixelColor <= player1Color;
|
||||
else
|
||||
pixelColor <= bgColor;
|
||||
end
|
||||
end
|
||||
// Collision register and latching update
|
||||
wire [14:0] collisions;
|
||||
reg collisionLatchReset;
|
||||
assign collisions = {pl0PixelOn && pl1PixelOn, mis0PixelOn && mis1PixelOn,
|
||||
ballPixelOn && pfPixelOn,
|
||||
mis1PixelOn && pfPixelOn, mis1PixelOn && ballPixelOn,
|
||||
mis0PixelOn && pfPixelOn, mis0PixelOn && ballPixelOn,
|
||||
pl1PixelOn && pfPixelOn, pl1PixelOn && ballPixelOn,
|
||||
pl0PixelOn && pfPixelOn, pl0PixelOn && ballPixelOn,
|
||||
mis1PixelOn && pl0PixelOn, mis1PixelOn && pl1PixelOn,
|
||||
mis0PixelOn && pl1PixelOn, mis0PixelOn && pl0PixelOn};
|
||||
always @(posedge MASTERCLK, posedge collisionLatchReset)
|
||||
begin
|
||||
if (collisionLatchReset)
|
||||
collisionLatch <= 15'b000000000000000;
|
||||
else
|
||||
collisionLatch <= collisionLatch | collisions;
|
||||
end
|
||||
// WSYNC logic
|
||||
// When a WSYNC is signalled by the programmer, the CPU ready line is lowered
|
||||
// until the end of a scanline
|
||||
reg wSync, wSyncReset;
|
||||
always @(hCount, wSyncReset)
|
||||
begin
|
||||
if (hCount == 8'd0)
|
||||
wSync <= 1'b0;
|
||||
else if (wSyncReset && hCount > 8'd2)
|
||||
wSync <= 1'b1;
|
||||
end
|
||||
assign RDY = ~wSync;
|
||||
// Latched input registers and update
|
||||
wire [1:0] latchedInputsValue;
|
||||
reg inputLatchEnabled;
|
||||
reg inputLatchReset;
|
||||
reg [1:0] latchedInputs;
|
||||
|
||||
/*always_ff @(Ilatch, inputLatchReset)
|
||||
begin
|
||||
if (inputLatchReset)
|
||||
latchedInputs <= 2'b11;
|
||||
else
|
||||
latchedInputs <= latchedInputs & Ilatch;
|
||||
end*/
|
||||
|
||||
assign latchedInputsValue = (inputLatchEnabled)? latchedInputs : Ilatch;
|
||||
// Dumped input registers update
|
||||
reg inputDumpEnabled;
|
||||
assign Idump = (inputDumpEnabled)? 4'b0000 : idump_in;
|
||||
// Software operations
|
||||
always @(posedge CLK2)
|
||||
begin
|
||||
// Reset operation
|
||||
if (~RES_n) begin
|
||||
inputLatchReset <= 1'b0;
|
||||
collisionLatchReset <= 1'b0;
|
||||
hCountReset[0] <= 1'b0;
|
||||
wSyncReset <= 1'b0;
|
||||
Dout <= 8'b00000000;
|
||||
end
|
||||
// If the chip is enabled, execute an operation
|
||||
else if (CS) begin
|
||||
// Software reset signals
|
||||
inputLatchReset <= ({R_W_n, A[5:0]} == `VBLANK && Din[6] && !inputLatchEnabled);
|
||||
collisionLatchReset <= ({R_W_n, A[5:0]} == `CXCLR);
|
||||
hCountReset[0] <= ({R_W_n, A[5:0]} == `RSYNC);
|
||||
wSyncReset <= ({R_W_n, A[5:0]} == `WSYNC) && !wSync;
|
||||
case({R_W_n, A[5:0]})
|
||||
// Collision latch reads
|
||||
`CXM0P, `CXM0P_7800: Dout <= {collisionLatch[1:0],6'b000000};
|
||||
`CXM1P, `CXM1P_7800: Dout <= {collisionLatch[3:2],6'b000000};
|
||||
`CXP0FB, `CXP0FB_7800: Dout <= {collisionLatch[5:4],6'b000000};
|
||||
`CXP1FB, `CXP1FB_7800: Dout <= {collisionLatch[7:6],6'b000000};
|
||||
`CXM0FB, `CXM0FB_7800: Dout <= {collisionLatch[9:8],6'b000000};
|
||||
`CXM1FB, `CXM1FB_7800: Dout <= {collisionLatch[11:10],6'b000000};
|
||||
`CXBLPF, `CXBLPF_7800: Dout <= {collisionLatch[12],7'b0000000};
|
||||
`CXPPMM, `CXPPMM_7800: Dout <= {collisionLatch[14:13],6'b000000};
|
||||
// I/O reads
|
||||
`INPT0, `INPT0_7800: Dout <= {Idump[0], 7'b0000000};
|
||||
`INPT1, `INPT1_7800: Dout <= {Idump[1], 7'b0000000};
|
||||
`INPT2, `INPT2_7800: Dout <= {Idump[2], 7'b0000000};
|
||||
`INPT3, `INPT3_7800: Dout <= {Idump[3], 7'b0000000};
|
||||
`INPT4, `INPT4_7800: Dout <= {latchedInputsValue[0], 7'b0000000};
|
||||
`INPT5, `INPT5_7800: Dout <= {latchedInputsValue[1], 7'b0000000};
|
||||
// Video signals
|
||||
`VSYNC: VSYNC <= Din[1];
|
||||
`VBLANK: begin
|
||||
inputLatchEnabled <= Din[6];
|
||||
inputDumpEnabled <= Din[7];
|
||||
VBLANK <= Din[1];
|
||||
end
|
||||
`WSYNC:;
|
||||
`RSYNC:;
|
||||
// Screen object register access
|
||||
`NUSIZ0: player0Size <= {Din[5:4],Din[2:0]};
|
||||
`NUSIZ1: player1Size <= {Din[5:4],Din[2:0]};
|
||||
`COLUP0: player0Color <= Din;
|
||||
`COLUP1: player1Color <= Din;
|
||||
`COLUPF: pfColor <= Din;
|
||||
`COLUBK: bgColor <= Din;
|
||||
`CTRLPF: begin
|
||||
pfReflect <= Din[0];
|
||||
pfColorCtrl <= Din[1];
|
||||
prioCtrl <= Din[2];
|
||||
ballSize <= Din[5:4];
|
||||
end
|
||||
`REFP0: player0Reflect <= Din[3];
|
||||
`REFP1: player1Reflect <= Din[3];
|
||||
`PF0: pfGraphic[3:0] <= Din[7:4];
|
||||
`PF1: pfGraphic[11:4] <= {Din[0], Din[1], Din[2], Din[3],
|
||||
Din[4], Din[5], Din[6], Din[7]};
|
||||
`PF2: pfGraphic[19:12] <= Din[7:0];
|
||||
`RESP0: player0Pos <= pixelNum;
|
||||
`RESP1: player1Pos <= pixelNum;
|
||||
`RESM0: missile0Pos <= pixelNum;
|
||||
`RESM1: missile1Pos <= pixelNum;
|
||||
`RESBL: ballPos <= pixelNum;
|
||||
// Audio controls
|
||||
`AUDC0: audc0 <= Din[3:0];
|
||||
`AUDC1: audc1 <= Din[3:0];
|
||||
`AUDF0: audf0 <= Din[4:0];
|
||||
`AUDF1: audf1 <= Din[4:0];
|
||||
`AUDV0: audv0 <= Din[3:0];
|
||||
`AUDV1: audv1 <= Din[3:0];
|
||||
// Screen object register access
|
||||
`GRP0: begin
|
||||
player0Graphic <= {Din[0], Din[1], Din[2], Din[3],
|
||||
Din[4], Din[5], Din[6], Din[7]};
|
||||
R_player1Graphic <= player1Graphic;
|
||||
end
|
||||
`GRP1: begin
|
||||
player1Graphic <= {Din[0], Din[1], Din[2], Din[3],
|
||||
Din[4], Din[5], Din[6], Din[7]};
|
||||
R_player0Graphic <= player0Graphic;
|
||||
R_ballEnable <= ballEnable;
|
||||
end
|
||||
`ENAM0: missile0Enable <= Din[1];
|
||||
`ENAM1: missile1Enable <= Din[1];
|
||||
`ENABL: ballEnable <= Din[1];
|
||||
`HMP0: player0Motion <= Din[7:4];
|
||||
`HMP1: player1Motion <= Din[7:4];
|
||||
`HMM0: missile0Motion <= Din[7:4];
|
||||
`HMM1: missile1Motion <= Din[7:4];
|
||||
`HMBL: ballMotion <= Din[7:4];
|
||||
`VDELP0: player0VertDelay <= Din[0];
|
||||
`VDELP1: player1VertDelay <= Din[0];
|
||||
`VDELBL: ballVertDelay <= Din[0];
|
||||
`RESMP0: missile0Lock <= Din[1];
|
||||
`RESMP1: missile1Lock <= Din[1];
|
||||
// Strobed line that initiates an object move
|
||||
`HMOVE: begin
|
||||
player0Pos <= player0Pos - {{4{player0Motion[3]}},
|
||||
player0Motion[3:0]};
|
||||
player1Pos <= player1Pos - {{4{player1Motion[3]}},
|
||||
player1Motion[3:0]};
|
||||
missile0Pos <= missile0Pos - {{4{missile0Motion[3]}},
|
||||
missile0Motion[3:0]};
|
||||
missile1Pos <= missile1Pos - {{4{missile1Motion[3]}},
|
||||
missile1Motion[3:0]};
|
||||
ballPos <= ballPos - {{4{ballMotion[3]}},ballMotion[3:0]};
|
||||
end
|
||||
// Motion register clear
|
||||
`HMCLR: begin
|
||||
player0Motion <= Din[7:4];
|
||||
player1Motion <= Din[7:4];
|
||||
missile0Motion <= Din[7:4];
|
||||
missile1Motion <= Din[7:4];
|
||||
ballMotion <= Din[7:4];
|
||||
end
|
||||
`CXCLR:;
|
||||
default: Dout <= 8'b00000000;
|
||||
endcase
|
||||
end
|
||||
// If the chip is not enabled, do nothing
|
||||
else begin
|
||||
inputLatchReset <= 1'b0;
|
||||
collisionLatchReset <= 1'b0;
|
||||
hCountReset[0] <= 1'b0;
|
||||
wSyncReset <= 1'b0;
|
||||
Dout <= 8'b00000000;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
// objPixelOn module
|
||||
// Checks the pixel number against a stretched and possibly duplicated version of the
|
||||
// object.
|
||||
module objPixelOn(pixelNum, objPos, objSize, objMask, pixelOn);
|
||||
input [7:0] pixelNum, objPos, objMask;
|
||||
input [2:0] objSize;
|
||||
output pixelOn;
|
||||
wire [7:0] objIndex;
|
||||
wire [8:0] objByteIndex;
|
||||
wire objMaskOn, objPosOn;
|
||||
reg objSizeOn;
|
||||
reg [2:0] objMaskSel;
|
||||
assign objIndex = pixelNum - objPos - 8'd1;
|
||||
assign objByteIndex = 9'b1 << (objIndex[7:3]);
|
||||
always @(objSize, objByteIndex)
|
||||
begin
|
||||
case (objSize)
|
||||
3'd0: objSizeOn <= (objByteIndex & 9'b00000001) != 0;
|
||||
3'd1: objSizeOn <= (objByteIndex & 9'b00000101) != 0;
|
||||
3'd2: objSizeOn <= (objByteIndex & 9'b00010001) != 0;
|
||||
3'd3: objSizeOn <= (objByteIndex & 9'b00010101) != 0;
|
||||
3'd4: objSizeOn <= (objByteIndex & 9'b10000001) != 0;
|
||||
3'd5: objSizeOn <= (objByteIndex & 9'b00000011) != 0;
|
||||
3'd6: objSizeOn <= (objByteIndex & 9'b10010001) != 0;
|
||||
3'd7: objSizeOn <= (objByteIndex & 9'b00001111) != 0;
|
||||
endcase
|
||||
end
|
||||
always @(objSize, objIndex)
|
||||
begin
|
||||
case (objSize)
|
||||
3'd5: objMaskSel <= objIndex[3:1];
|
||||
3'd7: objMaskSel <= objIndex[4:2];
|
||||
default: objMaskSel <= objIndex[2:0];
|
||||
endcase
|
||||
end
|
||||
assign objMaskOn = objMask[objMaskSel];
|
||||
assign objPosOn = (pixelNum > objPos) && ({1'b0, pixelNum} <= {1'b0, objPos} + 9'd72);
|
||||
assign pixelOn = objSizeOn && objMaskOn && objPosOn;
|
||||
endmodule
|
||||
11
Atari - 7800_TeST/rtl/atari7800.vh
Normal file
11
Atari - 7800_TeST/rtl/atari7800.vh
Normal file
@@ -0,0 +1,11 @@
|
||||
`define CS_NONE 'h0
|
||||
`define CS_RAM0 'h1
|
||||
`define CS_RAM1 'h2
|
||||
`define CS_RIOT_IO 'h3
|
||||
`define CS_RIOT_RAM 'h4
|
||||
`define CS_TIA 'h5
|
||||
`define CS_BIOS 'h6
|
||||
`define CS_MARIA 'h7
|
||||
`define CS_CART 'h8
|
||||
|
||||
`define chipselect logic[3:0]
|
||||
93
Atari - 7800_TeST/rtl/audio.sv
Normal file
93
Atari - 7800_TeST/rtl/audio.sv
Normal file
@@ -0,0 +1,93 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module audio(input logic [3:0] AUDC0, AUDC1,
|
||||
input logic [4:0] AUDF0, AUDF1,
|
||||
input logic CLK_30, //30khz clock
|
||||
output logic AUD0,AUD1
|
||||
);
|
||||
|
||||
logic [4:0] counter0, counter1 = 5'b0;
|
||||
integer rep0,rep1,ind0,ind1 = 0;
|
||||
logic [1:0] pattern45 = 2'b10;
|
||||
logic pattern0b = 1'b1;
|
||||
logic [14:0] pattern1 = 15'b111100010011010;
|
||||
logic [30:0] pattern6a = 31'b1111111111111111110000000000000;
|
||||
logic [30:0] pattern79 = 31'b1111100011011101010000100101100;
|
||||
logic [5:0] patterncd = 6'b111000;
|
||||
logic [92:0] patterne = 93'b111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000;
|
||||
logic [92:0] patternf = 93'b111111111100000111000000011110000000000111111000111111000011111111100000011111000000111100000;
|
||||
logic [464:0] pattern2 = 465'b111111111111111111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000111111111111100000000000000000000000000000001111111111111111111111111111111000000000000000000111111111111100000000000000000011111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000001111111111111111110000000000000000000000000000000111111111111111111111111111111100000000000001111111111111111110000000000000;
|
||||
logic [464:0] pattern3 = 465'b111111000000100011100111110001111111000111100011001100000111111111000100000111011001111111111100000100000111010011111111111100000100111110010111111111111000000100111110110111111111100000011100110000100111111000000000010000110111101111110000000000110000110100001111100000000011100011110101111111100000111110000011110101111111100001100000000111000101111111000011000000011111011101111111000010000111111110010001111000000010001111111000110111111000000110011110000011100;
|
||||
logic [510:0] pattern8 = 511'b1111111110000011110111110001011100110010000010010100111011010001111001111100110110001010100100011100011011010101110001001100010001000000001000010001100001001110010101011000011011110100110111001000101000010101101001111110110010010010110111111001001101010011001100000001100011001010001101001011111110100010110001110101100101100111100011111011101000001101011011011101100000101101011111010101010000001010010101111001011101110000001110011101001001111010111010100010010000110011100001011110110110011010000111011110000;
|
||||
|
||||
always_comb begin
|
||||
case (AUDC0)
|
||||
4'h0,4'hb: rep0 = 1;
|
||||
4'h1: rep0 = 15;
|
||||
4'h2,4'h3: rep0 = 465;
|
||||
4'h4,4'h5: rep0 = 2;
|
||||
4'h6,4'h7,4'h9,4'ha: rep0 = 31;
|
||||
4'h8: rep0 = 511;
|
||||
4'hc,4'hd: rep0 = 6;
|
||||
4'he,4'hf: rep0 = 93;
|
||||
default: rep0 = 1;
|
||||
endcase
|
||||
case (AUDC1)
|
||||
4'h0,4'hb: rep1 = 1;
|
||||
4'h1: rep1 = 15;
|
||||
4'h2,4'h3: rep1 = 465;
|
||||
4'h4,4'h5: rep1 = 2;
|
||||
4'h6,4'h7,4'h9,4'ha: rep1 = 31;
|
||||
4'h8: rep1 = 511;
|
||||
4'hc,4'hd: rep1 = 6;
|
||||
4'he,4'hf: rep1 = 93;
|
||||
default: rep0 = 1;
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge CLK_30) begin //divide the clk by the frequency value
|
||||
if (counter0 == AUDF0) begin
|
||||
case (AUDC0)
|
||||
4'h0,4'hb: AUD0 <= pattern0b;
|
||||
4'h1: AUD0 <= pattern1[ind0];
|
||||
4'h2: AUD0 <= pattern2[ind0];
|
||||
4'h3: AUD0 <= pattern3[ind0];
|
||||
4'h4,4'h5: AUD0 <= pattern45[ind0];
|
||||
4'h6,4'ha: AUD0 <= pattern6a[ind0];
|
||||
4'h7,4'h9: AUD0 <= pattern79[ind0];
|
||||
4'h8: AUD0 <= pattern8[ind0];
|
||||
4'hc,4'hd: AUD0 <= patterncd[ind0];
|
||||
4'he: AUD0 <= patterne[ind0];
|
||||
4'hf: AUD0 <= patternf[ind0];
|
||||
default: AUD0 <= 1'bx;
|
||||
endcase
|
||||
ind0 <= (ind0 + 1) % rep0;
|
||||
counter0 <= 0;
|
||||
end
|
||||
else
|
||||
counter0 <= counter0 + 1;
|
||||
|
||||
if (counter1 == AUDF1) begin
|
||||
case (AUDC1)
|
||||
4'h0,4'hb: AUD1 <= pattern0b;
|
||||
4'h1: AUD1 <= pattern1[ind1];
|
||||
4'h2: AUD1 <= pattern2[ind1];
|
||||
4'h3: AUD1 <= pattern3[ind1];
|
||||
4'h4,4'h5: AUD1 <= pattern45[ind1];
|
||||
4'h6,4'ha: AUD1 <= pattern6a[ind1];
|
||||
4'h7,4'h9: AUD1 <= pattern79[ind1];
|
||||
4'h8: AUD1 <= pattern8[ind1];
|
||||
4'hc,4'hd: AUD1 <= patterncd[ind1];
|
||||
4'he: AUD1 <= patterne[ind1];
|
||||
4'hf: AUD1 <= patternf[ind1];
|
||||
default: AUD1 <= 1'bx;
|
||||
endcase
|
||||
ind1 <= (ind1 + 1) % rep1;
|
||||
counter1 <= 0;
|
||||
end
|
||||
else
|
||||
counter1 <= counter1 + 1;
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
24
Atari - 7800_TeST/rtl/audio_xformer.sv
Normal file
24
Atari - 7800_TeST/rtl/audio_xformer.sv
Normal file
@@ -0,0 +1,24 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module audio_xformer(input logic AUD0, AUD1,
|
||||
input logic [3:0] AUDV0, AUDV1,
|
||||
output logic [15:0] AUD_SIGNAL);
|
||||
|
||||
logic [15:0] audio0,audio1;
|
||||
|
||||
|
||||
assign AUD_SIGNAL = audio0 + audio1;
|
||||
|
||||
always_comb begin
|
||||
case (AUD0)
|
||||
1: audio0 = 16'h3FF * AUDV0;
|
||||
0: audio0 = 16'hFC00 * AUDV0;
|
||||
endcase
|
||||
case (AUD1)
|
||||
1: audio1 = 16'h3FF * AUDV1;
|
||||
0: audio1 = 16'hFC00 * AUDV1;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
35
Atari - 7800_TeST/rtl/build_id.tcl
Normal file
35
Atari - 7800_TeST/rtl/build_id.tcl
Normal 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
|
||||
2
Atari - 7800_TeST/rtl/build_id.v
Normal file
2
Atari - 7800_TeST/rtl/build_id.v
Normal file
@@ -0,0 +1,2 @@
|
||||
`define BUILD_DATE "180630"
|
||||
`define BUILD_TIME "212824"
|
||||
257
Atari - 7800_TeST/rtl/cart_top.sv
Normal file
257
Atari - 7800_TeST/rtl/cart_top.sv
Normal file
@@ -0,0 +1,257 @@
|
||||
`timescale 1ns / 1ps
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Company:
|
||||
// Engineer:
|
||||
//
|
||||
// Create Date: 11/02/2015 11:36:06 AM
|
||||
// Design Name:
|
||||
// Module Name: cart_top
|
||||
// Project Name:
|
||||
// Target Devices:
|
||||
// Tool Versions:
|
||||
// Description:
|
||||
//
|
||||
// Dependencies:
|
||||
//
|
||||
// Revision:
|
||||
// Revision 0.01 - File Created
|
||||
// Additional Comments:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "atari7800.vh"
|
||||
|
||||
`define INPUT_CYCLES 256
|
||||
`define INPUT_CYCLES_NBITS 9
|
||||
|
||||
module cart_top(
|
||||
input CLOCK_27,
|
||||
output [5:0] VGA_R,
|
||||
output [5:0] VGA_G,
|
||||
output [5:0] VGA_B,
|
||||
output VGA_HS,
|
||||
output VGA_VS,
|
||||
output LED,
|
||||
output AUDIO_L,
|
||||
output AUDIO_R,
|
||||
// output UART_TX,//uses for Tape Record
|
||||
// input UART_RX,//uses for Tape Play
|
||||
input SPI_SCK,
|
||||
output SPI_DO,
|
||||
input SPI_DI,
|
||||
input SPI_SS2,
|
||||
input SPI_SS3,
|
||||
input SPI_SS4,
|
||||
input CONF_DATA0,
|
||||
|
||||
output logic [7:0] ld,
|
||||
|
||||
input logic [7:0] sw,
|
||||
input logic PB_UP,PB_DOWN,PB_LEFT,PB_RIGHT,PB_CENTER,
|
||||
|
||||
|
||||
inout logic [6:0] ctrl_0_fmc, ctrl_1_fmc
|
||||
);
|
||||
|
||||
`include "rtl\build_id.v"
|
||||
assign LED = 1;
|
||||
localparam CONF_STR = {
|
||||
"ATARI7800;;",
|
||||
"O34,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;",
|
||||
"T6,Reset;",
|
||||
"V,v0.0.",`BUILD_DATE
|
||||
};
|
||||
|
||||
|
||||
|
||||
wire clk25, clk7p143, clk6p25;
|
||||
wire locked;
|
||||
|
||||
pll pll (
|
||||
.inclk0(CLOCK_27),
|
||||
.c0(clk25),
|
||||
.c1(clk7p143),
|
||||
.c2(clk6p25),
|
||||
.locked(locked)
|
||||
);
|
||||
wire scandoubler_disable;
|
||||
wire ypbpr;
|
||||
wire ps2_kbd_clk, ps2_kbd_data;
|
||||
wire [31:0] status;
|
||||
wire [1:0] buttons;
|
||||
wire [1:0] switches;
|
||||
wire [3:0] r, g, b;
|
||||
wire hs, vs, hb, vb;
|
||||
wire blankn = ~(hb | vb);
|
||||
|
||||
|
||||
logic [7:0] cart_data_out;
|
||||
logic [15:0] AB;
|
||||
logic RW;
|
||||
logic pclk_0;
|
||||
reg [`INPUT_CYCLES_NBITS-1:0] paddleA0_ctr = {`INPUT_CYCLES_NBITS{1'b0}};
|
||||
reg [`INPUT_CYCLES_NBITS-1:0] paddleB0_ctr = {`INPUT_CYCLES_NBITS{1'b0}};
|
||||
reg [`INPUT_CYCLES_NBITS-1:0] paddleA1_ctr = {`INPUT_CYCLES_NBITS{1'b0}};
|
||||
reg [`INPUT_CYCLES_NBITS-1:0] paddleB1_ctr = {`INPUT_CYCLES_NBITS{1'b0}};
|
||||
|
||||
always_ff @(posedge pclk_0) begin
|
||||
if (~ctrl_0_fmc[6])
|
||||
paddleA0_ctr <= 0;
|
||||
else if (paddleA0_ctr < `INPUT_CYCLES)
|
||||
paddleA0_ctr <= paddleA0_ctr + 1;
|
||||
|
||||
if (~ctrl_0_fmc[4])
|
||||
paddleB0_ctr <= 0;
|
||||
else if (paddleB0_ctr < `INPUT_CYCLES)
|
||||
paddleB0_ctr <= paddleB0_ctr + 1;
|
||||
|
||||
if (~ctrl_1_fmc[6])
|
||||
paddleA1_ctr <= 0;
|
||||
else if (paddleA1_ctr < `INPUT_CYCLES)
|
||||
paddleA1_ctr <= paddleA1_ctr + 1;
|
||||
|
||||
if (~ctrl_1_fmc[4])
|
||||
paddleB1_ctr <= 0;
|
||||
else if (paddleB1_ctr < `INPUT_CYCLES)
|
||||
paddleB1_ctr <= paddleB1_ctr + 1;
|
||||
end
|
||||
|
||||
|
||||
logic [3:0] idump;
|
||||
logic [1:0] ilatch;
|
||||
logic [7:0] PAin, PBin, PAout, PBout;
|
||||
logic [15:0] audio;
|
||||
|
||||
|
||||
logic right_0_b, left_0_b, down_0_b, up_0_b, fire_0_b, paddle_A_0, paddle_B_0;
|
||||
logic right_1_b, left_1_b, down_1_b, up_1_b, fire_1_b, paddle_A_1, paddle_B_1;
|
||||
logic player1_2bmode, player2_2bmode;
|
||||
|
||||
assign player1_2bmode = ~PBout[2] & ~tia_en;
|
||||
assign player2_2bmode = ~PBout[4] & ~tia_en;
|
||||
|
||||
assign {right_0_b, left_0_b, down_0_b, up_0_b} = ctrl_0_fmc[3:0];
|
||||
assign {right_1_b, left_1_b, down_1_b, up_1_b} = ctrl_1_fmc[3:0];
|
||||
|
||||
assign paddle_B_0 = paddleB0_ctr == `INPUT_CYCLES;
|
||||
assign paddle_B_1 = paddleB1_ctr == `INPUT_CYCLES;
|
||||
assign paddle_A_0 = paddleA0_ctr == `INPUT_CYCLES;
|
||||
assign paddle_A_1 = paddleA1_ctr == `INPUT_CYCLES;
|
||||
|
||||
assign fire_0_b = (~paddle_A_0 & ~paddle_B_0);
|
||||
assign fire_1_b = (~paddle_A_1 & ~paddle_B_1);
|
||||
logic tia_en;
|
||||
|
||||
assign PAin[7:4] = {right_0_b, left_0_b, down_0_b, up_0_b};
|
||||
assign PAin[3:0] = {right_1_b, left_1_b, down_1_b, up_1_b};
|
||||
|
||||
assign PBin[7] = sw[1]; // RDiff
|
||||
assign PBin[6] = sw[0]; // LDiff
|
||||
assign PBin[5] = 1'b0; // Unused
|
||||
assign PBin[4] = 1'b0;
|
||||
assign PBin[3] = ~PB_DOWN; // Pause
|
||||
assign PBin[2] = 1'b0; // 2 Button mode
|
||||
assign PBin[1] = ~PB_LEFT; // Select
|
||||
assign PBin[0] = ~PB_UP; // Reset
|
||||
|
||||
|
||||
assign ilatch[0] = fire_0_b;
|
||||
assign ilatch[1] = fire_1_b;
|
||||
|
||||
assign idump = {paddle_A_0, paddle_B_0, paddle_A_1, paddle_B_1};
|
||||
|
||||
logic [7:0] def_dout;
|
||||
assign cart_data_out = def_dout;
|
||||
|
||||
defender_rom defender_rom (
|
||||
.clock(pclk_0),
|
||||
.address(AB[11:0]),
|
||||
.q(def_dout)
|
||||
);
|
||||
|
||||
Atari7800 console(
|
||||
.clock_25(clk25),
|
||||
.sysclk_7_143(clk7p143),
|
||||
.clock_divider_locked(locked),
|
||||
.reset((buttons[1] || status[0] || status[6])),
|
||||
.RED(r),
|
||||
.GREEN(g),
|
||||
.BLUE(b),
|
||||
.HSync(hs),
|
||||
.VSync(vs),
|
||||
.aud_signal_out(audio),
|
||||
|
||||
.cart_DB_out(cart_data_out),
|
||||
.AB(AB),
|
||||
.RW(RW),
|
||||
.pclk_0(pclk_0),
|
||||
.ld(ld),
|
||||
.tia_en(tia_en),
|
||||
|
||||
.idump(idump),
|
||||
.ilatch(ilatch),
|
||||
.PAin(PAin),
|
||||
.PBin(PBin),
|
||||
.PAout(PAout),
|
||||
.PBout(PBout)
|
||||
);
|
||||
|
||||
sigma_delta_dac #(.MSBI(15)) sigma_delta_dac (
|
||||
.DACout(AUDIO_L),
|
||||
.DACin(audio),
|
||||
.CLK(clk25),
|
||||
.RESET()
|
||||
);
|
||||
|
||||
mist_io #(.STRLEN(($size(CONF_STR)>>3))) mist_io
|
||||
(
|
||||
.conf_str(CONF_STR),
|
||||
.clk_sys(clk25),
|
||||
.SPI_SCK(SPI_SCK),
|
||||
.CONF_DATA0(CONF_DATA0),
|
||||
.SPI_SS2(SPI_SS2),
|
||||
.SPI_DO(SPI_DO),
|
||||
.SPI_DI(SPI_DI),
|
||||
.buttons(buttons),
|
||||
.switches(switches),
|
||||
.scandoubler_disable(scandoubler_disable),
|
||||
.ypbpr(ypbpr),
|
||||
.status(status),
|
||||
.ps2_kbd_clk(ps2_kbd_clk),
|
||||
.ps2_kbd_data(ps2_kbd_data)
|
||||
);
|
||||
|
||||
video_mixer #(.LINE_LENGTH(480), .HALF_DEPTH(0)) video_mixer
|
||||
(
|
||||
.clk_sys(clk25),
|
||||
.ce_pix(clk6p25),
|
||||
.ce_pix_actual(clk6p25),
|
||||
.SPI_SCK(SPI_SCK),
|
||||
.SPI_SS3(SPI_SS3),
|
||||
.SPI_DI(SPI_DI),
|
||||
.scanlines(scandoubler_disable ? 2'b00 : {status[4:3] == 3, status[4:3] == 2}),
|
||||
.scandoubler_disable(1),//scandoubler_disable),
|
||||
.hq2x(status[4:3]==1),
|
||||
.ypbpr(ypbpr),
|
||||
.ypbpr_full(1),
|
||||
.R({r,r[1:0]}),
|
||||
.G({g,g[1:0]}),
|
||||
.B({b,b[1:0]}),
|
||||
// .R(blankn ? {r,r[1:0]} : "000000"),
|
||||
// .G(blankn ? {g,g[1:0]} : "000000"),
|
||||
// .B(blankn ? {b,b[1:0]} : "000000"),
|
||||
.mono(0),
|
||||
.HSync(hs),
|
||||
.VSync(vs),
|
||||
.line_start(0),
|
||||
.VGA_R(VGA_R),
|
||||
.VGA_G(VGA_G),
|
||||
.VGA_B(VGA_B),
|
||||
.VGA_VS(VGA_VS),
|
||||
.VGA_HS(VGA_HS)
|
||||
);
|
||||
|
||||
|
||||
assign AUDIO_R = AUDIO_L;
|
||||
|
||||
endmodule
|
||||
1250
Atari - 7800_TeST/rtl/cpu.sv
Normal file
1250
Atari - 7800_TeST/rtl/cpu.sv
Normal file
File diff suppressed because it is too large
Load Diff
65
Atari - 7800_TeST/rtl/cpu_wrapper.sv
Normal file
65
Atari - 7800_TeST/rtl/cpu_wrapper.sv
Normal file
@@ -0,0 +1,65 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
|
||||
module cpu_wrapper( clk, sysclk, reset, AB, DB_IN, DB_OUT, RD, IRQ, NMI, RDY, halt_b, pc_temp, core_latch_data);
|
||||
|
||||
input clk; // CPU clock
|
||||
input sysclk; // MARIA Clock
|
||||
input reset; // reset signal
|
||||
output [15:0] AB; // address bus
|
||||
input [7:0] DB_IN; // data in,
|
||||
output [7:0] DB_OUT; // data_out,
|
||||
output RD; // read enable
|
||||
input IRQ; // interrupt request
|
||||
input NMI; // non-maskable interrupt request
|
||||
input RDY; // Ready signal. Pauses CPU when RDY=0
|
||||
input halt_b;
|
||||
input core_latch_data;
|
||||
|
||||
output [15:0] pc_temp;
|
||||
|
||||
logic res;
|
||||
logic rdy_in;
|
||||
logic WE_OUT;
|
||||
logic WE, holding;
|
||||
logic [7:0] DB_hold, DB_into_cpu;
|
||||
|
||||
cpu core(.clk(clk), .reset(reset),.AB(AB),.DI(DB_hold),.DO(DB_OUT),.WE(WE_OUT),.IRQ(IRQ),.NMI(NMI),.RDY(rdy_in), .pc_temp(pc_temp), .res(res));
|
||||
|
||||
assign RD = ~(WE & ~res & ~reset);
|
||||
assign WE = WE_OUT & rdy_in; //& ~core_latch_data;
|
||||
//assign rdy_in = RDY & halt_b;
|
||||
assign DB_hold = (holding) ? DB_hold : DB_IN;
|
||||
|
||||
//assign DB_into_cpu = (core_latch_data) ? DB_IN : DB_hold;
|
||||
//assign DB_into_cpu = DB_hold;
|
||||
|
||||
|
||||
/*always_ff @(posedge sysclk) begin
|
||||
if (core_latch_data & rdy_in) begin
|
||||
DB_hold <= DB_IN;
|
||||
end
|
||||
end*/
|
||||
|
||||
/*always_ff @(posedge clk) begin
|
||||
if (rdy_in)
|
||||
DB_hold <= DB_IN;
|
||||
end*/
|
||||
|
||||
/*always_ff @(posedge clk, posedge reset)
|
||||
if (reset)
|
||||
holding <= 1'b0;
|
||||
else
|
||||
holding <= ~rdy_in;*/
|
||||
|
||||
assign holding = ~rdy_in;
|
||||
|
||||
always_ff @(negedge clk, posedge reset)
|
||||
if (reset)
|
||||
rdy_in <= 1'b1;
|
||||
else if (halt_b & RDY)
|
||||
rdy_in <= 1'b1;
|
||||
else
|
||||
rdy_in <= 1'b0;
|
||||
|
||||
endmodule: cpu_wrapper
|
||||
164
Atari - 7800_TeST/rtl/defender_rom.v
Normal file
164
Atari - 7800_TeST/rtl/defender_rom.v
Normal file
@@ -0,0 +1,164 @@
|
||||
// megafunction wizard: %ROM: 1-PORT%
|
||||
// GENERATION: STANDARD
|
||||
// VERSION: WM1.0
|
||||
// MODULE: altsyncram
|
||||
|
||||
// ============================================================
|
||||
// File Name: defender_rom.v
|
||||
// Megafunction Name(s):
|
||||
// altsyncram
|
||||
//
|
||||
// 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 Web Edition
|
||||
// ************************************************************
|
||||
|
||||
|
||||
//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 defender_rom (
|
||||
address,
|
||||
clock,
|
||||
q);
|
||||
|
||||
input [11:0] address;
|
||||
input clock;
|
||||
output [7:0] q;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_off
|
||||
`endif
|
||||
tri1 clock;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_on
|
||||
`endif
|
||||
|
||||
wire [7:0] sub_wire0;
|
||||
wire [7:0] q = sub_wire0[7:0];
|
||||
|
||||
altsyncram altsyncram_component (
|
||||
.address_a (address),
|
||||
.clock0 (clock),
|
||||
.q_a (sub_wire0),
|
||||
.aclr0 (1'b0),
|
||||
.aclr1 (1'b0),
|
||||
.address_b (1'b1),
|
||||
.addressstall_a (1'b0),
|
||||
.addressstall_b (1'b0),
|
||||
.byteena_a (1'b1),
|
||||
.byteena_b (1'b1),
|
||||
.clock1 (1'b1),
|
||||
.clocken0 (1'b1),
|
||||
.clocken1 (1'b1),
|
||||
.clocken2 (1'b1),
|
||||
.clocken3 (1'b1),
|
||||
.data_a ({8{1'b1}}),
|
||||
.data_b (1'b1),
|
||||
.eccstatus (),
|
||||
.q_b (),
|
||||
.rden_a (1'b1),
|
||||
.rden_b (1'b1),
|
||||
.wren_a (1'b0),
|
||||
.wren_b (1'b0));
|
||||
defparam
|
||||
altsyncram_component.address_aclr_a = "NONE",
|
||||
altsyncram_component.clock_enable_input_a = "BYPASS",
|
||||
altsyncram_component.clock_enable_output_a = "BYPASS",
|
||||
`ifdef NO_PLI
|
||||
altsyncram_component.init_file = "../rtl/rom/Defender.rif"
|
||||
`else
|
||||
altsyncram_component.init_file = "../rtl/rom/Defender.hex"
|
||||
`endif
|
||||
,
|
||||
altsyncram_component.intended_device_family = "Cyclone III",
|
||||
altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
|
||||
altsyncram_component.lpm_type = "altsyncram",
|
||||
altsyncram_component.numwords_a = 4096,
|
||||
altsyncram_component.operation_mode = "ROM",
|
||||
altsyncram_component.outdata_aclr_a = "NONE",
|
||||
altsyncram_component.outdata_reg_a = "CLOCK0",
|
||||
altsyncram_component.widthad_a = 12,
|
||||
altsyncram_component.width_a = 8,
|
||||
altsyncram_component.width_byteena_a = 1;
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
// ============================================================
|
||||
// CNX file retrieval info
|
||||
// ============================================================
|
||||
// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrAddr NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrByte NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrOutput NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: BlankMemory NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Clken NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
|
||||
// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
|
||||
// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: MIFfilename STRING "../rtl/rom/Defender.hex"
|
||||
// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "4096"
|
||||
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: RegAddr NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: RegOutput NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
|
||||
// Retrieval info: PRIVATE: SingleClock NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: UseDQRAM NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: WidthAddr NUMERIC "12"
|
||||
// Retrieval info: PRIVATE: WidthData NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: rden NUMERIC "0"
|
||||
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
||||
// Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE"
|
||||
// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
|
||||
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
|
||||
// Retrieval info: CONSTANT: INIT_FILE STRING "../rtl/rom/Defender.hex"
|
||||
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO"
|
||||
// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
|
||||
// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "4096"
|
||||
// Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM"
|
||||
// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
|
||||
// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0"
|
||||
// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "12"
|
||||
// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
|
||||
// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
|
||||
// Retrieval info: USED_PORT: address 0 0 12 0 INPUT NODEFVAL "address[11..0]"
|
||||
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
|
||||
// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]"
|
||||
// Retrieval info: CONNECT: @address_a 0 0 12 0 address 0 0 12 0
|
||||
// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
|
||||
// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL defender_rom.v TRUE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL defender_rom.inc FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL defender_rom.cmp FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL defender_rom.bsf FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL defender_rom_inst.v FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL defender_rom_bb.v FALSE
|
||||
// Retrieval info: LIB_FILE: altera_mf
|
||||
403
Atari - 7800_TeST/rtl/dma_ctrl.sv
Normal file
403
Atari - 7800_TeST/rtl/dma_ctrl.sv
Normal file
@@ -0,0 +1,403 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module dma_ctrl(
|
||||
output logic [15:0] AddrB,
|
||||
output logic drive_AB,
|
||||
input logic [7:0] DataB,
|
||||
// from memory map
|
||||
input logic [15:0] ZP,
|
||||
|
||||
output logic palette_w, input_w, pixels_w,
|
||||
output logic wm_w,
|
||||
|
||||
input logic zp_dma_start, dp_dma_start, dp_dma_kill,
|
||||
output logic zp_dma_done, dp_dma_done, dp_dma_done_dli,
|
||||
|
||||
input logic character_width,
|
||||
input logic [7:0] char_base,
|
||||
|
||||
input logic sysclk, reset, last_line
|
||||
);
|
||||
logic [15:0] DP;
|
||||
logic [15:0] DP_saved;
|
||||
logic [15:0] PP;
|
||||
logic [15:0] ZP_saved, ZP_saved_next;
|
||||
logic [15:0] CHAR_PTR;
|
||||
logic [1:0] char_ptr_cycles;
|
||||
logic char_bytes_fetched;
|
||||
logic [4:0] WIDTH;
|
||||
logic [3:0] OFFSET;
|
||||
|
||||
logic INDIRECT_MODE;
|
||||
|
||||
// control regs
|
||||
logic DLIen, DLIen_prev, A12en, A11en;
|
||||
|
||||
// states
|
||||
enum logic [1:0] {waiting = 2'b00, zp_dma = 2'b01, dp_dma = 2'b10} state;
|
||||
enum logic [2:0] {drive_zp_addr = 3'b000, w_offset = 3'b001, w_DPH = 3'b010 ,w_DPL = 3'b100} zp_state;
|
||||
enum logic [3:0] {drive_dp_addr = 4'h00,
|
||||
w_PPL = 4'h01,
|
||||
w_PALETTE_WIDTH = 4'h02,
|
||||
w_PPH = 4'h03,
|
||||
w_PALETTE_WIDTH_2 = 4'h04,
|
||||
w_INPUT = 4'h05,
|
||||
drive_pp_addr = 4'h06,
|
||||
w_PIXELS = 4'h07,
|
||||
w_PIXELS_slow = 4'h08,
|
||||
drive_char_addr = 4'h09,
|
||||
w_CHAR_PTR = 4'ha,
|
||||
w_CHAR_PIXELS = 4'hb,
|
||||
drive_next_zp_addr = 4'hc,
|
||||
w_next_offset = 4'hd,
|
||||
w_next_DPL = 4'he,
|
||||
w_next_DPH = 4'hf} dp_state;
|
||||
|
||||
logic five_byte_mode, null_width, null_data, zero_offset;
|
||||
|
||||
logic PP_in_cart;
|
||||
assign PP_in_cart = |(PP_plus_offset[15:14]);
|
||||
|
||||
logic [7:0] CB_plus_offset;
|
||||
assign CB_plus_offset = char_base + {4'b0, OFFSET};
|
||||
|
||||
logic CB_in_cart;
|
||||
assign CB_in_cart = |(CB_plus_offset[7:6]);
|
||||
|
||||
assign null_width = (DataB[4:0] == 5'b0);
|
||||
assign null_data = (DataB == 8'b0);
|
||||
assign zero_offset = (OFFSET == 4'b0);
|
||||
|
||||
assign drive_AB = (state != waiting);
|
||||
|
||||
assign ZP_saved_next = ZP_saved + 1;
|
||||
|
||||
logic [15:0] PP_plus_offset;
|
||||
assign PP_plus_offset = PP + {4'b0, OFFSET, 8'b0};
|
||||
|
||||
always_comb begin
|
||||
AddrB = 'h1234;
|
||||
wm_w = 0;
|
||||
palette_w = 0;
|
||||
input_w = 0;
|
||||
pixels_w = 0;
|
||||
case (state)
|
||||
zp_dma: begin
|
||||
AddrB = ZP_saved;
|
||||
end
|
||||
dp_dma: begin
|
||||
AddrB = 16'hx;
|
||||
case (dp_state)
|
||||
drive_dp_addr: begin
|
||||
AddrB = DP_saved;
|
||||
end
|
||||
|
||||
w_PPL: begin
|
||||
AddrB = DP_saved;
|
||||
end
|
||||
|
||||
w_PALETTE_WIDTH: begin
|
||||
AddrB = DP_saved;
|
||||
if (~null_data) begin
|
||||
wm_w = null_width;
|
||||
palette_w = ~null_width;
|
||||
end
|
||||
end
|
||||
|
||||
w_PPH: begin
|
||||
AddrB = DP_saved;
|
||||
end
|
||||
|
||||
w_PALETTE_WIDTH_2: begin
|
||||
AddrB = DP_saved;
|
||||
palette_w = 1;
|
||||
end
|
||||
|
||||
w_INPUT: begin
|
||||
AddrB = DP_saved;
|
||||
input_w = 1;
|
||||
end
|
||||
|
||||
drive_pp_addr: begin
|
||||
AddrB = PP_plus_offset;
|
||||
end
|
||||
|
||||
w_PIXELS: begin
|
||||
AddrB = PP + 1;
|
||||
pixels_w = 1;
|
||||
end
|
||||
|
||||
w_PIXELS_slow: begin
|
||||
if (char_ptr_cycles == 2'b11) begin
|
||||
pixels_w = 1;
|
||||
AddrB = PP + 1;
|
||||
end else begin
|
||||
AddrB = PP;
|
||||
end
|
||||
end
|
||||
|
||||
drive_char_addr: begin
|
||||
AddrB = PP;
|
||||
end
|
||||
|
||||
w_CHAR_PTR: begin
|
||||
AddrB = {CB_plus_offset, DataB};
|
||||
end
|
||||
|
||||
w_CHAR_PIXELS: begin
|
||||
if (char_ptr_cycles == 2'b11) begin
|
||||
pixels_w = 1;
|
||||
if (~char_bytes_fetched & character_width) begin
|
||||
AddrB = CHAR_PTR + 1;
|
||||
end else begin
|
||||
AddrB = PP;
|
||||
end
|
||||
end else begin
|
||||
AddrB = CHAR_PTR;
|
||||
end
|
||||
end
|
||||
|
||||
drive_next_zp_addr: begin
|
||||
AddrB = ZP_saved;
|
||||
end
|
||||
w_next_offset: begin
|
||||
AddrB = ZP_saved;
|
||||
end
|
||||
w_next_DPL: begin
|
||||
AddrB = ZP_saved;
|
||||
end
|
||||
w_next_DPH: begin
|
||||
AddrB = ZP_saved;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge sysclk, posedge reset) begin
|
||||
if (reset) begin
|
||||
state <= waiting;
|
||||
zp_state <= drive_zp_addr;
|
||||
dp_state <= drive_dp_addr;
|
||||
zp_dma_done <= 0;
|
||||
dp_dma_done <= 0;
|
||||
dp_dma_done_dli <= 0;
|
||||
five_byte_mode <= 0;
|
||||
INDIRECT_MODE <= 0;
|
||||
end else begin
|
||||
case (state)
|
||||
waiting: begin
|
||||
if (zp_dma_start) begin
|
||||
state <= zp_dma;
|
||||
ZP_saved <= ZP;
|
||||
end else if (dp_dma_start) begin
|
||||
state <= dp_dma;
|
||||
DP_saved <= DP;
|
||||
end
|
||||
zp_dma_done <= 0;
|
||||
dp_dma_done <= 0;
|
||||
dp_dma_done_dli <= 0;
|
||||
end
|
||||
////////////////////////////////////////////////////////////
|
||||
zp_dma: begin
|
||||
case (zp_state)
|
||||
drive_zp_addr: begin // Read zp
|
||||
zp_state <= w_offset;
|
||||
// AddrB = ZP_saved;
|
||||
ZP_saved <= ZP_saved_next;
|
||||
end
|
||||
w_offset: begin //write cbits and offset
|
||||
zp_state <= w_DPH;
|
||||
{DLIen,A12en,A11en} <= DataB[7:5];
|
||||
OFFSET <= DataB[3:0];
|
||||
// AddrB = ZP_saved_next;
|
||||
ZP_saved <= ZP_saved_next;
|
||||
end
|
||||
w_DPH: begin //Write DPH
|
||||
zp_state <= w_DPL;
|
||||
DP[15:8] <= DataB;
|
||||
// AddrB = ZP_saved;
|
||||
ZP_saved <= ZP_saved_next;
|
||||
end
|
||||
w_DPL: begin //Write DPL
|
||||
zp_state <= drive_zp_addr;
|
||||
state <= waiting;
|
||||
DP[7:0] <= DataB;
|
||||
DP_saved <= {DP[15:8], DataB};
|
||||
zp_dma_done <= 1'b1;
|
||||
dp_dma_done_dli <= DLIen;
|
||||
end
|
||||
endcase // case (zp_state)
|
||||
end // case: zp_dma
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
dp_dma: begin
|
||||
if (dp_dma_kill) begin
|
||||
dp_state <= drive_dp_addr;
|
||||
state <= waiting;
|
||||
dp_dma_done <= 1'b1;
|
||||
end else case (dp_state)
|
||||
drive_dp_addr: begin //read from dp
|
||||
dp_state <= w_PPL;
|
||||
// AddrB = DP_saved;
|
||||
DP_saved <= DP_saved+1;
|
||||
five_byte_mode <= 0;
|
||||
INDIRECT_MODE <= 0;
|
||||
end
|
||||
w_PPL: begin //Write PPL
|
||||
dp_state <= w_PALETTE_WIDTH;
|
||||
PP[7:0] <= DataB;
|
||||
// AddrB = DP_saved;
|
||||
DP_saved <= DP_saved+1;
|
||||
end
|
||||
w_PALETTE_WIDTH:
|
||||
// Write palette/width or determine 5b
|
||||
// mode or find end of DP list
|
||||
if (null_data) begin //Found end of DP list
|
||||
if (last_line) begin // Found end of frame
|
||||
dp_state <= drive_dp_addr;
|
||||
state <= waiting;
|
||||
dp_dma_done <= 1;
|
||||
dp_dma_done_dli <= 1'b0;
|
||||
end else if (zero_offset) begin // Found end of zone, but not end of frame
|
||||
dp_state <= drive_next_zp_addr;
|
||||
state <= dp_dma;
|
||||
end else begin // Not at end of zone or frame. Get ready for next line in zone.
|
||||
state <= waiting;
|
||||
dp_state <= drive_dp_addr;
|
||||
OFFSET <= OFFSET - 1;
|
||||
dp_dma_done <= 1;
|
||||
end
|
||||
end else begin
|
||||
// Write palette and width or determine its 5b mode
|
||||
dp_state <= w_PPH;
|
||||
five_byte_mode <= null_width;
|
||||
INDIRECT_MODE <= null_width & DataB[5];
|
||||
// wm_w <= null_width;
|
||||
// ind_w <= null_width;
|
||||
// palette_w <= ~null_width;
|
||||
WIDTH <= DataB[4:0];
|
||||
// AddrB <= DP;
|
||||
DP_saved <= DP_saved+1;
|
||||
end
|
||||
w_PPH: begin //Write PPH
|
||||
dp_state <= (five_byte_mode) ? w_PALETTE_WIDTH_2 : w_INPUT;
|
||||
PP[15:8] <= DataB;
|
||||
// AddrB <= DP;
|
||||
DP_saved <= DP_saved+1;
|
||||
end
|
||||
w_PALETTE_WIDTH_2: begin //Write palette and width for realzies
|
||||
dp_state <= w_INPUT;
|
||||
// palette_w <= 1;
|
||||
WIDTH <= DataB[4:0];
|
||||
// AddrB <= DP;
|
||||
DP_saved <= DP_saved+1;
|
||||
end
|
||||
w_INPUT: begin //write INPUT
|
||||
if (INDIRECT_MODE) begin
|
||||
dp_state <= drive_char_addr;
|
||||
end else begin
|
||||
if ((A12en & PP_plus_offset[12]) | (A11en & PP_plus_offset[11]))
|
||||
dp_state <= drive_dp_addr;
|
||||
else
|
||||
dp_state <= drive_pp_addr;
|
||||
end
|
||||
// palette_w <= 0;
|
||||
// AddrB <= DP;
|
||||
// input_w <= 1;
|
||||
end
|
||||
drive_pp_addr: begin //read from pp
|
||||
if (PP_in_cart) begin
|
||||
dp_state <= w_PIXELS_slow;
|
||||
char_ptr_cycles <= 2'b00;
|
||||
end else begin
|
||||
dp_state <= w_PIXELS;
|
||||
end
|
||||
WIDTH <= WIDTH+1;
|
||||
PP <= PP_plus_offset;
|
||||
end
|
||||
w_PIXELS: begin //Write Pixel data
|
||||
PP <= PP + 1;
|
||||
WIDTH <= WIDTH + 1;
|
||||
dp_state <= (WIDTH == 5'b0) ? drive_dp_addr : w_PIXELS;
|
||||
end
|
||||
w_PIXELS_slow: begin
|
||||
// Similar to w_CHAR_PIXELS in that we wait 4 cycles,
|
||||
// but similar to w_PIXELS otherwise
|
||||
if (char_ptr_cycles == 2'b11) begin
|
||||
// Data is ready on the data bus
|
||||
WIDTH <= WIDTH + 1;
|
||||
PP <= PP + 1;
|
||||
dp_state <= (WIDTH == 5'b0) ? drive_dp_addr: w_PIXELS_slow;
|
||||
char_ptr_cycles <= 2'b00;
|
||||
end else begin
|
||||
char_ptr_cycles <= char_ptr_cycles + 1;
|
||||
end
|
||||
end
|
||||
drive_char_addr: begin // read character pointer from pp
|
||||
dp_state <= w_CHAR_PTR;
|
||||
WIDTH <= WIDTH + 1;
|
||||
PP <= PP + 1;
|
||||
end
|
||||
w_CHAR_PTR: begin
|
||||
dp_state <= w_CHAR_PIXELS;
|
||||
CHAR_PTR <= {CB_plus_offset, DataB};
|
||||
char_bytes_fetched <= 2'b0;
|
||||
char_ptr_cycles <= (CB_in_cart) ? 2'b00 : 2'b11;
|
||||
end
|
||||
|
||||
w_CHAR_PIXELS: begin
|
||||
if (char_ptr_cycles == 2'b11) begin
|
||||
if (~char_bytes_fetched & character_width) begin
|
||||
dp_state <= w_CHAR_PIXELS;
|
||||
char_bytes_fetched <= 1'b1;
|
||||
CHAR_PTR <= CHAR_PTR + 1;
|
||||
end else begin
|
||||
if (WIDTH == 5'b0) begin
|
||||
dp_state <= drive_dp_addr;
|
||||
end else begin
|
||||
dp_state <= w_CHAR_PTR;
|
||||
WIDTH <= WIDTH + 1;
|
||||
PP <= PP + 1;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
char_ptr_cycles <= char_ptr_cycles + 1;
|
||||
end
|
||||
end
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
//Loading next zp when OFFSET has been decremented to 0
|
||||
drive_next_zp_addr: begin //Read zp
|
||||
dp_state <= w_next_offset;
|
||||
// AddrB <= ZP_saved;
|
||||
ZP_saved <= ZP_saved_next;
|
||||
end
|
||||
w_next_offset: begin //write cbits and offset
|
||||
dp_state <= w_next_DPH;
|
||||
DLIen_prev <= DLIen;
|
||||
{DLIen,A12en,A11en} <= DataB[7:5];
|
||||
OFFSET <= DataB[3:0];
|
||||
// AddrB <= ZP_saved;
|
||||
ZP_saved <= ZP_saved_next;
|
||||
end
|
||||
w_next_DPH: begin //Write DPH
|
||||
dp_state <= w_next_DPL;
|
||||
DP[15:8] <= DataB;
|
||||
// AddrB <= ZP_saved;
|
||||
ZP_saved <= ZP_saved_next;
|
||||
end
|
||||
w_next_DPL: begin //Write DPH
|
||||
dp_state <= drive_dp_addr;
|
||||
state <= waiting;
|
||||
DP[7:0] <= DataB;
|
||||
DP_saved <= {DP[15:8], DataB};
|
||||
dp_dma_done <= 1;
|
||||
dp_dma_done_dli <= DLIen;
|
||||
end
|
||||
endcase // case (dp_state)
|
||||
end // case: dp_dma
|
||||
endcase
|
||||
end
|
||||
end // always_ff @
|
||||
endmodule // dma_ctrl
|
||||
454
Atari - 7800_TeST/rtl/hq2x.sv
Normal file
454
Atari - 7800_TeST/rtl/hq2x.sv
Normal file
@@ -0,0 +1,454 @@
|
||||
//
|
||||
//
|
||||
// Copyright (c) 2012-2013 Ludvig Strigeus
|
||||
// Copyright (c) 2017 Sorgelig
|
||||
//
|
||||
// This program is GPL Licensed. See COPYING for the full license.
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// synopsys translate_off
|
||||
`timescale 1 ps / 1 ps
|
||||
// synopsys translate_on
|
||||
|
||||
`define BITS_TO_FIT(N) ( \
|
||||
N <= 2 ? 0 : \
|
||||
N <= 4 ? 1 : \
|
||||
N <= 8 ? 2 : \
|
||||
N <= 16 ? 3 : \
|
||||
N <= 32 ? 4 : \
|
||||
N <= 64 ? 5 : \
|
||||
N <= 128 ? 6 : \
|
||||
N <= 256 ? 7 : \
|
||||
N <= 512 ? 8 : \
|
||||
N <=1024 ? 9 : 10 )
|
||||
|
||||
module hq2x_in #(parameter LENGTH, parameter DWIDTH)
|
||||
(
|
||||
input clk,
|
||||
|
||||
input [AWIDTH:0] rdaddr,
|
||||
input rdbuf,
|
||||
output[DWIDTH:0] q,
|
||||
|
||||
input [AWIDTH:0] wraddr,
|
||||
input wrbuf,
|
||||
input [DWIDTH:0] data,
|
||||
input wren
|
||||
);
|
||||
|
||||
localparam AWIDTH = `BITS_TO_FIT(LENGTH);
|
||||
wire [DWIDTH:0] out[2];
|
||||
assign q = out[rdbuf];
|
||||
|
||||
hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]);
|
||||
hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]);
|
||||
endmodule
|
||||
|
||||
|
||||
module hq2x_out #(parameter LENGTH, parameter DWIDTH)
|
||||
(
|
||||
input clk,
|
||||
|
||||
input [AWIDTH:0] rdaddr,
|
||||
input [1:0] rdbuf,
|
||||
output[DWIDTH:0] q,
|
||||
|
||||
input [AWIDTH:0] wraddr,
|
||||
input [1:0] wrbuf,
|
||||
input [DWIDTH:0] data,
|
||||
input wren
|
||||
);
|
||||
|
||||
localparam AWIDTH = `BITS_TO_FIT(LENGTH*2);
|
||||
wire [DWIDTH:0] out[4];
|
||||
assign q = out[rdbuf];
|
||||
|
||||
hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]);
|
||||
hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]);
|
||||
hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf2(clk,data,rdaddr,wraddr,wren && (wrbuf == 2),out[2]);
|
||||
hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf3(clk,data,rdaddr,wraddr,wren && (wrbuf == 3),out[3]);
|
||||
endmodule
|
||||
|
||||
|
||||
module hq2x_buf #(parameter NUMWORDS, parameter AWIDTH, parameter DWIDTH)
|
||||
(
|
||||
input clock,
|
||||
input [DWIDTH:0] data,
|
||||
input [AWIDTH:0] rdaddress,
|
||||
input [AWIDTH:0] wraddress,
|
||||
input wren,
|
||||
output [DWIDTH:0] q
|
||||
);
|
||||
|
||||
altsyncram altsyncram_component (
|
||||
.address_a (wraddress),
|
||||
.clock0 (clock),
|
||||
.data_a (data),
|
||||
.wren_a (wren),
|
||||
.address_b (rdaddress),
|
||||
.q_b(q),
|
||||
.aclr0 (1'b0),
|
||||
.aclr1 (1'b0),
|
||||
.addressstall_a (1'b0),
|
||||
.addressstall_b (1'b0),
|
||||
.byteena_a (1'b1),
|
||||
.byteena_b (1'b1),
|
||||
.clock1 (1'b1),
|
||||
.clocken0 (1'b1),
|
||||
.clocken1 (1'b1),
|
||||
.clocken2 (1'b1),
|
||||
.clocken3 (1'b1),
|
||||
.data_b ({(DWIDTH+1){1'b1}}),
|
||||
.eccstatus (),
|
||||
.q_a (),
|
||||
.rden_a (1'b1),
|
||||
.rden_b (1'b1),
|
||||
.wren_b (1'b0));
|
||||
defparam
|
||||
altsyncram_component.address_aclr_b = "NONE",
|
||||
altsyncram_component.address_reg_b = "CLOCK0",
|
||||
altsyncram_component.clock_enable_input_a = "BYPASS",
|
||||
altsyncram_component.clock_enable_input_b = "BYPASS",
|
||||
altsyncram_component.clock_enable_output_b = "BYPASS",
|
||||
altsyncram_component.intended_device_family = "Cyclone III",
|
||||
altsyncram_component.lpm_type = "altsyncram",
|
||||
altsyncram_component.numwords_a = NUMWORDS,
|
||||
altsyncram_component.numwords_b = NUMWORDS,
|
||||
altsyncram_component.operation_mode = "DUAL_PORT",
|
||||
altsyncram_component.outdata_aclr_b = "NONE",
|
||||
altsyncram_component.outdata_reg_b = "UNREGISTERED",
|
||||
altsyncram_component.power_up_uninitialized = "FALSE",
|
||||
altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE",
|
||||
altsyncram_component.widthad_a = AWIDTH+1,
|
||||
altsyncram_component.widthad_b = AWIDTH+1,
|
||||
altsyncram_component.width_a = DWIDTH+1,
|
||||
altsyncram_component.width_b = DWIDTH+1,
|
||||
altsyncram_component.width_byteena_a = 1;
|
||||
|
||||
endmodule
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module DiffCheck
|
||||
(
|
||||
input [17:0] rgb1,
|
||||
input [17:0] rgb2,
|
||||
output result
|
||||
);
|
||||
|
||||
wire [5:0] r = rgb1[5:1] - rgb2[5:1];
|
||||
wire [5:0] g = rgb1[11:7] - rgb2[11:7];
|
||||
wire [5:0] b = rgb1[17:13] - rgb2[17:13];
|
||||
wire [6:0] t = $signed(r) + $signed(b);
|
||||
wire [6:0] gx = {g[5], g};
|
||||
wire [7:0] y = $signed(t) + $signed(gx);
|
||||
wire [6:0] u = $signed(r) - $signed(b);
|
||||
wire [7:0] v = $signed({g, 1'b0}) - $signed(t);
|
||||
|
||||
// if y is inside (-24..24)
|
||||
wire y_inside = (y < 8'h18 || y >= 8'he8);
|
||||
|
||||
// if u is inside (-4, 4)
|
||||
wire u_inside = (u < 7'h4 || u >= 7'h7c);
|
||||
|
||||
// if v is inside (-6, 6)
|
||||
wire v_inside = (v < 8'h6 || v >= 8'hfA);
|
||||
assign result = !(y_inside && u_inside && v_inside);
|
||||
endmodule
|
||||
|
||||
module InnerBlend
|
||||
(
|
||||
input [8:0] Op,
|
||||
input [5:0] A,
|
||||
input [5:0] B,
|
||||
input [5:0] C,
|
||||
output [5:0] O
|
||||
);
|
||||
|
||||
function [8:0] mul6x3;
|
||||
input [5:0] op1;
|
||||
input [2:0] op2;
|
||||
begin
|
||||
mul6x3 = 9'd0;
|
||||
if(op2[0]) mul6x3 = mul6x3 + op1;
|
||||
if(op2[1]) mul6x3 = mul6x3 + {op1, 1'b0};
|
||||
if(op2[2]) mul6x3 = mul6x3 + {op1, 2'b00};
|
||||
end
|
||||
endfunction
|
||||
|
||||
wire OpOnes = Op[4];
|
||||
wire [8:0] Amul = mul6x3(A, Op[7:5]);
|
||||
wire [8:0] Bmul = mul6x3(B, {Op[3:2], 1'b0});
|
||||
wire [8:0] Cmul = mul6x3(C, {Op[1:0], 1'b0});
|
||||
wire [8:0] At = Amul;
|
||||
wire [8:0] Bt = (OpOnes == 0) ? Bmul : {3'b0, B};
|
||||
wire [8:0] Ct = (OpOnes == 0) ? Cmul : {3'b0, C};
|
||||
wire [9:0] Res = {At, 1'b0} + Bt + Ct;
|
||||
assign O = Op[8] ? A : Res[9:4];
|
||||
endmodule
|
||||
|
||||
module Blend
|
||||
(
|
||||
input [5:0] rule,
|
||||
input disable_hq2x,
|
||||
input [17:0] E,
|
||||
input [17:0] A,
|
||||
input [17:0] B,
|
||||
input [17:0] D,
|
||||
input [17:0] F,
|
||||
input [17:0] H,
|
||||
output [17:0] Result
|
||||
);
|
||||
|
||||
reg [1:0] input_ctrl;
|
||||
reg [8:0] op;
|
||||
localparam BLEND0 = 9'b1_xxx_x_xx_xx; // 0: A
|
||||
localparam BLEND1 = 9'b0_110_0_10_00; // 1: (A * 12 + B * 4) >> 4
|
||||
localparam BLEND2 = 9'b0_100_0_10_10; // 2: (A * 8 + B * 4 + C * 4) >> 4
|
||||
localparam BLEND3 = 9'b0_101_0_10_01; // 3: (A * 10 + B * 4 + C * 2) >> 4
|
||||
localparam BLEND4 = 9'b0_110_0_01_01; // 4: (A * 12 + B * 2 + C * 2) >> 4
|
||||
localparam BLEND5 = 9'b0_010_0_11_11; // 5: (A * 4 + (B + C) * 6) >> 4
|
||||
localparam BLEND6 = 9'b0_111_1_xx_xx; // 6: (A * 14 + B + C) >> 4
|
||||
localparam AB = 2'b00;
|
||||
localparam AD = 2'b01;
|
||||
localparam DB = 2'b10;
|
||||
localparam BD = 2'b11;
|
||||
wire is_diff;
|
||||
DiffCheck diff_checker(rule[1] ? B : H, rule[0] ? D : F, is_diff);
|
||||
|
||||
always @* begin
|
||||
case({!is_diff, rule[5:2]})
|
||||
1,17: {op, input_ctrl} = {BLEND1, AB};
|
||||
2,18: {op, input_ctrl} = {BLEND1, DB};
|
||||
3,19: {op, input_ctrl} = {BLEND1, BD};
|
||||
4,20: {op, input_ctrl} = {BLEND2, DB};
|
||||
5,21: {op, input_ctrl} = {BLEND2, AB};
|
||||
6,22: {op, input_ctrl} = {BLEND2, AD};
|
||||
|
||||
8: {op, input_ctrl} = {BLEND0, 2'bxx};
|
||||
9: {op, input_ctrl} = {BLEND0, 2'bxx};
|
||||
10: {op, input_ctrl} = {BLEND0, 2'bxx};
|
||||
11: {op, input_ctrl} = {BLEND1, AB};
|
||||
12: {op, input_ctrl} = {BLEND1, AB};
|
||||
13: {op, input_ctrl} = {BLEND1, AB};
|
||||
14: {op, input_ctrl} = {BLEND1, DB};
|
||||
15: {op, input_ctrl} = {BLEND1, BD};
|
||||
|
||||
24: {op, input_ctrl} = {BLEND2, DB};
|
||||
25: {op, input_ctrl} = {BLEND5, DB};
|
||||
26: {op, input_ctrl} = {BLEND6, DB};
|
||||
27: {op, input_ctrl} = {BLEND2, DB};
|
||||
28: {op, input_ctrl} = {BLEND4, DB};
|
||||
29: {op, input_ctrl} = {BLEND5, DB};
|
||||
30: {op, input_ctrl} = {BLEND3, BD};
|
||||
31: {op, input_ctrl} = {BLEND3, DB};
|
||||
default: {op, input_ctrl} = 11'bx;
|
||||
endcase
|
||||
|
||||
// Setting op[8] effectively disables HQ2X because blend will always return E.
|
||||
if (disable_hq2x) op[8] = 1;
|
||||
end
|
||||
|
||||
// Generate inputs to the inner blender. Valid combinations.
|
||||
// 00: E A B
|
||||
// 01: E A D
|
||||
// 10: E D B
|
||||
// 11: E B D
|
||||
wire [17:0] Input1 = E;
|
||||
wire [17:0] Input2 = !input_ctrl[1] ? A :
|
||||
!input_ctrl[0] ? D : B;
|
||||
|
||||
wire [17:0] Input3 = !input_ctrl[0] ? B : D;
|
||||
InnerBlend inner_blend1(op, Input1[5:0], Input2[5:0], Input3[5:0], Result[5:0]);
|
||||
InnerBlend inner_blend2(op, Input1[11:6], Input2[11:6], Input3[11:6], Result[11:6]);
|
||||
InnerBlend inner_blend3(op, Input1[17:12], Input2[17:12], Input3[17:12], Result[17:12]);
|
||||
endmodule
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module Hq2x #(parameter LENGTH, parameter HALF_DEPTH)
|
||||
(
|
||||
input clk,
|
||||
input ce_x4,
|
||||
input [DWIDTH:0] inputpixel,
|
||||
input mono,
|
||||
input disable_hq2x,
|
||||
input reset_frame,
|
||||
input reset_line,
|
||||
input [1:0] read_y,
|
||||
input [AWIDTH+1:0] read_x,
|
||||
output [DWIDTH:0] outpixel
|
||||
);
|
||||
|
||||
|
||||
localparam AWIDTH = `BITS_TO_FIT(LENGTH);
|
||||
localparam DWIDTH = HALF_DEPTH ? 8 : 17;
|
||||
|
||||
wire [5:0] hqTable[256] = '{
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39,
|
||||
19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 35, 35, 23, 15, 7, 35,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43,
|
||||
19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 51, 35, 23, 15, 7, 43,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 35, 35, 23, 61, 51, 35,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 7, 35, 23, 61, 7, 43,
|
||||
19, 19, 26, 11, 19, 19, 26, 58, 23, 15, 51, 35, 23, 61, 7, 43,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 39, 23, 15, 7, 43,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 39,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 35,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 43,
|
||||
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 7, 35, 23, 15, 7, 43
|
||||
};
|
||||
|
||||
reg [17:0] Prev0, Prev1, Prev2, Curr0, Curr1, Next0, Next1, Next2;
|
||||
reg [17:0] A, B, D, F, G, H;
|
||||
reg [7:0] pattern, nextpatt;
|
||||
reg [1:0] i;
|
||||
reg [7:0] y;
|
||||
|
||||
wire curbuf = y[0];
|
||||
reg prevbuf = 0;
|
||||
wire iobuf = !curbuf;
|
||||
|
||||
wire diff0, diff1;
|
||||
DiffCheck diffcheck0(Curr1, (i == 0) ? Prev0 : (i == 1) ? Curr0 : (i == 2) ? Prev2 : Next1, diff0);
|
||||
DiffCheck diffcheck1(Curr1, (i == 0) ? Prev1 : (i == 1) ? Next0 : (i == 2) ? Curr2 : Next2, diff1);
|
||||
|
||||
wire [7:0] new_pattern = {diff1, diff0, pattern[7:2]};
|
||||
|
||||
wire [17:0] X = (i == 0) ? A : (i == 1) ? Prev1 : (i == 2) ? Next1 : G;
|
||||
wire [17:0] blend_result;
|
||||
Blend blender(hqTable[nextpatt], disable_hq2x, Curr0, X, B, D, F, H, blend_result);
|
||||
|
||||
reg Curr2_addr1;
|
||||
reg [AWIDTH:0] Curr2_addr2;
|
||||
wire [17:0] Curr2 = HALF_DEPTH ? h2rgb(Curr2tmp) : Curr2tmp;
|
||||
wire [DWIDTH:0] Curr2tmp;
|
||||
|
||||
reg [AWIDTH:0] wrin_addr2;
|
||||
reg [DWIDTH:0] wrpix;
|
||||
reg wrin_en;
|
||||
|
||||
function [17:0] h2rgb;
|
||||
input [8:0] v;
|
||||
begin
|
||||
h2rgb = mono ? {v[5:3],v[2:0], v[5:3],v[2:0], v[5:3],v[2:0]} : {v[8:6],v[8:6],v[5:3],v[5:3],v[2:0],v[2:0]};
|
||||
end
|
||||
endfunction
|
||||
|
||||
function [8:0] rgb2h;
|
||||
input [17:0] v;
|
||||
begin
|
||||
rgb2h = mono ? {3'b000, v[17:15], v[14:12]} : {v[17:15], v[11:9], v[5:3]};
|
||||
end
|
||||
endfunction
|
||||
|
||||
hq2x_in #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_in
|
||||
(
|
||||
.clk(clk),
|
||||
|
||||
.rdaddr(Curr2_addr2),
|
||||
.rdbuf(Curr2_addr1),
|
||||
.q(Curr2tmp),
|
||||
|
||||
.wraddr(wrin_addr2),
|
||||
.wrbuf(iobuf),
|
||||
.data(wrpix),
|
||||
.wren(wrin_en)
|
||||
);
|
||||
|
||||
reg [1:0] wrout_addr1;
|
||||
reg [AWIDTH+1:0] wrout_addr2;
|
||||
reg wrout_en;
|
||||
reg [DWIDTH:0] wrdata;
|
||||
|
||||
hq2x_out #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_out
|
||||
(
|
||||
.clk(clk),
|
||||
|
||||
.rdaddr(read_x),
|
||||
.rdbuf(read_y),
|
||||
.q(outpixel),
|
||||
|
||||
.wraddr(wrout_addr2),
|
||||
.wrbuf(wrout_addr1),
|
||||
.data(wrdata),
|
||||
.wren(wrout_en)
|
||||
);
|
||||
|
||||
always @(posedge clk) begin
|
||||
reg [AWIDTH:0] offs;
|
||||
reg old_reset_line;
|
||||
reg old_reset_frame;
|
||||
|
||||
wrout_en <= 0;
|
||||
wrin_en <= 0;
|
||||
|
||||
if(ce_x4) begin
|
||||
|
||||
pattern <= new_pattern;
|
||||
|
||||
if(~&offs) begin
|
||||
if (i == 0) begin
|
||||
Curr2_addr1 <= prevbuf;
|
||||
Curr2_addr2 <= offs;
|
||||
end
|
||||
if (i == 1) begin
|
||||
Prev2 <= Curr2;
|
||||
Curr2_addr1 <= curbuf;
|
||||
Curr2_addr2 <= offs;
|
||||
end
|
||||
if (i == 2) begin
|
||||
Next2 <= HALF_DEPTH ? h2rgb(inputpixel) : inputpixel;
|
||||
wrpix <= inputpixel;
|
||||
wrin_addr2 <= offs;
|
||||
wrin_en <= 1;
|
||||
end
|
||||
if (i == 3) begin
|
||||
offs <= offs + 1'd1;
|
||||
end
|
||||
|
||||
if(HALF_DEPTH) wrdata <= rgb2h(blend_result);
|
||||
else wrdata <= blend_result;
|
||||
|
||||
wrout_addr1 <= {curbuf, i[1]};
|
||||
wrout_addr2 <= {offs, i[1]^i[0]};
|
||||
wrout_en <= 1;
|
||||
end
|
||||
|
||||
if(i==3) begin
|
||||
nextpatt <= {new_pattern[7:6], new_pattern[3], new_pattern[5], new_pattern[2], new_pattern[4], new_pattern[1:0]};
|
||||
{A, G} <= {Prev0, Next0};
|
||||
{B, F, H, D} <= {Prev1, Curr2, Next1, Curr0};
|
||||
{Prev0, Prev1} <= {Prev1, Prev2};
|
||||
{Curr0, Curr1} <= {Curr1, Curr2};
|
||||
{Next0, Next1} <= {Next1, Next2};
|
||||
end else begin
|
||||
nextpatt <= {nextpatt[5], nextpatt[3], nextpatt[0], nextpatt[6], nextpatt[1], nextpatt[7], nextpatt[4], nextpatt[2]};
|
||||
{B, F, H, D} <= {F, H, D, B};
|
||||
end
|
||||
|
||||
i <= i + 1'b1;
|
||||
if(old_reset_line && ~reset_line) begin
|
||||
old_reset_frame <= reset_frame;
|
||||
offs <= 0;
|
||||
i <= 0;
|
||||
y <= y + 1'd1;
|
||||
prevbuf <= curbuf;
|
||||
if(old_reset_frame & ~reset_frame) begin
|
||||
y <= 0;
|
||||
prevbuf <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
old_reset_line <= reset_line;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule // Hq2x
|
||||
261
Atari - 7800_TeST/rtl/line_ram.sv
Normal file
261
Atari - 7800_TeST/rtl/line_ram.sv
Normal file
@@ -0,0 +1,261 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
// Graphics Mode Definitions
|
||||
`define GM_160A 3'b000
|
||||
`define GM_160B 3'b100
|
||||
`define GM_320A 3'b011
|
||||
`define GM_320B 3'b110
|
||||
`define GM_320C 3'b111
|
||||
`define GM_320D 3'b010
|
||||
|
||||
module line_ram(
|
||||
input logic SYSCLK, RESET,
|
||||
output logic [7:0] PLAYBACK,
|
||||
// Databus inputs
|
||||
input logic [7:0] INPUT_ADDR,
|
||||
input logic [2:0] PALETTE,
|
||||
input logic [7:0] PIXELS,
|
||||
input logic WM,
|
||||
// Write enable for databus inputs
|
||||
input logic PALETTE_W, INPUT_W, PIXELS_W, WM_W,
|
||||
// Memory mapped registers
|
||||
input logic [24:0][7:0] COLOR_MAP,
|
||||
input logic [1:0] READ_MODE,
|
||||
input logic KANGAROO_MODE, BORDER_CONTROL,
|
||||
input logic COLOR_KILL,
|
||||
input logic LRAM_SWAP,
|
||||
// VGA Control signal
|
||||
input logic [8:0] LRAM_OUT_COL
|
||||
);
|
||||
|
||||
logic [159:0][4:0] lram_in, lram_out;
|
||||
logic rm_in, rm_out;
|
||||
|
||||
logic [7:0] input_addr;
|
||||
logic [2:0] palette;
|
||||
logic wm;
|
||||
|
||||
logic [2:0] display_mode;
|
||||
assign display_mode = {wm, READ_MODE};
|
||||
|
||||
logic [2:0] playback_palette;
|
||||
logic [1:0] playback_color;
|
||||
logic [4:0] playback_cell;
|
||||
logic [8:0] playback_ix;
|
||||
logic [7:0] lram_ix;
|
||||
|
||||
assign playback_ix = (LRAM_OUT_COL < 9'd320) ? LRAM_OUT_COL : 9'd0;
|
||||
|
||||
always_comb begin
|
||||
if (playback_color == 2'b0) begin
|
||||
PLAYBACK = COLOR_MAP[0];
|
||||
end else begin
|
||||
PLAYBACK = COLOR_MAP[3 * playback_palette + playback_color];
|
||||
end
|
||||
end
|
||||
|
||||
logic [4:0] cell1, cell2, cell3, cell4;
|
||||
logic [4:0] pcell1, pcell2, pcell3, pcell4;
|
||||
|
||||
assign cell1 = lram_in[input_addr];
|
||||
assign cell2 = lram_in[input_addr+1];
|
||||
assign cell3 = lram_in[input_addr+2];
|
||||
assign cell4 = lram_in[input_addr+3];
|
||||
|
||||
assign pcell1 = lram_in[input_addr-4];
|
||||
assign pcell2 = lram_in[input_addr-3];
|
||||
assign pcell3 = lram_in[input_addr-2];
|
||||
assign pcell4 = lram_in[input_addr-1];
|
||||
|
||||
// Assign playback_color and playback_palette based on
|
||||
// lram_in and playback_ix and display_mode
|
||||
always_comb begin
|
||||
lram_ix = playback_ix[8:1]; // 2 pixels per lram cell
|
||||
playback_cell = lram_out[lram_ix];
|
||||
playback_palette = playback_cell[4:2]; // Default to 160A/B
|
||||
playback_color = playback_cell[1:0];
|
||||
casex (rm_out)
|
||||
2'b0x: begin
|
||||
// 160A is read as four double-pixels per byte:
|
||||
// <P2 P1 P0> <D7 D6>
|
||||
// <P2 P1 P0> <D5 D4>
|
||||
// <P2 P1 P0> <D3 D2>
|
||||
// <P2 P1 P0> <D1 D0>
|
||||
// 160B is read as two double-pixels per byte:
|
||||
// <P2 D3 D2> <D7 D6>
|
||||
// <P2 D1 D0> <D5 D4>
|
||||
// In both cases, the lineram cells are stored in
|
||||
// exactly the order specified above. They can be
|
||||
// read directly.
|
||||
playback_palette = playback_cell[4:2];
|
||||
playback_color = playback_cell[1:0];
|
||||
end
|
||||
2'b10: begin
|
||||
// 320B is read as four pixels per byte:
|
||||
// <P2 0 0> <D7 D3>
|
||||
// <P2 0 0> <D6 D2>
|
||||
// <P2 0 0> <D5 D1>
|
||||
// <P2 0 0> <D4 D0>
|
||||
// 320B is stored as two cells per byte (wm=1):
|
||||
// [P2 D3 D2 D7 D6]
|
||||
// [P2 D1 D0 D5 D4]
|
||||
//
|
||||
// 320D is read as eight pixels per byte:
|
||||
// <P2 0 0> <D7 P1>
|
||||
// <P2 0 0> <D6 P0>
|
||||
// <P2 0 0> <D5 P1>
|
||||
// <P2 0 0> <D4 P0>
|
||||
// <P2 0 0> <D3 P1>
|
||||
// <P2 0 0> <D2 P0>
|
||||
// <P2 0 0> <D1 P1>
|
||||
// <P2 0 0> <D0 P0>
|
||||
// 320D is stored as four cells per byte (wm=0):
|
||||
// [P2 P1 P0 D7 D6]
|
||||
// [P2 P1 P0 D5 D4]
|
||||
// [P2 P1 P0 D3 D2]
|
||||
// [P2 P1 P0 D1 D0]
|
||||
//
|
||||
// In both cases, the palette is always <cell[4], 0, 0>
|
||||
// For a given pair of pixels, the color selectors
|
||||
// are, from left to right, <cell[1], cell[3]> and <cell[0], cell[2]>
|
||||
// Example: Either D7,D3:D6,D2 (320B) or D7,P1:D6,P0 (320D)
|
||||
playback_palette = {playback_cell[4], 2'b0};
|
||||
if (playback_ix[0]) begin
|
||||
// Right pixel
|
||||
playback_color = {playback_cell[0], playback_cell[2]};
|
||||
end else begin
|
||||
// Left pixel
|
||||
playback_color = {playback_cell[1], playback_cell[3]};
|
||||
end
|
||||
end
|
||||
2'b11: begin
|
||||
// 320A is read as eight pixels per byte:
|
||||
// <P2 P1 P0> <D7 0>
|
||||
// <P2 P1 P0> <D6 0>
|
||||
// <P2 P1 P0> <D5 0>
|
||||
// <P2 P1 P0> <D4 0>
|
||||
// <P2 P1 P0> <D3 0>
|
||||
// <P2 P1 P0> <D2 0>
|
||||
// <P2 P1 P0> <D1 0>
|
||||
// <P2 P1 P0> <D0 0>
|
||||
// 320A is stored as four cells per byte (wm=0):
|
||||
// [P2 P1 P0 D7 D6]
|
||||
// [P2 P1 P0 D5 D4]
|
||||
// [P2 P1 P0 D3 D2]
|
||||
// [P2 P1 P0 D1 D0]
|
||||
//
|
||||
// 320C is read as four pixels per byte:
|
||||
// <P2 D3 D2> <D7 0>
|
||||
// <P2 D3 D2> <D6 0>
|
||||
// <P2 D1 D0> <D5 0>
|
||||
// <P2 D1 D0> <D4 0>
|
||||
// 320C is stored as two cells per byte (wm=1):
|
||||
// [P2 D3 D2 D7 D6]
|
||||
// [P2 D1 D0 D5 D4]
|
||||
//
|
||||
// In both cases, the palette is always <cell[4], cell[3], cell[2]>
|
||||
// For a given pair of pixels, the color selectors
|
||||
// are, from left to right, <cell[1], 0> and <cell[0], 0>
|
||||
playback_palette = playback_cell[4:2];
|
||||
if (playback_ix[0]) begin
|
||||
// Right pixel
|
||||
playback_color = {playback_cell[0], 1'b0};
|
||||
end else begin
|
||||
// Left pixel
|
||||
playback_color = {playback_cell[1], 1'b0};
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge SYSCLK, posedge RESET) begin
|
||||
if (RESET) begin
|
||||
input_addr <= 8'b0;
|
||||
palette <= 3'b0;
|
||||
wm <= 1'b0;
|
||||
lram_in <= 800'd0;
|
||||
lram_out <= 800'd0;
|
||||
end else begin
|
||||
input_addr <= INPUT_W ? INPUT_ADDR : input_addr;
|
||||
palette <= PALETTE_W ? PALETTE : palette;
|
||||
wm <= WM_W ? WM : wm;
|
||||
if (LRAM_SWAP) begin
|
||||
lram_in <= 800'd0; // All background color
|
||||
lram_out <= lram_in;
|
||||
rm_out <= rm_in;
|
||||
end
|
||||
if (PIXELS_W) begin
|
||||
// Load PIXELS byte into lram_in
|
||||
rm_in <= READ_MODE;
|
||||
case (wm)
|
||||
1'b0: begin
|
||||
// "When wm = 0, each byte specifies four pixel cells
|
||||
// of the lineram"
|
||||
// This encompasses:
|
||||
// 160A:
|
||||
// [P2 P1 P0 D7 D6]
|
||||
// [P2 P1 P0 D5 D4]
|
||||
// [P2 P1 P0 D3 D2]
|
||||
// [P2 P1 P0 D1 D0]
|
||||
// 320A:
|
||||
// [P2 P1 P0 D7 0]
|
||||
// [P2 P1 P0 D6 0]
|
||||
// [P2 P1 P0 D5 0]
|
||||
// [P2 P1 P0 D4 0]
|
||||
// [P2 P1 P0 D3 0]
|
||||
// [P2 P1 P0 D2 0]
|
||||
// [P2 P1 P0 D1 0]
|
||||
// [P2 P1 P0 D0 0]
|
||||
// 320D:
|
||||
// [P2 0 0 D7 P1]
|
||||
// [P2 0 0 D6 P0]
|
||||
// [P2 0 0 D5 P1]
|
||||
// [P2 0 0 D4 P0]
|
||||
// [P2 0 0 D3 P1]
|
||||
// [P2 0 0 D2 P0]
|
||||
// [P2 0 0 D1 P1]
|
||||
// [P2 0 0 D0 P0]
|
||||
// These can all be written into the cells using
|
||||
// the same format and read out differently.
|
||||
input_addr <= input_addr + 4;
|
||||
if (|PIXELS[7:6])
|
||||
lram_in[input_addr+0] <= {palette, PIXELS[7:6]};
|
||||
if (|PIXELS[5:4])
|
||||
lram_in[input_addr+1] <= {palette, PIXELS[5:4]};
|
||||
if (|PIXELS[3:2])
|
||||
lram_in[input_addr+2] <= {palette, PIXELS[3:2]};
|
||||
if (|PIXELS[1:0])
|
||||
lram_in[input_addr+3] <= {palette, PIXELS[1:0]};
|
||||
end
|
||||
1'b1: begin
|
||||
// "When wm = 1, each byte specifies two cells within the lineram."
|
||||
// This encompasses:
|
||||
// 160B:
|
||||
// [P2 D3 D2 D7 D6]
|
||||
// [P2 D1 D0 D5 D4]
|
||||
// 320B:
|
||||
// [P2 0 0 D7 D3]
|
||||
// [P2 0 0 D6 D2]
|
||||
// [P2 0 0 D5 D1]
|
||||
// [P2 0 0 D4 D0]
|
||||
// 320C:
|
||||
// [P2 D3 D2 D7 0]
|
||||
// [P2 D3 D2 D6 0]
|
||||
// [P2 D1 D0 D5 0]
|
||||
// [P2 D1 D0 D4 0]
|
||||
// Again, these can be written into the cells in
|
||||
// the same format and read out differently. Note:
|
||||
// transparency may not be correct in 320B mode here
|
||||
// since the color bits are different than 160B and 320C.
|
||||
input_addr <= input_addr + 2;
|
||||
if (|PIXELS[7:6])
|
||||
lram_in[input_addr+0] <= {palette[2], PIXELS[3:2], PIXELS[7:6]};
|
||||
if (|PIXELS[5:4])
|
||||
lram_in[input_addr+1] <= {palette[2], PIXELS[1:0], PIXELS[5:4]};
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
178
Atari - 7800_TeST/rtl/maria.sv
Normal file
178
Atari - 7800_TeST/rtl/maria.sv
Normal file
@@ -0,0 +1,178 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "atari7800.vh"
|
||||
|
||||
|
||||
module maria(
|
||||
// Busses ("tristate")
|
||||
input logic [15:0] AB_in,
|
||||
output logic [15:0] AB_out,
|
||||
output logic drive_AB,
|
||||
|
||||
input logic [7:0] read_DB_in,
|
||||
input logic [7:0] write_DB_in,
|
||||
output logic [7:0] DB_out,
|
||||
// inout wire [15:0] AB,
|
||||
// inout wire [ 7:0] DB,
|
||||
//inout wire [7:0] DB,
|
||||
//inout wire [15:0] AB,
|
||||
|
||||
// Clocking
|
||||
input logic reset,
|
||||
input logic sysclk, pclk_2,
|
||||
output logic tia_clk, pclk_0, sel_slow_clock,
|
||||
|
||||
// Memory Map Select lines
|
||||
output `chipselect CS,
|
||||
input logic bios_en,
|
||||
input logic tia_en,
|
||||
//output logic ram0_b, ram1_b, p6532_b, tia_b,
|
||||
//output logic riot_ram_b,
|
||||
|
||||
// Maria configuration
|
||||
input logic RW, enable,
|
||||
|
||||
// VGA Interface
|
||||
input logic [9:0] vga_row, vga_col,
|
||||
output logic [7:0] UV_out,
|
||||
|
||||
// Outputs to 6502
|
||||
output logic int_b, halt_b, ready, core_latch_data
|
||||
);
|
||||
|
||||
// Bus interface
|
||||
// Defined as ports.
|
||||
//logic drive_AB;
|
||||
//logic [15:0] AB_in, AB_out;
|
||||
//logic drive_DB;
|
||||
//logic [7:0] DB_in, DB_out;
|
||||
//assign DB = drive_DB ? DB_out : 'bz;
|
||||
//assign AB = drive_AB ? AB_out : 'bz;
|
||||
//assign DB_in = DB;
|
||||
//assign AB_in = AB;
|
||||
|
||||
// For testing DMA.
|
||||
//assign DB_in = DB;
|
||||
//assign AB = AB_out;
|
||||
//assign AB_in = AB_out;
|
||||
|
||||
//// Memory Mapped Registers
|
||||
// Control register format:
|
||||
// {CK, DM1, DM0, CW, BC, KM, RM1, RM0}
|
||||
// CK: Color Kill
|
||||
// {DM1, DM0}: DMA Control. 0: Test A. 1: Test B.
|
||||
// 2: Normal DMA. 3: No DMA.
|
||||
// CW: Character Width (For indirect mode). 0=>2bytes. 1=>1byte.
|
||||
// BC: Border Control: 0=>Background Color. 1=>Black Border.
|
||||
// KM: Kangaroo Mode: 0=>Transparency, 1=>No transparency
|
||||
// {RM1, RM0}: Read mode.
|
||||
logic [7:0] ctrl;
|
||||
logic [24:0][7:0] color_map;
|
||||
logic [7:0] char_base;
|
||||
logic [15:0] ZP;
|
||||
|
||||
//// Signals from memory_map to timing_ctrl
|
||||
logic deassert_ready, zp_written;
|
||||
|
||||
// Write enables for internal Display List registers
|
||||
logic palette_w, input_w, pixels_w, wm_w;
|
||||
|
||||
//// Control signals between timing_ctrl and dma_ctrl
|
||||
logic zp_dma_start, dp_dma_start;
|
||||
logic zp_dma_done, dp_dma_done;
|
||||
// When dp_dma_done is asserted, use this signal to specify
|
||||
// whether timing_ctrl needs to raise a display list interrupt
|
||||
logic dp_dma_done_dli;
|
||||
// If a DMA is taking too long (too many objects,) kill it
|
||||
logic dp_dma_kill;
|
||||
// Next-line ZP DMA not needed at end of DP DMA
|
||||
logic last_line;
|
||||
|
||||
//// Control signals between timing_ctrl and line_ram
|
||||
logic lram_swap;
|
||||
|
||||
logic VBLANK;
|
||||
|
||||
line_ram line_ram_inst(
|
||||
.SYSCLK(sysclk), .RESET(reset),
|
||||
.PLAYBACK(UV_out),
|
||||
// Databus inputs
|
||||
.INPUT_ADDR(read_DB_in), .PALETTE(read_DB_in[7:5]), .PIXELS(read_DB_in),
|
||||
.WM(read_DB_in[7]),
|
||||
// Write enable for databus inputs
|
||||
.PALETTE_W(palette_w), .INPUT_W(input_w), .PIXELS_W(pixels_w),
|
||||
.WM_W(wm_w),
|
||||
// Memory mapped registers
|
||||
.COLOR_MAP(color_map),
|
||||
.READ_MODE(ctrl[1:0]),
|
||||
.KANGAROO_MODE(ctrl[2]),
|
||||
.BORDER_CONTROL(ctrl[3]),
|
||||
.COLOR_KILL(ctrl[7]),
|
||||
// Control signals from timing_ctrl
|
||||
.LRAM_SWAP(lram_swap),
|
||||
.LRAM_OUT_COL(vga_col[9:1])
|
||||
);
|
||||
|
||||
timing_ctrl timing_ctrl_inst(
|
||||
// Enabled only if men is asserted and display mode is 10
|
||||
.enable(enable & ctrl[6] & ~ctrl[5]),
|
||||
// Clocking
|
||||
.sysclk(sysclk), .reset(reset), .pclk_2(pclk_2),
|
||||
.pclk_0(pclk_0), .tia_clk(tia_clk),
|
||||
// Signals needed to slow pclk_0
|
||||
.sel_slow_clock(sel_slow_clock),
|
||||
// Outputs to 6502
|
||||
.halt_b(halt_b), .int_b(int_b), .ready(ready), .core_latch_data(core_latch_data),
|
||||
.VBLANK(VBLANK),
|
||||
// Signals to/from dma_ctrl
|
||||
.zp_dma_start(zp_dma_start), .dp_dma_start(dp_dma_start),
|
||||
.zp_dma_done(zp_dma_done), .dp_dma_done(dp_dma_done),
|
||||
.dp_dma_done_dli(dp_dma_done_dli),
|
||||
.dp_dma_kill(dp_dma_kill), .last_line(last_line),
|
||||
// Signals to/from line_ram
|
||||
.lram_swap(lram_swap),
|
||||
// Signals to/from VGA
|
||||
.vga_row(vga_row), .vga_col(vga_col),
|
||||
// Signals from memory map
|
||||
.deassert_ready(deassert_ready),
|
||||
.zp_written(zp_written)
|
||||
);
|
||||
|
||||
memory_map memory_map_inst(
|
||||
.maria_en(enable),
|
||||
.tia_en(tia_en),
|
||||
.AB(AB_in),
|
||||
.DB_in(write_DB_in), .DB_out(DB_out),
|
||||
//.drive_DB(drive_DB),
|
||||
.halt_b(halt_b), .we_b(RW),
|
||||
//.tia_b(tia_b), .p6532_b(p6532_b),
|
||||
//.ram0_b(ram0_b), .ram1_b(ram1_b),
|
||||
//.riot_ram_b(riot_ram_b),
|
||||
.cs(CS), .bios_en(bios_en),
|
||||
.drive_AB(drive_AB),
|
||||
.ctrl(ctrl),
|
||||
.color_map(color_map),
|
||||
.status_read({VBLANK, 7'b0}),
|
||||
.char_base(char_base),
|
||||
.ZP(ZP),
|
||||
.sel_slow_clock(sel_slow_clock),
|
||||
.deassert_ready(deassert_ready),
|
||||
.zp_written(zp_written),
|
||||
.sysclock(sysclk), .reset_b(~reset),
|
||||
.pclk_0(pclk_0), .pclk_2(pclk_2)
|
||||
);
|
||||
|
||||
dma_ctrl dma_ctrl_inst (
|
||||
.AddrB(AB_out), .drive_AB(drive_AB),
|
||||
.DataB(read_DB_in), .ZP(ZP),
|
||||
.palette_w(palette_w), .input_w(input_w), .pixels_w(pixels_w),
|
||||
.wm_w(wm_w),
|
||||
.zp_dma_start(zp_dma_start), .dp_dma_start(dp_dma_start),
|
||||
.dp_dma_kill(dp_dma_kill),
|
||||
.zp_dma_done(zp_dma_done), .dp_dma_done(dp_dma_done),
|
||||
.dp_dma_done_dli(dp_dma_done_dli),
|
||||
.sysclk(sysclk), .reset(reset),
|
||||
.last_line(last_line),
|
||||
.character_width(ctrl[4]), .char_base(char_base)
|
||||
);
|
||||
|
||||
endmodule
|
||||
232
Atari - 7800_TeST/rtl/memory_map.sv
Normal file
232
Atari - 7800_TeST/rtl/memory_map.sv
Normal file
@@ -0,0 +1,232 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
`include "atari7800.vh"
|
||||
|
||||
module memory_map (
|
||||
input logic maria_en,
|
||||
input logic tia_en,
|
||||
input logic [15:0] AB,
|
||||
input logic [7:0] DB_in,
|
||||
output logic [7:0] DB_out,
|
||||
input logic halt_b, we_b,
|
||||
|
||||
output `chipselect cs,
|
||||
input logic bios_en,
|
||||
input logic drive_AB,
|
||||
|
||||
output logic [7:0] ctrl,
|
||||
output logic [24:0][7:0] color_map,
|
||||
input logic [7:0] status_read,
|
||||
output logic [7:0] char_base,
|
||||
output logic [15:0] ZP,
|
||||
|
||||
// whether to slow pclk_0 for slow memory accesses
|
||||
output logic sel_slow_clock,
|
||||
|
||||
// when wait_sync is written to, ready is deasserted
|
||||
output logic deassert_ready, zp_written,
|
||||
|
||||
input logic sysclock, reset_b, pclk_0, pclk_2
|
||||
);
|
||||
|
||||
logic [3:0] signals_out;
|
||||
|
||||
// Internal Memory Mapped Registers
|
||||
logic [7:0] ZPH, ZPL;
|
||||
logic [7:0] wait_sync;
|
||||
|
||||
logic [7:0] read_addr_found, write_addr_found;
|
||||
|
||||
(* KEEP = "true" *)
|
||||
logic [7:0] ctrl_kept;
|
||||
|
||||
assign sel_slow_clock = (drive_AB) ? 1'b0 : ((tia_en) ? 1'b1 : ((cs == `CS_TIA) || (cs == `CS_RIOT_IO) || (cs == `CS_RIOT_RAM)));
|
||||
|
||||
assign ZP = {ZPH, ZPL};
|
||||
logic [1:0] zp_byte_written;
|
||||
|
||||
assign zp_written = &zp_byte_written;
|
||||
|
||||
always_comb begin
|
||||
// Generate Chip Select (cs) Signal
|
||||
cs = `CS_CART;
|
||||
|
||||
if (~tia_en) casex (AB)
|
||||
// RIOT RAM: "Do Not Use" in 7800 mode.
|
||||
16'b0000_010x_1xxx_xxxx: cs = `CS_RIOT_RAM;
|
||||
16'b0000_0010_1xxx_xxxx: cs = `CS_RIOT_IO;
|
||||
|
||||
// 1800-1FFF: 2K RAM.
|
||||
16'b0001_1xxx_xxxx_xxxx: cs = `CS_RAM1;
|
||||
|
||||
// 0040-00FF: Zero Page (Local variable space)
|
||||
// 0140-01FF: Stack
|
||||
16'b0000_000x_01xx_xxxx,
|
||||
16'b0000_000x_1xxx_xxxx,
|
||||
|
||||
// 2000-27FF: 2K RAM. Zero Page and Stack mirrored from here.
|
||||
16'b001x_xxxx_xxxx_xxxx: cs = `CS_RAM0;
|
||||
|
||||
// TIA Registers:
|
||||
// 0000-001F, 0100-001F, 0200-021F, 0300-031F
|
||||
// All mirrors are ranges of the same registers
|
||||
16'b0000_00xx_000x_xxxx: cs = `CS_TIA;
|
||||
|
||||
// MARIA Registers:
|
||||
// 0020-003F, 0120-003F, 0220-023F, 0320-033F
|
||||
// All ranges are mirrors of the same registers
|
||||
16'b0000_00xx_001x_xxxx: cs = `CS_MARIA;
|
||||
|
||||
endcase else casex (AB)
|
||||
16'bxxx0_xx0x_1xxx_xxxx: cs = `CS_RIOT_RAM;
|
||||
16'bxxx0_xx1x_1xxx_xxxx: cs = `CS_RIOT_IO;
|
||||
16'bxxx0_xxxx_0xxx_xxxx: cs = `CS_TIA;
|
||||
endcase
|
||||
|
||||
if (bios_en & AB[15])
|
||||
cs = `CS_BIOS;
|
||||
|
||||
// If MARIA is selected, handle memory mapped registers
|
||||
if (cs == `CS_MARIA) begin
|
||||
if (we_b) begin
|
||||
read_addr_found = AB[7:0];
|
||||
write_addr_found = 8'h0;
|
||||
end
|
||||
else begin
|
||||
write_addr_found = AB[7:0];
|
||||
read_addr_found = 8'h0;
|
||||
end
|
||||
end else begin
|
||||
read_addr_found = 8'h0;
|
||||
write_addr_found = 8'h0;
|
||||
end
|
||||
|
||||
/*
|
||||
//Find write addresses on bus to latch data on next tick
|
||||
casex ({AB, we_b})
|
||||
{16'b0000_00xx_001x_xxxx,1'b0}: wr_addr_found = AB[7:0];
|
||||
default: wr_addr_found = 8'b0;
|
||||
endcase
|
||||
|
||||
casex ({AB, we_b})
|
||||
{16'b0000_00xx_001x_xxxx,1'b1}: read_addr_found = AB[7:0];
|
||||
default: read_addr_found = 8'b0;
|
||||
endcase
|
||||
*/
|
||||
|
||||
|
||||
end // always_comb
|
||||
|
||||
always_ff @(posedge pclk_0, negedge reset_b) begin
|
||||
if (~reset_b) begin
|
||||
ctrl <= {1'b0, 2'b10, 1'b0, 1'b0, 1'b0, 2'b00}; // 8'b0
|
||||
ctrl_kept <= 8'b0;
|
||||
//color_map <= 200'b0;
|
||||
//////// TESTING COLOR MAP /////////
|
||||
// Background
|
||||
color_map[0] <= 8'h0c;
|
||||
// Palette 0
|
||||
color_map[3:1] <= {8'h32, 8'h55, 8'h55};
|
||||
// Palette 1
|
||||
color_map[6:4] <= {8'h83, 8'h55, 8'h55};
|
||||
// Palette 2
|
||||
color_map[9:7] <= {8'h1c, 8'h55, 8'h55};
|
||||
// Palette 3
|
||||
color_map[12:10] <= {8'h25, 8'h55, 8'h55};
|
||||
// Palette 4
|
||||
color_map[15:13] <= {8'hda, 8'h55, 8'h55};
|
||||
|
||||
color_map[24:16] <= 'b0;
|
||||
|
||||
wait_sync <= 8'b0;
|
||||
char_base <= 8'b0;
|
||||
{ZPH,ZPL} <= {8'h18, 8'h20};
|
||||
zp_byte_written <= 2'b0;
|
||||
end
|
||||
|
||||
else begin
|
||||
ctrl_kept <= ctrl;
|
||||
deassert_ready <= 1'b0;
|
||||
//Handle writes to mem mapped regs
|
||||
case(write_addr_found)
|
||||
8'h20: color_map[0] <= DB_in;
|
||||
8'h21: color_map[1] <= DB_in;
|
||||
8'h22: color_map[2] <= DB_in;
|
||||
8'h23: color_map[3] <= DB_in;
|
||||
8'h24: begin
|
||||
wait_sync <= DB_in;
|
||||
deassert_ready <= 1'b1;
|
||||
end
|
||||
8'h25: color_map[4] <= DB_in;
|
||||
8'h26: color_map[5] <= DB_in;
|
||||
8'h27: color_map[6] <= DB_in;
|
||||
//8'h28: status_read <= DB_in; Read only
|
||||
8'h29: color_map[7] <= DB_in;
|
||||
8'h2a: color_map[8] <= DB_in;
|
||||
8'h2b: color_map[9] <= DB_in;
|
||||
8'h2c: begin
|
||||
ZPH <= DB_in;
|
||||
zp_byte_written[1] <= 1'b1;
|
||||
end
|
||||
8'h2d: color_map[10] <= DB_in;
|
||||
8'h2e: color_map[11] <= DB_in;
|
||||
8'h2f: color_map[12] <= DB_in;
|
||||
8'h30: begin
|
||||
ZPL <= DB_in;
|
||||
zp_byte_written[0] <= 1'b1;
|
||||
end
|
||||
8'h31: color_map[13] <= DB_in;
|
||||
8'h32: color_map[14] <= DB_in;
|
||||
8'h33: color_map[15] <= DB_in;
|
||||
8'h34: char_base <= DB_in;
|
||||
8'h35: color_map[16] <= DB_in;
|
||||
8'h36: color_map[17] <= DB_in;
|
||||
8'h37: color_map[18] <= DB_in;
|
||||
//8'h38: NOT USED
|
||||
8'h39: color_map[19] <= DB_in;
|
||||
8'h3a: color_map[20] <= DB_in;
|
||||
8'h3b: color_map[21] <= DB_in;
|
||||
8'h3c: ctrl <= DB_in;
|
||||
8'h3d: color_map[22] <= DB_in;
|
||||
8'h3e: color_map[23] <= DB_in;
|
||||
8'h3f: color_map[24] <= DB_in;
|
||||
default: ;
|
||||
endcase // case (wr_addr_found)
|
||||
|
||||
case(read_addr_found)
|
||||
8'h20: DB_out <= color_map[0];
|
||||
8'h21: DB_out <= color_map[1];
|
||||
8'h22: DB_out <= color_map[2];
|
||||
8'h23: DB_out <= color_map[3];
|
||||
8'h25: DB_out <= color_map[4];
|
||||
8'h26: DB_out <= color_map[5];
|
||||
8'h27: DB_out <= color_map[6];
|
||||
8'h28: DB_out <= status_read;
|
||||
8'h29: DB_out <= color_map[7];
|
||||
8'h2a: DB_out <= color_map[8];
|
||||
8'h2b: DB_out <= color_map[9];
|
||||
8'h2c: DB_out <= ZPH;
|
||||
8'h2d: DB_out <= color_map[10];
|
||||
8'h2e: DB_out <= color_map[11];
|
||||
8'h2f: DB_out <= color_map[12];
|
||||
8'h30: DB_out <= ZPL;
|
||||
8'h31: DB_out <= color_map[13];
|
||||
8'h32: DB_out <= color_map[14];
|
||||
8'h33: DB_out <= color_map[15];
|
||||
8'h34: DB_out <= char_base;
|
||||
8'h35: DB_out <= color_map[16];
|
||||
8'h36: DB_out <= color_map[17];
|
||||
8'h37: DB_out <= color_map[18];
|
||||
//8'h38: NOT USED
|
||||
8'h39: DB_out <= color_map[19];
|
||||
8'h3a: DB_out <= color_map[20];
|
||||
8'h3b: DB_out <= color_map[21];
|
||||
8'h3c: DB_out <= ctrl;
|
||||
8'h3d: DB_out <= color_map[22];
|
||||
8'h3e: DB_out <= color_map[23];
|
||||
8'h3f: DB_out <= color_map[24];
|
||||
default: DB_out <= 8'hbe;
|
||||
endcase // case (wr_addr_found)
|
||||
end // else: !if(~reset_b)
|
||||
end // always_ff @
|
||||
endmodule
|
||||
532
Atari - 7800_TeST/rtl/mist_io.sv
Normal file
532
Atari - 7800_TeST/rtl/mist_io.sv
Normal file
@@ -0,0 +1,532 @@
|
||||
//
|
||||
// mist_io.v
|
||||
//
|
||||
// mist_io for the MiST board
|
||||
// http://code.google.com/p/mist-board/
|
||||
//
|
||||
// Copyright (c) 2014 Till Harbaum <till@harbaum.org>
|
||||
//
|
||||
// This source file 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 source file 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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Use buffer to access SD card. It's time-critical part.
|
||||
// Made module synchroneous with 2 clock domains: clk_sys and SPI_SCK
|
||||
// (Sorgelig)
|
||||
//
|
||||
// for synchronous projects default value for PS2DIV is fine for any frequency of system clock.
|
||||
// clk_ps2 = clk_sys/(PS2DIV*2)
|
||||
//
|
||||
|
||||
module mist_io #(parameter STRLEN=0, parameter PS2DIV=100)
|
||||
(
|
||||
|
||||
// parameter STRLEN and the actual length of conf_str have to match
|
||||
input [(8*STRLEN)-1:0] conf_str,
|
||||
|
||||
// Global clock. It should be around 100MHz (higher is better).
|
||||
input clk_sys,
|
||||
|
||||
// Global SPI clock from ARM. 24MHz
|
||||
input SPI_SCK,
|
||||
|
||||
input CONF_DATA0,
|
||||
input SPI_SS2,
|
||||
output SPI_DO,
|
||||
input SPI_DI,
|
||||
|
||||
output reg [7:0] joystick_0,
|
||||
output reg [7:0] joystick_1,
|
||||
output reg [15:0] joystick_analog_0,
|
||||
output reg [15:0] joystick_analog_1,
|
||||
output [1:0] buttons,
|
||||
output [1:0] switches,
|
||||
output scandoubler_disable,
|
||||
output ypbpr,
|
||||
|
||||
output reg [31:0] status,
|
||||
|
||||
// SD config
|
||||
input sd_conf,
|
||||
input sd_sdhc,
|
||||
output img_mounted, // signaling that new image has been mounted
|
||||
output reg [31:0] img_size, // size of image in bytes
|
||||
|
||||
// SD block level access
|
||||
input [31:0] sd_lba,
|
||||
input sd_rd,
|
||||
input sd_wr,
|
||||
output reg sd_ack,
|
||||
output reg sd_ack_conf,
|
||||
|
||||
// SD byte level access. Signals for 2-PORT altsyncram.
|
||||
output reg [8:0] sd_buff_addr,
|
||||
output reg [7:0] sd_buff_dout,
|
||||
input [7:0] sd_buff_din,
|
||||
output reg sd_buff_wr,
|
||||
|
||||
// ps2 keyboard emulation
|
||||
output ps2_kbd_clk,
|
||||
output reg ps2_kbd_data,
|
||||
output ps2_mouse_clk,
|
||||
output reg ps2_mouse_data,
|
||||
|
||||
// ARM -> FPGA download
|
||||
input ioctl_force_erase,
|
||||
output reg ioctl_download = 0, // signal indicating an active download
|
||||
output reg ioctl_erasing = 0, // signal indicating an active erase
|
||||
output reg [7:0] ioctl_index, // menu index used to upload the file
|
||||
output reg ioctl_wr = 0,
|
||||
output reg [24:0] ioctl_addr,
|
||||
output reg [7:0] ioctl_dout
|
||||
);
|
||||
|
||||
reg [7:0] b_data;
|
||||
reg [6:0] sbuf;
|
||||
reg [7:0] cmd;
|
||||
reg [2:0] bit_cnt; // counts bits 0-7 0-7 ...
|
||||
reg [7:0] byte_cnt; // counts bytes
|
||||
reg [7:0] but_sw;
|
||||
reg [2:0] stick_idx;
|
||||
|
||||
reg mount_strobe = 0;
|
||||
assign img_mounted = mount_strobe;
|
||||
|
||||
assign buttons = but_sw[1:0];
|
||||
assign switches = but_sw[3:2];
|
||||
assign scandoubler_disable = but_sw[4];
|
||||
assign ypbpr = but_sw[5];
|
||||
|
||||
wire [7:0] spi_dout = { sbuf, SPI_DI};
|
||||
|
||||
// this variant of user_io is for 8 bit cores (type == a4) only
|
||||
wire [7:0] core_type = 8'ha4;
|
||||
|
||||
// command byte read by the io controller
|
||||
wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd };
|
||||
|
||||
reg spi_do;
|
||||
assign SPI_DO = CONF_DATA0 ? 1'bZ : spi_do;
|
||||
|
||||
// drive MISO only when transmitting core id
|
||||
always@(negedge SPI_SCK) begin
|
||||
if(!CONF_DATA0) begin
|
||||
// first byte returned is always core type, further bytes are
|
||||
// command dependent
|
||||
if(byte_cnt == 0) begin
|
||||
spi_do <= core_type[~bit_cnt];
|
||||
|
||||
end else begin
|
||||
case(cmd)
|
||||
// reading config string
|
||||
8'h14: begin
|
||||
// returning a byte from string
|
||||
if(byte_cnt < STRLEN + 1) spi_do <= conf_str[{STRLEN - byte_cnt,~bit_cnt}];
|
||||
else spi_do <= 0;
|
||||
end
|
||||
|
||||
// reading sd card status
|
||||
8'h16: begin
|
||||
if(byte_cnt == 1) spi_do <= sd_cmd[~bit_cnt];
|
||||
else if((byte_cnt >= 2) && (byte_cnt < 6)) spi_do <= sd_lba[{5-byte_cnt, ~bit_cnt}];
|
||||
else spi_do <= 0;
|
||||
end
|
||||
|
||||
// reading sd card write data
|
||||
8'h18:
|
||||
spi_do <= b_data[~bit_cnt];
|
||||
|
||||
default:
|
||||
spi_do <= 0;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
reg b_wr2,b_wr3;
|
||||
always @(negedge clk_sys) begin
|
||||
b_wr3 <= b_wr2;
|
||||
sd_buff_wr <= b_wr3;
|
||||
end
|
||||
|
||||
// SPI receiver
|
||||
always@(posedge SPI_SCK or posedge CONF_DATA0) begin
|
||||
|
||||
if(CONF_DATA0) begin
|
||||
b_wr2 <= 0;
|
||||
bit_cnt <= 0;
|
||||
byte_cnt <= 0;
|
||||
sd_ack <= 0;
|
||||
sd_ack_conf <= 0;
|
||||
end else begin
|
||||
b_wr2 <= 0;
|
||||
|
||||
sbuf <= spi_dout[6:0];
|
||||
bit_cnt <= bit_cnt + 1'd1;
|
||||
if(bit_cnt == 5) begin
|
||||
if (byte_cnt == 0) sd_buff_addr <= 0;
|
||||
if((byte_cnt != 0) & (sd_buff_addr != 511)) sd_buff_addr <= sd_buff_addr + 1'b1;
|
||||
if((byte_cnt == 1) & ((cmd == 8'h17) | (cmd == 8'h19))) sd_buff_addr <= 0;
|
||||
end
|
||||
|
||||
// finished reading command byte
|
||||
if(bit_cnt == 7) begin
|
||||
if(~&byte_cnt) byte_cnt <= byte_cnt + 8'd1;
|
||||
if(byte_cnt == 0) begin
|
||||
cmd <= spi_dout;
|
||||
|
||||
if(spi_dout == 8'h19) begin
|
||||
sd_ack_conf <= 1;
|
||||
sd_buff_addr <= 0;
|
||||
end
|
||||
if((spi_dout == 8'h17) || (spi_dout == 8'h18)) begin
|
||||
sd_ack <= 1;
|
||||
sd_buff_addr <= 0;
|
||||
end
|
||||
if(spi_dout == 8'h18) b_data <= sd_buff_din;
|
||||
|
||||
mount_strobe <= 0;
|
||||
|
||||
end else begin
|
||||
|
||||
case(cmd)
|
||||
// buttons and switches
|
||||
8'h01: but_sw <= spi_dout;
|
||||
8'h02: joystick_0 <= spi_dout;
|
||||
8'h03: joystick_1 <= spi_dout;
|
||||
|
||||
// store incoming ps2 mouse bytes
|
||||
8'h04: begin
|
||||
ps2_mouse_fifo[ps2_mouse_wptr] <= spi_dout;
|
||||
ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1;
|
||||
end
|
||||
|
||||
// store incoming ps2 keyboard bytes
|
||||
8'h05: begin
|
||||
ps2_kbd_fifo[ps2_kbd_wptr] <= spi_dout;
|
||||
ps2_kbd_wptr <= ps2_kbd_wptr + 1'd1;
|
||||
end
|
||||
|
||||
8'h15: status[7:0] <= spi_dout;
|
||||
|
||||
// send SD config IO -> FPGA
|
||||
// flag that download begins
|
||||
// sd card knows data is config if sd_dout_strobe is asserted
|
||||
// with sd_ack still being inactive (low)
|
||||
8'h19,
|
||||
// send sector IO -> FPGA
|
||||
// flag that download begins
|
||||
8'h17: begin
|
||||
sd_buff_dout <= spi_dout;
|
||||
b_wr2 <= 1;
|
||||
end
|
||||
|
||||
8'h18: b_data <= sd_buff_din;
|
||||
|
||||
// joystick analog
|
||||
8'h1a: begin
|
||||
// first byte is joystick index
|
||||
if(byte_cnt == 1) stick_idx <= spi_dout[2:0];
|
||||
else if(byte_cnt == 2) begin
|
||||
// second byte is x axis
|
||||
if(stick_idx == 0) joystick_analog_0[15:8] <= spi_dout;
|
||||
else if(stick_idx == 1) joystick_analog_1[15:8] <= spi_dout;
|
||||
end else if(byte_cnt == 3) begin
|
||||
// third byte is y axis
|
||||
if(stick_idx == 0) joystick_analog_0[7:0] <= spi_dout;
|
||||
else if(stick_idx == 1) joystick_analog_1[7:0] <= spi_dout;
|
||||
end
|
||||
end
|
||||
|
||||
// notify image selection
|
||||
8'h1c: mount_strobe <= 1;
|
||||
|
||||
// send image info
|
||||
8'h1d: if(byte_cnt<5) img_size[(byte_cnt-1)<<3 +:8] <= spi_dout;
|
||||
|
||||
// status, 32bit version
|
||||
8'h1e: if(byte_cnt<5) status[(byte_cnt-1)<<3 +:8] <= spi_dout;
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
/////////////////////////////// PS2 ///////////////////////////////
|
||||
// 8 byte fifos to store ps2 bytes
|
||||
localparam PS2_FIFO_BITS = 3;
|
||||
|
||||
reg clk_ps2;
|
||||
always @(negedge clk_sys) begin
|
||||
integer cnt;
|
||||
cnt <= cnt + 1'd1;
|
||||
if(cnt == PS2DIV) begin
|
||||
clk_ps2 <= ~clk_ps2;
|
||||
cnt <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
// keyboard
|
||||
reg [7:0] ps2_kbd_fifo[1<<PS2_FIFO_BITS];
|
||||
reg [PS2_FIFO_BITS-1:0] ps2_kbd_wptr;
|
||||
reg [PS2_FIFO_BITS-1:0] ps2_kbd_rptr;
|
||||
|
||||
// ps2 transmitter state machine
|
||||
reg [3:0] ps2_kbd_tx_state;
|
||||
reg [7:0] ps2_kbd_tx_byte;
|
||||
reg ps2_kbd_parity;
|
||||
|
||||
assign ps2_kbd_clk = clk_ps2 || (ps2_kbd_tx_state == 0);
|
||||
|
||||
// ps2 transmitter
|
||||
// Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
|
||||
reg ps2_kbd_r_inc;
|
||||
always@(posedge clk_sys) begin
|
||||
reg old_clk;
|
||||
old_clk <= clk_ps2;
|
||||
if(~old_clk & clk_ps2) begin
|
||||
ps2_kbd_r_inc <= 0;
|
||||
|
||||
if(ps2_kbd_r_inc) ps2_kbd_rptr <= ps2_kbd_rptr + 1'd1;
|
||||
|
||||
// transmitter is idle?
|
||||
if(ps2_kbd_tx_state == 0) begin
|
||||
// data in fifo present?
|
||||
if(ps2_kbd_wptr != ps2_kbd_rptr) begin
|
||||
// load tx register from fifo
|
||||
ps2_kbd_tx_byte <= ps2_kbd_fifo[ps2_kbd_rptr];
|
||||
ps2_kbd_r_inc <= 1;
|
||||
|
||||
// reset parity
|
||||
ps2_kbd_parity <= 1;
|
||||
|
||||
// start transmitter
|
||||
ps2_kbd_tx_state <= 1;
|
||||
|
||||
// put start bit on data line
|
||||
ps2_kbd_data <= 0; // start bit is 0
|
||||
end
|
||||
end else begin
|
||||
|
||||
// transmission of 8 data bits
|
||||
if((ps2_kbd_tx_state >= 1)&&(ps2_kbd_tx_state < 9)) begin
|
||||
ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits
|
||||
ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down
|
||||
if(ps2_kbd_tx_byte[0])
|
||||
ps2_kbd_parity <= !ps2_kbd_parity;
|
||||
end
|
||||
|
||||
// transmission of parity
|
||||
if(ps2_kbd_tx_state == 9) ps2_kbd_data <= ps2_kbd_parity;
|
||||
|
||||
// transmission of stop bit
|
||||
if(ps2_kbd_tx_state == 10) ps2_kbd_data <= 1; // stop bit is 1
|
||||
|
||||
// advance state machine
|
||||
if(ps2_kbd_tx_state < 11) ps2_kbd_tx_state <= ps2_kbd_tx_state + 1'd1;
|
||||
else ps2_kbd_tx_state <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// mouse
|
||||
reg [7:0] ps2_mouse_fifo[1<<PS2_FIFO_BITS];
|
||||
reg [PS2_FIFO_BITS-1:0] ps2_mouse_wptr;
|
||||
reg [PS2_FIFO_BITS-1:0] ps2_mouse_rptr;
|
||||
|
||||
// ps2 transmitter state machine
|
||||
reg [3:0] ps2_mouse_tx_state;
|
||||
reg [7:0] ps2_mouse_tx_byte;
|
||||
reg ps2_mouse_parity;
|
||||
|
||||
assign ps2_mouse_clk = clk_ps2 || (ps2_mouse_tx_state == 0);
|
||||
|
||||
// ps2 transmitter
|
||||
// Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
|
||||
reg ps2_mouse_r_inc;
|
||||
always@(posedge clk_sys) begin
|
||||
reg old_clk;
|
||||
old_clk <= clk_ps2;
|
||||
if(~old_clk & clk_ps2) begin
|
||||
ps2_mouse_r_inc <= 0;
|
||||
|
||||
if(ps2_mouse_r_inc) ps2_mouse_rptr <= ps2_mouse_rptr + 1'd1;
|
||||
|
||||
// transmitter is idle?
|
||||
if(ps2_mouse_tx_state == 0) begin
|
||||
// data in fifo present?
|
||||
if(ps2_mouse_wptr != ps2_mouse_rptr) begin
|
||||
// load tx register from fifo
|
||||
ps2_mouse_tx_byte <= ps2_mouse_fifo[ps2_mouse_rptr];
|
||||
ps2_mouse_r_inc <= 1;
|
||||
|
||||
// reset parity
|
||||
ps2_mouse_parity <= 1;
|
||||
|
||||
// start transmitter
|
||||
ps2_mouse_tx_state <= 1;
|
||||
|
||||
// put start bit on data line
|
||||
ps2_mouse_data <= 0; // start bit is 0
|
||||
end
|
||||
end else begin
|
||||
|
||||
// transmission of 8 data bits
|
||||
if((ps2_mouse_tx_state >= 1)&&(ps2_mouse_tx_state < 9)) begin
|
||||
ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits
|
||||
ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down
|
||||
if(ps2_mouse_tx_byte[0])
|
||||
ps2_mouse_parity <= !ps2_mouse_parity;
|
||||
end
|
||||
|
||||
// transmission of parity
|
||||
if(ps2_mouse_tx_state == 9) ps2_mouse_data <= ps2_mouse_parity;
|
||||
|
||||
// transmission of stop bit
|
||||
if(ps2_mouse_tx_state == 10) ps2_mouse_data <= 1; // stop bit is 1
|
||||
|
||||
// advance state machine
|
||||
if(ps2_mouse_tx_state < 11) ps2_mouse_tx_state <= ps2_mouse_tx_state + 1'd1;
|
||||
else ps2_mouse_tx_state <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
/////////////////////////////// DOWNLOADING ///////////////////////////////
|
||||
|
||||
reg [7:0] data_w;
|
||||
reg [24:0] addr_w;
|
||||
reg rclk = 0;
|
||||
|
||||
localparam UIO_FILE_TX = 8'h53;
|
||||
localparam UIO_FILE_TX_DAT = 8'h54;
|
||||
localparam UIO_FILE_INDEX = 8'h55;
|
||||
|
||||
// data_io has its own SPI interface to the io controller
|
||||
always@(posedge SPI_SCK, posedge SPI_SS2) begin
|
||||
reg [6:0] sbuf;
|
||||
reg [7:0] cmd;
|
||||
reg [4:0] cnt;
|
||||
reg [24:0] addr;
|
||||
|
||||
if(SPI_SS2) cnt <= 0;
|
||||
else begin
|
||||
rclk <= 0;
|
||||
|
||||
// don't shift in last bit. It is evaluated directly
|
||||
// when writing to ram
|
||||
if(cnt != 15) sbuf <= { sbuf[5:0], SPI_DI};
|
||||
|
||||
// increase target address after write
|
||||
if(rclk) addr <= addr + 1'd1;
|
||||
|
||||
// count 0-7 8-15 8-15 ...
|
||||
if(cnt < 15) cnt <= cnt + 1'd1;
|
||||
else cnt <= 8;
|
||||
|
||||
// finished command byte
|
||||
if(cnt == 7) cmd <= {sbuf, SPI_DI};
|
||||
|
||||
// prepare/end transmission
|
||||
if((cmd == UIO_FILE_TX) && (cnt == 15)) begin
|
||||
// prepare
|
||||
if(SPI_DI) begin
|
||||
case(ioctl_index)
|
||||
0: addr <= 'h080000; // BOOT ROM
|
||||
'h01: addr <= 'h000100; // ROM file
|
||||
'h41: addr <= 'h000100; // COM file
|
||||
'h81: addr <= 'h000000; // C00 file
|
||||
'hC1: addr <= 'h010000; // EDD file
|
||||
default: addr <= 'h100000; // FDD file
|
||||
endcase
|
||||
ioctl_download <= 1;
|
||||
end else begin
|
||||
addr_w <= addr;
|
||||
ioctl_download <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
// command 0x54: UIO_FILE_TX
|
||||
if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin
|
||||
addr_w <= addr;
|
||||
data_w <= {sbuf, SPI_DI};
|
||||
rclk <= 1;
|
||||
end
|
||||
|
||||
// expose file (menu) index
|
||||
if((cmd == UIO_FILE_INDEX) && (cnt == 15)) ioctl_index <= {sbuf, SPI_DI};
|
||||
end
|
||||
end
|
||||
|
||||
reg [24:0] erase_mask;
|
||||
wire [24:0] next_erase = (ioctl_addr + 1'd1) & erase_mask;
|
||||
|
||||
always@(posedge clk_sys) begin
|
||||
reg rclkD, rclkD2;
|
||||
reg old_force = 0;
|
||||
reg [5:0] erase_clk_div;
|
||||
reg [24:0] end_addr;
|
||||
reg erase_trigger = 0;
|
||||
|
||||
rclkD <= rclk;
|
||||
rclkD2 <= rclkD;
|
||||
ioctl_wr <= 0;
|
||||
|
||||
if(rclkD & ~rclkD2) begin
|
||||
ioctl_dout <= data_w;
|
||||
ioctl_addr <= addr_w;
|
||||
ioctl_wr <= 1;
|
||||
end
|
||||
|
||||
if(ioctl_download) begin
|
||||
old_force <= 0;
|
||||
ioctl_erasing <= 0;
|
||||
erase_trigger <= (ioctl_index == 1);
|
||||
end else begin
|
||||
|
||||
old_force <= ioctl_force_erase;
|
||||
|
||||
// start erasing
|
||||
if(erase_trigger) begin
|
||||
erase_trigger <= 0;
|
||||
erase_mask <= 'hFFFF;
|
||||
end_addr <= 'h0100;
|
||||
erase_clk_div <= 1;
|
||||
ioctl_erasing <= 1;
|
||||
end else if((ioctl_force_erase & ~old_force)) begin
|
||||
erase_trigger <= 0;
|
||||
ioctl_addr <= 'h1FFFFFF;
|
||||
erase_mask <= 'h1FFFFFF;
|
||||
end_addr <= 'h0050000;
|
||||
erase_clk_div <= 1;
|
||||
ioctl_erasing <= 1;
|
||||
end else if(ioctl_erasing) begin
|
||||
erase_clk_div <= erase_clk_div + 1'd1;
|
||||
if(!erase_clk_div) begin
|
||||
if(next_erase == end_addr) ioctl_erasing <= 0;
|
||||
else begin
|
||||
ioctl_addr <= next_erase;
|
||||
ioctl_dout <= 0;
|
||||
ioctl_wr <= 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
179
Atari - 7800_TeST/rtl/osd.sv
Normal file
179
Atari - 7800_TeST/rtl/osd.sv
Normal file
@@ -0,0 +1,179 @@
|
||||
// A simple OSD implementation. Can be hooked up between a cores
|
||||
// VGA output and the physical VGA pins
|
||||
|
||||
module osd (
|
||||
// OSDs pixel clock, should be synchronous to cores pixel clock to
|
||||
// avoid jitter.
|
||||
input clk_sys,
|
||||
|
||||
// SPI interface
|
||||
input SPI_SCK,
|
||||
input SPI_SS3,
|
||||
input SPI_DI,
|
||||
|
||||
// VGA signals coming from core
|
||||
input [5:0] R_in,
|
||||
input [5:0] G_in,
|
||||
input [5:0] B_in,
|
||||
input HSync,
|
||||
input VSync,
|
||||
|
||||
// VGA signals going to video connector
|
||||
output [5:0] R_out,
|
||||
output [5:0] G_out,
|
||||
output [5:0] B_out
|
||||
);
|
||||
|
||||
parameter OSD_X_OFFSET = 10'd0;
|
||||
parameter OSD_Y_OFFSET = 10'd0;
|
||||
parameter OSD_COLOR = 3'd0;
|
||||
|
||||
localparam OSD_WIDTH = 10'd256;
|
||||
localparam OSD_HEIGHT = 10'd128;
|
||||
|
||||
// *********************************************************************************
|
||||
// spi client
|
||||
// *********************************************************************************
|
||||
|
||||
// this core supports only the display related OSD commands
|
||||
// of the minimig
|
||||
reg osd_enable;
|
||||
(* ramstyle = "no_rw_check" *) reg [7:0] osd_buffer[2047:0]; // the OSD buffer itself
|
||||
|
||||
// the OSD has its own SPI interface to the io controller
|
||||
always@(posedge SPI_SCK, posedge SPI_SS3) begin
|
||||
reg [4:0] cnt;
|
||||
reg [10:0] bcnt;
|
||||
reg [7:0] sbuf;
|
||||
reg [7:0] cmd;
|
||||
|
||||
if(SPI_SS3) begin
|
||||
cnt <= 0;
|
||||
bcnt <= 0;
|
||||
end else begin
|
||||
sbuf <= {sbuf[6:0], SPI_DI};
|
||||
|
||||
// 0:7 is command, rest payload
|
||||
if(cnt < 15) cnt <= cnt + 1'd1;
|
||||
else cnt <= 8;
|
||||
|
||||
if(cnt == 7) begin
|
||||
cmd <= {sbuf[6:0], SPI_DI};
|
||||
|
||||
// lower three command bits are line address
|
||||
bcnt <= {sbuf[1:0], SPI_DI, 8'h00};
|
||||
|
||||
// command 0x40: OSDCMDENABLE, OSDCMDDISABLE
|
||||
if(sbuf[6:3] == 4'b0100) osd_enable <= SPI_DI;
|
||||
end
|
||||
|
||||
// command 0x20: OSDCMDWRITE
|
||||
if((cmd[7:3] == 5'b00100) && (cnt == 15)) begin
|
||||
osd_buffer[bcnt] <= {sbuf[6:0], SPI_DI};
|
||||
bcnt <= bcnt + 1'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// *********************************************************************************
|
||||
// video timing and sync polarity anaylsis
|
||||
// *********************************************************************************
|
||||
|
||||
// horizontal counter
|
||||
reg [9:0] h_cnt;
|
||||
reg [9:0] hs_low, hs_high;
|
||||
wire hs_pol = hs_high < hs_low;
|
||||
wire [9:0] dsp_width = hs_pol ? hs_low : hs_high;
|
||||
|
||||
// vertical counter
|
||||
reg [9:0] v_cnt;
|
||||
reg [9:0] vs_low, vs_high;
|
||||
wire vs_pol = vs_high < vs_low;
|
||||
wire [9:0] dsp_height = vs_pol ? vs_low : vs_high;
|
||||
|
||||
wire doublescan = (dsp_height>350);
|
||||
|
||||
reg ce_pix;
|
||||
always @(negedge clk_sys) begin
|
||||
integer cnt = 0;
|
||||
integer pixsz, pixcnt;
|
||||
reg hs;
|
||||
|
||||
cnt <= cnt + 1;
|
||||
hs <= HSync;
|
||||
|
||||
pixcnt <= pixcnt + 1;
|
||||
if(pixcnt == pixsz) pixcnt <= 0;
|
||||
ce_pix <= !pixcnt;
|
||||
|
||||
if(hs && ~HSync) begin
|
||||
cnt <= 0;
|
||||
pixsz <= (cnt >> 9) - 1;
|
||||
pixcnt <= 0;
|
||||
ce_pix <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
reg hsD, hsD2;
|
||||
reg vsD, vsD2;
|
||||
|
||||
if(ce_pix) begin
|
||||
// bring hsync into local clock domain
|
||||
hsD <= HSync;
|
||||
hsD2 <= hsD;
|
||||
|
||||
// falling edge of HSync
|
||||
if(!hsD && hsD2) begin
|
||||
h_cnt <= 0;
|
||||
hs_high <= h_cnt;
|
||||
end
|
||||
|
||||
// rising edge of HSync
|
||||
else if(hsD && !hsD2) begin
|
||||
h_cnt <= 0;
|
||||
hs_low <= h_cnt;
|
||||
v_cnt <= v_cnt + 1'd1;
|
||||
end else begin
|
||||
h_cnt <= h_cnt + 1'd1;
|
||||
end
|
||||
|
||||
vsD <= VSync;
|
||||
vsD2 <= vsD;
|
||||
|
||||
// falling edge of VSync
|
||||
if(!vsD && vsD2) begin
|
||||
v_cnt <= 0;
|
||||
vs_high <= v_cnt;
|
||||
end
|
||||
|
||||
// rising edge of VSync
|
||||
else if(vsD && !vsD2) begin
|
||||
v_cnt <= 0;
|
||||
vs_low <= v_cnt;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// area in which OSD is being displayed
|
||||
wire [9:0] h_osd_start = ((dsp_width - OSD_WIDTH)>> 1) + OSD_X_OFFSET;
|
||||
wire [9:0] h_osd_end = h_osd_start + OSD_WIDTH;
|
||||
wire [9:0] v_osd_start = ((dsp_height- (OSD_HEIGHT<<doublescan))>> 1) + OSD_Y_OFFSET;
|
||||
wire [9:0] v_osd_end = v_osd_start + (OSD_HEIGHT<<doublescan);
|
||||
wire [9:0] osd_hcnt = h_cnt - h_osd_start + 1'd1; // one pixel offset for osd_byte register
|
||||
wire [9:0] osd_vcnt = v_cnt - v_osd_start;
|
||||
|
||||
wire osd_de = osd_enable &&
|
||||
(HSync != hs_pol) && (h_cnt >= h_osd_start) && (h_cnt < h_osd_end) &&
|
||||
(VSync != vs_pol) && (v_cnt >= v_osd_start) && (v_cnt < v_osd_end);
|
||||
|
||||
reg [7:0] osd_byte;
|
||||
always @(posedge clk_sys) if(ce_pix) osd_byte <= osd_buffer[{doublescan ? osd_vcnt[7:5] : osd_vcnt[6:4], osd_hcnt[7:0]}];
|
||||
|
||||
wire osd_pixel = osd_byte[doublescan ? osd_vcnt[4:2] : osd_vcnt[3:1]];
|
||||
|
||||
assign R_out = !osd_de ? R_in : {osd_pixel, osd_pixel, OSD_COLOR[2], R_in[5:3]};
|
||||
assign G_out = !osd_de ? G_in : {osd_pixel, osd_pixel, OSD_COLOR[1], G_in[5:3]};
|
||||
assign B_out = !osd_de ? B_in : {osd_pixel, osd_pixel, OSD_COLOR[0], B_in[5:3]};
|
||||
|
||||
endmodule
|
||||
376
Atari - 7800_TeST/rtl/pll.v
Normal file
376
Atari - 7800_TeST/rtl/pll.v
Normal file
@@ -0,0 +1,376 @@
|
||||
// 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 Web Edition
|
||||
// ************************************************************
|
||||
|
||||
|
||||
//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,
|
||||
c2,
|
||||
locked);
|
||||
|
||||
input areset;
|
||||
input inclk0;
|
||||
output c0;
|
||||
output c1;
|
||||
output c2;
|
||||
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_wire7 = 1'h0;
|
||||
wire [2:2] sub_wire4 = sub_wire0[2:2];
|
||||
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 c2 = sub_wire4;
|
||||
wire sub_wire5 = inclk0;
|
||||
wire [1:0] sub_wire6 = {sub_wire7, sub_wire5};
|
||||
|
||||
altpll altpll_component (
|
||||
.areset (areset),
|
||||
.inclk (sub_wire6),
|
||||
.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 = 27,
|
||||
altpll_component.clk0_duty_cycle = 50,
|
||||
altpll_component.clk0_multiply_by = 25,
|
||||
altpll_component.clk0_phase_shift = "0",
|
||||
altpll_component.clk1_divide_by = 189,
|
||||
altpll_component.clk1_duty_cycle = 50,
|
||||
altpll_component.clk1_multiply_by = 50,
|
||||
altpll_component.clk1_phase_shift = "0",
|
||||
altpll_component.clk2_divide_by = 108,
|
||||
altpll_component.clk2_duty_cycle = 50,
|
||||
altpll_component.clk2_multiply_by = 25,
|
||||
altpll_component.clk2_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_USED",
|
||||
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 "27"
|
||||
// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "189"
|
||||
// Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "108"
|
||||
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
|
||||
// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
|
||||
// Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000"
|
||||
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "25.000000"
|
||||
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "7.142857"
|
||||
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "6.250000"
|
||||
// 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 "deg"
|
||||
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "deg"
|
||||
// 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: MIRROR_CLK2 STRING "0"
|
||||
// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "25"
|
||||
// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "50"
|
||||
// Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "25"
|
||||
// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "25.00000000"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "7.14300000"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "6.25000000"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "0"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 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_SHIFT2 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: PHASE_SHIFT_UNIT2 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: STICKY_CLK2 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_CLK2 STRING "1"
|
||||
// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
|
||||
// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
|
||||
// Retrieval info: PRIVATE: USE_CLKENA2 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 "27"
|
||||
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
|
||||
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "25"
|
||||
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
|
||||
// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "189"
|
||||
// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
|
||||
// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "50"
|
||||
// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
|
||||
// Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "108"
|
||||
// Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50"
|
||||
// Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "25"
|
||||
// Retrieval info: CONSTANT: CLK2_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_USED"
|
||||
// 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: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2"
|
||||
// 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: c2 0 0 0 0 @clk 0 0 1 2
|
||||
// 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
|
||||
177
Atari - 7800_TeST/rtl/ram2k.v
Normal file
177
Atari - 7800_TeST/rtl/ram2k.v
Normal file
@@ -0,0 +1,177 @@
|
||||
// megafunction wizard: %RAM: 1-PORT%
|
||||
// GENERATION: STANDARD
|
||||
// VERSION: WM1.0
|
||||
// MODULE: altsyncram
|
||||
|
||||
// ============================================================
|
||||
// File Name: ram2k.v
|
||||
// Megafunction Name(s):
|
||||
// altsyncram
|
||||
//
|
||||
// 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 Web Edition
|
||||
// ************************************************************
|
||||
|
||||
|
||||
//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 ram2k (
|
||||
address,
|
||||
clken,
|
||||
clock,
|
||||
data,
|
||||
wren,
|
||||
q);
|
||||
|
||||
input [10:0] address;
|
||||
input clken;
|
||||
input clock;
|
||||
input [7:0] data;
|
||||
input wren;
|
||||
output [7:0] q;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_off
|
||||
`endif
|
||||
tri1 clken;
|
||||
tri1 clock;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_on
|
||||
`endif
|
||||
|
||||
wire [7:0] sub_wire0;
|
||||
wire [7:0] q = sub_wire0[7:0];
|
||||
|
||||
altsyncram altsyncram_component (
|
||||
.address_a (address),
|
||||
.clock0 (clock),
|
||||
.data_a (data),
|
||||
.wren_a (wren),
|
||||
.clocken0 (clken),
|
||||
.q_a (sub_wire0),
|
||||
.aclr0 (1'b0),
|
||||
.aclr1 (1'b0),
|
||||
.address_b (1'b1),
|
||||
.addressstall_a (1'b0),
|
||||
.addressstall_b (1'b0),
|
||||
.byteena_a (1'b1),
|
||||
.byteena_b (1'b1),
|
||||
.clock1 (1'b1),
|
||||
.clocken1 (1'b1),
|
||||
.clocken2 (1'b1),
|
||||
.clocken3 (1'b1),
|
||||
.data_b (1'b1),
|
||||
.eccstatus (),
|
||||
.q_b (),
|
||||
.rden_a (1'b1),
|
||||
.rden_b (1'b1),
|
||||
.wren_b (1'b0));
|
||||
defparam
|
||||
altsyncram_component.clock_enable_input_a = "NORMAL",
|
||||
altsyncram_component.clock_enable_output_a = "NORMAL",
|
||||
altsyncram_component.intended_device_family = "Cyclone III",
|
||||
altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
|
||||
altsyncram_component.lpm_type = "altsyncram",
|
||||
altsyncram_component.numwords_a = 2048,
|
||||
altsyncram_component.operation_mode = "SINGLE_PORT",
|
||||
altsyncram_component.outdata_aclr_a = "NONE",
|
||||
altsyncram_component.outdata_reg_a = "CLOCK0",
|
||||
altsyncram_component.power_up_uninitialized = "FALSE",
|
||||
altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
|
||||
altsyncram_component.widthad_a = 11,
|
||||
altsyncram_component.width_a = 8,
|
||||
altsyncram_component.width_byteena_a = 1;
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
// ============================================================
|
||||
// CNX file retrieval info
|
||||
// ============================================================
|
||||
// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrAddr NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrByte NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrData NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrOutput NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: BlankMemory NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: Clken NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
|
||||
// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
|
||||
// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: MIFfilename STRING ""
|
||||
// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "2048"
|
||||
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3"
|
||||
// Retrieval info: PRIVATE: RegAddr NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: RegData NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: RegOutput NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
|
||||
// Retrieval info: PRIVATE: SingleClock NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: UseDQRAM NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: WidthAddr NUMERIC "11"
|
||||
// Retrieval info: PRIVATE: WidthData NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: rden NUMERIC "0"
|
||||
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
||||
// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "NORMAL"
|
||||
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "NORMAL"
|
||||
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO"
|
||||
// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
|
||||
// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "2048"
|
||||
// Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT"
|
||||
// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
|
||||
// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0"
|
||||
// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE"
|
||||
// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ"
|
||||
// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "11"
|
||||
// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
|
||||
// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
|
||||
// Retrieval info: USED_PORT: address 0 0 11 0 INPUT NODEFVAL "address[10..0]"
|
||||
// Retrieval info: USED_PORT: clken 0 0 0 0 INPUT VCC "clken"
|
||||
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
|
||||
// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]"
|
||||
// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]"
|
||||
// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL "wren"
|
||||
// Retrieval info: CONNECT: @address_a 0 0 11 0 address 0 0 11 0
|
||||
// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
|
||||
// Retrieval info: CONNECT: @clocken0 0 0 0 0 clken 0 0 0 0
|
||||
// Retrieval info: CONNECT: @data_a 0 0 8 0 data 0 0 8 0
|
||||
// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0
|
||||
// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL ram2k.v TRUE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL ram2k.inc FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL ram2k.cmp FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL ram2k.bsf FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL ram2k_inst.v FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL ram2k_bb.v FALSE
|
||||
// Retrieval info: LIB_FILE: altera_mf
|
||||
26
Atari - 7800_TeST/rtl/riot.vh
Normal file
26
Atari - 7800_TeST/rtl/riot.vh
Normal file
@@ -0,0 +1,26 @@
|
||||
/* Atari on an FPGA
|
||||
Masters of Engineering Project
|
||||
Cornell University, 2007
|
||||
Daniel Beer
|
||||
RIOT.h
|
||||
Header file that contains useful definitions for the RIOT module.
|
||||
*/
|
||||
`define READ_RAM 7'b01xxxxx
|
||||
`define WRITE_RAM 7'b00xxxxx
|
||||
`define READ_DRA 7'b11xx000
|
||||
`define WRITE_DRA 7'b10xx000
|
||||
`define READ_DDRA 7'b11xx001
|
||||
`define WRITE_DDRA 7'b10xx001
|
||||
`define READ_DRB 7'b11xx010
|
||||
`define WRITE_DRB 7'b10xx010
|
||||
`define READ_DDRB 7'b11xx011
|
||||
`define WRITE_DDRB 7'b10xx011
|
||||
`define WRITE_TIMER 7'b101x1xx
|
||||
`define READ_TIMER 7'b11xx1x0
|
||||
`define READ_INT_FLAG 7'b11xx1x1
|
||||
`define WRITE_EDGE_DETECT 7'b100x1x0
|
||||
`define NOP 7'b0100000
|
||||
`define TM_1 2'b00
|
||||
`define TM_8 2'b01
|
||||
`define TM_64 2'b10
|
||||
`define TM_1024 2'b11
|
||||
257
Atari - 7800_TeST/rtl/rom/7800ntsc.hex
Normal file
257
Atari - 7800_TeST/rtl/rom/7800ntsc.hex
Normal file
@@ -0,0 +1,257 @@
|
||||
:10000000486CF400FFFFFFFFFFFFFFFFFFFFFFFF54
|
||||
:10001000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0
|
||||
:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
|
||||
:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0
|
||||
:10004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0
|
||||
:10005000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0
|
||||
:10006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0
|
||||
:10007000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90
|
||||
:10008000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80
|
||||
:10009000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70
|
||||
:1000A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60
|
||||
:1000B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50
|
||||
:1000C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40
|
||||
:1000D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF30
|
||||
:1000E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20
|
||||
:1000F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10
|
||||
:10010000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
||||
:10011000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF
|
||||
:10012000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF
|
||||
:10013000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF
|
||||
:10014000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF
|
||||
:10015000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF
|
||||
:10016000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F
|
||||
:10017000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F
|
||||
:10018000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F
|
||||
:10019000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F
|
||||
:1001A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F
|
||||
:1001B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F
|
||||
:1001C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F
|
||||
:1001D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F
|
||||
:1001E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F
|
||||
:1001F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0F
|
||||
:10020000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE
|
||||
:10021000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEE
|
||||
:10022000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDE
|
||||
:10023000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCE
|
||||
:10024000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBE
|
||||
:10025000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAE
|
||||
:10026000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E
|
||||
:10027000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E
|
||||
:10028000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E
|
||||
:10029000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E
|
||||
:1002A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E
|
||||
:1002B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E
|
||||
:1002C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3E
|
||||
:1002D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E
|
||||
:1002E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E
|
||||
:1002F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0E
|
||||
:10030000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD
|
||||
:10031000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED
|
||||
:10032000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDD
|
||||
:10033000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD
|
||||
:10034000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD
|
||||
:10035000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD
|
||||
:10036000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9D
|
||||
:10037000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D
|
||||
:10038000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7D
|
||||
:10039000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D
|
||||
:1003A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D
|
||||
:1003B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D
|
||||
:1003C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3D
|
||||
:1003D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2D
|
||||
:1003E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1D
|
||||
:1003F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0D
|
||||
:100400004CC2264CC226A9168501A0FFA27FBD00C2
|
||||
:10041000FED980FDD0EA88CA10F4ADFCFF2DFDFFA7
|
||||
:10042000C9FFF0DCADFCFF0DFDFFF0D4ADF8FF0916
|
||||
:10043000FEC9FFD0CEADF8FF49F029F0D0C5ADF927
|
||||
:10044000FF290BC903D0BCADF9FF29F085EE8D065D
|
||||
:1004500024C94090AEE901CDFDFFB0A7203625A903
|
||||
:100460000085F0201B24A9168501A2008A9D001892
|
||||
:10047000CAD0FA48A07FB900FF99001888C0F8D008
|
||||
:10048000F5A92E8D0924A9248D0A24201B24682077
|
||||
:10049000FF2348EE0624AD0624C9FFD0EE201B241E
|
||||
:1004A000201224201224A9368D0924A9248D0A247F
|
||||
:1004B000CE0624201B246820FF2348CE0624AD0648
|
||||
:1004C00024C5EEB0EEA960853CA277BD00185D5052
|
||||
:1004D000185D88189D001ACA10F1AD001A29078D01
|
||||
:1004E000001AA900A2049D001A9D0020A277BD0059
|
||||
:1004F00020DD001AD006CA10F54CB9264CC226A23F
|
||||
:10050000007D00187D00FFA8B9D52D9D0018E8D00A
|
||||
:10051000F060A2003E0018E8D0FA6008C6F0100CA7
|
||||
:10052000A9028501A5F030FCA91685012860C765E0
|
||||
:10053000ABCAEEF78309E1D0926762B672558E912D
|
||||
:10054000DCC581BE782059B7E63D0645AFC8083105
|
||||
:1005500038D1FB7384A917FC3487A394FA90B8EDC3
|
||||
:10056000CE3B5B0A43D9F35382B30D6D5A609D5164
|
||||
:10057000A7B91110BCE47F8041E7E3F6562635ECBD
|
||||
:10058000D6DF0C7FF49EAC5246EFCFBFA23FA41340
|
||||
:1005900015974A1CB0428CB105588018772B023E43
|
||||
:1005A000A8491A6ACB6E0B8AEBF14F14798BD89F4E
|
||||
:1005B0009B5719F82A2D760EE82E4BF90703DE9388
|
||||
:1005C000167ED4E5B2F07D7ADAD2A1CC1DE05E23AE
|
||||
:1005D000A095221E3685FE1F39AA8996AD0F2FC021
|
||||
:1005E00047275D24EAC3A5F5215F1B408FAE742524
|
||||
:1005F000DDC17CCDA670D7337B2C75BB8699BD54ED
|
||||
:100600009A6C6332484C8DBA5C61C44E293712C66D
|
||||
:10061000989CD5696BE2044DE9C2883ADB640144D9
|
||||
:100620006FB5F23028FD50713CB46668C9D3CA83F7
|
||||
:10063000C7ABF76509EEA27786E486E5BD80FF9D2E
|
||||
:1006400001199D0020CA10F4A90285012084FB2015
|
||||
:100650007B25C6F2A27786E4BDD5FE9D0119CA109E
|
||||
:10066000F7A5E185E320E125C6F2A5E08D7225A27C
|
||||
:1006700077BD00189D0020CA10F760203926A4E538
|
||||
:10068000C884E1981865E248AAA9008D71269D00EA
|
||||
:1006900018CAD0FA8D0018C88C6E268C74268C7CF3
|
||||
:1006A000268C8126A200CE6E26CE7426CE7C26CE47
|
||||
:1006B0008126C6E1301BA4E1B900203DD925F0090F
|
||||
:1006C000BD62268D7226206A26E8E00830E84CA438
|
||||
:1006D000256885E1A90185E0600102040810204039
|
||||
:1006E00080203926A5E338E5E485E085E1A2008E87
|
||||
:1006F00000188E8F268EAC26CA8EA9268E8C268E4A
|
||||
:1007000092268E9A268E9F26A207EEA926EE8C268A
|
||||
:10071000EE9226EE9A26EE9F26C6E13017BD62269F
|
||||
:100720008D90268DAD2620A6269003208826CA10FF
|
||||
:10073000EC4C0826A5E385E160A6E4E886E2A0008B
|
||||
:100740008C0019B962268D5526C8B962268D5926A6
|
||||
:10075000A6E218BD00192A9D0019CA10F6C007307C
|
||||
:10076000E260191A1B1C1D1E1F21A4E218B90018F3
|
||||
:100770007900199900188810F4900CB900176900D5
|
||||
:10078000990017884C792660A4E238B90018F9005E
|
||||
:10079000199900188810F4B00CB90017E9009900F5
|
||||
:1007A00017884C972660A000B90018D90019F001ED
|
||||
:1007B00060C4E2F0FBC84CA826A21686019AF86C29
|
||||
:1007C000FCFFA9028501A27FBDD4F79D8004CA1059
|
||||
:1007D000F74C8004A900AA85019503E8E02AD0F926
|
||||
:1007E0008502A904EA3023A204CA10FD9A8D1001E3
|
||||
:1007F00020CB0420CB048511851B851C850FEA8541
|
||||
:1008000002A900EA300424033009A90285098D12E7
|
||||
:10081000F1D01E2402300CA90285068D18F18D60DE
|
||||
:10082000F4D00E852CA908851B20CB04EA240230C5
|
||||
:10083000D9A9FD85086CFCFFEAFFFFFFFFFFFFFF62
|
||||
:10084000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB8
|
||||
:10085000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA8
|
||||
:10086000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF98
|
||||
:10087000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF88
|
||||
:10088000A91D850178D8A9028501A9FB85F5A912C2
|
||||
:1008900085F4A97F853CA9008520A205BD1DF9A08E
|
||||
:1008A00000990020D90020D027990021D90021D01B
|
||||
:1008B0001F88D0EDCA10E5A9438D8020C580D00BDC
|
||||
:1008C0008D8021CD8001D0034C38F9A0044C80F8F4
|
||||
:1008D0008D0018CD0018D00AA0014C80F8A0024C61
|
||||
:1008E00080F8A0034C80F8A90085F085F2A0078469
|
||||
:1008F000F4B923F985F1B92BF985F3A205BD1DF9EA
|
||||
:10090000A00091F0D1F0D0D091F2D1F2D0CF88D028
|
||||
:10091000F1CA10E9C6F4A4F410D74C17FB00FF5538
|
||||
:10092000AA690F222324252627222318191A1B1C03
|
||||
:100930001D1E1FA0004C80F8A9AAF0F710F5300387
|
||||
:100940004C33F9D0034C33F985AAC5AAD0E5A900E8
|
||||
:10095000D0E130DF10034C33F9F0034C33F9C90018
|
||||
:10096000D0D190CFB0034C33F9C901B0C690034C3D
|
||||
:1009700033F9A255E056F0BB8EAA01ECAA01D0B320
|
||||
:10098000A4AAC0ABF0AD8C5501CC5501D0A5CA9A34
|
||||
:10099000E868C9AAD0558A48EC5501D04E98C9AA32
|
||||
:1009A000D049AABD0001A8C055D040B500C5AAD005
|
||||
:1009B0003AC9AAD03649FF990000C555D02DD900B3
|
||||
:1009C00001D028DDAB20D023A92085F1A9CC85F06A
|
||||
:1009D0008146C5CCD01591F0CD2121D00EA9EE8550
|
||||
:1009E000F0A9F985F16CF0004CEBF94C33F9A955FD
|
||||
:1009F000186955EAB0F510F3F0F1C9AAD0ED6955C0
|
||||
:100A0000EA90E830E6D0E4E955B0E010DEF0DCC969
|
||||
:100A1000ABD0D818E9AA90D330D1D0CFA9FFAAE89B
|
||||
:100A2000D036CAF0331031E0FFD02DA8C8D02988C5
|
||||
:100A3000F026C8D02385F0E6F0D01DC4F0D019C64A
|
||||
:100A4000F0F015C5F0D011A9AA182A2A2AC952D047
|
||||
:100A5000076A6A6AC9AAF0034C33F90A90FA0AB025
|
||||
:100A6000F70AC950D0F249054A90ED4AB0EA4AC99E
|
||||
:100A70000AD0E5A955091BC95FD0DD2955291BC935
|
||||
:100A800011D0D50955491BC94ED0CD2091FA4C58EB
|
||||
:100A9000FABAE052D0C268C98DD0BD68C9FAD0B8E0
|
||||
:100AA000A9F848A9E648604C58FA8A48A943853C09
|
||||
:100AB000A20FA5EF852224F3500610028524852479
|
||||
:100AC000852438E910C910B002E90F8522CA10EC5C
|
||||
:100AD000A240863C29F0090E8527A5EF29F00906DA
|
||||
:100AE000852529F01869409002690F09038526C6FB
|
||||
:100AF000F11019A5F369609011A5EF186910900223
|
||||
:100B0000690F85EFA5F285F1A90085F3A90285F0AB
|
||||
:100B100068AA68404C14FBA2FF9AA900AA9501E8B4
|
||||
:100B2000E02CD0F9A9028501A2008620BD00F49D29
|
||||
:100B30000023BD00F59D0024BD00F69D0025BD00ED
|
||||
:100B4000F79D0026BD00F89D0027BDBEFB9D00223D
|
||||
:100B5000E000302ABD4BFC9D841FBDC6FC9D84195E
|
||||
:100B6000BD3DFD9D841ABDB4FD9D841BBD18FE9D39
|
||||
:100B7000841CBD57FE9D841DBD96FE9D841ECAD05B
|
||||
:100B8000AB4C0623ADF9FF2904F032A90385F185AA
|
||||
:100B9000F2A94985EFA9668525A9568526A92E853E
|
||||
:100BA00027A9AA85F4A9FA85F5242830FC24281061
|
||||
:100BB000FCA9848530A91F852CA943853C60841F2E
|
||||
:100BC00019BB00008440191FBB0000851C194A0096
|
||||
:100BD00000891C194A00008D1C19480000911B193E
|
||||
:100BE0004600009619194200009D17193E0000A604
|
||||
:100BF00017193E0000AF2C1C00AF2C1C500000AF9A
|
||||
:100C00002C1D00AF2C1D500000AF2D19280000C274
|
||||
:100C10002D19280000D52D19280000E82D192800CD
|
||||
:100C200000AF2D1A280000C22D1A280000D52D1A59
|
||||
:100C3000280000E82D1A280000AF2D1B280000C254
|
||||
:100C40002D1B280000D52D1B2800000F22060F2287
|
||||
:100C5000000F22000F220003220085220D0522131F
|
||||
:100C600005221905221F05222505222B0522310FF9
|
||||
:100C7000220001223700224B022237002251022299
|
||||
:100C80003700225702223700225D022237002263FA
|
||||
:100C900002223700226902223700226F0222370027
|
||||
:100CA000227502223700227B022237002281022293
|
||||
:100CB000370022870122410F22000F22000F22005D
|
||||
:100CC0000F22000F2200007C7F8F80FC7F8FC01FCF
|
||||
:100CD00087F87E0FE07F81FC07FF807F807FF81F11
|
||||
:100CE000FFF0007F8003FFFE1F0000007F800000F8
|
||||
:100CF0003E00000C003FFFFFFFF000C000003FFF80
|
||||
:100D0000FF0003FC00003F003FFFFFFFF003F00087
|
||||
:100D1000003FFFFFFC03FC0000FFC00003FF0000DA
|
||||
:100D20000FFC00003FF003FFC3FC0003FFF00003D3
|
||||
:100D3000FF00003FFF00003FF0003FC3FC007C7F4E
|
||||
:100D40008F807C7F8F801F87F87E0FF07F83FC0170
|
||||
:100D5000FF807F807FE01FFFF8007F8007FFFE1F7E
|
||||
:100D6000F000007F800003FE000FF3FC0003FF0093
|
||||
:100D700000FF3FC0003FF000FFC3FC003FC0FF008A
|
||||
:100D800003FF0003FC0FF0003FF03FFC03FC00FFFB
|
||||
:100D9000003FC003FF000FF003FC003FF0FFC00363
|
||||
:100DA000FC03FFFFFFF003FF003FFFFFFF003FF0EA
|
||||
:100DB0003FF003FC007C7F8F807C7F8F801F87F853
|
||||
:100DC0007E07F07F83F800FFC07F80FFC01FFFFC1D
|
||||
:100DD000007F800FFFFE1FFC00007F80000FFE0FD2
|
||||
:100DE000FFFFFFFC03FF00FFFFFFFFC03FF00FFC12
|
||||
:100DF00003FC3FF00003FF03FF03FF00003FF03F51
|
||||
:100E0000F003FF03FCFFC00000FFC3FF0FFC000066
|
||||
:100E10000FFC3FF000FFC3FC007C7F8F807C7F8F46
|
||||
:100E2000800F87F87C07F07F83F8007FC07F80FF0A
|
||||
:100E3000801FFFFE007F801FFFFE1FFF00007F80DE
|
||||
:100E4000003FFE5555555555555555555555555514
|
||||
:100E500055555555555555007C7F8F807C7F8F802B
|
||||
:100E60000FC7F8FC03F07F83F0003FE07F81FF00B5
|
||||
:100E700001FFFE007F801FFFE01FFFC0007F80009A
|
||||
:100E8000FFFEAAAAAAAAAAAAAAAAAAAAAAAAAAAA19
|
||||
:100E9000AAAAAAAAAAAA007C7F8F807C7F8F800F33
|
||||
:100EA000C7F8FC03F87F87F0001FE07F81FE000099
|
||||
:100EB0001FFF007F803FFE001FFFE0007F8001FFDB
|
||||
:100EC000FE55555555555555555555555555555529
|
||||
:100ED000555555555509CAC9C6B412081B605881E5
|
||||
:100EE0004B8601D8BFD925A07BDC3279843B7CBC02
|
||||
:100EF0002FE2E2FA8D0A003BC5ECAF2D8ACD0693B6
|
||||
:100F00006AA5144677C46AB25336EF8CCE0CA26839
|
||||
:100F100071D373E8F76D06B520EF23470C5155C820
|
||||
:100F2000FEF458C43F20A76738B076E2C4D8056302
|
||||
:100F3000F83C583B2D22CC88B3718F1D800A87BDA9
|
||||
:100F4000A15923E970E2D3EC4668804239EAFFFFF9
|
||||
:100F5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1
|
||||
:100F6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91
|
||||
:100F7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81
|
||||
:100F8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71
|
||||
:100F9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61
|
||||
:100FA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51
|
||||
:100FB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41
|
||||
:100FC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31
|
||||
:100FD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21
|
||||
:100FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFF474385
|
||||
:100FF00043284329313938342DF700F084F833F988
|
||||
:00000001FF
|
||||
BIN
Atari - 7800_TeST/rtl/rom/7800ntsc.rom
Normal file
BIN
Atari - 7800_TeST/rtl/rom/7800ntsc.rom
Normal file
Binary file not shown.
1025
Atari - 7800_TeST/rtl/rom/7800pal.hex
Normal file
1025
Atari - 7800_TeST/rtl/rom/7800pal.hex
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Atari - 7800_TeST/rtl/rom/7800pal.rom
Normal file
BIN
Atari - 7800_TeST/rtl/rom/7800pal.rom
Normal file
Binary file not shown.
BIN
Atari - 7800_TeST/rtl/rom/Defender (1981) (Atari).a26
Normal file
BIN
Atari - 7800_TeST/rtl/rom/Defender (1981) (Atari).a26
Normal file
Binary file not shown.
257
Atari - 7800_TeST/rtl/rom/Defender.hex
Normal file
257
Atari - 7800_TeST/rtl/rom/Defender.hex
Normal file
@@ -0,0 +1,257 @@
|
||||
:1000000078D8A2FF9AA9009502CAD0FBA2FF8698D1
|
||||
:10001000869B203BFD201CFD85A22017FD208CF037
|
||||
:10002000A5CBD013A5B4D00620F0F020D6F1202720
|
||||
:10003000F220E8F2203CF320EAF32051F520FFF50E
|
||||
:100040002028F6206EF6205BF420A2F44CC7F6A51B
|
||||
:10005000CBF00FC884E6C6CBA5CBD02820C3FD20AB
|
||||
:10006000E3FC20ABF82069F920A2F920FBF9204F2E
|
||||
:10007000FAA591D00620DDFA2037FB2090FB200C5A
|
||||
:10008000FC2043FCAD8402D0FB4C1DF0A9FF85028F
|
||||
:10009000850085018502850285028502A9368D9637
|
||||
:1000A00002A000840D8400A27F8601A4A2B9C20030
|
||||
:1000B00085C0B9C40085C1A5980A45980A0A269842
|
||||
:1000C000A5CBF009A90085BD85BF20ACFCAD8002A1
|
||||
:1000D000A4A239DDFF85B3C001D0060A0A0A0A8549
|
||||
:1000E000B3A68DD0028691C9F0F004A978858D6001
|
||||
:1000F000207BFCA5CD3043C901F073C902F04AC989
|
||||
:1001000003F055A6BBB58029F0D03DB580290FC9B5
|
||||
:1001100004D035A5AA3031A5CE302DA5A8C5A9D0CB
|
||||
:1001200027A9FF85CD85C685AFA5AC38E9010A0AA8
|
||||
:100130000A0A85C7A5CE85CA86B9A5A32593D00886
|
||||
:10014000A5C7C9179020C6C760C5AFB06BA5A329C6
|
||||
:1001500003D0F5C6AFC6C760A5ADC91ED0EA858A73
|
||||
:10016000A9058599D063E6AFA5AFC90E90DAA5C7FA
|
||||
:10017000A00184CDC987B010A5A32593D0CAE6C736
|
||||
:10018000A5C738E90C85AF60A6B9A9059580A4CAB2
|
||||
:10019000A591D035A6A2A931858AB5CF1912FF95B0
|
||||
:1001A000CFC9FFD02485CBA207B580290FC904D0C1
|
||||
:1001B00002F680CA10F33011A5BAC932F0D0202F50
|
||||
:1001C000FDA905859AA9028599A96485CA85B9A959
|
||||
:1001D0000085CD85AF60207BFCA4B8BE06FFA5A33B
|
||||
:1001E0002593D024A589D020C005F004E000D018C4
|
||||
:1001F000E6E3A5B0C5AD9004C6E3C6E3F6E0A5A569
|
||||
:10020000C5A6B004D6E0D6E0E6E4A5A32907D0163B
|
||||
:10021000C6C8C6AEC6E2A58B1004E6C8E6C8A59857
|
||||
:100220003004E6E2E6E260A591F005A90185CC6024
|
||||
:10023000A208A5B4D0F0BD8EFEC5B3F003CAD0F6B7
|
||||
:10024000BD97FE8593BDA0FEAAC5CCF012A5A3293B
|
||||
:100250000FD00EA9FF85B5E000F004A90085E68661
|
||||
:10026000CCA5CDC903D008A982C5ADB00285ADA586
|
||||
:10027000ADC919D006A5A3291FD040A000A6A2BDD4
|
||||
:10028000E6FE2D8202F001C88494A5A32594D00730
|
||||
:10029000A5AD18659385ADA5ADC9AA9018A9AA8585
|
||||
:1002A000ADA90085B185E6A588F00AA93B85CBA557
|
||||
:1002B0009885C885AEA5ADD002E6ADA5CDC903D061
|
||||
:1002C00026A5CAC5CED020A5AD38E90F85C785AF14
|
||||
:1002D000A205E48BF002A2018693A5A5186593857B
|
||||
:1002E000A44A18695885C660A5CC8594C901D00474
|
||||
:1002F000A205868BC9FFD004A9FB858BA58BA20024
|
||||
:100300008689C905D01B860BA5B4D02FA5A5C91F0A
|
||||
:100310009029A5A32901D002C6A5A90185898594A4
|
||||
:1003200060A0FF840BA5B4D012A5A5C982B00CA50E
|
||||
:10033000A32901D002E6A58489849460A5B4D0FBEA
|
||||
:10034000A58B8595A589F01AA205E495D002A2FF98
|
||||
:100350008695A900C5B6F00AC5CCF014C5B5F00263
|
||||
:100360008594A594F00AA5B6C930F020E6B6D01C55
|
||||
:10037000A5B6F054C6B6A5B6D00285B5A594D00CE6
|
||||
:10038000A201A595C905F002A2FF8694A5B6F03892
|
||||
:10039000F818690D4A4A4A4AD8AAA5A33DB5FED025
|
||||
:1003A00027A5943024C6C9C6C9C6C8A5CD3002C683
|
||||
:1003B000C6A20356DC36D876D4B5D42908F006B5E3
|
||||
:1003C000DC098095DCCA10EB60E6C9E6C9E6C8A581
|
||||
:1003D000CD3002E6C6A2031836D476D836DC9006B5
|
||||
:1003E000B5D4091095D4CA10EE60A591F008A58D7A
|
||||
:1003F000F004A53C1006AD82026AB010A59B100463
|
||||
:10040000E69BE69B203BFD201CFDF0386A9006A28F
|
||||
:100410000186E7D02F2017FD20E3FDC6E71025A9B0
|
||||
:100420002D85E7A59B1002E69BA59BF81869018521
|
||||
:100430009BA278868DA20086A386A2C9219004A9DA
|
||||
:1004400001859BD8A91085048505A6E88609A20523
|
||||
:10045000A5A3290FD002A225860A60A58DD004A9E4
|
||||
:10046000FF8591A5A3D00DE68CA591D007C68D1070
|
||||
:10047000032017FDAD8202A0F7A20F2908F002A207
|
||||
:10048000FFA5913002A0FF258C859586968497A2C2
|
||||
:1004900006BDEFFF45952596259795E8CA10F2858C
|
||||
:1004A0002C60A200A0008619A591D057A5CBC997B2
|
||||
:1004B000F0469011A007A5982907AAB5E899E80089
|
||||
:1004C0008810F33035A5B4D033A5CBC93CB039A5DD
|
||||
:1004D000CD1013A5AFC904B00DA205A5982937A862
|
||||
:1004E000A90E8519D01DA58AF036C68AC920B00A82
|
||||
:1004F000C91FD023868AF00B86CBA598293FA8A2D6
|
||||
:100500000886198615841760A5A3292FA8A201A91A
|
||||
:100510000A8519A5D1F0ECA5A32922A8A20ED0E145
|
||||
:10052000A5ADC9AAD004A5CBD0D0A5E5D0CCA5CB8C
|
||||
:10053000D00EA5B3C9F0F008A030A208A903851910
|
||||
:10054000A5E6F0052A2AA8D0B6A5B2C938F0ABD0E6
|
||||
:10055000B2A5C0F008A58DF004A591D06BA4A2A50A
|
||||
:100560009AF01FAAA59D1879DBFF859DCAD0F58654
|
||||
:100570009A39D9FFD9D5FFD009E699A59D39DDFF74
|
||||
:10058000859DA599F078C699A202B59C1879DBFFE4
|
||||
:10059000959C39D9FFD9D7FFD007B59C39DFFF9596
|
||||
:1005A0009C39D9FFD9D5FFD055B59C39DDFF959C35
|
||||
:1005B000E8E004D0032025FDE006D0CECAB59C3982
|
||||
:1005C000E1FF959CCA10F660A20A869D869CA00455
|
||||
:1005D000E8969C8810FAA59B3024A5C0F02020093D
|
||||
:1005E000FE859DA59BA201C9119001E8869C290F5B
|
||||
:1005F00085A0A59B29F0F0064A4A4A4A85A160A534
|
||||
:10060000A58595A5B1C960D007A5A538E58B85A5B9
|
||||
:10061000A5A3291FF011A5E6F00D85A52034FDA99D
|
||||
:100620006B85B1A91F850460A5D1F041A5CBC90197
|
||||
:10063000F03BA96485B0A95D85ADA246A5A32901BB
|
||||
:10064000D002A24E86A586A6A5EC858EA5E8858F4C
|
||||
:10065000A95285B1A5D2E04EF00B4A4A4A4AD005CC
|
||||
:10066000A98585B260290FAABDBAFE85B260A980AE
|
||||
:10067000C5B0B00285B0A204A5A4F00E85A7A0FF66
|
||||
:10068000A5CAC5CED002A4AF84ABA000B5A5C952FF
|
||||
:100690009004E94BA005E0026902C8E90FB0FB49EC
|
||||
:1006A000FFE9060A85020A0A0A95208810FD9510BE
|
||||
:1006B000CA10D78502852AA0058810FD852B8502E2
|
||||
:1006C000852AA59585A560A000A200B59C8693A665
|
||||
:1006D000A2F0044A4A4A4A290FA69385940A0A0AB4
|
||||
:1006E00038E59418695F99EF00A9FF99F000C8C830
|
||||
:1006F000E8E006D0D6AD8402D0FB85028501E6A3F2
|
||||
:10070000A5908507A5D22903AAB5EB85028508A97E
|
||||
:10071000FF850FA901850EA00BA2008502B9A9FED5
|
||||
:10072000850FC4AAD001CA861F8502A200C4ACD01E
|
||||
:1007300001CA861E8810E28502C8841D841F888431
|
||||
:100740000D840E840FA00FA6A2B5CFA6E9C9FFD0D5
|
||||
:1007500004A000A6E884978696A58F8506A58E85B9
|
||||
:1007600007A9F0850AA0848502A900850D850E855C
|
||||
:100770000FA900C4B0B009A6B2BD26FFF002C6B2F0
|
||||
:10078000C4ADA6B18502851CB00BBD1AFEC9F0F040
|
||||
:1007900004851BC6B1A20198E5AB2592D001E8867D
|
||||
:1007A0001D88C497D0CBA5968508A200861B984AC1
|
||||
:1007B0004A8502AAB5D4850DB5D8850EB5DC850F5E
|
||||
:1007C0008693A20198E5AB2592D001E8861DA693F9
|
||||
:1007D0008810DB8502A900840D840E840FA2018697
|
||||
:1007E0000AA4EE85028409851D851C8407850D8574
|
||||
:1007F0000E850F850BA90385048505A00686258631
|
||||
:1008000026849384028810FDEA85108511A9F0855D
|
||||
:10081000208502852AA0FEA5E885088502840FA60A
|
||||
:10082000EC86068607A493B1F9851B8502B1F7858E
|
||||
:100830001CB1F5851BB1F38594B1F1AAB1EFA8A560
|
||||
:1008400094851C861B841C851BC69310D8A9008523
|
||||
:10085000258526851B851C85208502850FA5EA85B3
|
||||
:10086000068507A008851088D0FD8511C88502A2DD
|
||||
:1008700003B9C000C903B001AABDDEFE990400BDE2
|
||||
:10088000E2FE9996008810E7A20BA0058502BD1A2A
|
||||
:10089000FE2596851BB983FE2597851CCA8810EC1A
|
||||
:1008A000A9268D9602A2FF9A4C4FF0E6BBA5BB2964
|
||||
:1008B0000785BBAA20A0FC8593C8B58029F0F0026B
|
||||
:1008C000A000B9E8008590A493A5CDF009E4B9D0C3
|
||||
:1008D00005A5C64CD9F820B5FC4A4A18692F85A849
|
||||
:1008E000A5CDF009E4B9D005A5C74CF0F820CAFCA5
|
||||
:1008F0004A4A4A4A18690285ACA4A2A9FF85AAD926
|
||||
:10090000CF00F045E6CEA5CEC9059004A90085CE5E
|
||||
:10091000AAB9CF003D12FFD030A5C9187DF2FE4A1A
|
||||
:100920004A18693085A9A90185AAA5CDF01BA5CAD9
|
||||
:10093000C5CED015A5CD3011A5C74A4A4A4A85AAC9
|
||||
:10094000A5C64A4A18693085A9A5A3290FD019A9B7
|
||||
:10095000FF85CEA5AD4A4A4A4A85AAA5A54A186987
|
||||
:10096000584A4A18692F85A960A90085A4A4A2B98C
|
||||
:10097000CF00C9FFF02B3D12FFD026A5C9187DF28C
|
||||
:10098000FEE4CAD008A4CD100285C6A5C6C95990F8
|
||||
:1009900010C9A8B00C38E958859418659469028587
|
||||
:1009A000A460A0078494A5A68595A5B78596A5B053
|
||||
:1009B0008597E6B7A5B7290785B7AAB5803014296A
|
||||
:1009C0000FA820B5FCE4B9D002A5C6C9599004C946
|
||||
:1009D000A5900DC69410DBA9FF85B7A90085A66078
|
||||
:1009E00020CAFCE4B9D002A5C785B020B5FCE4B9A3
|
||||
:1009F000D002A5C638E9580A85A66020EEFDA6B744
|
||||
:100A0000304C84B8C8B9E800858E88B920FF85B21B
|
||||
:100A1000A5CDC903D00EA925C5D2D008C5AD900477
|
||||
:100A2000A9AE85B2B5802910F024A93885B2E4B901
|
||||
:100A3000D00285B920A0FCA9809580C002D00FA566
|
||||
:100A4000E5D00BC8948085B2A5801002848060A593
|
||||
:100A500091D06CA5B4D0398593A5E6D0F1A5302905
|
||||
:100A600040F01BA692E0FCD01385B9A6CDE002D0E1
|
||||
:100A70000BE6CDA2058699202FFDA9008593A53709
|
||||
:100A800010028593A593F008A90085B6A91E85B428
|
||||
:100A9000A4B4F048A5A32903D002C6B42034FDC0F5
|
||||
:100AA00005B039B989FE85B1A5B4D03020C9F1A906
|
||||
:100AB0003285CB20ACFCA6A2D6C2D00320EBFCA58D
|
||||
:100AC000C2D019A59BC9119010A5C3D00FA5A32909
|
||||
:100AD0001FD006A5A2490185A22017FD60A696A5F4
|
||||
:100AE000B2C938F051B5803004A5373015A5E5F00E
|
||||
:100AF00045A599D041A6B71009A6A2D6C4A90085DC
|
||||
:100B0000E56020A0FCA90085E6B9FAFE859AB90047
|
||||
:100B1000FF8599B58009109580E4B9D019A5CD104D
|
||||
:100B200007A5AF1003E6CD60A90285CD85BAA9322D
|
||||
:100B3000C5C7B00285BA60A5B4D054A6A2B53C1012
|
||||
:100B400009A9008588A5E6D02060A588D0F7201CDB
|
||||
:100B5000FDC688A914C5ADB02AA5A538E90285E669
|
||||
:100B6000A68B100538E91785E6A207A58B1002A20F
|
||||
:100B7000F98A1865E6AAC982B004C900B002A200C9
|
||||
:100B800086E660A5C1F008A9FFC5B7F00285E5605B
|
||||
:100B9000A2A0A000A9FC8592A5A4D06BA5BFD032CD
|
||||
:100BA000A5B73063A4B8C002F05DA201A5B085BCB2
|
||||
:100BB000C5AD9002A2FF86BEA58AD002E68AA5A690
|
||||
:100BC00085BDC5A59002A2FE86BFC000D004A9F0D5
|
||||
:100BD00085BFA6BCA4BDC9F0D008A5A3295AF01DA5
|
||||
:100BE000D0218A1865BE85BCC90F9011AAA5BD1871
|
||||
:100BF00065BF85BDA8A5B4D004C0A09006A00084A0
|
||||
:100C0000BFA2A0A9FE859286AB84A760A207B5808B
|
||||
:100C10001030CA10F9A900A818659A659965B4D072
|
||||
:100C200021A6A2B5CFA2076AB001C8CA10F984995B
|
||||
:100C3000A99685CB85D185B9A5E5F006A6A2D6C42F
|
||||
:100C4000E6E560A5D3F033A5982907AAE4B9F02A10
|
||||
:100C5000B5801026A4A2B9CF00C9FFD004A005D04A
|
||||
:100C60000AA004A5A3291FD002A00120B5FCC959E0
|
||||
:100C70009004C9A890049480C6D36020A6FCBDC48B
|
||||
:100C8000FE8593E000F018A6D28497A001E00790BB
|
||||
:100C90000188CAF008C493F0044693D0F5A4976085
|
||||
:100CA000B580290FA860A59B290FAA60A9A085ABD4
|
||||
:100CB00085AC85AA608693BE06FFA900E003F0021A
|
||||
:100CC000B5E0A69365C87DF2FE608693BE0CFFA9D1
|
||||
:100CD00000E003F002B5E3A69365AE7DF2FE4A188C
|
||||
:100CE000691860A5D1F0FBA90085D1A59BC9119019
|
||||
:100CF00018A5A24901AAB5C2F00F86A2E001D00949
|
||||
:100D0000F8A5D238E90185D2D84C73FD20A6FCBDE8
|
||||
:100D1000CDFE85CF85D060A9FF859160A978858DAE
|
||||
:100D2000A9008591608693A6A2F6C4F6C2A693A9EF
|
||||
:100D30001E858A60A6BBB5E8858F60A90085A2855F
|
||||
:100D4000D185CD85A4859A859985B4850BA996858D
|
||||
:100D5000CB20E3FD2009FE200CFDBDE8FE85D2A2DC
|
||||
:100D600003BDE3FF95D4BDE7FF95D8BDEBFF95DC50
|
||||
:100D7000CA10EEA59885C985E385E485AEA90085EE
|
||||
:100D8000B685BD85BF85CDA9FE859285B985CAA5E5
|
||||
:100D9000D2290FF004C905D003200CFDF8A5D21804
|
||||
:100DA000690185D2D8A90F85D3A207BD18FF958008
|
||||
:100DB000A4A2B9CF00C9FFD004A9059580CA10EB41
|
||||
:100DC00020EEFDA93285ADA91E85A520ACFC85C805
|
||||
:100DD00085ABA905858BA90085E085E185E285CCF9
|
||||
:100DE00085E660A90385C285C385C485C560A91051
|
||||
:100DF00085B1A5EA858FA5B4D00EA5A32907D00893
|
||||
:100E0000A96085B1A5EE858F60A900859C859DA907
|
||||
:100E1000AA859E859F85A085A160F0000000000046
|
||||
:100E200000387F7C70200000000000F0000000040B
|
||||
:100E3000084428261C280420000000F000000800B8
|
||||
:100E40004220044110420840022000F000100240FD
|
||||
:100E50000041002002004004004012F00001400068
|
||||
:100E60000000000001000000400021F0FF0000F041
|
||||
:100E7000007CFE3C3CFE7C00000000F000FE7F0099
|
||||
:100E80000000000000005C3E5C0050403020F0E0BC
|
||||
:100E9000D070B0605090A00001FF000001FFFF0182
|
||||
:100EA00000000001FF0101FFFFC000000000000082
|
||||
:100EB00000000000C0FF070301013F464D545B6284
|
||||
:100EC0006970777E0F070307070307070307070704
|
||||
:100ED000FF0707FF0707FF07070707070707F0F0E8
|
||||
:100EE000F1F300FFFFFF4080000000000202020457
|
||||
:100EF0000404002850789BAF645A050000000505E3
|
||||
:100F000002020A05010103000200020101000300C0
|
||||
:100F1000030080402010080400020204040404803E
|
||||
:100F20000810182028300000000000F8D8D8F80079
|
||||
:100F3000000000007EE77E00105438FE3854100098
|
||||
:100F400042E742044EE44000FF7E24183C3C180077
|
||||
:100F5000C33C24183C3C4400102040142854207EFC
|
||||
:100F600072727272727E1C1C1C1C1C1C3C7E407EA9
|
||||
:100F70000E0E4E7E7E4E0E1C0E4E7E1C1C7E5C5C4B
|
||||
:100F80005C7C7E4E0E7E404E7E7E4E4E7E404E7E81
|
||||
:100F90000E0E0E0E0E4E7E7E4E4E7E72727E7E7255
|
||||
:100FA000027E72727E000000000000007985B5A507
|
||||
:100FB000B58579171515775555774141414141411F
|
||||
:100FC00040494949C94949BE555555D955559900D2
|
||||
:100FD000C4A4C6A5C60AA00BB00FF00110F00FF113
|
||||
:100FE0001FFAAFE06040407B795910CEC6C6C00002
|
||||
:100FF000888FFF1D1A3700000000000000F000F08D
|
||||
:00000001FF
|
||||
BIN
Atari - 7800_TeST/rtl/rom/Joust.a78
Normal file
BIN
Atari - 7800_TeST/rtl/rom/Joust.a78
Normal file
Binary file not shown.
195
Atari - 7800_TeST/rtl/scandoubler.sv
Normal file
195
Atari - 7800_TeST/rtl/scandoubler.sv
Normal file
@@ -0,0 +1,195 @@
|
||||
//
|
||||
// scandoubler.v
|
||||
//
|
||||
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
|
||||
// Copyright (c) 2017 Sorgelig
|
||||
//
|
||||
// This source file 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 source file 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
// TODO: Delay vsync one line
|
||||
|
||||
`define BITS_TO_FIT(N) ( \
|
||||
N <= 2 ? 0 : \
|
||||
N <= 4 ? 1 : \
|
||||
N <= 8 ? 2 : \
|
||||
N <= 16 ? 3 : \
|
||||
N <= 32 ? 4 : \
|
||||
N <= 64 ? 5 : \
|
||||
N <= 128 ? 6 : \
|
||||
N <= 256 ? 7 : \
|
||||
N <= 512 ? 8 : \
|
||||
N <=1024 ? 9 : 10 )
|
||||
|
||||
module scandoubler #(parameter LENGTH, parameter HALF_DEPTH)
|
||||
(
|
||||
// system interface
|
||||
input clk_sys,
|
||||
input ce_pix,
|
||||
input ce_pix_actual,
|
||||
|
||||
input hq2x,
|
||||
|
||||
// shifter video interface
|
||||
input hs_in,
|
||||
input vs_in,
|
||||
input line_start,
|
||||
|
||||
input [DWIDTH:0] r_in,
|
||||
input [DWIDTH:0] g_in,
|
||||
input [DWIDTH:0] b_in,
|
||||
input mono,
|
||||
|
||||
// output interface
|
||||
output reg hs_out,
|
||||
output vs_out,
|
||||
output [DWIDTH:0] r_out,
|
||||
output [DWIDTH:0] g_out,
|
||||
output [DWIDTH:0] b_out
|
||||
);
|
||||
|
||||
|
||||
localparam DWIDTH = HALF_DEPTH ? 2 : 5;
|
||||
|
||||
assign vs_out = vs_in;
|
||||
|
||||
reg [2:0] phase;
|
||||
reg [2:0] ce_div;
|
||||
reg [7:0] pix_len = 0;
|
||||
wire [7:0] pl = pix_len + 1'b1;
|
||||
|
||||
reg ce_x1, ce_x4;
|
||||
reg req_line_reset;
|
||||
wire ls_in = hs_in | line_start;
|
||||
always @(negedge clk_sys) begin
|
||||
reg old_ce;
|
||||
reg [2:0] ce_cnt;
|
||||
|
||||
reg [7:0] pixsz2, pixsz4 = 0;
|
||||
|
||||
old_ce <= ce_pix;
|
||||
if(~&pix_len) pix_len <= pix_len + 1'd1;
|
||||
|
||||
ce_x4 <= 0;
|
||||
ce_x1 <= 0;
|
||||
|
||||
// use such odd comparison to place c_x4 evenly if master clock isn't multiple 4.
|
||||
if((pl == pixsz4) || (pl == pixsz2) || (pl == (pixsz2+pixsz4))) begin
|
||||
phase <= phase + 1'd1;
|
||||
ce_x4 <= 1;
|
||||
end
|
||||
|
||||
if(~old_ce & ce_pix) begin
|
||||
pixsz2 <= {1'b0, pl[7:1]};
|
||||
pixsz4 <= {2'b00, pl[7:2]};
|
||||
ce_x1 <= 1;
|
||||
ce_x4 <= 1;
|
||||
pix_len <= 0;
|
||||
phase <= phase + 1'd1;
|
||||
|
||||
ce_cnt <= ce_cnt + 1'd1;
|
||||
if(ce_pix_actual) begin
|
||||
phase <= 0;
|
||||
ce_div <= ce_cnt + 1'd1;
|
||||
ce_cnt <= 0;
|
||||
req_line_reset <= 0;
|
||||
end
|
||||
|
||||
if(ls_in) req_line_reset <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
reg ce_sd;
|
||||
always @(*) begin
|
||||
case(ce_div)
|
||||
2: ce_sd = !phase[0];
|
||||
4: ce_sd = !phase[1:0];
|
||||
default: ce_sd <= 1;
|
||||
endcase
|
||||
end
|
||||
|
||||
localparam AWIDTH = `BITS_TO_FIT(LENGTH);
|
||||
Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x
|
||||
(
|
||||
.clk(clk_sys),
|
||||
.ce_x4(ce_x4 & ce_sd),
|
||||
.inputpixel({b_in,g_in,r_in}),
|
||||
.mono(mono),
|
||||
.disable_hq2x(~hq2x),
|
||||
.reset_frame(vs_in),
|
||||
.reset_line(req_line_reset),
|
||||
.read_y(sd_line),
|
||||
.read_x(sd_h_actual),
|
||||
.outpixel({b_out,g_out,r_out})
|
||||
);
|
||||
|
||||
reg [10:0] sd_h_actual;
|
||||
always @(*) begin
|
||||
case(ce_div)
|
||||
2: sd_h_actual = sd_h[10:1];
|
||||
4: sd_h_actual = sd_h[10:2];
|
||||
default: sd_h_actual = sd_h;
|
||||
endcase
|
||||
end
|
||||
|
||||
reg [10:0] sd_h;
|
||||
reg [1:0] sd_line;
|
||||
always @(posedge clk_sys) begin
|
||||
|
||||
reg [11:0] hs_max,hs_rise,hs_ls;
|
||||
reg [10:0] hcnt;
|
||||
reg [11:0] sd_hcnt;
|
||||
|
||||
reg hs, hs2, vs, ls;
|
||||
|
||||
if(ce_x1) begin
|
||||
hs <= hs_in;
|
||||
ls <= ls_in;
|
||||
|
||||
if(ls && !ls_in) hs_ls <= {hcnt,1'b1};
|
||||
|
||||
// falling edge of hsync indicates start of line
|
||||
if(hs && !hs_in) begin
|
||||
hs_max <= {hcnt,1'b1};
|
||||
hcnt <= 0;
|
||||
if(ls && !ls_in) hs_ls <= {10'd0,1'b1};
|
||||
end else begin
|
||||
hcnt <= hcnt + 1'd1;
|
||||
end
|
||||
|
||||
// save position of rising edge
|
||||
if(!hs && hs_in) hs_rise <= {hcnt,1'b1};
|
||||
|
||||
vs <= vs_in;
|
||||
if(vs && ~vs_in) sd_line <= 0;
|
||||
end
|
||||
|
||||
if(ce_x4) begin
|
||||
hs2 <= hs_in;
|
||||
|
||||
// output counter synchronous to input and at twice the rate
|
||||
sd_hcnt <= sd_hcnt + 1'd1;
|
||||
sd_h <= sd_h + 1'd1;
|
||||
if(hs2 && !hs_in) sd_hcnt <= hs_max;
|
||||
if(sd_hcnt == hs_max) sd_hcnt <= 0;
|
||||
|
||||
// replicate horizontal sync at twice the speed
|
||||
if(sd_hcnt == hs_max) hs_out <= 0;
|
||||
if(sd_hcnt == hs_rise) hs_out <= 1;
|
||||
|
||||
if(sd_hcnt == hs_ls) sd_h <= 0;
|
||||
if(sd_hcnt == hs_ls) sd_line <= sd_line + 1'd1;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
33
Atari - 7800_TeST/rtl/sigma_delta_dac.sv
Normal file
33
Atari - 7800_TeST/rtl/sigma_delta_dac.sv
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// PWM DAC
|
||||
//
|
||||
// MSBI is the highest bit number. NOT amount of bits!
|
||||
//
|
||||
module sigma_delta_dac #(parameter MSBI=0)
|
||||
(
|
||||
output reg DACout, //Average Output feeding analog lowpass
|
||||
input [MSBI:0] DACin, //DAC input (excess 2**MSBI)
|
||||
input CLK,
|
||||
input RESET
|
||||
);
|
||||
|
||||
reg [MSBI+2:0] DeltaAdder; //Output of Delta Adder
|
||||
reg [MSBI+2:0] SigmaAdder; //Output of Sigma Adder
|
||||
reg [MSBI+2:0] SigmaLatch; //Latches output of Sigma Adder
|
||||
reg [MSBI+2:0] DeltaB; //B input of Delta Adder
|
||||
|
||||
always @(*) DeltaB = {SigmaLatch[MSBI+2], SigmaLatch[MSBI+2]} << (MSBI+1);
|
||||
always @(*) DeltaAdder = DACin + DeltaB;
|
||||
always @(*) SigmaAdder = DeltaAdder + SigmaLatch;
|
||||
|
||||
always @(posedge CLK or posedge RESET) begin
|
||||
if(RESET) begin
|
||||
SigmaLatch <= 1'b1 << (MSBI+1);
|
||||
DACout <= 1;
|
||||
end else begin
|
||||
SigmaLatch <= SigmaAdder;
|
||||
DACout <= ~SigmaLatch[MSBI+2];
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
81
Atari - 7800_TeST/rtl/tia.vh
Normal file
81
Atari - 7800_TeST/rtl/tia.vh
Normal file
@@ -0,0 +1,81 @@
|
||||
/* Atari on an FPGA
|
||||
Masters of Engineering Project
|
||||
Cornell University, 2007
|
||||
Daniel Beer
|
||||
TIA.h
|
||||
Header file that contains useful definitions for the TIA module.
|
||||
*/
|
||||
`define CXM0P 7'h70
|
||||
`define CXM1P 7'h71
|
||||
`define CXP0FB 7'h72
|
||||
`define CXP1FB 7'h73
|
||||
`define CXM0FB 7'h74
|
||||
`define CXM1FB 7'h75
|
||||
`define CXBLPF 7'h76
|
||||
`define CXPPMM 7'h77
|
||||
`define INPT0 7'h78
|
||||
`define INPT1 7'h79
|
||||
`define INPT2 7'h7A
|
||||
`define INPT3 7'h7B
|
||||
`define INPT4 7'h7C
|
||||
`define INPT5 7'h7D
|
||||
`define VSYNC 7'h00
|
||||
`define VBLANK 7'h01
|
||||
`define WSYNC 7'h02
|
||||
`define RSYNC 7'h03
|
||||
`define NUSIZ0 7'h04
|
||||
`define NUSIZ1 7'h05
|
||||
`define COLUP0 7'h06
|
||||
`define COLUP1 7'h07
|
||||
`define COLUPF 7'h08
|
||||
`define COLUBK 7'h09
|
||||
`define CTRLPF 7'h0A
|
||||
`define REFP0 7'h0B
|
||||
`define REFP1 7'h0C
|
||||
`define PF0 7'h0D
|
||||
`define PF1 7'h0E
|
||||
`define PF2 7'h0F
|
||||
`define RESP0 7'h10
|
||||
`define RESP1 7'h11
|
||||
`define RESM0 7'h12
|
||||
`define RESM1 7'h13
|
||||
`define RESBL 7'h14
|
||||
`define AUDC0 7'h15
|
||||
`define AUDC1 7'h16
|
||||
`define AUDF0 7'h17
|
||||
`define AUDF1 7'h18
|
||||
`define AUDV0 7'h19
|
||||
`define AUDV1 7'h1A
|
||||
`define GRP0 7'h1B
|
||||
`define GRP1 7'h1C
|
||||
`define ENAM0 7'h1D
|
||||
`define ENAM1 7'h1E
|
||||
`define ENABL 7'h1F
|
||||
`define HMP0 7'h20
|
||||
`define HMP1 7'h21
|
||||
`define HMM0 7'h22
|
||||
`define HMM1 7'h23
|
||||
`define HMBL 7'h24
|
||||
`define VDELP0 7'h25
|
||||
`define VDELP1 7'h26
|
||||
`define VDELBL 7'h27
|
||||
`define RESMP0 7'h28
|
||||
`define RESMP1 7'h29
|
||||
`define HMOVE 7'h2A
|
||||
`define HMCLR 7'h2B
|
||||
`define CXCLR 7'h2C
|
||||
|
||||
`define CXM0P_7800 7'h40
|
||||
`define CXM1P_7800 7'h41
|
||||
`define CXP0FB_7800 7'h42
|
||||
`define CXP1FB_7800 7'h43
|
||||
`define CXM0FB_7800 7'h44
|
||||
`define CXM1FB_7800 7'h45
|
||||
`define CXBLPF_7800 7'h46
|
||||
`define CXPPMM_7800 7'h47
|
||||
`define INPT0_7800 7'h48
|
||||
`define INPT1_7800 7'h49
|
||||
`define INPT2_7800 7'h4A
|
||||
`define INPT3_7800 7'h4B
|
||||
`define INPT4_7800 7'h4C
|
||||
`define INPT5_7800 7'h4D
|
||||
361
Atari - 7800_TeST/rtl/timing_ctrl.sv
Normal file
361
Atari - 7800_TeST/rtl/timing_ctrl.sv
Normal file
@@ -0,0 +1,361 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
// Number of sysclk cycles needed for the halt signal to take on the CPU
|
||||
`define DMA_STARTUP_CYCLES 9
|
||||
|
||||
// Number of sysclk cycles that the cpu gets at the start of a line
|
||||
`define START_OF_LINE_CYCLES 24
|
||||
|
||||
// At which column we terminate DP DMA
|
||||
`define DP_DMA_KILL_COL 435
|
||||
|
||||
// Column to start the ZP DMA, given that about 29 cycles are needed
|
||||
// and there are 452 columns total. Plus some slack cycles.
|
||||
// 9 for startup, 7 for access, 13 for shutdown
|
||||
`define ZP_READY_COL 420
|
||||
|
||||
// VGA Row to start the ZP DMA. Rows 0-1 are the first visible line,
|
||||
// rows 523-524 are the virst invisible line, rows 521-522 are buffering
|
||||
// for the first invisible line, so ZP needs to be fetched by row 521.
|
||||
`define ZP_READY_ROW 520
|
||||
|
||||
`define VGA_VISIBLE_COLS 640
|
||||
|
||||
`define NTSC_SCANLINE_COUNT 242
|
||||
|
||||
`define COOLDOWN_CYCLES 1
|
||||
|
||||
//`define OVERCLOCK
|
||||
|
||||
|
||||
|
||||
module timing_ctrl (
|
||||
input logic enable,
|
||||
|
||||
// Clocking
|
||||
input logic sysclk, reset, pclk_2,
|
||||
output logic pclk_0, tia_clk,
|
||||
input logic sel_slow_clock,
|
||||
|
||||
// Outputs to 6502
|
||||
output logic halt_b, int_b, ready, core_latch_data,
|
||||
output logic VBLANK,
|
||||
|
||||
// Signals to/from dma_ctrl
|
||||
output logic zp_dma_start, dp_dma_start,
|
||||
input logic zp_dma_done, dp_dma_done,
|
||||
input logic dp_dma_done_dli,
|
||||
output logic dp_dma_kill,
|
||||
output logic last_line,
|
||||
|
||||
// Signals to/from line_ram
|
||||
output logic lram_swap,
|
||||
|
||||
// VGA Status
|
||||
input logic [9:0] vga_row, vga_col,
|
||||
|
||||
// Signals from memory map
|
||||
input logic deassert_ready, zp_written
|
||||
);
|
||||
|
||||
// Output buffers
|
||||
logic [5:0] int_b_sr;
|
||||
assign int_b = &int_b_sr;
|
||||
|
||||
// Current NTSC row and col
|
||||
logic [8:0] row, col;
|
||||
|
||||
logic [9:0] vga_row_prev, vga_row_prev_prev;
|
||||
|
||||
// Each ntsc line is two vga lines. Asserted => we are on second one
|
||||
logic second_vga_line;
|
||||
|
||||
// vga_row has changed in the last cycle
|
||||
logic vga_line_delta;
|
||||
|
||||
// Clock division
|
||||
`ifndef OVERCLOCK
|
||||
logic fast_ctr;
|
||||
`endif
|
||||
|
||||
logic [1:0] slow_ctr;
|
||||
logic fast_clk, slow_clk;
|
||||
|
||||
logic ready_for_lswap, ready_for_lswap_prev;
|
||||
|
||||
// Ready to move to ZP_DMA_STARTUP
|
||||
logic zp_ready;
|
||||
|
||||
// interrupt on next cycle
|
||||
logic dli_next, raise_dli;
|
||||
|
||||
logic [4:0] startup_ctr;
|
||||
logic cooldown_count;
|
||||
|
||||
enum logic [31:0] {
|
||||
VWAIT = 'h0, // Waiting for VSYNC to complete before starting ZP DMA
|
||||
HWAIT = 'h1, // Waiting for HSYNC to complete before starting DP DMA
|
||||
ZP_DMA_STARTUP = 'h2, // Waiting for HALT to reach CPU before starting ZP DMA
|
||||
ZP_DMA = 'h3, // Waiting for DMA CTRL to finish ZP DMA
|
||||
START_OF_LINE = 'h4, // Waiting for first 7 CPU cycles of line before DP DMA
|
||||
DP_DMA_STARTUP = 'h5, // Waiting for HALT to reach CPU before starting DP DMA
|
||||
DP_DMA = 'h6, // Waiting for DMA CTRL to finish DP DMA
|
||||
DP_DMA_WAITSWAP = 'h7, // Done with DP DMA, but not ready to swap linerams yet
|
||||
VWAIT_COOLDOWN = 'h8,
|
||||
HWAIT_COOLDOWN = 'h9
|
||||
} state;
|
||||
|
||||
assign vga_line_delta = vga_row_prev_prev != vga_row_prev;
|
||||
|
||||
// In general, we are on the second row if the row number is odd (vga_row[0])
|
||||
// However, above 512 (521/522, 523/524) we are on the second row if the row
|
||||
// number is even.
|
||||
assign second_vga_line = vga_row[9] ^ vga_row[0];
|
||||
|
||||
assign dp_dma_kill = ((enable) &
|
||||
(state == DP_DMA) &
|
||||
(second_vga_line) &
|
||||
(col == `DP_DMA_KILL_COL));
|
||||
|
||||
assign zp_ready = ((enable) & (vga_row == `ZP_READY_ROW) &
|
||||
(col == `ZP_READY_COL));
|
||||
|
||||
assign last_line = (row == (`NTSC_SCANLINE_COUNT - 1));
|
||||
|
||||
assign VBLANK = (row >= 9'd241);
|
||||
|
||||
assign pclk_0 = sel_slow_clock ? slow_clk : fast_clk;
|
||||
|
||||
assign ready_for_lswap = ((enable) & second_vga_line &
|
||||
(vga_col > `VGA_VISIBLE_COLS));
|
||||
assign lram_swap = (ready_for_lswap &
|
||||
(((state == DP_DMA) & (dp_dma_done | dp_dma_kill)) ||
|
||||
(state == DP_DMA_WAITSWAP)));
|
||||
|
||||
|
||||
always @(posedge sysclk, posedge reset) begin
|
||||
if (reset) begin
|
||||
state <= VWAIT;
|
||||
row <= 9'b0;
|
||||
col <= 9'b0;
|
||||
vga_row_prev <= 10'd0;
|
||||
fast_clk <= 1'b0;
|
||||
cooldown_count <= 1'b0;
|
||||
slow_clk <= 1'b0;
|
||||
`ifndef OVERCLOCK
|
||||
fast_ctr <= 1'b0;
|
||||
`endif
|
||||
slow_ctr <= 2'b0;
|
||||
int_b_sr <= 6'b111111;
|
||||
raise_dli <= 1'b0;
|
||||
startup_ctr <= 4'd0;
|
||||
dli_next <= 1'b0;
|
||||
halt_b <= 1'b1;
|
||||
zp_dma_start <= 1'b0;
|
||||
dp_dma_start <= 1'b0;
|
||||
core_latch_data <= 1'b0;
|
||||
ready_for_lswap_prev <= 1'b0;
|
||||
ready <= 1'b1;
|
||||
tia_clk <= 1'b0;
|
||||
end else begin
|
||||
// Clock generation
|
||||
tia_clk <= ~tia_clk;
|
||||
core_latch_data <= 1'b0;
|
||||
if (sel_slow_clock) begin
|
||||
`ifndef OVERCLOCK
|
||||
fast_ctr <= 1'b0;
|
||||
`endif
|
||||
|
||||
fast_clk <= 1'b1;
|
||||
if (slow_ctr == 2'd2) begin
|
||||
slow_ctr <= 2'b0;
|
||||
slow_clk <= ~slow_clk;
|
||||
if (slow_clk == 1'b0)
|
||||
core_latch_data <= 1'b1;
|
||||
end
|
||||
else
|
||||
slow_ctr <= slow_ctr + 2'b01;
|
||||
end
|
||||
else begin
|
||||
slow_ctr <= 2'b00;
|
||||
slow_clk <= 1'b1;
|
||||
`ifdef OVERCLOCK
|
||||
fast_clk <= ~fast_clk;
|
||||
`else
|
||||
fast_ctr <= ~fast_ctr;
|
||||
if (fast_ctr) begin
|
||||
fast_clk <= ~fast_clk;
|
||||
if (fast_clk == 1'b0)
|
||||
core_latch_data <= 1'b1;
|
||||
end
|
||||
`endif
|
||||
end
|
||||
|
||||
// Interrupt generation
|
||||
int_b_sr <= {int_b_sr[4:0], ~(dli_next & enable)};
|
||||
//int_b_reg <= ~(dli_next & enable);
|
||||
|
||||
vga_row_prev <= vga_row;
|
||||
vga_row_prev_prev <= vga_row_prev;
|
||||
ready_for_lswap_prev <= ready_for_lswap;
|
||||
|
||||
// Column counting
|
||||
if (vga_line_delta & ~second_vga_line) // Just changed to first line
|
||||
col <= 0;
|
||||
else
|
||||
col <= col + 1;
|
||||
|
||||
// Row counting
|
||||
if (vga_line_delta & ~second_vga_line) begin
|
||||
if (vga_row == 10'd521)
|
||||
row <= 0;
|
||||
else
|
||||
row <= row + 1;
|
||||
end
|
||||
|
||||
// Ready signal
|
||||
if (enable & deassert_ready)
|
||||
ready <= 1'b0;
|
||||
else if (ready_for_lswap & ~ready_for_lswap_prev)
|
||||
ready <= 1'b1;
|
||||
|
||||
// Next state logic
|
||||
case (state)
|
||||
VWAIT: begin
|
||||
if (zp_ready & zp_written) begin
|
||||
halt_b <= 1'b0;
|
||||
raise_dli <= 1'b0;
|
||||
dli_next <= 1'b0;
|
||||
state <= ZP_DMA_STARTUP;
|
||||
startup_ctr <= 1;
|
||||
end
|
||||
end
|
||||
HWAIT: begin
|
||||
if (~enable) begin
|
||||
state <= VWAIT_COOLDOWN;
|
||||
halt_b <= 1'b0;
|
||||
raise_dli <= 1'b0;
|
||||
dli_next <= 1'b0;
|
||||
cooldown_count <= `COOLDOWN_CYCLES;
|
||||
end else if (vga_line_delta) begin
|
||||
state <= START_OF_LINE;
|
||||
startup_ctr <= 1;
|
||||
end
|
||||
end
|
||||
ZP_DMA_STARTUP: begin
|
||||
startup_ctr <= startup_ctr + 1;
|
||||
if (~enable) begin
|
||||
state <= VWAIT_COOLDOWN;
|
||||
raise_dli <= 1'b0;
|
||||
halt_b <= 1'b0;
|
||||
cooldown_count <= `COOLDOWN_CYCLES;
|
||||
end else if (startup_ctr == `DMA_STARTUP_CYCLES) begin
|
||||
zp_dma_start <= 1'b1;
|
||||
state <= ZP_DMA;
|
||||
end
|
||||
end
|
||||
ZP_DMA: begin
|
||||
zp_dma_start <= 1'b0;
|
||||
if (~enable) begin
|
||||
state <= VWAIT_COOLDOWN;
|
||||
raise_dli <= 1'b0;
|
||||
halt_b <= 1'b0;
|
||||
cooldown_count <= `COOLDOWN_CYCLES;
|
||||
end else if (zp_dma_done) begin
|
||||
state <= HWAIT_COOLDOWN;
|
||||
raise_dli <= dp_dma_done_dli;
|
||||
raise_dli <= 1'b0;
|
||||
halt_b <= 1'b0;
|
||||
cooldown_count <= `COOLDOWN_CYCLES;
|
||||
end
|
||||
end
|
||||
START_OF_LINE: begin
|
||||
startup_ctr <= startup_ctr + 1;
|
||||
if (~enable) begin
|
||||
state <= VWAIT_COOLDOWN;
|
||||
raise_dli <= 1'b0;
|
||||
halt_b <= 1'b0;
|
||||
cooldown_count <= `COOLDOWN_CYCLES;
|
||||
end else if (startup_ctr == `START_OF_LINE_CYCLES) begin
|
||||
halt_b <= 1'b0;
|
||||
state <= DP_DMA_STARTUP;
|
||||
startup_ctr <= 1;
|
||||
end
|
||||
end
|
||||
DP_DMA_STARTUP: begin
|
||||
startup_ctr <= startup_ctr + 1;
|
||||
if (~enable) begin
|
||||
state <= VWAIT_COOLDOWN;
|
||||
raise_dli <= 1'b0;
|
||||
halt_b <= 1'b0;
|
||||
cooldown_count <= `COOLDOWN_CYCLES;
|
||||
end else if (startup_ctr == `DMA_STARTUP_CYCLES) begin
|
||||
dp_dma_start <= 1'b1;
|
||||
raise_dli <= 1'b0;
|
||||
state <= DP_DMA;
|
||||
end
|
||||
end
|
||||
DP_DMA: begin
|
||||
dp_dma_start <= 1'b0;
|
||||
if (~enable) begin
|
||||
state <= VWAIT_COOLDOWN;
|
||||
halt_b <= 1'b0;
|
||||
cooldown_count <= `COOLDOWN_CYCLES;
|
||||
end else if (dp_dma_done | dp_dma_kill) begin
|
||||
halt_b <= 1'b0;
|
||||
raise_dli <= dp_dma_done_dli;
|
||||
cooldown_count <= `COOLDOWN_CYCLES;
|
||||
if (ready_for_lswap) begin
|
||||
state <= last_line ? VWAIT_COOLDOWN : HWAIT_COOLDOWN;
|
||||
end else begin
|
||||
state <= DP_DMA_WAITSWAP;
|
||||
end
|
||||
end
|
||||
end
|
||||
DP_DMA_WAITSWAP: begin
|
||||
if (~enable) begin
|
||||
state <= VWAIT_COOLDOWN;
|
||||
end else if (cooldown_count == 0) begin
|
||||
if ((sel_slow_clock && slow_ctr != 2'b10) ||
|
||||
(~sel_slow_clock && fast_clk == 1'b1)) begin
|
||||
halt_b <= 1'b1;
|
||||
raise_dli <= 1'b0;
|
||||
dli_next <= raise_dli;
|
||||
end
|
||||
end else begin
|
||||
cooldown_count <= cooldown_count - 1;
|
||||
end
|
||||
if (ready_for_lswap) begin
|
||||
state <= last_line ? VWAIT_COOLDOWN : HWAIT_COOLDOWN;
|
||||
end
|
||||
end
|
||||
VWAIT_COOLDOWN: begin
|
||||
if (cooldown_count == 0) begin
|
||||
if ((sel_slow_clock && slow_ctr != 2'b10) ||
|
||||
(~sel_slow_clock && fast_clk == 1'b1)) begin
|
||||
halt_b <= 1'b1;
|
||||
raise_dli <= 1'b0;
|
||||
dli_next <= raise_dli;
|
||||
state <= VWAIT;
|
||||
end
|
||||
end else begin
|
||||
cooldown_count <= cooldown_count - 1;
|
||||
end
|
||||
end
|
||||
HWAIT_COOLDOWN: begin
|
||||
if (cooldown_count == 0) begin
|
||||
if ((sel_slow_clock && slow_ctr != 2'b10) ||
|
||||
(~sel_slow_clock && fast_clk == 1'b1)) begin
|
||||
halt_b <= 1'b1;
|
||||
raise_dli <= 1'b0;
|
||||
dli_next <= raise_dli;
|
||||
state <= HWAIT;
|
||||
end
|
||||
end else begin
|
||||
cooldown_count <= cooldown_count - 1;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
218
Atari - 7800_TeST/rtl/uv_to_vga.sv
Normal file
218
Atari - 7800_TeST/rtl/uv_to_vga.sv
Normal file
@@ -0,0 +1,218 @@
|
||||
`timescale 1ns / 1ps
|
||||
/** Line buffer to VGA Interface
|
||||
*
|
||||
* input lbuffer is the line buffer.
|
||||
* For column c, 0 <= c < 640, where 0 is left and 639 is right,
|
||||
* lbuffer[c][0] is RED, where 4'hF is the most intense red and
|
||||
* 4'h0 is the least intense red.
|
||||
* lbuffer[c][1] is GREEN and lbuffer[c][2] is BLUE.
|
||||
*
|
||||
* output line_number indicates the current row, where the top
|
||||
* of the screen is 0 and 479 is the bottom of the screen. Other
|
||||
* values indicate that no line is currently being drawn.
|
||||
*
|
||||
* clk should be hooked up to a 25MHz clock (or 25.175 if available.)
|
||||
* reset should be hooked up to system reset.
|
||||
* RED, GREEN, BLUE, HSync, and VSync should be hooked up to the
|
||||
* appropriate VGA pins.
|
||||
**/
|
||||
|
||||
//`define FRAMEBUF
|
||||
|
||||
module uv_to_vga (
|
||||
input logic clk, reset,
|
||||
input logic [7:0] uv_in,
|
||||
|
||||
output logic [9:0] row, col,
|
||||
output logic [3:0] RED, GREEN, BLUE,
|
||||
output logic HSync, VSync,
|
||||
|
||||
input logic tia_en, tia_clk,
|
||||
input logic tia_hblank,
|
||||
input logic tia_vblank
|
||||
);
|
||||
|
||||
|
||||
|
||||
logic col_clear, row_clear;
|
||||
logic col_enable, row_enable;
|
||||
|
||||
// Chrominance-Luminance palettes (represented as rgb)
|
||||
logic [255:0][3:0] red_palette, green_palette, blue_palette;
|
||||
|
||||
logic [7:0] rbuf, gbuf, bbuf;
|
||||
logic [7:0] uv;
|
||||
|
||||
logic visible, tia_visible;
|
||||
assign visible = (row < 10'd480) & (col < 10'd640);
|
||||
|
||||
`ifdef FRAMEBUF
|
||||
assign tia_visible = (row >= 10'd48) & (row <10'd432) & (col < 10'd640);
|
||||
|
||||
logic [9:0] tia_row, tia_col;
|
||||
assign tia_row = row - 10'd48;
|
||||
assign tia_col = col;
|
||||
|
||||
logic [7:0] fbuf_uv1, fbuf_uv2;
|
||||
(* keep = "true" *) logic [7:0] fbuf_uv1_kept, fbuf_uv2_kept;
|
||||
assign fbuf_uv1_kept = fbuf_uv1;
|
||||
assign fbuf_uv2_kept = fbuf_uv2;
|
||||
|
||||
logic [14:0] buf_w_addr, buf_r_addr;
|
||||
(* keep = "true" *) logic [14:0] buf_w_addr_kept;
|
||||
(* keep = "true" *) logic [14:0] buf_r_addr_kept;
|
||||
assign buf_w_addr = tia_write_row*14'd160+tia_write_col;
|
||||
assign buf_r_addr = tia_row[8:1]*14'd160+tia_col[9:2];
|
||||
assign buf_w_addr_kept = buf_w_addr;
|
||||
assign buf_r_addr_kept = buf_r_addr;
|
||||
logic write_buf1;
|
||||
|
||||
Frame_Buf frame_buffer1(
|
||||
.clka(tia_clk), // input wire clka
|
||||
.ena(~tia_vblank & ~tia_hblank & write_buf1), // input wire ena
|
||||
.wea(write_buf1), // input wire [0 : 0] wea
|
||||
.addra(buf_w_addr), // input wire [14 : 0] addra
|
||||
.dina(uv_in), // input wire [7 : 0] dina
|
||||
.clkb(clk), // input wire clkb
|
||||
.enb(tia_visible), // input wire enb
|
||||
.addrb(buf_r_addr), // input wire [14 : 0] addrb
|
||||
.doutb(fbuf_uv1) // output wire [7 : 0] doutb
|
||||
);
|
||||
|
||||
Frame_Buf frame_buffer2(
|
||||
.clka(tia_clk), // input wire clka
|
||||
.ena(~tia_vblank & ~tia_hblank & ~write_buf1), // input wire ena
|
||||
.wea(~write_buf1), // input wire [0 : 0] wea
|
||||
.addra(buf_w_addr), // input wire [14 : 0] addra
|
||||
.dina(uv_in), // input wire [7 : 0] dina
|
||||
.clkb(clk), // input wire clkb
|
||||
.enb(tia_visible), // input wire enb
|
||||
.addrb(buf_r_addr), // input wire [14 : 0] addrb
|
||||
.doutb(fbuf_uv2) // output wire [7 : 0] doutb
|
||||
);
|
||||
|
||||
logic [7:0] tia_write_row;
|
||||
logic [7:0] tia_write_col;
|
||||
(* keep = "true" *) logic [7:0] tia_write_row_kept;
|
||||
(* keep = "true" *) logic [7:0] tia_write_col_kept;
|
||||
assign tia_write_row_kept = tia_write_row;
|
||||
assign tia_write_col_kept = tia_write_col;
|
||||
|
||||
logic tia_hblank_buf, tia_vblank_buf;
|
||||
|
||||
always_ff @(posedge tia_clk, posedge reset) begin
|
||||
if (reset) begin
|
||||
tia_write_row <= 0;
|
||||
tia_write_col <= 0;
|
||||
tia_hblank_buf <= 0;
|
||||
tia_vblank_buf <= 0;
|
||||
end else begin
|
||||
tia_hblank_buf <= tia_hblank;
|
||||
tia_vblank_buf <= tia_vblank;
|
||||
if (~tia_vblank_buf & tia_vblank)
|
||||
write_buf1 <= ~write_buf1;
|
||||
if (tia_hblank) begin
|
||||
tia_write_col <= 8'b0;
|
||||
if (~tia_hblank_buf & ~tia_vblank) begin
|
||||
tia_write_row <= tia_write_row + 1;
|
||||
end
|
||||
end else begin
|
||||
tia_write_col <= tia_write_col + 1;
|
||||
end
|
||||
|
||||
if (tia_vblank)
|
||||
tia_write_row <= 8'd0;
|
||||
end
|
||||
end
|
||||
|
||||
logic [7:0] uv_from_fbuf;
|
||||
assign uv_from_fbuf = (write_buf1) ? fbuf_uv2 : fbuf_uv1;
|
||||
assign uv = tia_en ? (tia_visible ? uv_from_fbuf : 8'd0) : (visible ? uv_in : 8'd0);
|
||||
`else
|
||||
assign uv = uv_in;
|
||||
`endif
|
||||
|
||||
|
||||
assign RED = rbuf;
|
||||
assign GREEN = gbuf;
|
||||
assign BLUE = bbuf;
|
||||
// UV Palette data found at: http://atariage.com/forums/topic/209210-complete-ntsc-pal-color-palettes/
|
||||
// These three assign statements generated by Atari7800/palettes.py
|
||||
assign red_palette = {4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'hf, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'hf, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0};
|
||||
assign rbuf = red_palette[uv];
|
||||
|
||||
assign green_palette = {4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'hf, 4'hf, 4'hf, 4'hf, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h2, 4'h1, 4'h0, 4'hf, 4'hf, 4'he, 4'hd, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h1, 4'h0, 4'h0, 4'hf, 4'he, 4'hd, 4'hc, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h1, 4'h0, 4'h0, 4'h0, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'he, 4'hd, 4'hc, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h0, 4'h0, 4'h0, 4'h0, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'hf, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'he, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0};
|
||||
assign gbuf = green_palette[uv];
|
||||
|
||||
assign blue_palette = {4'ha, 4'h9, 4'h8, 4'h7, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'ha, 4'h9, 4'h8, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'hf, 4'he, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h4, 4'h3, 4'h2, 4'h1, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'hf, 4'hf, 4'hf, 4'hf, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h4, 4'h3, 4'h2, 4'h1, 4'hf, 4'he, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'hb, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'ha, 4'h9, 4'h8, 4'h7, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0};
|
||||
assign bbuf = blue_palette[uv];
|
||||
|
||||
|
||||
// Row counter counts from 0 to 520
|
||||
// count of 0 - 479 is display time (row == line_number here)
|
||||
// count of 480 - 489 is front porch
|
||||
// count of 490 - 491 is VS=0 pulse width
|
||||
// count of 492 - 525 is back porch
|
||||
|
||||
always @(posedge clk, posedge reset)
|
||||
if (reset) begin
|
||||
row <= 10'd519;
|
||||
end else if (row_clear)
|
||||
row <= 10'd0;
|
||||
else
|
||||
row <= row + row_enable;
|
||||
|
||||
assign row_clear = (row == 10'd524) & row_enable;
|
||||
assign row_enable = (col == 10'd799);
|
||||
assign VSync = (row < 10'd490) | (row > 10'd491);
|
||||
|
||||
// Col counter counts from 0 to 799
|
||||
// count of 0 - 639 is display time
|
||||
// count of 640 - 655 is front porch
|
||||
// count of 656 - 751 is HS=0 pulse width
|
||||
// count of 752 - 799 is back porch
|
||||
|
||||
always @(posedge clk)//, reset)
|
||||
if (reset | col_clear)
|
||||
col <= 10'd0;
|
||||
else
|
||||
col <= col + col_enable;
|
||||
|
||||
/*logic [7:0] tia_buf_col;
|
||||
logic write_buf1;
|
||||
logic [7:0][159:0] tia_buf1;
|
||||
logic [7:0][159:0] tia_buf2;
|
||||
integer i;
|
||||
|
||||
always @(posedge tia_hblank)
|
||||
write_buf1 <= ~write_buf1;
|
||||
|
||||
always @(posedge tia_clk, posedge reset) begin
|
||||
if (reset) begin
|
||||
tia_buf_col <= 7'b0;
|
||||
tia_buf1 <= 1280'b0;
|
||||
tia_buf2 <= 1280'b0;
|
||||
end else if (tia_en & tia_vsync_delta) begin
|
||||
tia_buf_col <= 7'b0;
|
||||
for (i=0;i<160;i=i+1) begin
|
||||
tia_buf1[i] <= 8'b0;
|
||||
tia_buf2[i] <= 8'b0;
|
||||
end
|
||||
end else if (tia_hblank)
|
||||
tia_buf_col <= 8'd160;
|
||||
else if (tia_buf_col == 8'd227)
|
||||
tia_buf_col <= 8'd0;
|
||||
else begin
|
||||
tia_buf_col <= tia_buf_col + 1;
|
||||
if (write_buf1)
|
||||
tia_buf1[tia_buf_col] <= uv_in;
|
||||
else
|
||||
tia_buf2[tia_buf_col] <= uv_in;
|
||||
end
|
||||
end*/
|
||||
|
||||
assign col_clear = row_enable;
|
||||
assign col_enable = 1'b1;
|
||||
assign HSync = (col < 10'd656) | (col > 10'd751);
|
||||
|
||||
endmodule
|
||||
242
Atari - 7800_TeST/rtl/video_mixer.sv
Normal file
242
Atari - 7800_TeST/rtl/video_mixer.sv
Normal file
@@ -0,0 +1,242 @@
|
||||
//
|
||||
//
|
||||
// Copyright (c) 2017 Sorgelig
|
||||
//
|
||||
// This program is GPL Licensed. See COPYING for the full license.
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
//
|
||||
// LINE_LENGTH: Length of display line in pixels
|
||||
// Usually it's length from HSync to HSync.
|
||||
// May be less if line_start is used.
|
||||
//
|
||||
// HALF_DEPTH: If =1 then color dept is 3 bits per component
|
||||
// For half depth 6 bits monochrome is available with
|
||||
// mono signal enabled and color = {G, R}
|
||||
|
||||
module video_mixer
|
||||
#(
|
||||
parameter LINE_LENGTH = 768,
|
||||
parameter HALF_DEPTH = 0,
|
||||
|
||||
parameter OSD_COLOR = 3'd7,
|
||||
parameter OSD_X_OFFSET = 10'd0,
|
||||
parameter OSD_Y_OFFSET = 10'd0
|
||||
)
|
||||
(
|
||||
// master clock
|
||||
// it should be multiple by (ce_pix*4).
|
||||
input clk_sys,
|
||||
|
||||
// Pixel clock or clock_enable (both are accepted).
|
||||
input ce_pix,
|
||||
|
||||
// Some systems have multiple resolutions.
|
||||
// ce_pix_actual should match ce_pix where every second or fourth pulse is enabled,
|
||||
// thus half or qurter resolutions can be used without brake video sync while switching resolutions.
|
||||
// For fixed single resolution (or when video sync stability isn't required) ce_pix_actual = ce_pix.
|
||||
input ce_pix_actual,
|
||||
|
||||
// OSD SPI interface
|
||||
input SPI_SCK,
|
||||
input SPI_SS3,
|
||||
input SPI_DI,
|
||||
|
||||
// scanlines (00-none 01-25% 10-50% 11-75%)
|
||||
input [1:0] scanlines,
|
||||
|
||||
// 0 = HVSync 31KHz, 1 = CSync 15KHz
|
||||
input scandoubler_disable,
|
||||
|
||||
// High quality 2x scaling
|
||||
input hq2x,
|
||||
|
||||
// YPbPr always uses composite sync
|
||||
input ypbpr,
|
||||
|
||||
// 0 = 16-240 range. 1 = 0-255 range. (only for YPbPr color space)
|
||||
input ypbpr_full,
|
||||
|
||||
// color
|
||||
input [DWIDTH:0] R,
|
||||
input [DWIDTH:0] G,
|
||||
input [DWIDTH:0] B,
|
||||
|
||||
// Monochrome mode (for HALF_DEPTH only)
|
||||
input mono,
|
||||
|
||||
// interlace sync. Positive pulses.
|
||||
input HSync,
|
||||
input VSync,
|
||||
|
||||
// Falling of this signal means start of informative part of line.
|
||||
// It can be horizontal blank signal.
|
||||
// This signal can be used to reduce amount of required FPGA RAM for HQ2x scan doubler
|
||||
// If FPGA RAM is not an issue, then simply set it to 0 for whole line processing.
|
||||
// Keep in mind: due to algo first and last pixels of line should be black to avoid side artefacts.
|
||||
// Thus, if blank signal is used to reduce the line, make sure to feed at least one black (or paper) pixel
|
||||
// before first informative pixel.
|
||||
input line_start,
|
||||
|
||||
// MiST video output signals
|
||||
output [5:0] VGA_R,
|
||||
output [5:0] VGA_G,
|
||||
output [5:0] VGA_B,
|
||||
output VGA_VS,
|
||||
output VGA_HS
|
||||
);
|
||||
|
||||
localparam DWIDTH = HALF_DEPTH ? 2 : 5;
|
||||
|
||||
wire [DWIDTH:0] R_sd;
|
||||
wire [DWIDTH:0] G_sd;
|
||||
wire [DWIDTH:0] B_sd;
|
||||
wire hs_sd, vs_sd;
|
||||
|
||||
scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH)) scandoubler
|
||||
(
|
||||
.*,
|
||||
.hs_in(HSync),
|
||||
.vs_in(VSync),
|
||||
.r_in(R),
|
||||
.g_in(G),
|
||||
.b_in(B),
|
||||
|
||||
.hs_out(hs_sd),
|
||||
.vs_out(vs_sd),
|
||||
.r_out(R_sd),
|
||||
.g_out(G_sd),
|
||||
.b_out(B_sd)
|
||||
);
|
||||
|
||||
wire [DWIDTH:0] rt = (scandoubler_disable ? R : R_sd);
|
||||
wire [DWIDTH:0] gt = (scandoubler_disable ? G : G_sd);
|
||||
wire [DWIDTH:0] bt = (scandoubler_disable ? B : B_sd);
|
||||
|
||||
generate
|
||||
if(HALF_DEPTH) begin
|
||||
wire [5:0] r = mono ? {gt,rt} : {rt,rt};
|
||||
wire [5:0] g = mono ? {gt,rt} : {gt,gt};
|
||||
wire [5:0] b = mono ? {gt,rt} : {bt,bt};
|
||||
end else begin
|
||||
wire [5:0] r = rt;
|
||||
wire [5:0] g = gt;
|
||||
wire [5:0] b = bt;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
wire hs = (scandoubler_disable ? HSync : hs_sd);
|
||||
wire vs = (scandoubler_disable ? VSync : vs_sd);
|
||||
|
||||
reg scanline = 0;
|
||||
always @(posedge clk_sys) begin
|
||||
reg old_hs, old_vs;
|
||||
|
||||
old_hs <= hs;
|
||||
old_vs <= vs;
|
||||
|
||||
if(old_hs && ~hs) scanline <= ~scanline;
|
||||
if(old_vs && ~vs) scanline <= 0;
|
||||
end
|
||||
|
||||
wire [5:0] r_out, g_out, b_out;
|
||||
always @(*) begin
|
||||
case(scanlines & {scanline, scanline})
|
||||
1: begin // reduce 25% = 1/2 + 1/4
|
||||
r_out = {1'b0, r[5:1]} + {2'b00, r[5:2]};
|
||||
g_out = {1'b0, g[5:1]} + {2'b00, g[5:2]};
|
||||
b_out = {1'b0, b[5:1]} + {2'b00, b[5:2]};
|
||||
end
|
||||
|
||||
2: begin // reduce 50% = 1/2
|
||||
r_out = {1'b0, r[5:1]};
|
||||
g_out = {1'b0, g[5:1]};
|
||||
b_out = {1'b0, b[5:1]};
|
||||
end
|
||||
|
||||
3: begin // reduce 75% = 1/4
|
||||
r_out = {2'b00, r[5:2]};
|
||||
g_out = {2'b00, g[5:2]};
|
||||
b_out = {2'b00, b[5:2]};
|
||||
end
|
||||
|
||||
default: begin
|
||||
r_out = r;
|
||||
g_out = g;
|
||||
b_out = b;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
wire [5:0] red, green, blue;
|
||||
osd #(OSD_X_OFFSET, OSD_Y_OFFSET, OSD_COLOR) osd
|
||||
(
|
||||
.*,
|
||||
|
||||
.R_in(r_out),
|
||||
.G_in(g_out),
|
||||
.B_in(b_out),
|
||||
.HSync(hs),
|
||||
.VSync(vs),
|
||||
|
||||
.R_out(red),
|
||||
.G_out(green),
|
||||
.B_out(blue)
|
||||
);
|
||||
|
||||
wire [5:0] yuv_full[225] = '{
|
||||
6'd0, 6'd0, 6'd0, 6'd0, 6'd1, 6'd1, 6'd1, 6'd1,
|
||||
6'd2, 6'd2, 6'd2, 6'd3, 6'd3, 6'd3, 6'd3, 6'd4,
|
||||
6'd4, 6'd4, 6'd5, 6'd5, 6'd5, 6'd5, 6'd6, 6'd6,
|
||||
6'd6, 6'd7, 6'd7, 6'd7, 6'd7, 6'd8, 6'd8, 6'd8,
|
||||
6'd9, 6'd9, 6'd9, 6'd9, 6'd10, 6'd10, 6'd10, 6'd11,
|
||||
6'd11, 6'd11, 6'd11, 6'd12, 6'd12, 6'd12, 6'd13, 6'd13,
|
||||
6'd13, 6'd13, 6'd14, 6'd14, 6'd14, 6'd15, 6'd15, 6'd15,
|
||||
6'd15, 6'd16, 6'd16, 6'd16, 6'd17, 6'd17, 6'd17, 6'd17,
|
||||
6'd18, 6'd18, 6'd18, 6'd19, 6'd19, 6'd19, 6'd19, 6'd20,
|
||||
6'd20, 6'd20, 6'd21, 6'd21, 6'd21, 6'd21, 6'd22, 6'd22,
|
||||
6'd22, 6'd23, 6'd23, 6'd23, 6'd23, 6'd24, 6'd24, 6'd24,
|
||||
6'd25, 6'd25, 6'd25, 6'd25, 6'd26, 6'd26, 6'd26, 6'd27,
|
||||
6'd27, 6'd27, 6'd27, 6'd28, 6'd28, 6'd28, 6'd29, 6'd29,
|
||||
6'd29, 6'd29, 6'd30, 6'd30, 6'd30, 6'd31, 6'd31, 6'd31,
|
||||
6'd31, 6'd32, 6'd32, 6'd32, 6'd33, 6'd33, 6'd33, 6'd33,
|
||||
6'd34, 6'd34, 6'd34, 6'd35, 6'd35, 6'd35, 6'd35, 6'd36,
|
||||
6'd36, 6'd36, 6'd36, 6'd37, 6'd37, 6'd37, 6'd38, 6'd38,
|
||||
6'd38, 6'd38, 6'd39, 6'd39, 6'd39, 6'd40, 6'd40, 6'd40,
|
||||
6'd40, 6'd41, 6'd41, 6'd41, 6'd42, 6'd42, 6'd42, 6'd42,
|
||||
6'd43, 6'd43, 6'd43, 6'd44, 6'd44, 6'd44, 6'd44, 6'd45,
|
||||
6'd45, 6'd45, 6'd46, 6'd46, 6'd46, 6'd46, 6'd47, 6'd47,
|
||||
6'd47, 6'd48, 6'd48, 6'd48, 6'd48, 6'd49, 6'd49, 6'd49,
|
||||
6'd50, 6'd50, 6'd50, 6'd50, 6'd51, 6'd51, 6'd51, 6'd52,
|
||||
6'd52, 6'd52, 6'd52, 6'd53, 6'd53, 6'd53, 6'd54, 6'd54,
|
||||
6'd54, 6'd54, 6'd55, 6'd55, 6'd55, 6'd56, 6'd56, 6'd56,
|
||||
6'd56, 6'd57, 6'd57, 6'd57, 6'd58, 6'd58, 6'd58, 6'd58,
|
||||
6'd59, 6'd59, 6'd59, 6'd60, 6'd60, 6'd60, 6'd60, 6'd61,
|
||||
6'd61, 6'd61, 6'd62, 6'd62, 6'd62, 6'd62, 6'd63, 6'd63,
|
||||
6'd63
|
||||
};
|
||||
|
||||
// http://marsee101.blog19.fc2.com/blog-entry-2311.html
|
||||
// Y = 16 + 0.257*R + 0.504*G + 0.098*B (Y = 0.299*R + 0.587*G + 0.114*B)
|
||||
// Pb = 128 - 0.148*R - 0.291*G + 0.439*B (Pb = -0.169*R - 0.331*G + 0.500*B)
|
||||
// Pr = 128 + 0.439*R - 0.368*G - 0.071*B (Pr = 0.500*R - 0.419*G - 0.081*B)
|
||||
|
||||
wire [18:0] y_8 = 19'd04096 + ({red, 8'd0} + {red, 3'd0}) + ({green, 9'd0} + {green, 2'd0}) + ({blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0});
|
||||
wire [18:0] pb_8 = 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0}) - ({green, 8'd0} + {green, 5'd0} + {green, 3'd0}) + ({blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0});
|
||||
wire [18:0] pr_8 = 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0}) - ({green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0}) - ({blue, 6'd0} + {blue , 3'd0});
|
||||
|
||||
wire [7:0] y = ( y_8[17:8] < 16) ? 8'd16 : ( y_8[17:8] > 235) ? 8'd235 : y_8[15:8];
|
||||
wire [7:0] pb = (pb_8[17:8] < 16) ? 8'd16 : (pb_8[17:8] > 240) ? 8'd240 : pb_8[15:8];
|
||||
wire [7:0] pr = (pr_8[17:8] < 16) ? 8'd16 : (pr_8[17:8] > 240) ? 8'd240 : pr_8[15:8];
|
||||
|
||||
assign VGA_R = ypbpr ? (ypbpr_full ? yuv_full[pr-8'd16] : pr[7:2]) : red;
|
||||
assign VGA_G = ypbpr ? (ypbpr_full ? yuv_full[y -8'd16] : y[7:2]) : green;
|
||||
assign VGA_B = ypbpr ? (ypbpr_full ? yuv_full[pb-8'd16] : pb[7:2]) : blue;
|
||||
assign VGA_VS = (scandoubler_disable | ypbpr) ? 1'b1 : ~vs_sd;
|
||||
assign VGA_HS = scandoubler_disable ? ~(HSync ^ VSync) : ypbpr ? ~(hs_sd ^ vs_sd) : ~hs_sd;
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user