1
0
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:
gehstock
2018-07-17 14:41:52 +02:00
parent bfc3b3ed46
commit ab51b822bb
43 changed files with 9062 additions and 0 deletions

View 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"

View 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

Binary file not shown.

View File

@@ -0,0 +1,2 @@
{ "" "" "" "*" { } { } 0 10230 "" 0 0 "Quartus II" 0 -1 0 ""}
{ "" "" "" "*" { } { } 0 10036 "" 0 0 "Quartus II" 0 -1 0 ""}

Binary file not shown.

View 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

View 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

View 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

View 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

View 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

View 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

View 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]

View 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

View 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

View File

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

View File

@@ -0,0 +1,2 @@
`define BUILD_DATE "180630"
`define BUILD_TIME "212824"

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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
View 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

View 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

View 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

View 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

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View 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

Binary file not shown.

View 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

View 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

View 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

View 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

View 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

View 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